diff options
Diffstat (limited to 'src/classes/streamed_resource.rs')
-rw-r--r-- | src/classes/streamed_resource.rs | 50 |
1 files changed, 50 insertions, 0 deletions
diff --git a/src/classes/streamed_resource.rs b/src/classes/streamed_resource.rs new file mode 100644 index 0000000..945c8e1 --- /dev/null +++ b/src/classes/streamed_resource.rs @@ -0,0 +1,50 @@ +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 StreamedResource { + pub offset: u64, + pub size: u64, + pub path: String, +} + +impl FromValue for StreamedResource { + fn from_value(v: Value) -> Result<Self> { + let mut fields = v.as_class("StreamedResource")?; + Ok(StreamedResource { + offset: fields.field("m_Offset")?, + size: fields.field("m_Size")?, + path: fields.field("m_Source")?, + }) + } +} + +impl StreamedResource { + pub fn read(&self, fs: &UnityFS<impl Read + Seek>) -> Result<Vec<u8>> { + if !self.path.starts_with("archive:") { + bail!( + "StreamedResource 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).read_to_end(&mut buf)?; + Ok(buf) + } +} |