aboutsummaryrefslogtreecommitdiff
path: root/src/unityfs/multi_reader.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/unityfs/multi_reader.rs')
-rw-r--r--src/unityfs/multi_reader.rs50
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)
+ }
+}