wfrs_model/
json.rs

1use rkyv::{Archive, Deserialize, Serialize};
2use std::{collections::HashMap, fmt, hash::Hash};
3
4#[derive(Archive, Debug, Deserialize, Serialize, PartialEq, Eq, PartialOrd, Ord, Hash)]
5pub struct JsonKey(String);
6
7impl AsRef<str> for JsonKey {
8    fn as_ref(&self) -> &str {
9        self.0.as_str()
10    }
11}
12
13#[derive(Archive, Debug, Deserialize, Serialize, PartialEq)]
14#[archive(
15    bound(
16        serialize = "__S: rkyv::ser::ScratchSpace + rkyv::ser::SharedSerializeRegistry + rkyv::ser::Serializer",
17        deserialize = "__D: rkyv::de::SharedDeserializeRegistry"
18    ),
19    check_bytes
20)]
21#[archive_attr(
22    check_bytes(
23        bound = "__C: rkyv::validation::ArchiveContext, <__C as rkyv::Fallible>::Error: rkyv::bytecheck::Error"
24    ),
25    derive(Debug)
26)]
27pub enum JsonValue {
28    Null,
29    Bool(bool),
30    Number(JsonNumber),
31    String(String),
32    Array(
33        #[omit_bounds]
34        #[archive_attr(omit_bounds)]
35        Vec<JsonValue>,
36    ),
37    Object(
38        #[omit_bounds]
39        #[archive_attr(omit_bounds)]
40        HashMap<String, JsonValue>,
41    ),
42}
43
44impl PartialEq<JsonValue> for ArchivedJsonValue {
45    fn eq(&self, other: &JsonValue) -> bool {
46        match self {
47            ArchivedJsonValue::Null => other.is_null(),
48            ArchivedJsonValue::Bool(v) => Some(*v) == other.as_bool(),
49            ArchivedJsonValue::Number(v) => match v {
50                ArchivedJsonNumber::Float(v) => Some(*v) == other.as_f64(),
51                ArchivedJsonNumber::PosInt(v) => Some(*v) == other.as_u64(),
52                ArchivedJsonNumber::NegInt(v) => Some(*v) == other.as_i64(),
53            },
54            ArchivedJsonValue::String(v) => match other {
55                JsonValue::String(s) => s.as_str() == v.as_str(),
56                _ => false,
57            },
58            ArchivedJsonValue::Array(v) => {
59                if other.is_array() {
60                    let other = other.as_array().unwrap();
61                    let o = other.len();
62                    let l = v.len();
63                    if o != l {
64                        return false;
65                    }
66                    for i in 0..l {
67                        if !v[i].eq(&other[i]) {
68                            return false;
69                        }
70                    }
71                    return true;
72                }
73                false
74            }
75            ArchivedJsonValue::Object(v) => {
76                if other.is_object() {
77                    let other = other.as_object().unwrap();
78                    let o = other.len();
79                    let l = v.len();
80                    if o != l {
81                        return false;
82                    }
83                    for (key, value) in other.iter() {
84                        if !v.contains_key(key.as_str()) {
85                            return false;
86                        }
87                        if !v.get(key.as_str()).unwrap().eq(value) {
88                            return false;
89                        }
90                    }
91                    return true;
92                }
93                false
94            }
95        }
96    }
97}
98
99impl JsonValue {
100    pub fn map() -> Self {
101        Self::Object(HashMap::default())
102    }
103
104    pub fn is_null(&self) -> bool {
105        match self {
106            JsonValue::Null => true,
107            _ => false,
108        }
109    }
110
111    pub fn is_object(&self) -> bool {
112        match self {
113            JsonValue::Object(_) => true,
114            _ => false,
115        }
116    }
117
118    pub fn as_object(&self) -> Option<&HashMap<String, JsonValue>> {
119        match self {
120            JsonValue::Object(v) => Some(v),
121            _ => None,
122        }
123    }
124
125    pub fn is_array(&self) -> bool {
126        match self {
127            JsonValue::Array(_) => true,
128            _ => false,
129        }
130    }
131
132    pub fn as_array(&self) -> Option<&[JsonValue]> {
133        match self {
134            JsonValue::Array(v) => Some(v),
135            _ => None,
136        }
137    }
138
139    pub fn as_bool(&self) -> Option<bool> {
140        match self {
141            JsonValue::Bool(b) => Some(*b),
142            _ => None,
143        }
144    }
145
146    pub fn as_number(&self) -> Option<&JsonNumber> {
147        match self {
148            JsonValue::Number(n) => Some(n),
149            _ => None,
150        }
151    }
152
153    pub fn as_str(&self) -> Option<&str> {
154        match self {
155            JsonValue::String(s) => Some(s.as_str()),
156            _ => None,
157        }
158    }
159
160    pub fn as_f64(&self) -> Option<f64> {
161        match self {
162            JsonValue::Number(n) => match n {
163                JsonNumber::Float(v) => Some(*v),
164                _ => None,
165            },
166            _ => None,
167        }
168    }
169
170    pub fn as_i64(&self) -> Option<i64> {
171        match self {
172            JsonValue::Number(n) => match n {
173                JsonNumber::NegInt(v) => Some(*v),
174                _ => None,
175            },
176            _ => None,
177        }
178    }
179
180    pub fn as_u64(&self) -> Option<u64> {
181        match self {
182            JsonValue::Number(n) => match n {
183                JsonNumber::PosInt(v) => Some(*v),
184                _ => None,
185            },
186            _ => None,
187        }
188    }
189
190    pub fn as_object_mut(&mut self) -> Option<&mut HashMap<String, JsonValue>> {
191        match self {
192            JsonValue::Object(obj) => Some(obj),
193            _ => None,
194        }
195    }
196}
197
198impl fmt::Display for ArchivedJsonValue {
199    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
200        match self {
201            Self::Null => write!(f, "null")?,
202            Self::Bool(b) => write!(f, "{}", b)?,
203            Self::Number(n) => write!(f, "{}", n)?,
204            Self::String(s) => write!(f, "{}", s)?,
205            Self::Array(a) => {
206                write!(f, "[")?;
207                for (i, value) in a.iter().enumerate() {
208                    write!(f, "{}", value)?;
209                    if i < a.len() - 1 {
210                        write!(f, ", ")?;
211                    }
212                }
213                write!(f, "]")?;
214            }
215            Self::Object(h) => {
216                write!(f, "{{")?;
217                for (i, (key, value)) in h.iter().enumerate() {
218                    write!(f, "\"{}\": {}", key, value)?;
219                    if i < h.len() - 1 {
220                        write!(f, ", ")?;
221                    }
222                }
223                write!(f, "}}")?;
224            }
225        }
226        Ok(())
227    }
228}
229
230#[derive(Archive, Debug, Deserialize, Serialize, PartialEq, PartialOrd)]
231#[archive(check_bytes)]
232#[archive_attr(derive(Debug))]
233pub enum JsonNumber {
234    PosInt(u64),
235    NegInt(i64),
236    Float(f64),
237}
238
239impl JsonNumber {
240    pub fn as_f64(&self) -> f64 {
241        match self {
242            Self::PosInt(n) => *n as f64,
243            Self::NegInt(n) => *n as f64,
244            Self::Float(n) => *n,
245        }
246    }
247}
248
249impl fmt::Display for ArchivedJsonNumber {
250    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
251        match self {
252            Self::PosInt(n) => write!(f, "{}", n),
253            Self::NegInt(n) => write!(f, "{}", n),
254            Self::Float(n) => write!(f, "{}", n),
255        }
256    }
257}
258
259impl PartialEq<JsonNumber> for ArchivedJsonNumber {
260    fn eq(&self, other: &JsonNumber) -> bool {
261        match self {
262            ArchivedJsonNumber::PosInt(v) => JsonNumber::PosInt(*v).eq(other),
263            ArchivedJsonNumber::NegInt(v) => JsonNumber::NegInt(*v).eq(other),
264            ArchivedJsonNumber::Float(v) => JsonNumber::Float(*v).eq(other),
265        }
266    }
267}
268
269impl PartialOrd<JsonNumber> for ArchivedJsonNumber {
270    fn partial_cmp(&self, other: &JsonNumber) -> Option<std::cmp::Ordering> {
271        match self {
272            ArchivedJsonNumber::PosInt(v) => JsonNumber::PosInt(*v).partial_cmp(other),
273            ArchivedJsonNumber::NegInt(v) => JsonNumber::NegInt(*v).partial_cmp(other),
274            ArchivedJsonNumber::Float(v) => JsonNumber::Float(*v).partial_cmp(other),
275        }
276    }
277}