1use std::borrow::Cow;
4
5use serde_json::{Map, Value};
6
7use crate::{cmp, types::JsonType};
8
9use super::{Array, Json, Node, NodeIdentity, Object};
10
11pub struct SerdeJson;
12
13impl Json for SerdeJson {
14 type Node<'a> = &'a Value;
15 type PreparedKey = String;
16 type StringBuffer = Value;
17
18 const KEYS_PER_LOOKUP: usize = 2;
20
21 fn prepare_key(key: &str) -> String {
22 key.to_owned()
23 }
24
25 fn with_string_node<T>(buffer: &mut Value, string: &str, f: impl FnOnce(&Value) -> T) -> T {
26 if let Value::String(existing) = buffer {
28 existing.clear();
29 existing.push_str(string);
30 } else {
31 *buffer = Value::String(string.to_owned());
32 }
33 f(buffer)
34 }
35}
36
37impl<'a> Node<'a, SerdeJson> for &'a Value {
38 type Object = &'a Map<String, Value>;
39 type Array = &'a [Value];
40 type Number = &'a serde_json::Number;
41
42 fn as_object(&self) -> Option<&'a Map<String, Value>> {
43 match self {
44 Value::Object(members) => Some(members),
45 _ => None,
46 }
47 }
48
49 fn as_array(&self) -> Option<&'a [Value]> {
50 match self {
51 Value::Array(items) => Some(items),
52 _ => None,
53 }
54 }
55
56 fn as_string(&self) -> Option<Cow<'a, str>> {
57 match self {
58 Value::String(string) => Some(Cow::Borrowed(string)),
59 _ => None,
60 }
61 }
62
63 fn as_number(&self) -> Option<&'a serde_json::Number> {
64 match self {
65 Value::Number(number) => Some(number),
66 _ => None,
67 }
68 }
69
70 fn as_boolean(&self) -> Option<bool> {
71 match self {
72 Value::Bool(boolean) => Some(*boolean),
73 _ => None,
74 }
75 }
76
77 fn is_null(&self) -> bool {
78 matches!(self, Value::Null)
79 }
80
81 fn json_type(&self) -> JsonType {
82 match self {
83 Value::Null => JsonType::Null,
84 Value::Bool(_) => JsonType::Boolean,
85 Value::Number(_) => JsonType::Number,
86 Value::String(_) => JsonType::String,
87 Value::Array(_) => JsonType::Array,
88 Value::Object(_) => JsonType::Object,
89 }
90 }
91
92 fn string_length(&self) -> Option<u64> {
93 match self {
94 Value::String(string) => Some(bytecount::num_chars(string.as_bytes()) as u64),
96 _ => None,
97 }
98 }
99
100 fn equals_value(&self, expected: &Value) -> bool {
101 cmp::equal(self, expected)
102 }
103
104 fn to_value(&self) -> Cow<'a, Value> {
105 Cow::Borrowed(self)
106 }
107
108 fn identity(&self) -> Option<NodeIdentity> {
109 Some(NodeIdentity::new(std::ptr::from_ref::<Value>(self) as usize))
110 }
111}
112
113pub struct SerdeMembersIter<'a>(serde_json::map::Iter<'a>);
114
115impl<'a> Iterator for SerdeMembersIter<'a> {
116 type Item = (&'a str, &'a Value);
117
118 fn next(&mut self) -> Option<Self::Item> {
119 self.0.next().map(|(key, value)| (key.as_str(), value))
120 }
121}
122
123impl<'a> Object<'a, SerdeJson> for &'a Map<String, Value> {
124 type Node = &'a Value;
125 type MemberName = &'a str;
126 type MembersIter = SerdeMembersIter<'a>;
127
128 fn len(&self) -> usize {
129 Map::len(self)
130 }
131
132 fn get(&self, key: &String) -> Option<&'a Value> {
133 (*self).get(key.as_str())
134 }
135
136 fn members(&self) -> SerdeMembersIter<'a> {
137 SerdeMembersIter((*self).iter())
138 }
139}
140
141impl<'a> Array<'a, SerdeJson> for &'a [Value] {
142 type Node = &'a Value;
143 type ElementsIter = std::slice::Iter<'a, Value>;
144
145 fn len(&self) -> usize {
146 <[Value]>::len(self)
147 }
148
149 fn elements(&self) -> std::slice::Iter<'a, Value> {
150 (*self).iter()
151 }
152
153 fn is_unique(&self) -> bool {
154 crate::unique::is_unique(self)
155 }
156}
157
158#[cfg(test)]
159mod tests {
160 use std::borrow::Cow;
161
162 use serde_json::{json, Value};
163 use test_case::test_case;
164
165 use super::{
166 super::{Array, Json, JsonNumber, Node, Object},
167 SerdeJson,
168 };
169 use crate::types::JsonType;
170
171 fn assert_document_accessors<F: Json>(node: &F::Node<'_>) {
174 let object = node.as_object().expect("object");
175
176 let member = |name: &str| object.get(&F::prepare_key(name)).expect("present");
177
178 assert!(member("object").as_object().is_some());
179 assert_eq!(member("array").as_array().expect("array").len(), 3);
180 assert_eq!(member("string").as_string().as_deref(), Some("héllo"));
181 assert_eq!(member("string").json_type(), JsonType::String);
182 assert_eq!(member("string").string_length(), Some(5));
183 assert_eq!(
184 member("integer").as_number().expect("number").as_u64(),
185 Some(42)
186 );
187 assert_eq!(
188 member("float").as_number().expect("number").as_f64(),
189 Some(1.5)
190 );
191 assert_eq!(member("boolean").as_boolean(), Some(true));
192 assert!(member("null").is_null());
193 assert_eq!(member("null").json_type(), JsonType::Null);
194 assert!(object.get(&F::prepare_key("missing")).is_none());
195 }
196
197 #[test]
198 fn accessors_match_value_kinds() {
199 let document = json!({
200 "object": {"a": 1},
201 "array": [1, 2, 3],
202 "string": "héllo",
203 "integer": 42,
204 "float": 1.5,
205 "boolean": true,
206 "null": null
207 });
208 assert_document_accessors::<SerdeJson>(&&document);
209 }
210
211 #[test_case(&json!(1), &json!(1.0), true; "integer equals float")]
212 #[test_case(&json!(1.0), &json!(1), true; "float equals integer")]
213 #[test_case(&json!(1), &json!(2), false; "different integers")]
214 #[test_case(&json!(true), &json!(1), false; "boolean is not a number")]
215 #[test_case(&json!({"a": [1, {"b": 1.0}]}), &json!({"a": [1.0, {"b": 1}]}), true; "nested numeric equality")]
216 #[test_case(&json!({"a": [1, {"b": 1.0}]}), &json!({"a": [1, {"b": 2}]}), false; "nested mismatch")]
217 fn equals_value_follows_json_schema_semantics(left: &Value, right: &Value, expected: bool) {
218 assert_eq!(left.equals_value(right), expected);
219 }
220
221 #[test_case("", 0; "empty")]
222 #[test_case("héllo", 5; "multi-byte")]
223 #[test_case("🦀🦀", 2; "astral plane")]
224 fn string_length_counts_code_points(input: &str, expected: u64) {
225 let value = json!(input);
226 assert_eq!((&value).string_length(), Some(expected));
227 }
228
229 #[test]
230 fn to_value_borrows() {
231 let document = json!({"a": 1});
232 let node = &document;
233 assert!(matches!(node.to_value(), Cow::Borrowed(_)));
234 }
235
236 fn assert_identity_stability<F: Json>(node: &F::Node<'_>) {
237 let child = node
238 .as_object()
239 .expect("object")
240 .get(&F::prepare_key("a"))
241 .expect("present");
242 assert_eq!(node.identity(), node.identity());
243 assert_ne!(node.identity(), child.identity());
244 }
245
246 #[test]
247 fn identity_is_stable_per_node() {
248 let document = json!({"a": {"b": 1}});
249 assert_identity_stability::<SerdeJson>(&&document);
250 }
251
252 fn assert_iteration_order<F: Json>(node: &F::Node<'_>) {
253 let object = node.as_object().expect("object");
254 let names: Vec<_> = object
255 .members()
256 .map(|(name, _)| name.as_ref().to_owned())
257 .collect();
258 assert_eq!(names, ["a", "b"]);
259
260 let items = object
261 .get(&F::prepare_key("b"))
262 .expect("present")
263 .as_array()
264 .expect("array");
265 let collected: Vec<Option<u64>> = items
266 .elements()
267 .map(|item| item.as_number().and_then(|number| number.as_u64()))
268 .collect();
269 assert_eq!(collected, [Some(10), Some(20)]);
270 }
271
272 #[test]
273 fn members_and_items_iterate_in_order() {
274 let document = json!({"a": 1, "b": [10, 20]});
275 assert_iteration_order::<SerdeJson>(&&document);
276 }
277}