diff options
Diffstat (limited to 'src/unityfs/multi_reader.rs')
-rw-r--r-- | src/unityfs/multi_reader.rs | 50 |
1 files changed, 50 insertions, 0 deletions
diff --git a/src/unityfs/multi_reader.rs b/src/unityfs/multi_reader.rs new file mode 100644 index 0000000..3de6cd5 --- /dev/null +++ b/src/unityfs/multi_reader.rs @@ -0,0 +1,50 @@ +use std::{ + io::{Read, Seek, SeekFrom}, + sync::{Arc, Mutex}, +}; + +use anyhow::Result; + +pub struct MultiReader<T> { + position: u64, + inner: Arc<Mutex<(u64, T)>>, +} +impl<T: Seek> MultiReader<T> { + pub fn new(mut inner: T) -> Result<Self> { + let position = inner.stream_position()?; + Ok(Self { + position, + inner: Arc::new(Mutex::new((position, inner))), + }) + } +} +impl<T> Clone for MultiReader<T> { + fn clone(&self) -> Self { + Self { + position: self.position, + inner: self.inner.clone(), + } + } +} +impl<T: Read + Seek> Read for MultiReader<T> { + fn read(&mut self, buf: &mut [u8]) -> std::io::Result<usize> { + let mut g = self.inner.lock().unwrap(); + if g.0 != self.position { + g.1.seek(SeekFrom::Start(self.position))?; + } + let size = g.1.read(buf)?; + g.0 += size as u64; + self.position += size as u64; + Ok(size) + } +} +impl<T: Seek> Seek for MultiReader<T> { + fn seek(&mut self, pos: SeekFrom) -> std::io::Result<u64> { + self.position = match pos { + SeekFrom::Start(x) => x, + SeekFrom::Current(x) => self.position.saturating_add_signed(x), + SeekFrom::End(_) => unimplemented!(), + }; + Ok(self.position) + } +} |