Skip to main content

sonic_rs/value/
partial_eq.rs

1use faststr::FastStr;
2
3use crate::value::{
4    node::{Value, ValueRefInner},
5    value_trait::{JsonContainerTrait, JsonValueTrait},
6};
7impl Eq for Value {}
8
9impl PartialEq for Value {
10    #[inline]
11    fn eq(&self, other: &Self) -> bool {
12        if self.get_type() != other.get_type() {
13            return false;
14        }
15        match self.as_ref2() {
16            ValueRefInner::Null => other.is_null(),
17            ValueRefInner::Bool(a) => other.as_bool() == Some(a),
18            ValueRefInner::Number(_) | ValueRefInner::RawNum(_) => {
19                other.as_number() == self.as_number()
20            }
21            ValueRefInner::Str(a) => other.as_str() == Some(a),
22            ValueRefInner::Array(_) | ValueRefInner::EmptyArray => {
23                other.as_value_slice() == self.as_value_slice()
24            }
25            ValueRefInner::Object(_)
26            | ValueRefInner::EmptyObject
27            | ValueRefInner::ObjectOwned(_) => other.as_object() == self.as_object(),
28        }
29    }
30}
31
32macro_rules! impl_str_eq {
33    ($($eq:ident [$($ty:ty)*])*) => {
34        $($(
35            impl PartialEq<$ty> for Value {
36                #[inline]
37                fn eq(&self, other: &$ty) -> bool {
38                    let s: &str = other.as_ref();
39                    $eq(self, s)
40                }
41            }
42
43            impl PartialEq<Value> for $ty {
44                #[inline]
45                fn eq(&self, other: &Value) -> bool {
46                    let s: &str = self.as_ref();
47                    $eq(other, s)
48                }
49            }
50
51            impl PartialEq<$ty> for &Value {
52                #[inline]
53                fn eq(&self, other: &$ty) -> bool {
54                    let s: &str = other.as_ref();
55                    $eq(*self, s)
56                }
57            }
58
59            impl PartialEq<$ty> for &mut Value {
60                #[inline]
61                fn eq(&self, other: &$ty) -> bool {
62                    let s: &str = other.as_ref();
63                    $eq(*self, s)
64                }
65            }
66        )*)*
67    }
68}
69
70impl_str_eq! {
71    eq_str[str String FastStr]
72}
73
74impl PartialEq<&str> for Value {
75    #[inline]
76    fn eq(&self, other: &&str) -> bool {
77        eq_str(self, other)
78    }
79}
80
81impl PartialEq<Value> for &str {
82    #[inline]
83    fn eq(&self, other: &Value) -> bool {
84        eq_str(other, self)
85    }
86}
87
88///////////////////////////////////////////////////////////////////
89// Copied from serde_json
90
91macro_rules! impl_eq_fn {
92    ($($name:ident($ty:ty) => $accessor:ident;)*) => {
93        $(
94            #[inline]
95            fn $name(value: &Value, other: $ty) -> bool {
96                value.$accessor() == Some(other)
97            }
98        )*
99    };
100}
101
102impl_eq_fn! {
103    eq_i64(i64) => as_i64;
104    eq_u64(u64) => as_u64;
105    eq_f64(f64) => as_f64;
106    eq_bool(bool) => as_bool;
107}
108
109#[inline]
110fn eq_str(value: &Value, other: &str) -> bool {
111    value.as_str() == Some(other)
112}
113
114macro_rules! impl_numeric_eq {
115    ($($eq:ident [$($ty:ty)*])*) => {
116        $($(
117            impl PartialEq<$ty> for Value {
118                #[inline]
119                fn eq(&self, other: &$ty) -> bool {
120                    $eq(self, *other as _)
121                }
122            }
123
124            impl PartialEq<Value> for $ty {
125                #[inline]
126                fn eq(&self, other: &Value) -> bool {
127                    $eq(other, *self as _)
128                }
129            }
130
131            impl PartialEq<$ty> for &Value {
132                #[inline]
133                fn eq(&self, other: &$ty) -> bool {
134                    $eq(*self, *other as _)
135                }
136            }
137
138            impl PartialEq<$ty> for &mut Value {
139                #[inline]
140                fn eq(&self, other: &$ty) -> bool {
141                    $eq(*self, *other as _)
142                }
143            }
144        )*)*
145    }
146}
147
148impl_numeric_eq! {
149    eq_i64[i8 i16 i32 i64 isize]
150    eq_u64[u8 u16 u32 u64 usize]
151    eq_f64[f32 f64]
152    eq_bool[bool]
153}
154
155//////////////////////////////////////////////////////////////////////////////
156
157macro_rules! impl_slice_eq {
158    ([$($vars:tt)*], $rhs:ty $(where $ty:ty: $bound:ident)?) => {
159        impl<U, $($vars)*> PartialEq<$rhs> for Array
160        where
161            Value: PartialEq<U>,
162            $($ty: $bound)?
163        {
164            #[inline]
165            fn eq(&self, other: &$rhs) -> bool {
166                let len = self.len();
167                if len != other.len() {
168                    return false;
169                }
170                let slf = self.as_ref();
171                let other: &[U] = other.as_ref();
172                slf.iter().zip(other).all(|(a, b)| *a == *b )
173            }
174        }
175
176        impl<U, $($vars)*> PartialEq<$rhs> for Value
177        where
178            Value: PartialEq<U>,
179            $($ty: $bound)?
180        {
181            #[inline]
182            fn eq(&self, other: &$rhs) -> bool {
183                self.as_array().map(|arr| arr == other).unwrap_or(false)
184            }
185        }
186
187
188        impl<U, $($vars)*> PartialEq<Array> for $rhs
189        where
190            Value: PartialEq<U>,
191            $($ty: $bound)?
192        {
193            #[inline]
194            fn eq(&self, other: &Array) -> bool {
195                other == self
196            }
197        }
198
199        impl<U, $($vars)*> PartialEq<Value> for $rhs
200        where
201            Value: PartialEq<U>,
202            $($ty: $bound)?
203        {
204            #[inline]
205            fn eq(&self, other: &Value) -> bool {
206                other == self
207            }
208        }
209    }
210}
211
212impl_slice_eq!([], &[U]);
213impl_slice_eq!([], &mut [U]);
214impl_slice_eq!([], [U]);
215impl_slice_eq!([const N: usize], &[U; N]);
216impl_slice_eq!([const N: usize], [U; N]);
217impl_slice_eq!([], Vec<U>);
218
219//////////////////////////////////////////////////////////////////////////////
220
221use super::{array::Array, object::Object};
222
223macro_rules! impl_container_eq {
224    ($($ty:ty)*) => {
225        $(
226            impl PartialEq<$ty> for Value {
227                #[inline]
228                fn eq(&self, other: &$ty) -> bool {
229                    self == &other.0
230                }
231            }
232
233            impl PartialEq<Value> for $ty {
234                #[inline]
235                fn eq(&self, other: &Value) -> bool {
236                    other == &self.0
237                }
238            }
239
240            impl  PartialEq<$ty> for &Value {
241                #[inline]
242                fn eq(&self, other: &$ty) -> bool {
243                    *self == &other.0
244                }
245            }
246
247            impl  PartialEq<$ty> for &mut Value {
248                #[inline]
249                fn eq(&self, other: &$ty) -> bool {
250                    *self == &other.0
251                }
252            }
253
254            impl PartialEq<Value> for &$ty {
255                #[inline]
256                fn eq(&self, other: &Value) -> bool {
257                    other == &self.0
258                }
259            }
260
261            impl PartialEq<Value> for &mut $ty {
262                #[inline]
263                fn eq(&self, other: &Value) -> bool {
264                    other == &self.0
265                }
266            }
267
268        )*
269    }
270}
271
272impl_container_eq!(Array Object);
273
274#[cfg(test)]
275mod test {
276    use faststr::FastStr;
277
278    #[test]
279    fn test_slice_eq() {
280        assert_eq!(json!([1, 2, 3]), &[1, 2, 3]);
281        assert_eq!(array![1, 2, 3], &[1, 2, 3]);
282        assert_eq!(json!([1, 2, 3]), array![1, 2, 3].as_slice());
283
284        assert_eq!(json!([1, 2, 3]), vec![1, 2, 3]);
285        assert_eq!(vec![1, 2, 3], array![1, 2, 3]);
286        assert_eq!(array![1, 2, 3], &[1, 2, 3][..]);
287        assert_eq!(json!([1, 2, 3]), array![1, 2, 3].as_slice());
288    }
289
290    #[test]
291    fn test_str_eq() {
292        assert_eq!(json!("123"), FastStr::new("123"));
293        assert_eq!(json!("123"), "123");
294    }
295
296    #[test]
297    fn test_container_eq() {
298        assert_eq!(json!([1, 2, 3]), array![1, 2, 3]);
299        assert_eq!(array![1, 2, 3], json!([1, 2, 3]));
300        assert_eq!(json!({"a": 1, "b": 2}), json!({"b": 2, "a": 1}));
301        assert_eq!(json!({"a": 1, "b": 2}), object! {"a": 1, "b": 2});
302        assert_eq!(object! {"a": 1, "b": 2}, json!({"a": 1, "b": 2}));
303    }
304}