aboutsummaryrefslogtreecommitdiff
path: root/src/object/parser.rs
diff options
context:
space:
mode:
authormetamuffin <metamuffin@disroot.org>2025-03-12 22:39:58 +0100
committermetamuffin <metamuffin@disroot.org>2025-03-12 22:39:58 +0100
commit5555c8bbefb4f52f5002603eb91b6c95cbdd97e4 (patch)
tree208e88359deb3cf5f7e2a4135693f12d76ad97e1 /src/object/parser.rs
parent4906844cbfd2717a29b434fb7d8f90c5117fddd5 (diff)
downloadunity-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.rs92
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()
+ }
+}