corvus_json_schema/
instance.rs1use serde_json::{Map, Number, Value};
6
7pub trait Instance<'a>: Copy {
10 type Array: ArrayView<'a, Item = Self>;
12 type Object: ObjectView<'a, Item = Self>;
14
15 fn view(self) -> View<'a, Self>;
17
18 #[inline]
20 fn kind(self) -> Kind {
21 match self.view() {
22 View::Null => Kind::Null,
23 View::Bool(_) => Kind::Bool,
24 View::Number(_) => Kind::Number,
25 View::String(_) => Kind::String,
26 View::Array(_) => Kind::Array,
27 View::Object(_) => Kind::Object,
28 }
29 }
30}
31
32#[derive(Clone, Copy, PartialEq, Eq, Debug)]
35#[repr(u8)]
36pub enum Kind {
37 Null = 1,
38 Bool = 2,
39 Object = 4,
40 Array = 8,
41 Number = 16,
42 String = 32,
43}
44
45pub enum View<'a, I: Instance<'a>> {
47 Null,
48 Bool(bool),
49 Number(Number),
50 String(&'a str),
51 Array(I::Array),
52 Object(I::Object),
53}
54
55pub trait ArrayView<'a>: Copy {
57 type Item: Instance<'a>;
58
59 fn len(self) -> usize;
60
61 fn is_empty(self) -> bool {
62 self.len() == 0
63 }
64
65 fn get(self, index: usize) -> Self::Item;
67
68 fn iter(self) -> impl Iterator<Item = Self::Item>;
69
70 fn tail(self, start: usize) -> impl Iterator<Item = Self::Item> {
72 self.iter().skip(start)
73 }
74}
75
76pub trait ObjectView<'a>: Copy {
78 type Item: Instance<'a>;
79
80 fn len(self) -> usize;
81
82 fn is_empty(self) -> bool {
83 self.len() == 0
84 }
85
86 fn get(self, name: &str) -> Option<Self::Item>;
88
89 fn contains_key(self, name: &str) -> bool {
90 self.get(name).is_some()
91 }
92
93 fn iter(self) -> impl Iterator<Item = (&'a str, Self::Item)>;
94
95 fn values(self) -> impl Iterator<Item = Self::Item> {
96 self.iter().map(|(_, v)| v)
97 }
98}
99
100impl<'a> Instance<'a> for &'a Value {
101 type Array = &'a [Value];
102 type Object = &'a Map<String, Value>;
103
104 #[inline(always)]
105 fn view(self) -> View<'a, Self> {
106 match self {
107 Value::Null => View::Null,
108 Value::Bool(b) => View::Bool(*b),
109 Value::Number(n) => View::Number(n.clone()),
110 Value::String(s) => View::String(s),
111 Value::Array(a) => View::Array(a.as_slice()),
112 Value::Object(o) => View::Object(o),
113 }
114 }
115
116 #[inline(always)]
117 fn kind(self) -> Kind {
118 match self {
119 Value::Null => Kind::Null,
120 Value::Bool(_) => Kind::Bool,
121 Value::Number(_) => Kind::Number,
122 Value::String(_) => Kind::String,
123 Value::Array(_) => Kind::Array,
124 Value::Object(_) => Kind::Object,
125 }
126 }
127}
128
129impl<'a> ArrayView<'a> for &'a [Value] {
130 type Item = &'a Value;
131
132 #[inline(always)]
133 fn len(self) -> usize {
134 <[Value]>::len(self)
135 }
136
137 #[inline(always)]
138 fn get(self, index: usize) -> &'a Value {
139 &self[index]
140 }
141
142 #[inline(always)]
143 fn iter(self) -> impl Iterator<Item = &'a Value> {
144 <[Value]>::iter(self)
145 }
146
147 #[inline(always)]
148 fn tail(self, start: usize) -> impl Iterator<Item = &'a Value> {
149 self.get(start..).unwrap_or_default().iter()
150 }
151}
152
153const LINEAR_KEYS: usize = 32;
156
157impl<'a> ObjectView<'a> for &'a Map<String, Value> {
158 type Item = &'a Value;
159
160 #[inline(always)]
161 fn len(self) -> usize {
162 Map::len(self)
163 }
164
165 #[inline]
166 fn get(self, name: &str) -> Option<&'a Value> {
167 if Map::len(self) <= LINEAR_KEYS {
168 Map::iter(self).find(|(k, _)| str_eq(k, name)).map(|(_, v)| v)
169 } else {
170 Map::get(self, name)
171 }
172 }
173
174 #[inline]
175 fn contains_key(self, name: &str) -> bool {
176 if Map::len(self) <= LINEAR_KEYS { self.keys().any(|k| str_eq(k, name)) } else { Map::contains_key(self, name) }
177 }
178
179 #[inline(always)]
180 fn iter(self) -> impl Iterator<Item = (&'a str, &'a Value)> {
181 Map::iter(self).map(|(k, v)| (k.as_str(), v))
182 }
183
184 #[inline(always)]
185 fn values(self) -> impl Iterator<Item = &'a Value> {
186 Map::values(self)
187 }
188}
189
190#[inline(always)]
192pub(crate) fn str_eq(a: &str, b: &str) -> bool {
193 let (a, b) = (a.as_bytes(), b.as_bytes());
194 if a.len() != b.len() {
195 return false;
196 }
197 let n = a.len();
198 if n <= 8 {
199 if n >= 4 {
200 let word = |s: &[u8], i: usize| u32::from_le_bytes(s[i..i + 4].try_into().unwrap());
202 return word(a, 0) == word(b, 0) && word(a, n - 4) == word(b, n - 4);
203 }
204 return a == b;
205 }
206 let word = |s: &[u8], i: usize| u64::from_le_bytes(s[i..i + 8].try_into().unwrap());
209 let mut i = 0;
210 while i + 8 < n {
211 if word(a, i) != word(b, i) {
212 return false;
213 }
214 i += 8;
215 }
216 word(a, n - 8) == word(b, n - 8)
217}
218
219const _: () = {
221 use crate::node::type_mask;
222 assert!(Kind::Null as u8 == type_mask::NULL);
223 assert!(Kind::Bool as u8 == type_mask::BOOLEAN);
224 assert!(Kind::Object as u8 == type_mask::OBJECT);
225 assert!(Kind::Array as u8 == type_mask::ARRAY);
226 assert!(Kind::Number as u8 == type_mask::NUMBER);
227 assert!(Kind::String as u8 == type_mask::STRING);
228};