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}