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