The 0.18 trait split into FrameSource (read-only) and FrameSink
(write-only) was an over-engineered API. Consumers don't think
"frame source backed by MKV" — they think "open MKV for reading".
The split paid a real API-complexity cost (two trait names, two
re-exports, dual impls per bidirectional type, deprecation bridge)
for one marginal property: compile-time direction-safety at the
trait-object boundary. The runtime error path on a wrong-direction
call (StreamReadOnly / StreamWriteOnly) is unambiguous and rare in
practice.
Deletions:
- pes::Stream is no longer #[deprecated]
- pes::FrameSource trait + its blanket-from-Stream bridge
- pes::FrameSink trait + the trampoline impls on every concrete type
- The compile-time-direction-safety test scaffolding
- Crate-root FrameSource / FrameSink re-exports
Additions:
- Stream is now Send-bounded (Stream: Send supertrait). Every
concrete impl was already Send-compliant — Box<dyn Read + Send>
and Box<dyn Write + Send> were already in place on the trait
objects MkvStream / M2tsStream / etc hold internally. Promoting
Send into the trait makes Box<dyn Stream> Send too, which lets
autorip drop its SendStream unsafe newtype.
The public API is now: one Stream trait, one concrete type per
format, two constructors (open/create or input/output). Bidirectional
types route through internal Mode { Read | Write } discriminants.
Net: -347 lines libfreemkv, -38 lines autorip, -5 lines freemkv.
56 lines
1.3 KiB
Rust
56 lines
1.3 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(),
|
|
}
|
|
}
|
|
}
|
|
|
|
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
|
|
}
|
|
}
|
|
|
|
#[cfg(test)]
|
|
mod tests {
|
|
use super::*;
|
|
use crate::pes::Stream;
|
|
|
|
/// Verify NullStream routes through the `Stream` trait object cleanly.
|
|
#[test]
|
|
fn stream_via_dyn_object_writes_and_finishes() {
|
|
let title = DiscTitle::empty();
|
|
let mut sink: Box<dyn Stream> = 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();
|
|
let _ = sink.info();
|
|
sink.finish().unwrap();
|
|
}
|
|
}
|