From 5555c8bbefb4f52f5002603eb91b6c95cbdd97e4 Mon Sep 17 00:00:00 2001 From: metamuffin Date: Wed, 12 Mar 2025 22:39:58 +0100 Subject: more parsing helpers --- src/object/parser.rs | 92 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 92 insertions(+) create mode 100644 src/object/parser.rs (limited to 'src/object/parser.rs') 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; +} + +impl Value { + pub fn parse(self) -> Result { + T::from_value(self) + } + pub fn as_class(self, name: &'static str) -> Result { + 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, +} + +impl Fields { + pub fn field(&mut self, name: &str) -> Result { + 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 { + self.fields.remove(key) + } +} + +impl FromValue for u8 { + fn from_value(v: Value) -> anyhow::Result { + v.as_u8().ok_or(anyhow!("expected u8")) + } +} +impl FromValue for u16 { + fn from_value(v: Value) -> anyhow::Result { + v.as_u16().ok_or(anyhow!("expected u16")) + } +} +impl FromValue for f32 { + fn from_value(v: Value) -> anyhow::Result { + v.as_f32().ok_or(anyhow!("expected f32")) + } +} +impl FromValue for u32 { + fn from_value(v: Value) -> anyhow::Result { + v.as_u32().ok_or(anyhow!("expected u32")) + } +} +impl FromValue for i32 { + fn from_value(v: Value) -> anyhow::Result { + v.as_i32().ok_or(anyhow!("expected i32")) + } +} +impl FromValue for u64 { + fn from_value(v: Value) -> anyhow::Result { + v.as_u64().ok_or(anyhow!("expected u64")) + } +} +impl FromValue for bool { + fn from_value(v: Value) -> anyhow::Result { + v.as_bool().ok_or(anyhow!("expected bool")) + } +} +impl FromValue for String { + fn from_value(v: Value) -> anyhow::Result { + v.as_string().ok_or(anyhow!("expected string")) + } +} + +impl Value { + pub fn as_vector(self) -> Option> { + self.as_class("vector").ok()?.remove("Array")?.as_array() + } +} -- cgit v1.2.3-70-g09d2