diff options
author | metamuffin <metamuffin@disroot.org> | 2025-03-12 22:39:58 +0100 |
---|---|---|
committer | metamuffin <metamuffin@disroot.org> | 2025-03-12 22:39:58 +0100 |
commit | 5555c8bbefb4f52f5002603eb91b6c95cbdd97e4 (patch) | |
tree | 208e88359deb3cf5f7e2a4135693f12d76ad97e1 /src/object/parser.rs | |
parent | 4906844cbfd2717a29b434fb7d8f90c5117fddd5 (diff) | |
download | unity-tools-5555c8bbefb4f52f5002603eb91b6c95cbdd97e4.tar unity-tools-5555c8bbefb4f52f5002603eb91b6c95cbdd97e4.tar.bz2 unity-tools-5555c8bbefb4f52f5002603eb91b6c95cbdd97e4.tar.zst |
more parsing helpers
Diffstat (limited to 'src/object/parser.rs')
-rw-r--r-- | src/object/parser.rs | 92 |
1 files changed, 92 insertions, 0 deletions
diff --git a/src/object/parser.rs b/src/object/parser.rs new file mode 100644 index 0000000..5879e9a --- /dev/null +++ b/src/object/parser.rs @@ -0,0 +1,92 @@ +use super::Value; +use anyhow::{Context, Result, anyhow, bail}; +use std::collections::BTreeMap; + +pub trait FromValue: Sized { + fn from_value(v: Value) -> Result<Self>; +} + +impl Value { + pub fn parse<T: FromValue>(self) -> Result<T> { + T::from_value(self) + } + pub fn as_class(self, name: &'static str) -> Result<Fields> { + if let Value::Object { class, fields } = self { + if class == name { + Ok(Fields { + class: name, + fields, + }) + } else { + bail!("expected class {name} but found {class}") + } + } else { + bail!("expected class {name}") + } + } +} + +pub struct Fields { + class: &'static str, + fields: BTreeMap<String, Value>, +} + +impl Fields { + pub fn field<T: FromValue>(&mut self, name: &str) -> Result<T> { + self.fields + .remove(name) + .ok_or(anyhow!("expected {name} field in {}", self.class))? + .parse() + .context(anyhow!("in {}.{name} field", self.class)) + } + pub fn remove(&mut self, key: &str) -> Option<Value> { + self.fields.remove(key) + } +} + +impl FromValue for u8 { + fn from_value(v: Value) -> anyhow::Result<Self> { + v.as_u8().ok_or(anyhow!("expected u8")) + } +} +impl FromValue for u16 { + fn from_value(v: Value) -> anyhow::Result<Self> { + v.as_u16().ok_or(anyhow!("expected u16")) + } +} +impl FromValue for f32 { + fn from_value(v: Value) -> anyhow::Result<Self> { + v.as_f32().ok_or(anyhow!("expected f32")) + } +} +impl FromValue for u32 { + fn from_value(v: Value) -> anyhow::Result<Self> { + v.as_u32().ok_or(anyhow!("expected u32")) + } +} +impl FromValue for i32 { + fn from_value(v: Value) -> anyhow::Result<Self> { + v.as_i32().ok_or(anyhow!("expected i32")) + } +} +impl FromValue for u64 { + fn from_value(v: Value) -> anyhow::Result<Self> { + v.as_u64().ok_or(anyhow!("expected u64")) + } +} +impl FromValue for bool { + fn from_value(v: Value) -> anyhow::Result<Self> { + v.as_bool().ok_or(anyhow!("expected bool")) + } +} +impl FromValue for String { + fn from_value(v: Value) -> anyhow::Result<Self> { + v.as_string().ok_or(anyhow!("expected string")) + } +} + +impl Value { + pub fn as_vector(self) -> Option<Vec<Value>> { + self.as_class("vector").ok()?.remove("Array")?.as_array() + } +} |