context_weaver/
types.rs

1use std::collections::HashMap;
2use std::convert::TryInto;
3
4#[derive(Clone, Debug)]
5pub enum WorldInfoType {
6    String(String),
7    Boolean(bool),
8    Number(Number),
9    List(Vec<WorldInfoType>),
10    Map(HashMap<String, WorldInfoType>),
11    Null
12}
13
14#[derive(Clone, Debug)]
15pub enum Number {
16    Int(i64),
17    UInt(u64),
18    Float(f64),
19}
20
21impl Number {
22    pub fn as_i64(&self) -> Option<i64> {
23        match self {
24            Number::Int(i) => Some(*i),
25            _ => None,
26        }
27    }
28
29    pub fn as_u64(&self) -> Option<u64> {
30        match self {
31            Number::UInt(u) => Some(*u),
32            _ => None,
33        }
34    }
35
36    pub fn as_f64(&self) -> f64 {
37        match self {
38            Number::Int(i) => *i as f64,
39            Number::UInt(u) => *u as f64,
40            Number::Float(f) => *f,
41        }
42    }
43}
44
45// Macro to generate TryFrom and TryInto impls
46macro_rules! impl_world_info_type_conversion {
47    ($variant:ident, $type:ty, $error_msg:expr) => {
48        impl TryInto<$type> for WorldInfoType {
49            type Error = String;
50
51            fn try_into(self) -> Result<$type, Self::Error> {
52                if let WorldInfoType::$variant(value) = self {
53                    Ok(value)
54                } else {
55                    Err($error_msg.to_string())
56                }
57            }
58        }
59
60        impl Into<WorldInfoType> for $type {
61            fn into(self) -> WorldInfoType {
62                WorldInfoType::$variant(self)
63            }
64        }
65    };
66}
67
68macro_rules! impl_number_type_conversion {
69    ($variant:ident, $type:ty) => {
70        impl Into<Number> for $type {
71            fn into(self) -> Number {
72                Number::$variant(self)
73            }
74        }
75    }
76} 
77
78macro_rules! impl_world_info_number_type_conversion {
79    ($variant:ident, $type:ty) => {
80        impl Into<WorldInfoType> for $type {
81            fn into(self) -> WorldInfoType {
82                WorldInfoType::Number(Number::$variant(self))
83            }
84        }
85    }
86} 
87
88// Use marcos to implement the TryFrom and TryInto impls
89impl_world_info_type_conversion!(String, String, "Not a string");
90impl_world_info_type_conversion!(Boolean, bool, "Not a boolean");
91impl_world_info_type_conversion!(List, Vec<WorldInfoType>, "Not a list");
92impl_world_info_type_conversion!(Map, HashMap<String, WorldInfoType>, "Not a map");
93impl_number_type_conversion!(Int, i64);
94impl_number_type_conversion!(UInt, u64);
95impl_number_type_conversion!(Float, f64);
96impl_world_info_number_type_conversion!(Int, i64);
97impl_world_info_number_type_conversion!(UInt, u64);
98impl_world_info_number_type_conversion!(Float, f64);
99
100impl Into<WorldInfoType> for serde_json::Value {
101    fn into(self) -> WorldInfoType {
102        match self {
103            serde_json::Value::Null => WorldInfoType::Null,
104            serde_json::Value::Bool(b) => WorldInfoType::Boolean(b),
105            serde_json::Value::Number(number) => WorldInfoType::Number(number.into()),
106            serde_json::Value::String(s) => WorldInfoType::String(s),
107            serde_json::Value::Array(values) => WorldInfoType::List(values.into_iter().map(|x| x.into()).collect()),
108            serde_json::Value::Object(map) => WorldInfoType::Map(map.into_iter().map(|(k, v)| (k, v.into())).collect()),
109        }
110    }
111}
112
113impl Into<WorldInfoType> for &serde_json::Value {
114    fn into(self) -> WorldInfoType {
115        match self {
116            serde_json::Value::Null => WorldInfoType::Null,
117            serde_json::Value::Bool(b) => WorldInfoType::Boolean(b.clone()),
118            serde_json::Value::Number(number) => WorldInfoType::Number(number.clone().into()),
119            serde_json::Value::String(s) => WorldInfoType::String(s.clone()),
120            serde_json::Value::Array(values) => WorldInfoType::List(values.into_iter().map(|x| x.into()).collect()),
121            serde_json::Value::Object(map) => WorldInfoType::Map(map.into_iter().map(|(k, v)| (k.clone(), v.clone().into())).collect()),
122        }
123    }
124}
125
126impl Into<Number> for serde_json::Number {
127    fn into(self) -> Number {
128        if self.is_f64() { 
129            Number::Float(self.as_f64().unwrap())
130        } else if self.is_u64() {
131            Number::UInt(self.as_u64().unwrap())
132        } else {
133            Number::Int(self.as_i64().unwrap())
134        }
135    }
136}