1use std::{collections::BTreeSet, fmt, sync::Arc};
2
3use serde::{
4 Deserialize, Deserializer, Serialize, Serializer,
5 de::{DeserializeSeed, Error as DeError, MapAccess, SeqAccess, Visitor},
6};
7use serde_json::{Map as SerdeJsonMap, Value as SerdeJsonValue};
8
9use crate::{
10 CoreError, CoreResult, DbString, db_string::MAX_DB_STRING_BYTES, json_patch::apply_json_patch,
11};
12
13#[derive(Clone, Debug, Eq, PartialEq)]
15pub enum JsonPathSelector {
16 Key(DbString),
18 Index(i64),
22 UnsignedIndex(u64),
24}
25
26#[derive(Clone, Debug, PartialEq)]
32pub struct JsonValue {
33 value: Arc<SerdeJsonValue>,
34}
35
36#[derive(Clone, Copy, Debug, PartialEq)]
41pub struct JsonValueRef<'a> {
42 value: &'a SerdeJsonValue,
43}
44
45impl<'a> JsonValueRef<'a> {
46 #[must_use]
48 pub fn as_serde(self) -> &'a SerdeJsonValue {
49 self.value
50 }
51
52 #[must_use]
54 pub fn to_owned_json_value(self) -> JsonValue {
55 JsonValue {
56 value: Arc::new(self.value.clone()),
57 }
58 }
59}
60
61impl JsonValue {
62 pub fn new(value: SerdeJsonValue) -> CoreResult<Self> {
64 validate_json_value(&value)?;
65 Ok(Self {
66 value: Arc::new(value),
67 })
68 }
69
70 pub fn parse_str(text: &str) -> CoreResult<Self> {
77 let value = parse_json_text(text).map_err(|err| CoreError::JsonParse {
78 message: err.to_string(),
79 })?;
80 Self::new(value)
81 }
82
83 #[must_use]
85 pub fn as_serde(&self) -> &SerdeJsonValue {
86 &self.value
87 }
88
89 #[must_use]
91 pub fn as_arc(&self) -> Arc<SerdeJsonValue> {
92 Arc::clone(&self.value)
93 }
94
95 #[must_use]
97 pub fn to_canonical_string(&self) -> String {
98 let mut output = String::new();
99 write_json_canonical(self.as_serde(), &mut output);
100 output
101 }
102
103 #[must_use]
105 pub fn json_type_name(&self) -> &'static str {
106 match self.as_serde() {
107 SerdeJsonValue::Null => "null",
108 SerdeJsonValue::Bool(_) => "boolean",
109 SerdeJsonValue::Number(_) => "number",
110 SerdeJsonValue::String(_) => "string",
111 SerdeJsonValue::Array(_) => "array",
112 SerdeJsonValue::Object(_) => "object",
113 }
114 }
115
116 #[must_use]
123 pub fn contains(&self, candidate: &Self) -> bool {
124 json_contains_value(self.as_serde(), candidate.as_serde())
125 }
126
127 #[must_use]
133 pub fn path_exists(&self, path: &[JsonPathSelector]) -> bool {
134 select_json_path(self.as_serde(), path).is_some()
135 }
136
137 #[must_use]
143 pub fn path_value(&self, path: &[JsonPathSelector]) -> Option<Self> {
144 self.path_value_ref(path)
145 .map(JsonValueRef::to_owned_json_value)
146 }
147
148 #[must_use]
154 pub fn path_value_ref(&self, path: &[JsonPathSelector]) -> Option<JsonValueRef<'_>> {
155 select_json_path(self.as_serde(), path).map(|value| JsonValueRef { value })
156 }
157
158 #[must_use]
164 pub fn path_contains(&self, path: &[JsonPathSelector], candidate: &Self) -> bool {
165 select_json_path(self.as_serde(), path)
166 .is_some_and(|value| json_contains_value(value, candidate.as_serde()))
167 }
168
169 pub fn merge_patch(&self, patch: &Self) -> CoreResult<Self> {
179 let mut target = self.as_serde().clone();
180 merge_patch_value(&mut target, patch.as_serde());
181 Self::new(target)
182 }
183
184 pub fn apply_patch(&self, patch: &Self) -> CoreResult<Self> {
196 Self::new(apply_json_patch(self.as_serde(), patch.as_serde())?)
197 }
198}
199
200fn select_json_path<'a>(
201 mut current: &'a SerdeJsonValue,
202 path: &[JsonPathSelector],
203) -> Option<&'a SerdeJsonValue> {
204 for selector in path {
205 current = select_json_child(current, selector)?;
206 }
207 Some(current)
208}
209
210fn select_json_child<'a>(
211 current: &'a SerdeJsonValue,
212 selector: &JsonPathSelector,
213) -> Option<&'a SerdeJsonValue> {
214 match (current, selector) {
215 (SerdeJsonValue::Object(values), JsonPathSelector::Key(key)) => values.get(key.as_str()),
216 (SerdeJsonValue::Array(values), JsonPathSelector::Index(index)) => {
217 signed_array_index(*index, values.len()).and_then(|index| values.get(index))
218 }
219 (SerdeJsonValue::Array(values), JsonPathSelector::UnsignedIndex(index)) => {
220 usize::try_from(*index)
221 .ok()
222 .and_then(|index| values.get(index))
223 }
224 _ => None,
225 }
226}
227
228fn signed_array_index(index: i64, len: usize) -> Option<usize> {
229 if index >= 0 {
230 usize::try_from(index).ok().filter(|index| *index < len)
231 } else {
232 let offset = usize::try_from(index.unsigned_abs()).ok()?;
233 (offset <= len).then_some(len - offset)
234 }
235}
236
237impl TryFrom<SerdeJsonValue> for JsonValue {
238 type Error = CoreError;
239
240 fn try_from(value: SerdeJsonValue) -> Result<Self, Self::Error> {
241 Self::new(value)
242 }
243}
244
245impl From<JsonValue> for SerdeJsonValue {
246 fn from(value: JsonValue) -> Self {
247 value.as_serde().clone()
248 }
249}
250
251impl Serialize for JsonValue {
252 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
253 where
254 S: Serializer,
255 {
256 if serializer.is_human_readable() {
257 self.as_serde().serialize(serializer)
258 } else {
259 serializer.serialize_str(&self.to_canonical_string())
260 }
261 }
262}
263
264impl<'de> Deserialize<'de> for JsonValue {
265 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
266 where
267 D: Deserializer<'de>,
268 {
269 let value = if deserializer.is_human_readable() {
270 StrictJsonValueSeed.deserialize(deserializer)?
271 } else {
272 let value = String::deserialize(deserializer)?;
273 parse_json_text(&value).map_err(serde::de::Error::custom)?
274 };
275 Self::new(value).map_err(serde::de::Error::custom)
276 }
277}
278
279fn parse_json_text(text: &str) -> Result<SerdeJsonValue, serde_json::Error> {
280 let mut deserializer = serde_json::Deserializer::from_str(text);
281 let value = StrictJsonValueSeed.deserialize(&mut deserializer)?;
282 deserializer.end()?;
283 Ok(value)
284}
285
286struct StrictJsonValueSeed;
287
288impl<'de> DeserializeSeed<'de> for StrictJsonValueSeed {
289 type Value = SerdeJsonValue;
290
291 fn deserialize<D>(self, deserializer: D) -> Result<Self::Value, D::Error>
292 where
293 D: Deserializer<'de>,
294 {
295 deserializer.deserialize_any(StrictJsonValueVisitor)
296 }
297}
298
299struct StrictJsonValueVisitor;
300
301impl<'de> Visitor<'de> for StrictJsonValueVisitor {
302 type Value = SerdeJsonValue;
303
304 fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
305 formatter.write_str("a JSON value with unique object keys")
306 }
307
308 fn visit_bool<E>(self, value: bool) -> Result<Self::Value, E> {
309 Ok(SerdeJsonValue::Bool(value))
310 }
311
312 fn visit_i64<E>(self, value: i64) -> Result<Self::Value, E> {
313 Ok(SerdeJsonValue::Number(value.into()))
314 }
315
316 fn visit_u64<E>(self, value: u64) -> Result<Self::Value, E> {
317 Ok(SerdeJsonValue::Number(value.into()))
318 }
319
320 fn visit_f64<E>(self, value: f64) -> Result<Self::Value, E>
321 where
322 E: DeError,
323 {
324 let number = serde_json::Number::from_f64(value)
325 .ok_or_else(|| E::custom("JSON number is not finite"))?;
326 Ok(SerdeJsonValue::Number(number))
327 }
328
329 fn visit_str<E>(self, value: &str) -> Result<Self::Value, E> {
330 Ok(SerdeJsonValue::String(value.to_owned()))
331 }
332
333 fn visit_string<E>(self, value: String) -> Result<Self::Value, E> {
334 Ok(SerdeJsonValue::String(value))
335 }
336
337 fn visit_none<E>(self) -> Result<Self::Value, E> {
338 Ok(SerdeJsonValue::Null)
339 }
340
341 fn visit_unit<E>(self) -> Result<Self::Value, E> {
342 Ok(SerdeJsonValue::Null)
343 }
344
345 fn visit_some<D>(self, deserializer: D) -> Result<Self::Value, D::Error>
346 where
347 D: Deserializer<'de>,
348 {
349 StrictJsonValueSeed.deserialize(deserializer)
350 }
351
352 fn visit_seq<A>(self, mut seq: A) -> Result<Self::Value, A::Error>
353 where
354 A: SeqAccess<'de>,
355 {
356 let mut values = Vec::with_capacity(seq.size_hint().unwrap_or(0));
357 while let Some(value) = seq.next_element_seed(StrictJsonValueSeed)? {
358 values.push(value);
359 }
360 Ok(SerdeJsonValue::Array(values))
361 }
362
363 fn visit_map<A>(self, mut map: A) -> Result<Self::Value, A::Error>
364 where
365 A: MapAccess<'de>,
366 {
367 let mut seen = BTreeSet::new();
368 let mut values = SerdeJsonMap::new();
369 while let Some(key) = map.next_key::<String>()? {
370 if !seen.insert(key.clone()) {
371 return Err(A::Error::custom(format!(
372 "duplicate JSON object key '{key}'"
373 )));
374 }
375 let value = map.next_value_seed(StrictJsonValueSeed)?;
376 values.insert(key, value);
377 }
378 Ok(SerdeJsonValue::Object(values))
379 }
380}
381
382fn validate_json_value(value: &SerdeJsonValue) -> CoreResult<()> {
383 match value {
384 SerdeJsonValue::Null | SerdeJsonValue::Bool(_) | SerdeJsonValue::Number(_) => Ok(()),
385 SerdeJsonValue::String(value) => {
386 validate_json_string_len(value.len())?;
387 Ok(())
388 }
389 SerdeJsonValue::Array(values) => {
390 ensure_json_container_len(values.len())?;
391 for value in values {
392 validate_json_value(value)?;
393 }
394 Ok(())
395 }
396 SerdeJsonValue::Object(values) => {
397 ensure_json_container_len(values.len())?;
398 for (key, value) in values {
399 validate_json_string_len(key.len())?;
400 validate_json_value(value)?;
401 }
402 Ok(())
403 }
404 }
405}
406
407fn validate_json_string_len(len: usize) -> CoreResult<()> {
408 if len > MAX_DB_STRING_BYTES {
409 return Err(CoreError::StringTooLong {
410 got: len,
411 max: u32::MAX,
412 });
413 }
414 Ok(())
415}
416
417fn ensure_json_container_len(len: usize) -> CoreResult<()> {
418 if len > u32::MAX as usize {
419 return Err(CoreError::ConstructedValueTooLarge {
420 got: len,
421 max: u32::MAX,
422 });
423 }
424 Ok(())
425}
426
427fn json_contains_value(target: &SerdeJsonValue, candidate: &SerdeJsonValue) -> bool {
428 match (target, candidate) {
429 (SerdeJsonValue::Object(target), SerdeJsonValue::Object(candidate)) => {
430 candidate.iter().all(|(key, value)| {
431 target
432 .get(key)
433 .is_some_and(|found| json_contains_value(found, value))
434 })
435 }
436 (SerdeJsonValue::Array(target), SerdeJsonValue::Array(candidate)) => candidate
437 .iter()
438 .all(|value| target.iter().any(|found| json_contains_value(found, value))),
439 (SerdeJsonValue::Array(target), candidate) => target
440 .iter()
441 .any(|found| json_contains_value(found, candidate)),
442 _ => target == candidate,
443 }
444}
445
446fn merge_patch_value(target: &mut SerdeJsonValue, patch: &SerdeJsonValue) {
447 let SerdeJsonValue::Object(patch) = patch else {
448 *target = patch.clone();
449 return;
450 };
451
452 if !target.is_object() {
453 *target = SerdeJsonValue::Object(SerdeJsonMap::new());
454 }
455 let target = target
456 .as_object_mut()
457 .expect("target was normalized to object");
458
459 for (key, value) in patch {
460 if value.is_null() {
461 target.remove(key);
462 } else {
463 let entry = target.entry(key.clone()).or_insert(SerdeJsonValue::Null);
464 merge_patch_value(entry, value);
465 }
466 }
467}
468
469fn write_json_canonical(value: &SerdeJsonValue, output: &mut String) {
470 match value {
471 SerdeJsonValue::Null => output.push_str("null"),
472 SerdeJsonValue::Bool(value) => output.push_str(if *value { "true" } else { "false" }),
473 SerdeJsonValue::Number(value) => output.push_str(&value.to_string()),
474 SerdeJsonValue::String(value) => {
475 output.push_str(&serde_json::to_string(value).expect("JSON string rendering succeeds"));
476 }
477 SerdeJsonValue::Array(values) => {
478 output.push('[');
479 for (index, value) in values.iter().enumerate() {
480 if index > 0 {
481 output.push(',');
482 }
483 write_json_canonical(value, output);
484 }
485 output.push(']');
486 }
487 SerdeJsonValue::Object(values) => {
488 output.push('{');
489 let mut entries = values.iter().collect::<Vec<_>>();
490 entries.sort_unstable_by(|lhs, rhs| lhs.0.cmp(rhs.0));
491 for (index, (key, value)) in entries.into_iter().enumerate() {
492 if index > 0 {
493 output.push(',');
494 }
495 output.push_str(&serde_json::to_string(key).expect("JSON key rendering succeeds"));
496 output.push(':');
497 write_json_canonical(value, output);
498 }
499 output.push('}');
500 }
501 }
502}
503
504#[cfg(test)]
505mod tests;