1use core::fmt;
7use std::str::FromStr;
8
9use serde_json::Value;
10
11use crate::{Json, Node};
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 crate::JsonNumber::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::numeric::bignum;
219 use num_traits::One;
220
221 if n.is_i64() || n.is_u64() {
222 return true;
223 }
224 let text = serde_json::Number::as_str(n);
227 if let Some((integer, fraction)) = text.split_once('.') {
228 if !fraction.contains(['e', 'E']) {
229 return fraction.bytes().all(|byte| byte == b'0')
230 && integer
231 .bytes()
232 .all(|byte| byte.is_ascii_digit() || byte == b'-');
233 }
234 }
235
236 if bignum::try_parse_bigint(n).is_some() {
238 true
239 } else if let Some(bigfrac) = bignum::try_parse_bigfraction(n) {
240 bigfrac.denom().is_none_or(One::is_one)
241 } else if let Some(f) = n.as_f64() {
242 f.fract() == 0.
243 } else {
244 false
246 }
247 }
248 #[cfg(not(feature = "arbitrary-precision"))]
249 {
250 if n.is_i64() || n.is_u64() {
251 true
252 } else if let Some(f) = n.as_f64() {
253 f.fract() == 0.
254 } else {
255 unreachable!("Numbers always fit in u64/i64/f64 without arbitrary-precision")
256 }
257 }
258}
259
260impl IntoIterator for &JsonTypeSet {
261 type Item = JsonType;
262 type IntoIter = JsonTypeSetIterator;
263 fn into_iter(self) -> Self::IntoIter {
264 self.iter()
265 }
266}
267
268impl IntoIterator for JsonTypeSet {
269 type Item = JsonType;
270 type IntoIter = JsonTypeSetIterator;
271
272 fn into_iter(self) -> Self::IntoIter {
273 JsonTypeSetIterator { set: self }
274 }
275}
276
277impl fmt::Debug for JsonTypeSet {
278 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
279 write!(f, "(")?;
280
281 let mut iter = self.iter();
282
283 if let Some(ty) = iter.next() {
284 write!(f, "{ty}")?;
285 }
286
287 for ty in iter {
288 write!(f, ", {ty}")?;
289 }
290
291 write!(f, ")")
292 }
293}
294
295#[derive(Debug)]
297pub struct JsonTypeSetIterator {
298 set: JsonTypeSet,
299}
300
301impl Iterator for JsonTypeSetIterator {
302 type Item = JsonType;
303
304 fn next(&mut self) -> Option<Self::Item> {
305 if self.set.0 == 0 {
306 None
307 } else {
308 let lsb = self.set.0 & self.set.0.wrapping_neg();
310
311 self.set.0 &= self.set.0 - 1;
313
314 Some(JsonType::from_repr(lsb))
315 }
316 }
317 fn size_hint(&self) -> (usize, Option<usize>) {
318 let count = self.set.0.count_ones() as usize;
319 (count, Some(count))
320 }
321}
322
323impl ExactSizeIterator for JsonTypeSetIterator {}
324
325#[cfg(test)]
326mod tests {
327 use super::*;
328 use serde_json::json;
329 use test_case::test_case;
330
331 #[test]
332 fn type_bitor_builds_set() {
333 let set = JsonType::String | JsonType::Integer;
334 assert!(set.contains(JsonType::String));
335 assert!(set.contains(JsonType::Integer));
336 assert!(!set.contains(JsonType::Null));
337 let extended = set | JsonType::Null;
338 assert_eq!(
339 extended,
340 JsonType::String | JsonType::Integer | JsonType::Null
341 );
342 assert!(extended.contains(JsonType::Null));
343 }
344
345 #[test_case("array" => Ok(JsonType::Array) ; "parse array")]
346 #[test_case("boolean" => Ok(JsonType::Boolean) ; "parse boolean")]
347 #[test_case("integer" => Ok(JsonType::Integer) ; "parse integer")]
348 #[test_case("null" => Ok(JsonType::Null) ; "parse null")]
349 #[test_case("number" => Ok(JsonType::Number) ; "parse number")]
350 #[test_case("object" => Ok(JsonType::Object) ; "parse object")]
351 #[test_case("string" => Ok(JsonType::String) ; "parse string")]
352 #[test_case("invalid" => Err(()) ; "parse invalid")]
353 fn test_from_str(input: &str) -> Result<JsonType, ()> {
354 JsonType::from_str(input)
355 }
356
357 #[test_case(JsonType::Array => "array" ; "display array")]
358 #[test_case(JsonType::Boolean => "boolean" ; "display boolean")]
359 #[test_case(JsonType::Integer => "integer" ; "display integer")]
360 #[test_case(JsonType::Null => "null" ; "display null")]
361 #[test_case(JsonType::Number => "number" ; "display number")]
362 #[test_case(JsonType::Object => "object" ; "display object")]
363 #[test_case(JsonType::String => "string" ; "display string")]
364 fn test_display(json_type: JsonType) -> String {
365 json_type.to_string()
366 }
367
368 #[test_case(&json!(null) => JsonType::Null ; "value null")]
369 #[test_case(&json!(true) => JsonType::Boolean ; "value boolean")]
370 #[test_case(&json!(42) => JsonType::Number ; "value number int")]
371 #[test_case(&json!(1.12) => JsonType::Number ; "value number float")]
372 #[test_case(&json!("hello") => JsonType::String ; "value string")]
373 #[test_case(&json!([1, 2, 3]) => JsonType::Array ; "value array")]
374 #[test_case(&json!({"key": "value"}) => JsonType::Object ; "value object")]
375 fn test_from_value(value: &Value) -> JsonType {
376 JsonType::from(value)
377 }
378
379 #[test]
380 fn test_insert_types() {
381 let mut set = JsonTypeSet::empty();
382 set = set.insert(JsonType::String);
383 assert!(set.contains(JsonType::String));
384 assert!(!set.contains(JsonType::Number));
385
386 set = set.insert(JsonType::Number);
387 assert!(set.contains(JsonType::String));
388 assert!(set.contains(JsonType::Number));
389 assert!(!set.contains(JsonType::Array));
390 }
391
392 #[test]
393 fn test_from_json_type() {
394 let set = JsonTypeSet::from(JsonType::String);
395 assert!(set.contains(JsonType::String));
396 assert_eq!(set.len(), 1);
397 }
398
399 #[cfg(feature = "serde_json")]
400 #[test_case(&json!(null), JsonType::Null.into() => true ; "null type")]
401 #[test_case(&json!(true), JsonType::Boolean.into() => true ; "boolean type")]
402 #[test_case(&json!("test"), JsonType::String.into() => true ; "string type")]
403 #[test_case(&json!([1,2]), JsonType::Array.into() => true ; "array type")]
404 #[test_case(&json!({"a": 1}), JsonType::Object.into() => true ; "object type")]
405 #[test_case(&json!(42), JsonType::Number.into() => true ; "number matches number")]
406 #[test_case(&json!(42), JsonType::Integer.into() => true ; "int matches integer")]
407 #[test_case(&json!(1.23), JsonType::Number.into() => true ; "float matches number")]
408 #[test_case(&json!(1.23), JsonType::Integer.into() => false ; "float doesn't match integer")]
409 fn test_contains_value_type(value: &Value, set: JsonTypeSet) -> bool {
410 set.contains_value_type::<crate::SerdeJson>(&value)
411 }
412
413 #[test]
414 fn test_remove_types() {
415 let set = JsonTypeSet::all().remove(JsonType::Number);
416 assert!(!set.contains(JsonType::Number));
417 assert!(set.contains(JsonType::Integer));
418 assert_eq!(set.len(), 6);
419
420 let empty = JsonTypeSet::empty();
421 assert_eq!(empty.remove(JsonType::Boolean), empty);
422 }
423
424 #[test]
425 fn test_len() {
426 let empty = JsonTypeSet::empty();
427 assert!(empty.is_empty());
428 assert_eq!(empty.len(), 0);
429
430 let with_string = empty.insert(JsonType::String);
431 assert!(!with_string.is_empty());
432 assert_eq!(with_string.len(), 1);
433 assert_eq!(JsonTypeSet::all().len(), 7);
434 }
435
436 #[test]
437 fn test_debug_format() {
438 assert_eq!(format!("{:?}", JsonTypeSet::default()), "()");
439 assert_eq!(
440 format!("{:?}", JsonTypeSet::from(JsonType::String)),
441 "(string)"
442 );
443 assert_eq!(
444 format!(
445 "{:?}",
446 JsonTypeSet::from(JsonType::String).insert(JsonType::Number)
447 ),
448 "(number, string)"
449 );
450 }
451
452 #[test]
453 fn test_empty_iterator() {
454 let set = JsonTypeSet::empty();
455 let mut iter = set.iter();
456 assert_eq!(iter.next(), None);
457 assert_eq!(iter.size_hint(), (0, Some(0)));
458 }
459
460 #[test]
461 fn test_single_type_iterator() {
462 let set = JsonTypeSet::from(JsonType::String);
463 let mut iter = set.iter();
464 assert_eq!(iter.size_hint(), (1, Some(1)));
465 assert_eq!(iter.next(), Some(JsonType::String));
466 assert_eq!(iter.size_hint(), (0, Some(0)));
467 assert_eq!(iter.next(), None);
468 assert_eq!(iter.size_hint(), (0, Some(0)));
469 }
470
471 #[test]
472 fn test_multiple_types_iterator() {
473 let set = JsonTypeSet::from(JsonType::String)
474 .insert(JsonType::Number)
475 .insert(JsonType::Boolean);
476
477 let types: Vec<JsonType> = set.iter().collect();
478 assert_eq!(types.len(), 3);
479 assert!(types.contains(&JsonType::String));
480 assert!(types.contains(&JsonType::Number));
481 assert!(types.contains(&JsonType::Boolean));
482
483 assert_eq!(set.iter().size_hint(), (3, Some(3)));
484 }
485
486 #[test]
487 fn test_all_types_iterator() {
488 let set = JsonTypeSet::all();
489
490 let types: Vec<JsonType> = set.iter().collect();
491 assert_eq!(types.len(), 7);
492
493 let mut iter = set.iter();
494 assert_eq!(iter.len(), 7);
495 iter.next();
496 assert_eq!(iter.len(), 6);
497 }
498}