1pub mod cmp;
4#[cfg(feature = "conformance")]
5pub mod conformance;
6pub mod numeric;
7#[cfg(feature = "serde_json")]
9pub mod numeric_check;
10pub mod types;
11pub mod unique;
12
13#[cfg(feature = "magnus")]
14mod magnus;
15#[cfg(feature = "pyo3")]
16mod pyo3;
17#[cfg(feature = "serde_json")]
18mod serde_json;
19
20#[cfg(feature = "magnus")]
21pub use magnus::{
22 child as magnus_child, invalidate_members_cache as magnus_invalidate_members_cache,
23 is_object as magnus_is_object, probe_root as magnus_probe_root,
24 take_pending_error as magnus_take_pending_error, Magnus, PendingError,
25 PendingErrorScope as MagnusPendingErrorScope, RbNode,
26};
27#[cfg(feature = "pyo3")]
28pub use pyo3::{probe_root, take_pending_error, PendingErrorScope, Pyo3};
29#[cfg(feature = "serde_json")]
30pub use serde_json::SerdeJson;
31
32use std::borrow::Cow;
33
34use ::serde_json::Value;
35
36use crate::types::JsonType;
37
38pub trait Json: Sized + Send + Sync + 'static {
40 type Node<'a>: Node<'a, Self>;
41
42 type PreparedKey: Send + Sync;
44
45 type StringBuffer: Default;
47
48 fn prepare_key(key: &str) -> Self::PreparedKey;
49
50 fn with_string_node<T>(
58 buffer: &mut Self::StringBuffer,
59 string: &str,
60 f: impl FnOnce(Self::Node<'_>) -> T,
61 ) -> T;
62}
63
64#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
66pub struct NodeIdentity {
67 address: usize,
68 tag: u32,
69}
70
71impl NodeIdentity {
72 #[must_use]
74 pub fn new(address: usize) -> Self {
75 Self { address, tag: 0 }
76 }
77
78 #[must_use]
80 pub fn tagged(address: usize, tag: u32) -> Self {
81 Self { address, tag }
82 }
83}
84
85pub trait JsonNumber {
87 fn as_u64(&self) -> Option<u64>;
88 fn as_i64(&self) -> Option<i64>;
89 fn as_f64(&self) -> Option<f64>;
90
91 fn as_str(&self) -> Cow<'_, str>;
93
94 fn to_number(&self) -> Cow<'_, ::serde_json::Number>;
96
97 fn is_integer(&self) -> bool {
100 crate::types::number_is_integer(&self.to_number())
101 }
102}
103
104pub trait Node<'a, F: Json>: Clone {
106 type Object: Object<'a, F, Node = Self>;
107 type Array: Array<'a, F, Node = Self>;
108 type Number: JsonNumber;
109
110 fn as_object(&self) -> Option<Self::Object>;
111 fn as_array(&self) -> Option<Self::Array>;
112 fn as_string(&self) -> Option<Cow<'a, str>>;
113
114 fn as_number(&self) -> Option<Self::Number>;
115 fn as_boolean(&self) -> Option<bool>;
116 fn is_null(&self) -> bool;
117
118 fn is_number(&self) -> bool {
120 self.as_number().is_some()
121 }
122
123 fn is_string(&self) -> bool {
124 self.json_type() == JsonType::String
125 }
126
127 fn json_type(&self) -> JsonType;
129
130 fn string_length(&self) -> Option<u64> {
132 self.as_string().map(|string| string.chars().count() as u64)
133 }
134
135 fn equals_value(&self, expected: &Value) -> bool {
137 crate::cmp::equal(&self.to_value(), expected)
138 }
139
140 fn to_value(&self) -> Cow<'a, Value>;
143
144 fn identity(&self) -> Option<NodeIdentity>;
151
152 fn container_identity(&self) -> Option<NodeIdentity> {
153 if matches!(self.json_type(), JsonType::Object | JsonType::Array) {
154 self.identity()
155 } else {
156 None
157 }
158 }
159}
160
161pub trait Object<'a, F: Json> {
162 type Node: Node<'a, F>;
163 type MemberName: AsRef<str> + Into<Cow<'a, str>>;
164 type MembersIter: Iterator<Item = (Self::MemberName, Self::Node)>;
165
166 fn len(&self) -> usize;
167 fn is_empty(&self) -> bool {
168 self.len() == 0
169 }
170 fn get(&self, key: &F::PreparedKey) -> Option<Self::Node>;
171 fn members(&self) -> Self::MembersIter;
172}
173
174#[allow(clippy::len_without_is_empty)]
176pub trait Array<'a, F: Json> {
177 type Node: Node<'a, F>;
178 type ElementsIter: Iterator<Item = Self::Node>;
179
180 fn len(&self) -> usize;
181 fn elements(&self) -> Self::ElementsIter;
182
183 fn is_unique(&self) -> bool {
185 let values: Vec<Cow<'a, Value>> =
186 self.elements().map(|element| element.to_value()).collect();
187 crate::unique::is_unique(&values)
188 }
189}