1use std::cmp::Ordering;
2use std::convert::TryFrom;
3use std::hash::{Hash, Hasher};
4use std::ops::Deref;
5use std::str::FromStr;
6use std::sync::Arc;
7
8use serde::{Deserialize, Deserializer, Serialize, Serializer};
9
10#[macro_export]
13macro_rules! ijson {
14 ($($json:tt)+) => {
15 $crate::Json::new(serde_json::json!($($json)+))
16 }
17}
18
19fn hash<H: Hasher>(value: &serde_json::Value, state: &mut H) {
20 match value {
21 serde_json::Value::Null => {
22 state.write_u8(0);
23 }
24 serde_json::Value::Bool(v) => {
25 state.write_u8(1);
26 v.hash(state);
27 }
28 serde_json::Value::Number(v) => {
29 state.write_u8(2);
30 if v.is_i64() {
31 v.as_i64().unwrap().hash(state);
32 } else if v.is_u64() {
33 v.as_u64().unwrap().hash(state);
34 } else {
35 v.as_f64().unwrap().to_bits().hash(state);
37 }
38 }
39 serde_json::Value::String(v) => {
40 state.write_u8(3);
41 v.hash(state);
42 }
43 serde_json::Value::Array(v) => {
44 state.write_u8(4);
45 for sv in v {
46 hash(sv, state);
47 }
48 }
49 serde_json::Value::Object(v) => {
50 state.write_u8(5);
51 for (sk, sv) in v {
52 sk.hash(state);
53 hash(sv, state);
54 }
55 }
56 }
57}
58
59fn partial_cmp(first: &serde_json::Value, second: &serde_json::Value) -> Option<Ordering> {
60 match (first, second) {
61 (serde_json::Value::Null, serde_json::Value::Null) => Some(Ordering::Equal),
62 (serde_json::Value::Bool(v1), serde_json::Value::Bool(v2)) => v1.partial_cmp(v2),
63 (serde_json::Value::Number(v1), serde_json::Value::Number(v2)) => {
64 if v1.is_i64() {
65 let v1 = v1.as_i64().unwrap();
66 if v2.is_i64() {
67 v1.partial_cmp(&v2.as_i64().unwrap())
68 } else if v2.is_u64() {
69 match i64::try_from(v2.as_u64().unwrap()) {
70 Ok(v2) => v1.partial_cmp(&v2),
71 Err(_) => Some(Ordering::Less),
72 }
73 } else {
74 (v1 as f64).partial_cmp(&v2.as_f64().unwrap())
75 }
76 } else if v1.is_u64() {
77 let v1 = v1.as_u64().unwrap();
78 if v2.is_i64() {
79 match u64::try_from(v2.as_i64().unwrap()) {
80 Ok(v2) => v1.partial_cmp(&v2),
81 Err(_) => Some(Ordering::Greater),
82 }
83 } else if v2.is_u64() {
84 v1.partial_cmp(&v2.as_u64().unwrap())
85 } else {
86 (v1 as f64).partial_cmp(&v2.as_f64().unwrap())
87 }
88 } else {
89 let v1 = v1.as_f64().unwrap();
90 if v2.is_i64() {
91 v1.partial_cmp(&(v2.as_i64().unwrap() as f64))
92 } else if v2.is_u64() {
93 v1.partial_cmp(&(v2.as_u64().unwrap() as f64))
94 } else {
95 v1.partial_cmp(&v2.as_f64().unwrap())
96 }
97 }
98 }
99 (serde_json::Value::String(v1), serde_json::Value::String(v2)) => v1.partial_cmp(v2),
100 (serde_json::Value::Array(v1), serde_json::Value::Array(v2)) => {
101 partial_cmp_by(v1.iter(), v2.iter(), partial_cmp)
102 }
103 (serde_json::Value::Object(v1), serde_json::Value::Object(v2)) => {
104 partial_cmp_by(v1.iter(), v2.iter(), |v1, v2| {
105 let (v1_key, v1_value) = v1;
106 let (v2_key, v2_value) = v2;
107 match v1_key.partial_cmp(v2_key) {
108 Some(Ordering::Equal) => partial_cmp(v1_value, v2_value),
109 non_eq => non_eq,
110 }
111 })
112 }
113 _ => None,
114 }
115}
116
117fn partial_cmp_by<I, F>(mut first: I, mut second: I, mut f: F) -> Option<Ordering>
118where
119 I: Iterator,
120 F: FnMut(I::Item, I::Item) -> Option<Ordering>,
121{
122 loop {
123 let x = match first.next() {
124 None => {
125 if second.next().is_none() {
126 return Some(Ordering::Equal);
127 } else {
128 return Some(Ordering::Less);
129 }
130 }
131 Some(val) => val,
132 };
133
134 let y = match second.next() {
135 None => return Some(Ordering::Greater),
136 Some(val) => val,
137 };
138
139 match f(x, y) {
140 Some(Ordering::Equal) => (),
141 non_eq => return non_eq,
142 }
143 }
144}
145
146#[derive(Clone, Eq, Debug)]
149pub struct Json(pub Arc<serde_json::Value>);
150
151impl Json {
152 pub fn new(value: serde_json::Value) -> Self {
157 Self(Arc::new(value))
158 }
159}
160
161impl From<serde_json::Value> for Json {
162 fn from(value: serde_json::Value) -> Self {
163 Self(Arc::new(value))
164 }
165}
166
167impl From<Arc<serde_json::Value>> for Json {
168 fn from(value: Arc<serde_json::Value>) -> Self {
169 Self(value)
170 }
171}
172
173impl Hash for Json {
174 fn hash<H: Hasher>(&self, state: &mut H) {
175 hash(&self.0, state);
176 }
177}
178
179impl PartialEq for Json {
180 fn eq(&self, other: &Self) -> bool {
181 self.partial_cmp(other) == Some(Ordering::Equal)
182 }
183}
184
185impl PartialOrd for Json {
186 fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
187 partial_cmp(&self.0, &other.0)
188 }
189}
190
191impl Deref for Json {
192 type Target = serde_json::Value;
193 fn deref(&self) -> &Self::Target {
194 &self.0
195 }
196}
197
198impl Serialize for Json {
199 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
200 where
201 S: Serializer,
202 {
203 (*self.0).serialize(serializer)
204 }
205}
206
207impl<'de> Deserialize<'de> for Json {
208 fn deserialize<D>(deserializer: D) -> Result<Json, D::Error>
209 where
210 D: Deserializer<'de>,
211 {
212 let v: serde_json::Value = Deserialize::deserialize(deserializer)?;
213 Ok(Json::new(v))
214 }
215}
216
217impl FromStr for Json {
218 type Err = serde_json::Error;
219
220 fn from_str(s: &str) -> Result<Self, Self::Err> {
221 let sj = serde_json::from_str(s)?;
222 Ok(Self::new(sj))
223 }
224}
225
226#[cfg(test)]
227mod tests {
228 use super::Json;
229 use std::collections::HashSet;
230
231 fn json_u64() -> Json {
232 Json::new(serde_json::Value::Number(serde_json::Number::from(u64::max_value())))
233 }
234
235 fn json_i64() -> Json {
236 Json::new(serde_json::Value::Number(serde_json::Number::from(i64::min_value())))
237 }
238
239 #[test]
240 fn should_hash() {
241 assert_eq!(HashSet::from([ijson!(null)]), HashSet::from([ijson!(null)]));
242 assert_eq!(HashSet::from([json_i64()]), HashSet::from([json_i64()]));
243 assert_eq!(HashSet::from([json_u64()]), HashSet::from([json_u64()]));
244 assert_eq!(HashSet::from([ijson!(3.0)]), HashSet::from([ijson!(3.0)]));
245 assert_eq!(HashSet::from([ijson!("foo")]), HashSet::from([ijson!("foo")]));
246 assert_eq!(HashSet::from([ijson!(["foo"])]), HashSet::from([ijson!(["foo"])]));
247 assert_eq!(
248 HashSet::from([ijson!({"foo": true})]),
249 HashSet::from([ijson!({"foo": true})])
250 );
251 }
252
253 #[test]
254 fn should_compare() {
255 assert!(ijson!("foo1") < ijson!("foo2"));
256 assert_eq!(ijson!(null), ijson!(null));
257 assert!(ijson!(true) > ijson!(false));
258 assert!(ijson!(3) < ijson!(4));
259 assert!(ijson!(3) < ijson!(4.0));
260 assert_eq!(ijson!(4.0), ijson!(4.0));
261 assert!(ijson!(3.0) < ijson!(4));
262 assert!(ijson!([3.0, 4.0]) < ijson!([4.0, 3.0]));
263
264 assert_eq!(json_u64(), json_u64());
265 assert!(ijson!(3) < json_u64());
266 assert!(json_u64() > ijson!(3.0));
267 assert!(ijson!(3.0) < json_u64());
268
269 assert!(json_u64() > json_i64());
270 assert!(json_i64() < json_u64());
271 assert!(ijson!(3) > json_i64());
272 assert!(json_i64() < ijson!(3.0));
273
274 assert!(ijson!({}) == ijson!({}));
275 assert!(ijson!({"key": "value0"}) < ijson!({"key": "value1"}));
276 assert!(ijson!({"key": "value1"}) > ijson!({"key": "value0"}));
277 assert!(ijson!({"key1": "value0"}) > ijson!({"key0": "value1"}));
278 assert_eq!(ijson!({"key": "value"}), ijson!({"key": "value"}));
279 assert!(ijson!({"key": "value"}) > ijson!({}));
280 assert!(ijson!({}) < ijson!({"key": "value"}));
281 assert!(ijson!({"key": "value"}) > ijson!({}));
282 }
283}