1use core::fmt;
7use std::str::FromStr;
8
9use serde_json::Value;
10
11use crate::{Json, JsonNode};
12
13#[derive(Debug, Clone, Copy, Eq, PartialEq, Ord, PartialOrd, Hash)]
18#[repr(u8)]
19pub enum JsonType {
20 Null = 1 << 0,
21 Boolean = 1 << 1,
22 Integer = 1 << 2,
23 Number = 1 << 3,
24 String = 1 << 4,
25 Array = 1 << 5,
26 Object = 1 << 6,
27}
28
29impl fmt::Display for JsonType {
30 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
31 f.write_str(self.as_str())
32 }
33}
34
35impl JsonType {
36 #[must_use]
37 pub fn as_str(self) -> &'static str {
38 match self {
39 JsonType::Array => "array",
40 JsonType::Boolean => "boolean",
41 JsonType::Integer => "integer",
42 JsonType::Null => "null",
43 JsonType::Number => "number",
44 JsonType::Object => "object",
45 JsonType::String => "string",
46 }
47 }
48
49 pub(crate) fn from_repr(repr: u8) -> Self {
50 match repr {
51 1 => JsonType::Null,
52 2 => JsonType::Boolean,
53 4 => JsonType::Integer,
54 8 => JsonType::Number,
55 16 => JsonType::String,
56 32 => JsonType::Array,
57 64 => JsonType::Object,
58 _ => panic!("Invalid JsonType representation: {repr}"),
59 }
60 }
61}
62
63impl From<&Value> for JsonType {
64 fn from(instance: &Value) -> Self {
65 match instance {
66 Value::Null => JsonType::Null,
67 Value::Bool(_) => JsonType::Boolean,
68 Value::Number(_) => JsonType::Number,
69 Value::String(_) => JsonType::String,
70 Value::Array(_) => JsonType::Array,
71 Value::Object(_) => JsonType::Object,
72 }
73 }
74}
75
76impl FromStr for JsonType {
77 type Err = ();
78
79 fn from_str(s: &str) -> Result<Self, Self::Err> {
80 match s {
81 "array" => Ok(JsonType::Array),
82 "boolean" => Ok(JsonType::Boolean),
83 "integer" => Ok(JsonType::Integer),
84 "null" => Ok(JsonType::Null),
85 "number" => Ok(JsonType::Number),
86 "object" => Ok(JsonType::Object),
87 "string" => Ok(JsonType::String),
88 _ => Err(()),
89 }
90 }
91}
92
93#[derive(Clone, Copy, Eq, PartialEq, Ord, PartialOrd, Hash)]
95pub struct JsonTypeSet(u8);
96
97impl Default for JsonTypeSet {
98 fn default() -> Self {
99 Self::empty()
100 }
101}
102
103impl From<JsonType> for JsonTypeSet {
104 #[inline]
105 fn from(ty: JsonType) -> Self {
106 Self(ty as u8)
107 }
108}
109
110impl std::ops::BitOr for JsonType {
111 type Output = JsonTypeSet;
112 #[inline]
113 fn bitor(self, rhs: JsonType) -> JsonTypeSet {
114 JsonTypeSet::from(self).insert(rhs)
115 }
116}
117
118impl std::ops::BitOr<JsonType> for JsonTypeSet {
119 type Output = JsonTypeSet;
120 #[inline]
121 fn bitor(self, rhs: JsonType) -> JsonTypeSet {
122 self.insert(rhs)
123 }
124}
125
126impl JsonTypeSet {
127 #[inline]
129 #[must_use]
130 pub const fn empty() -> Self {
131 Self(0)
132 }
133 #[inline]
135 #[must_use]
136 pub const fn all() -> Self {
137 JsonTypeSet::empty()
138 .insert(JsonType::Null)
139 .insert(JsonType::Boolean)
140 .insert(JsonType::Integer)
141 .insert(JsonType::Number)
142 .insert(JsonType::String)
143 .insert(JsonType::Array)
144 .insert(JsonType::Object)
145 }
146 #[inline]
148 #[must_use]
149 pub const fn insert(mut self, ty: JsonType) -> Self {
150 self.0 |= ty as u8;
151 self
152 }
153 #[inline]
155 #[must_use]
156 pub const fn remove(mut self, ty: JsonType) -> Self {
157 self.0 &= !(ty as u8);
158 self
159 }
160 #[inline]
162 #[must_use]
163 pub const fn intersect(self, other: Self) -> Self {
164 Self(self.0 & other.0)
165 }
166 #[inline]
168 #[must_use]
169 pub const fn union(self, other: Self) -> Self {
170 Self(self.0 | other.0)
171 }
172 #[inline]
174 #[must_use]
175 pub const fn len(self) -> usize {
176 self.0.count_ones() as usize
177 }
178 #[inline]
180 #[must_use]
181 pub const fn is_empty(self) -> bool {
182 self.0 == 0
183 }
184 #[inline]
186 #[must_use]
187 pub fn contains(self, ty: JsonType) -> bool {
188 self.0 & ty as u8 != 0
189 }
190 #[must_use]
192 pub fn contains_value_type<F: Json>(self, value: &F::Node<'_>) -> bool {
193 match value.json_type() {
194 JsonType::Number => match value.as_number() {
195 Some(n) if number_is_integer(&n) => {
197 self.contains(JsonType::Integer) || self.contains(JsonType::Number)
198 }
199 Some(_) => self.contains(JsonType::Number),
200 None => false,
201 },
202 other => self.contains(other),
203 }
204 }
205 #[inline]
207 #[must_use]
208 pub fn iter(&self) -> JsonTypeSetIterator {
209 JsonTypeSetIterator { set: *self }
210 }
211}
212
213#[must_use]
215pub fn number_is_integer(n: &serde_json::Number) -> bool {
216 #[cfg(feature = "arbitrary-precision")]
217 {
218 use crate::ext::numeric::bignum;
219 use num_traits::One;
220
221 n.is_i64()
223 || n.is_u64()
224 || if bignum::try_parse_bigint(n).is_some() {
225 true
226 } else if let Some(bigfrac) = bignum::try_parse_bigfraction(n) {
227 bigfrac.denom().is_none_or(One::is_one)
228 } else if let Some(f) = n.as_f64() {
229 f.fract() == 0.
230 } else {
231 false
233 }
234 }
235 #[cfg(not(feature = "arbitrary-precision"))]
236 {
237 if n.is_i64() || n.is_u64() {
238 true
239 } else if let Some(f) = n.as_f64() {
240 f.fract() == 0.
241 } else {
242 unreachable!("Numbers always fit in u64/i64/f64 without arbitrary-precision")
243 }
244 }
245}
246
247impl IntoIterator for &JsonTypeSet {
248 type Item = JsonType;
249 type IntoIter = JsonTypeSetIterator;
250 fn into_iter(self) -> Self::IntoIter {
251 self.iter()
252 }
253}
254
255impl IntoIterator for JsonTypeSet {
256 type Item = JsonType;
257 type IntoIter = JsonTypeSetIterator;
258
259 fn into_iter(self) -> Self::IntoIter {
260 JsonTypeSetIterator { set: self }
261 }
262}
263
264impl fmt::Debug for JsonTypeSet {
265 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
266 write!(f, "(")?;
267
268 let mut iter = self.iter();
269
270 if let Some(ty) = iter.next() {
271 write!(f, "{ty}")?;
272 }
273
274 for ty in iter {
275 write!(f, ", {ty}")?;
276 }
277
278 write!(f, ")")
279 }
280}
281
282#[derive(Debug)]
284pub struct JsonTypeSetIterator {
285 set: JsonTypeSet,
286}
287
288impl Iterator for JsonTypeSetIterator {
289 type Item = JsonType;
290
291 fn next(&mut self) -> Option<Self::Item> {
292 if self.set.0 == 0 {
293 None
294 } else {
295 let lsb = self.set.0 & self.set.0.wrapping_neg();
297
298 self.set.0 &= self.set.0 - 1;
300
301 Some(JsonType::from_repr(lsb))
302 }
303 }
304 fn size_hint(&self) -> (usize, Option<usize>) {
305 let count = self.set.0.count_ones() as usize;
306 (count, Some(count))
307 }
308}
309
310impl ExactSizeIterator for JsonTypeSetIterator {}
311
312#[cfg(test)]
313mod tests {
314 use super::*;
315 use serde_json::json;
316 use test_case::test_case;
317
318 #[test]
319 fn type_bitor_builds_set() {
320 let set = JsonType::String | JsonType::Integer;
321 assert!(set.contains(JsonType::String));
322 assert!(set.contains(JsonType::Integer));
323 assert!(!set.contains(JsonType::Null));
324 let extended = set | JsonType::Null;
325 assert_eq!(
326 extended,
327 JsonType::String | JsonType::Integer | JsonType::Null
328 );
329 assert!(extended.contains(JsonType::Null));
330 }
331
332 #[test_case("array" => Ok(JsonType::Array) ; "parse array")]
333 #[test_case("boolean" => Ok(JsonType::Boolean) ; "parse boolean")]
334 #[test_case("integer" => Ok(JsonType::Integer) ; "parse integer")]
335 #[test_case("null" => Ok(JsonType::Null) ; "parse null")]
336 #[test_case("number" => Ok(JsonType::Number) ; "parse number")]
337 #[test_case("object" => Ok(JsonType::Object) ; "parse object")]
338 #[test_case("string" => Ok(JsonType::String) ; "parse string")]
339 #[test_case("invalid" => Err(()) ; "parse invalid")]
340 fn test_from_str(input: &str) -> Result<JsonType, ()> {
341 JsonType::from_str(input)
342 }
343
344 #[test_case(JsonType::Array => "array" ; "display array")]
345 #[test_case(JsonType::Boolean => "boolean" ; "display boolean")]
346 #[test_case(JsonType::Integer => "integer" ; "display integer")]
347 #[test_case(JsonType::Null => "null" ; "display null")]
348 #[test_case(JsonType::Number => "number" ; "display number")]
349 #[test_case(JsonType::Object => "object" ; "display object")]
350 #[test_case(JsonType::String => "string" ; "display string")]
351 fn test_display(json_type: JsonType) -> String {
352 json_type.to_string()
353 }
354
355 #[test_case(&json!(null) => JsonType::Null ; "value null")]
356 #[test_case(&json!(true) => JsonType::Boolean ; "value boolean")]
357 #[test_case(&json!(42) => JsonType::Number ; "value number int")]
358 #[test_case(&json!(1.12) => JsonType::Number ; "value number float")]
359 #[test_case(&json!("hello") => JsonType::String ; "value string")]
360 #[test_case(&json!([1, 2, 3]) => JsonType::Array ; "value array")]
361 #[test_case(&json!({"key": "value"}) => JsonType::Object ; "value object")]
362 fn test_from_value(value: &Value) -> JsonType {
363 JsonType::from(value)
364 }
365
366 #[test]
367 fn test_insert_types() {
368 let mut set = JsonTypeSet::empty();
369 set = set.insert(JsonType::String);
370 assert!(set.contains(JsonType::String));
371 assert!(!set.contains(JsonType::Number));
372
373 set = set.insert(JsonType::Number);
374 assert!(set.contains(JsonType::String));
375 assert!(set.contains(JsonType::Number));
376 assert!(!set.contains(JsonType::Array));
377 }
378
379 #[test]
380 fn test_from_json_type() {
381 let set = JsonTypeSet::from(JsonType::String);
382 assert!(set.contains(JsonType::String));
383 assert_eq!(set.len(), 1);
384 }
385
386 #[cfg(feature = "serde_json")]
387 #[test_case(&json!(null), JsonType::Null.into() => true ; "null type")]
388 #[test_case(&json!(true), JsonType::Boolean.into() => true ; "boolean type")]
389 #[test_case(&json!("test"), JsonType::String.into() => true ; "string type")]
390 #[test_case(&json!([1,2]), JsonType::Array.into() => true ; "array type")]
391 #[test_case(&json!({"a": 1}), JsonType::Object.into() => true ; "object type")]
392 #[test_case(&json!(42), JsonType::Number.into() => true ; "number matches number")]
393 #[test_case(&json!(42), JsonType::Integer.into() => true ; "int matches integer")]
394 #[test_case(&json!(1.23), JsonType::Number.into() => true ; "float matches number")]
395 #[test_case(&json!(1.23), JsonType::Integer.into() => false ; "float doesn't match integer")]
396 fn test_contains_value_type(value: &Value, set: JsonTypeSet) -> bool {
397 set.contains_value_type::<crate::SerdeJson>(&value)
398 }
399
400 #[test]
401 fn test_remove_types() {
402 let set = JsonTypeSet::all().remove(JsonType::Number);
403 assert!(!set.contains(JsonType::Number));
404 assert!(set.contains(JsonType::Integer));
405 assert_eq!(set.len(), 6);
406
407 let empty = JsonTypeSet::empty();
408 assert_eq!(empty.remove(JsonType::Boolean), empty);
409 }
410
411 #[test]
412 fn test_len() {
413 let empty = JsonTypeSet::empty();
414 assert!(empty.is_empty());
415 assert_eq!(empty.len(), 0);
416
417 let with_string = empty.insert(JsonType::String);
418 assert!(!with_string.is_empty());
419 assert_eq!(with_string.len(), 1);
420 assert_eq!(JsonTypeSet::all().len(), 7);
421 }
422
423 #[test]
424 fn test_debug_format() {
425 assert_eq!(format!("{:?}", JsonTypeSet::default()), "()");
426 assert_eq!(
427 format!("{:?}", JsonTypeSet::from(JsonType::String)),
428 "(string)"
429 );
430 assert_eq!(
431 format!(
432 "{:?}",
433 JsonTypeSet::from(JsonType::String).insert(JsonType::Number)
434 ),
435 "(number, string)"
436 );
437 }
438
439 #[test]
440 fn test_empty_iterator() {
441 let set = JsonTypeSet::empty();
442 let mut iter = set.iter();
443 assert_eq!(iter.next(), None);
444 assert_eq!(iter.size_hint(), (0, Some(0)));
445 }
446
447 #[test]
448 fn test_single_type_iterator() {
449 let set = JsonTypeSet::from(JsonType::String);
450 let mut iter = set.iter();
451 assert_eq!(iter.size_hint(), (1, Some(1)));
452 assert_eq!(iter.next(), Some(JsonType::String));
453 assert_eq!(iter.size_hint(), (0, Some(0)));
454 assert_eq!(iter.next(), None);
455 assert_eq!(iter.size_hint(), (0, Some(0)));
456 }
457
458 #[test]
459 fn test_multiple_types_iterator() {
460 let set = JsonTypeSet::from(JsonType::String)
461 .insert(JsonType::Number)
462 .insert(JsonType::Boolean);
463
464 let types: Vec<JsonType> = set.iter().collect();
465 assert_eq!(types.len(), 3);
466 assert!(types.contains(&JsonType::String));
467 assert!(types.contains(&JsonType::Number));
468 assert!(types.contains(&JsonType::Boolean));
469
470 assert_eq!(set.iter().size_hint(), (3, Some(3)));
471 }
472
473 #[test]
474 fn test_all_types_iterator() {
475 let set = JsonTypeSet::all();
476
477 let types: Vec<JsonType> = set.iter().collect();
478 assert_eq!(types.len(), 7);
479
480 let mut iter = set.iter();
481 assert_eq!(iter.len(), 7);
482 iter.next();
483 assert_eq!(iter.len(), 6);
484 }
485}