diff options
Diffstat (limited to 'remuxer/src/trim_writer.rs')
-rw-r--r-- | remuxer/src/trim_writer.rs | 64 |
1 files changed, 64 insertions, 0 deletions
diff --git a/remuxer/src/trim_writer.rs b/remuxer/src/trim_writer.rs new file mode 100644 index 0000000..65d3589 --- /dev/null +++ b/remuxer/src/trim_writer.rs @@ -0,0 +1,64 @@ +use std::{ + io::{Seek, Write}, + ops::Range, +}; + +use anyhow::anyhow; +use log::warn; + +pub struct TrimWriter<W> { + inner: W, + position: usize, + range: Range<usize>, +} +impl<W: Write> TrimWriter<W> { + pub fn new(inner: W, range: Range<usize>) -> Self { + Self { + inner, + range, + position: 0, + } + } +} + +impl<W: Write> Write for TrimWriter<W> { + fn write(&mut self, buf: &[u8]) -> std::io::Result<usize> { + let start = self.range.start as isize - self.position as isize; + let end = self.range.end as isize - self.position as isize; + + let start = start.clamp(0, buf.len() as isize) as usize; + let end = end.clamp(0, buf.len() as isize) as usize; + + if self.position >= self.range.end { + return Err(std::io::Error::new( + std::io::ErrorKind::Other, + anyhow!("range ended"), + )); + } + + let buf = &buf[start..end]; + if !buf.is_empty() { + self.inner.write_all(buf)?; + self.position += buf.len() + } + Ok(buf.len()) + } + + fn flush(&mut self) -> std::io::Result<()> { + self.inner.flush() + } +} + +impl<W> Seek for TrimWriter<W> { + fn seek(&mut self, pos: std::io::SeekFrom) -> std::io::Result<u64> { + match pos { + std::io::SeekFrom::Start(s) => self.position = s as usize, + std::io::SeekFrom::End(_) => unimplemented!(), + std::io::SeekFrom::Current(s) => self.position += s as usize, + } + if self.position < self.range.end { + warn!("seeked beyond end") + } + Ok(self.position as u64) + } +} |