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