diff options
Diffstat (limited to 'src/classes/streaming_info.rs')
-rw-r--r-- | src/classes/streaming_info.rs | 51 |
1 files changed, 51 insertions, 0 deletions
diff --git a/src/classes/streaming_info.rs b/src/classes/streaming_info.rs new file mode 100644 index 0000000..9f7ce23 --- /dev/null +++ b/src/classes/streaming_info.rs @@ -0,0 +1,51 @@ +use crate::{ + object::{Value, parser::FromValue}, + unityfs::UnityFS, +}; +use anyhow::{Result, anyhow, bail}; +use serde::Serialize; +use std::io::{Read, Seek, SeekFrom}; + +#[derive(Debug, Serialize)] +pub struct StreamingInfo { + pub offset: u64, + pub path: String, + pub size: u32, +} + +impl FromValue for StreamingInfo { + fn from_value(v: Value) -> Result<Self> { + let mut fields = v.as_class("StreamingInfo")?; + Ok(StreamingInfo { + offset: fields.field("offset")?, + size: fields.field("size")?, + path: fields.field("path")?, + }) + } +} + +impl StreamingInfo { + pub fn read(&self, fs: &UnityFS<impl Read + Seek>) -> Result<Vec<u8>> { + if !self.path.starts_with("archive:") { + bail!( + "StreamingInfo path does not start on 'archive:' ({:?})", + self.path + ) + } + let nodeinfo = fs + .header + .nodes() + .iter() + .find(|n| self.path.ends_with(&n.name)) + .ok_or(anyhow!("node with path {:?} not found", self.path))? + .to_owned(); + + let mut buf = Vec::new(); + + let mut node = fs.read(&nodeinfo)?; + node.seek(SeekFrom::Start(self.offset))?; + node.take(self.size as u64).read_to_end(&mut buf)?; + + Ok(buf) + } +} |