Per-impl migration of MkvStream / M2tsStream / NetworkStream / NullStream / StdioStream from the deprecated pes::Stream trait to the typed pes::FrameSink trait. Both impls coexist during the 0.18 deprecation window — the existing Stream impls are unchanged. The FrameSink::finish signature differs (Box<Self> vs &mut self), which is why this couldn't be a blanket impl. Each migration re-borrows the box and delegates to the underlying Stream::finish body. FrameSink: Send forced two struct fields (M2tsStream's boxed Write/Read, MkvStream's boxed WriteSeek/Read) to gain `+ Send` bounds — minimum surface needed to make the Send-bounded trait impl-able. mux::resolve::output's local Box<dyn WriteSeek> construction picks up the same `+ Send`. tests/streams.rs's shared `stream.write/.finish/.info/.read` calls were disambiguated to `PesStream::*` to resolve the now-multiple candidates from coexisting trait impls. Caller migration (mux::resolve::output return type, autorip, CLI) is a later slice. This commit only adds new impls; nothing removed. See freemkv-private/memory/0_18_redesign.md. Single contributor: MattJackson.
86 lines
2.8 KiB
Rust
86 lines
2.8 KiB
Rust
//! NullStream — discards all data. Write-only PES sink. For benchmarking.
|
|
|
|
use crate::disc::DiscTitle;
|
|
use std::io;
|
|
|
|
/// Null stream — accepts PES writes, discards data. For benchmarking rip speed.
|
|
pub struct NullStream {
|
|
disc_title: DiscTitle,
|
|
}
|
|
|
|
impl NullStream {
|
|
pub fn new(title: &DiscTitle) -> Self {
|
|
Self {
|
|
disc_title: title.clone(),
|
|
}
|
|
}
|
|
}
|
|
|
|
#[allow(deprecated)] // 0.18 trait split: migrate to FrameSink in follow-up commit.
|
|
impl crate::pes::Stream for NullStream {
|
|
fn read(&mut self) -> io::Result<Option<crate::pes::PesFrame>> {
|
|
Ok(None)
|
|
}
|
|
fn write(&mut self, _: &crate::pes::PesFrame) -> io::Result<()> {
|
|
Ok(())
|
|
}
|
|
fn finish(&mut self) -> io::Result<()> {
|
|
Ok(())
|
|
}
|
|
fn info(&self) -> &DiscTitle {
|
|
&self.disc_title
|
|
}
|
|
}
|
|
|
|
/// FrameSink sibling to the deprecated Stream impl; both coexist during the
|
|
/// 0.18 deprecation window. Caller may pick either at the trait-object
|
|
/// boundary — `Box<dyn Stream>` (deprecated) or `Box<dyn FrameSink>` (new).
|
|
/// The deprecation-window callers eventually migrate; this impl exists so
|
|
/// new callers can target `FrameSink` without waiting for the rest of the
|
|
/// migration to complete.
|
|
#[allow(deprecated)] // delegating to deprecated Stream during the 0.18 deprecation window so callers don't see the deprecation twice.
|
|
impl crate::pes::FrameSink for NullStream {
|
|
fn write(&mut self, frame: &crate::pes::PesFrame) -> io::Result<()> {
|
|
<Self as crate::pes::Stream>::write(self, frame)
|
|
}
|
|
|
|
fn finish(self: Box<Self>) -> io::Result<()> {
|
|
// Why: Stream::finish takes &mut self, FrameSink::finish takes Box<Self>.
|
|
// Re-borrow inside the box, call Stream::finish, drop the box.
|
|
let mut s: Self = *self;
|
|
<Self as crate::pes::Stream>::finish(&mut s)
|
|
}
|
|
|
|
fn info(&self) -> &DiscTitle {
|
|
<Self as crate::pes::Stream>::info(self)
|
|
}
|
|
}
|
|
|
|
#[cfg(test)]
|
|
mod tests {
|
|
use super::*;
|
|
use crate::pes::FrameSink;
|
|
|
|
/// Smallest credible witness that the new FrameSink impl on a concrete
|
|
/// `mux/*` sink works through the trait object: build a boxed
|
|
/// `dyn FrameSink`, write a frame, finish it. The trait-bridge correctness
|
|
/// is what's being verified — not NullStream-specific behaviour.
|
|
#[test]
|
|
fn frame_sink_via_dyn_object_writes_and_finishes() {
|
|
let title = DiscTitle::empty();
|
|
let mut sink: Box<dyn FrameSink> = Box::new(NullStream::new(&title));
|
|
|
|
let frame = crate::pes::PesFrame {
|
|
track: 0,
|
|
pts: 0,
|
|
keyframe: true,
|
|
data: vec![0x01, 0x02, 0x03],
|
|
};
|
|
sink.write(&frame).unwrap();
|
|
// info() routes through the trait object.
|
|
let _ = sink.info();
|
|
// finish() consumes the Box<Self> — must compile and run.
|
|
sink.finish().unwrap();
|
|
}
|
|
}
|