From d836e24357b81496c61f3cc9195ba36758523578 Mon Sep 17 00:00:00 2001 From: metamuffin Date: Sat, 15 Mar 2025 15:18:40 +0100 Subject: more abstraction around unityfs to read multiple files from a single reader --- src/unityfs/multi_reader.rs | 50 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 50 insertions(+) create mode 100644 src/unityfs/multi_reader.rs (limited to 'src/unityfs/multi_reader.rs') 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 { + position: u64, + inner: Arc>, +} +impl MultiReader { + pub fn new(mut inner: T) -> Result { + let position = inner.stream_position()?; + Ok(Self { + position, + inner: Arc::new(Mutex::new((position, inner))), + }) + } +} +impl Clone for MultiReader { + fn clone(&self) -> Self { + Self { + position: self.position, + inner: self.inner.clone(), + } + } +} +impl Read for MultiReader { + fn read(&mut self, buf: &mut [u8]) -> std::io::Result { + 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 Seek for MultiReader { + fn seek(&mut self, pos: SeekFrom) -> std::io::Result { + self.position = match pos { + SeekFrom::Start(x) => x, + SeekFrom::Current(x) => self.position.saturating_add_signed(x), + SeekFrom::End(_) => unimplemented!(), + }; + Ok(self.position) + } +} -- cgit v1.2.3-70-g09d2