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