facet_json/
deserialize.rs

1use core::num::{
2    NonZeroI8, NonZeroI16, NonZeroI32, NonZeroI64, NonZeroIsize, NonZeroU8, NonZeroU16, NonZeroU32,
3    NonZeroU64, NonZeroUsize,
4};
5
6use facet_core::{Def, Facet, FieldAttribute, ScalarAffinity, ShapeAttribute};
7use facet_reflect::{HeapValue, Wip};
8use log::trace;
9
10use alloc::format;
11use alloc::string::{String, ToString};
12use alloc::vec::Vec;
13use owo_colors::OwoColorize;
14
15mod error;
16pub use error::*;
17
18/// Deserializes a JSON string into a value of type `T` that implements `Facet`.
19///
20/// This function takes a JSON string representation and converts it into a Rust
21/// value of the specified type `T`. The type must implement the `Facet` trait
22/// to provide the necessary type information for deserialization.
23pub fn from_str<T: Facet>(json: &str) -> Result<T, JsonParseErrorWithContext<'_>> {
24    from_slice(json.as_bytes())
25}
26
27/// Deserialize JSON from a slice
28///
29/// # Arguments
30///
31/// * `json` - A slice of bytes representing the JSON input.
32///
33/// # Returns
34///
35/// A result containing the deserialized value of type `T` or a `JsonParseErrorWithContext`.
36pub fn from_slice<T: Facet>(json: &[u8]) -> Result<T, JsonParseErrorWithContext<'_>> {
37    let wip = Wip::alloc::<T>();
38    let heap_value = from_slice_wip(wip, json)?;
39    Ok(heap_value.materialize::<T>().unwrap())
40}
41
42/// Deserialize a JSON string into a Wip object.
43///
44/// # Arguments
45///
46/// * `wip` - A mutable Wip object to deserialize into.
47/// * `input` - A byte slice representing the JSON input.
48///
49/// # Returns
50///
51/// A result containing the updated `Wip` or a `JsonParseErrorWithContext`.
52pub fn from_slice_wip<'input, 'a>(
53    mut wip: Wip<'a>,
54    input: &'input [u8],
55) -> Result<HeapValue<'a>, JsonParseErrorWithContext<'input>> {
56    let mut pos = 0;
57
58    macro_rules! err {
59        ($kind:expr) => {
60            Err(JsonParseErrorWithContext::new(
61                $kind,
62                input,
63                pos,
64                wip.path(),
65            ))
66        };
67    }
68    macro_rules! bail {
69        ($kind:expr) => {
70            return err!($kind)
71        };
72    }
73
74    /// Indicates why we are expecting a value in the parsing stack.
75    #[derive(Debug, Clone, Copy, PartialEq, Eq)]
76    enum WhyValue {
77        /// At the top level of the JSON input.
78        TopLevel,
79        /// Expecting an object key.
80        ObjectKey,
81        /// Expecting an object value.
82        ObjectValue,
83        /// Expecting an array element.
84        ArrayElement,
85    }
86
87    /// Indicates the context for a comma separator in JSON (object or array).
88    #[derive(Debug, Clone, Copy, PartialEq, Eq)]
89    enum WhyComma {
90        /// A comma in an object context.
91        Object,
92        /// A comma in an array context.
93        Array,
94    }
95
96    /// Indicates the type of separator expected (colon or comma).
97    #[derive(Debug, Clone, Copy, PartialEq, Eq)]
98    enum Separator {
99        /// Expecting a colon separator in object key-value pairs.
100        Colon,
101        /// Expecting a comma separator (in objects or arrays).
102        Comma(WhyComma),
103    }
104
105    /// Represents the next expected token or structure while parsing.
106    #[derive(Debug, Clone, Copy, PartialEq, Eq)]
107    enum Expect {
108        /// Expecting a value, with its reason/context.
109        Value(WhyValue),
110        /// Expecting a separator (colon or comma).
111        Separator(Separator),
112        /// We did `push_some` and now we need to pop it
113        PopOption,
114    }
115
116    let mut stack: Vec<Expect> = Vec::new();
117    stack.push(Expect::Value(WhyValue::TopLevel));
118
119    loop {
120        // skip over whitespace
121        while let Some(c) = input.get(pos).copied() {
122            match c {
123                b' ' | b'\t' | b'\n' | b'\r' => {
124                    pos += 1;
125                }
126                _ => break,
127            }
128        }
129
130        let frame_count = wip.frames_count();
131        let expect = match stack.pop() {
132            Some(expect) => expect,
133            None => {
134                if frame_count == 1 {
135                    return Ok(wip.build().unwrap());
136                } else {
137                    trace!("frame_count isn't 1, it's {}", frame_count);
138                    bail!(JsonErrorKind::UnexpectedEof("frame_count isn't 1"));
139                }
140            }
141        };
142        trace!("[{frame_count}] Expecting {:?}", expect.yellow());
143
144        let Some(c) = input.get(pos).copied() else {
145            bail!(JsonErrorKind::UnexpectedEof("no input at pos"));
146        };
147
148        let mut finished_value: Option<WhyValue> = None;
149
150        match expect {
151            Expect::PopOption => {
152                // that's all, carry on
153                trace!("Popping option");
154                finished_value = Some(WhyValue::ObjectValue);
155            }
156            Expect::Value(why) => {
157                if let Def::Option(_) = wip.shape().def {
158                    wip = wip.push_some().unwrap();
159                    stack.push(Expect::PopOption);
160                }
161
162                match c {
163                    b'{' => {
164                        trace!("Object starting");
165                        pos += 1;
166                        let Some(c) = input.get(pos).copied() else {
167                            bail!(JsonErrorKind::UnexpectedEof("nothing after {"));
168                        };
169                        match c {
170                            b'}' => {
171                                trace!("Empty object ended");
172                                pos += 1;
173                                finished_value = Some(why);
174                            }
175                            _ => {
176                                trace!("Object's not empty, let's do `key: value ,` next");
177                                // okay, next we expect a "key: value"
178                                stack.push(Expect::Separator(Separator::Comma(WhyComma::Object)));
179                                stack.push(Expect::Value(WhyValue::ObjectValue));
180                                stack.push(Expect::Separator(Separator::Colon));
181                                stack.push(Expect::Value(WhyValue::ObjectKey));
182                            }
183                        }
184                    }
185                    b'[' => {
186                        pos += 1;
187                        let Some(c) = input.get(pos).copied() else {
188                            bail!(JsonErrorKind::UnexpectedEof("nothing after ["));
189                        };
190
191                        wip = wip.begin_pushback().unwrap();
192                        match c {
193                            b']' => {
194                                // an array just closed, somewhere
195                                pos += 1;
196                                trace!("Got empty array");
197                                finished_value = Some(why);
198                            }
199                            _ => {
200                                // okay, next we expect an item and a separator (or the end of the array)
201                                stack.push(Expect::Separator(Separator::Comma(WhyComma::Array)));
202                                stack.push(Expect::Value(WhyValue::ArrayElement));
203                                wip = wip.push().unwrap();
204                                continue; // we didn't finish a value so don't pop yet
205                            }
206                        }
207                    }
208                    b'"' => {
209                        pos += 1;
210                        // Our value is a string: collect bytes first
211                        let mut bytes = Vec::new();
212                        loop {
213                            let Some(c) = input.get(pos).copied() else {
214                                bail!(JsonErrorKind::UnexpectedEof("nothing after \""));
215                            };
216                            match c {
217                                b'"' => {
218                                    pos += 1;
219                                    break;
220                                }
221                                b'\\' => {
222                                    // Handle escape sequences
223                                    pos += 1;
224                                    if let Some(next) = input.get(pos) {
225                                        bytes.push(*next);
226                                        pos += 1;
227                                    } else {
228                                        bail!(JsonErrorKind::UnexpectedEof("nothing after \\"));
229                                    }
230                                }
231                                _ => {
232                                    bytes.push(c);
233                                    pos += 1;
234                                }
235                            }
236                        }
237
238                        // Convert collected bytes to string at once
239                        let value = match core::str::from_utf8(&bytes) {
240                            Ok(s) => s.to_string(),
241                            Err(e) => {
242                                bail!(JsonErrorKind::InvalidUtf8(format!(
243                                    "Invalid UTF-8 sequence: {}",
244                                    e
245                                )))
246                            }
247                        };
248
249                        trace!(
250                            "Parsed string {:?} for {} (why? {:?})",
251                            value.yellow(),
252                            wip.shape().blue(),
253                            why.cyan()
254                        );
255
256                        match why {
257                            WhyValue::TopLevel | WhyValue::ArrayElement | WhyValue::ObjectValue => {
258                                wip = wip.parse(&value).unwrap();
259                                finished_value = Some(why);
260                            }
261                            WhyValue::ObjectKey => {
262                                // Look for field with matching name or rename attribute
263                                let shape = wip.shape();
264
265                                if let Def::Struct(struct_def) = shape.def {
266                                    let field = struct_def.fields.iter().find(|f| {
267                                        // Check original name
268                                        if f.name == value {
269                                            return true;
270                                        }
271
272                                        // Check rename attribute
273                                        f.attributes.iter().any(|attr| {
274                                            if let FieldAttribute::Rename(rename) = attr {
275                                                rename == &value
276                                            } else {
277                                                false
278                                            }
279                                        })
280                                    });
281
282                                    if let Some(field) = field {
283                                        trace!("found field {:?}", field.blue());
284                                        wip = wip.field_named(field.name).unwrap();
285                                    } else if shape.attributes.iter().any(|attr| {
286                                        matches!(attr, ShapeAttribute::DenyUnknownFields)
287                                    }) {
288                                        // Field not found - original or renamed, and unknown fields denied
289                                        bail!(JsonErrorKind::UnknownField(value.to_string()));
290                                    } else {
291                                        // pop Expect::Colon (assert)
292                                        let expect_colon = stack.pop();
293                                        assert!(matches!(
294                                            expect_colon,
295                                            Some(Expect::Separator(Separator::Colon))
296                                        ));
297                                        // skip over whitespace
298                                        while let Some(b' ' | b'\t' | b'\n' | b'\r') =
299                                            input.get(pos).copied()
300                                        {
301                                            pos += 1;
302                                        }
303                                        // skip over colon
304                                        if let Some(b':') = input.get(pos) {
305                                            pos += 1;
306                                        } else {
307                                            bail!(JsonErrorKind::UnexpectedCharacter(
308                                                input
309                                                    .get(pos)
310                                                    .copied()
311                                                    .map(|c| c as char)
312                                                    .unwrap_or('\0')
313                                            ));
314                                        }
315                                        // skip over whitespace
316                                        while let Some(b' ' | b'\t' | b'\n' | b'\r') =
317                                            input.get(pos).copied()
318                                        {
319                                            pos += 1;
320                                        }
321                                        // pop Expect::Value
322                                        let expect_value = stack.pop();
323                                        assert!(matches!(
324                                            expect_value,
325                                            Some(Expect::Value(WhyValue::ObjectValue))
326                                        ));
327                                        // skip over value
328                                        skip_over_value(&mut pos, input).map_err(|e| {
329                                            JsonParseErrorWithContext::new(
330                                                e,
331                                                input,
332                                                pos,
333                                                wip.path(),
334                                            )
335                                        })?;
336                                        trace!(
337                                            "immediately after skip over value, we're at pos {}, char is {}",
338                                            pos,
339                                            input.get(pos).copied().unwrap_or(b'$') as char
340                                        );
341                                    }
342                                } else {
343                                    trace!(
344                                        "Getting field {}, not in a Struct, but in a... {}",
345                                        value.blue(),
346                                        wip.shape()
347                                    );
348                                    wip = wip.field_named(&value).expect("assuming only structs have a fixed set of fields (which is not true, cf. enums)");
349                                }
350                            }
351                        }
352                    }
353                    b'0'..=b'9' | b'-' => {
354                        pos += 1;
355                        let start = pos - 1;
356                        while let Some(c) = input.get(pos) {
357                            match c {
358                                b'0'..=b'9' | b'.' => {
359                                    pos += 1;
360                                }
361                                _ => break,
362                            }
363                        }
364                        let number = &input[start..pos];
365                        let number = core::str::from_utf8(number).unwrap();
366                        let number = number.parse::<f64>().unwrap();
367                        trace!("Parsed {:?}", number.yellow());
368
369                        let shape = wip.shape();
370                        match shape.def {
371                            Def::Scalar(sd) => match sd.affinity {
372                                ScalarAffinity::Number(_na) => {
373                                    if shape.is_type::<u8>() {
374                                        if number >= 0.0 && number <= u8::MAX as f64 {
375                                            let value = number as u8;
376                                            wip = wip.put::<u8>(value).unwrap();
377                                        } else {
378                                            bail!(JsonErrorKind::NumberOutOfRange(number));
379                                        }
380                                    } else if shape.is_type::<u16>() {
381                                        if number >= 0.0 && number <= u16::MAX as f64 {
382                                            let value = number as u16;
383                                            wip = wip.put::<u16>(value).unwrap();
384                                        } else {
385                                            bail!(JsonErrorKind::NumberOutOfRange(number));
386                                        }
387                                    } else if shape.is_type::<u32>() {
388                                        if number >= 0.0 && number <= u32::MAX as f64 {
389                                            let value = number as u32;
390                                            wip = wip.put::<u32>(value).unwrap();
391                                        } else {
392                                            bail!(JsonErrorKind::NumberOutOfRange(number));
393                                        }
394                                    } else if shape.is_type::<u64>() {
395                                        if number >= 0.0 && number <= u64::MAX as f64 {
396                                            let value = number as u64;
397                                            wip = wip.put::<u64>(value).unwrap();
398                                        } else {
399                                            bail!(JsonErrorKind::NumberOutOfRange(number));
400                                        }
401                                    } else if shape.is_type::<i8>() {
402                                        if number >= i8::MIN as f64 && number <= i8::MAX as f64 {
403                                            let value = number as i8;
404                                            wip = wip.put::<i8>(value).unwrap();
405                                        } else {
406                                            bail!(JsonErrorKind::NumberOutOfRange(number));
407                                        }
408                                    } else if shape.is_type::<i16>() {
409                                        if number >= i16::MIN as f64 && number <= i16::MAX as f64 {
410                                            let value = number as i16;
411                                            wip = wip.put::<i16>(value).unwrap();
412                                        } else {
413                                            bail!(JsonErrorKind::NumberOutOfRange(number));
414                                        }
415                                    } else if shape.is_type::<i32>() {
416                                        if number >= i32::MIN as f64 && number <= i32::MAX as f64 {
417                                            let value = number as i32;
418                                            wip = wip.put::<i32>(value).unwrap();
419                                        } else {
420                                            bail!(JsonErrorKind::NumberOutOfRange(number));
421                                        }
422                                    } else if shape.is_type::<i64>() {
423                                        // Note: f64 might lose precision for large i64 values, but this is a common limitation.
424                                        if number >= i64::MIN as f64 && number <= i64::MAX as f64 {
425                                            let value = number as i64;
426                                            wip = wip.put::<i64>(value).unwrap();
427                                        } else {
428                                            bail!(JsonErrorKind::NumberOutOfRange(number));
429                                        }
430                                    } else if shape.is_type::<f32>() {
431                                        if number >= f32::MIN as f64 && number <= f32::MAX as f64 {
432                                            let value = number as f32;
433                                            wip = wip.put::<f32>(value).unwrap();
434                                        } else {
435                                            bail!(JsonErrorKind::NumberOutOfRange(number));
436                                        }
437                                    } else if shape.is_type::<f64>() {
438                                        wip = wip.put::<f64>(number).unwrap();
439                                    } else if shape.is_type::<NonZeroU8>() {
440                                        if number >= 1.0 && number <= u8::MAX as f64 {
441                                            let value = NonZeroU8::new(number as u8).unwrap();
442                                            wip = wip.put::<NonZeroU8>(value).unwrap();
443                                        } else {
444                                            bail!(JsonErrorKind::NumberOutOfRange(number));
445                                        }
446                                    } else if shape.is_type::<NonZeroU16>() {
447                                        if number >= 1.0 && number <= u16::MAX as f64 {
448                                            let value = NonZeroU16::new(number as u16).unwrap();
449                                            wip = wip.put::<NonZeroU16>(value).unwrap();
450                                        } else {
451                                            bail!(JsonErrorKind::NumberOutOfRange(number));
452                                        }
453                                    } else if shape.is_type::<NonZeroU32>() {
454                                        if number >= 1.0 && number <= u32::MAX as f64 {
455                                            let value = NonZeroU32::new(number as u32).unwrap();
456                                            wip = wip.put::<NonZeroU32>(value).unwrap();
457                                        } else {
458                                            bail!(JsonErrorKind::NumberOutOfRange(number));
459                                        }
460                                    } else if shape.is_type::<NonZeroU64>() {
461                                        if number >= 1.0 && number <= u64::MAX as f64 {
462                                            let value = NonZeroU64::new(number as u64).unwrap();
463                                            wip = wip.put::<NonZeroU64>(value).unwrap();
464                                        } else {
465                                            bail!(JsonErrorKind::NumberOutOfRange(number));
466                                        }
467                                    } else if shape.is_type::<NonZeroUsize>() {
468                                        if number >= 1.0 && number <= usize::MAX as f64 {
469                                            let value = NonZeroUsize::new(number as usize).unwrap();
470                                            wip = wip.put::<NonZeroUsize>(value).unwrap();
471                                        } else {
472                                            bail!(JsonErrorKind::NumberOutOfRange(number));
473                                        }
474                                    } else if shape.is_type::<NonZeroI8>() {
475                                        if number >= 1.0 && number <= i8::MAX as f64 {
476                                            let value = NonZeroI8::new(number as i8).unwrap();
477                                            wip = wip.put::<NonZeroI8>(value).unwrap();
478                                        } else {
479                                            bail!(JsonErrorKind::NumberOutOfRange(number));
480                                        }
481                                    } else if shape.is_type::<NonZeroI16>() {
482                                        if number >= 1.0 && number <= i16::MAX as f64 {
483                                            let value = NonZeroI16::new(number as i16).unwrap();
484                                            wip = wip.put::<NonZeroI16>(value).unwrap();
485                                        } else {
486                                            bail!(JsonErrorKind::NumberOutOfRange(number));
487                                        }
488                                    } else if shape.is_type::<NonZeroI32>() {
489                                        if number >= 1.0 && number <= i32::MAX as f64 {
490                                            let value = NonZeroI32::new(number as i32).unwrap();
491                                            wip = wip.put::<NonZeroI32>(value).unwrap();
492                                        } else {
493                                            bail!(JsonErrorKind::NumberOutOfRange(number));
494                                        }
495                                    } else if shape.is_type::<NonZeroI64>() {
496                                        if number >= 1.0 && number <= i64::MAX as f64 {
497                                            let value = NonZeroI64::new(number as i64).unwrap();
498                                            wip = wip.put::<NonZeroI64>(value).unwrap();
499                                        } else {
500                                            bail!(JsonErrorKind::NumberOutOfRange(number));
501                                        }
502                                    } else if shape.is_type::<NonZeroIsize>() {
503                                        if number >= 1.0 && number <= isize::MAX as f64 {
504                                            let value = NonZeroIsize::new(number as isize).unwrap();
505                                            wip = wip.put::<NonZeroIsize>(value).unwrap();
506                                        } else {
507                                            bail!(JsonErrorKind::NumberOutOfRange(number));
508                                        }
509                                    } else {
510                                        todo!("number type, but unknown")
511                                    }
512                                }
513                                ScalarAffinity::String(_sa) => {
514                                    if shape.is_type::<String>() {
515                                        let value = number.to_string();
516                                        bail!(JsonErrorKind::StringAsNumber(value));
517                                    } else {
518                                        todo!()
519                                    }
520                                }
521                                _ => {
522                                    todo!("saw number in JSON but expected.. shape {}?", shape)
523                                }
524                            },
525                            _ => {
526                                todo!("saw number in JSON but expected.. shape {}?", shape)
527                            }
528                        }
529                        finished_value = Some(why);
530                    }
531                    b'n' => {
532                        // wow it's a null — probably
533                        let slice_rest = &input[pos..];
534                        if slice_rest.starts_with(b"null") {
535                            pos += 4;
536
537                            // ok but we already pushed some! luckily wip has the method for us
538                            wip = wip.pop_some_push_none().unwrap();
539                            finished_value = Some(why);
540                        } else {
541                            bail!(JsonErrorKind::UnexpectedCharacter('n'));
542                        }
543                    }
544                    c => {
545                        bail!(JsonErrorKind::UnexpectedCharacter(c as char));
546                    }
547                }
548            }
549            Expect::Separator(separator) => match separator {
550                Separator::Colon => match c {
551                    b':' => {
552                        pos += 1;
553                    }
554                    _ => {
555                        bail!(JsonErrorKind::UnexpectedCharacter(c as char));
556                    }
557                },
558                Separator::Comma(why) => match c {
559                    b',' => {
560                        pos += 1;
561                        match why {
562                            WhyComma::Array => {
563                                stack.push(Expect::Separator(Separator::Comma(WhyComma::Array)));
564                                stack.push(Expect::Value(WhyValue::ArrayElement));
565                                wip = wip.push().unwrap();
566                            }
567                            WhyComma::Object => {
568                                // looks like we're in for another round of object parsing
569                                stack.push(Expect::Separator(Separator::Comma(WhyComma::Object)));
570                                stack.push(Expect::Value(WhyValue::ObjectValue));
571                                stack.push(Expect::Separator(Separator::Colon));
572                                stack.push(Expect::Value(WhyValue::ObjectKey));
573                            }
574                        }
575                    }
576                    b'}' => match why {
577                        WhyComma::Object => {
578                            pos += 1;
579                            finished_value = Some(WhyValue::ObjectValue);
580                        }
581                        _ => {
582                            bail!(JsonErrorKind::UnexpectedCharacter(c as char));
583                        }
584                    },
585                    b']' => {
586                        pos += 1;
587                        match why {
588                            WhyComma::Array => {
589                                // we finished the array, neat
590                                if frame_count > 1 {
591                                    wip = wip.pop().unwrap();
592                                }
593                            }
594                            _ => {
595                                bail!(JsonErrorKind::UnexpectedCharacter(c as char));
596                            }
597                        }
598                    }
599                    _ => {
600                        bail!(JsonErrorKind::UnexpectedCharacter(c as char));
601                    }
602                },
603            },
604        }
605
606        if let Some(why) = finished_value {
607            trace!("Just finished value because of {:?}", why.green());
608            match why {
609                WhyValue::TopLevel => {}
610                WhyValue::ObjectKey => {}
611                WhyValue::ObjectValue | WhyValue::ArrayElement => {
612                    if frame_count == 1 {
613                        return Ok(wip.build().unwrap());
614                    } else {
615                        wip = wip.pop().unwrap();
616                    }
617                }
618            }
619        }
620    }
621}
622
623fn skip_over_value(pos: &mut usize, input: &[u8]) -> Result<(), JsonErrorKind> {
624    let bytes = input;
625
626    // Helper for skipping whitespace
627    let skip_whitespace = |pos: &mut usize| {
628        while *pos < bytes.len() {
629            match bytes[*pos] {
630                b' ' | b'\t' | b'\n' | b'\r' => *pos += 1,
631                _ => break,
632            }
633        }
634    };
635
636    skip_whitespace(pos);
637
638    if *pos >= bytes.len() {
639        return Err(JsonErrorKind::UnexpectedEof(
640            "while skipping over value: input ended unexpectedly at root",
641        ));
642    }
643
644    match bytes[*pos] {
645        b'{' => {
646            // Skip a full object, recursively
647            *pos += 1;
648            skip_whitespace(pos);
649            if *pos < bytes.len() && bytes[*pos] == b'}' {
650                *pos += 1;
651                return Ok(());
652            }
653            loop {
654                // Skip key
655                skip_over_value(pos, input)?;
656                skip_whitespace(pos);
657                // Expect colon between key and value
658                if *pos >= bytes.len() || bytes[*pos] != b':' {
659                    return Err(JsonErrorKind::UnexpectedEof(
660                        "while skipping over value: object key with no colon or input ended",
661                    ));
662                }
663                *pos += 1;
664                skip_whitespace(pos);
665                // Skip value
666                skip_over_value(pos, input)?;
667                skip_whitespace(pos);
668                if *pos >= bytes.len() {
669                    return Err(JsonErrorKind::UnexpectedEof(
670                        "while skipping over value: object value with EOF after",
671                    ));
672                }
673                if bytes[*pos] == b'}' {
674                    *pos += 1;
675                    break;
676                } else if bytes[*pos] == b',' {
677                    *pos += 1;
678                    skip_whitespace(pos);
679                    continue;
680                } else {
681                    return Err(JsonErrorKind::UnexpectedCharacter(bytes[*pos] as char));
682                }
683            }
684        }
685        b'[' => {
686            // Skip a full array, recursively
687            *pos += 1;
688            skip_whitespace(pos);
689            if *pos < bytes.len() && bytes[*pos] == b']' {
690                *pos += 1;
691                return Ok(());
692            }
693            loop {
694                skip_over_value(pos, input)?;
695                skip_whitespace(pos);
696                if *pos >= bytes.len() {
697                    return Err(JsonErrorKind::UnexpectedEof(
698                        "while skipping over value: EOF inside array",
699                    ));
700                }
701                if bytes[*pos] == b']' {
702                    *pos += 1;
703                    break;
704                } else if bytes[*pos] == b',' {
705                    *pos += 1;
706                    skip_whitespace(pos);
707                    continue;
708                } else {
709                    return Err(JsonErrorKind::UnexpectedCharacter(bytes[*pos] as char));
710                }
711            }
712        }
713        b'"' => {
714            // Skip a string, with escape processing
715            *pos += 1;
716            while *pos < bytes.len() {
717                match bytes[*pos] {
718                    b'\\' => {
719                        // Could have EOF after backslash
720                        if *pos + 1 >= bytes.len() {
721                            return Err(JsonErrorKind::UnexpectedEof(
722                                "while skipping over value: EOF after backslash in string",
723                            ));
724                        }
725                        *pos += 2; // Skip backslash and the next character (escaped)
726                    }
727                    b'"' => {
728                        *pos += 1;
729                        break;
730                    }
731                    _ => {
732                        *pos += 1;
733                    }
734                }
735            }
736            if *pos > bytes.len() {
737                return Err(JsonErrorKind::UnexpectedEof(
738                    "while skipping over value: string ended unexpectedly",
739                ));
740            }
741        }
742        b't' => {
743            // Expect "true"
744            if bytes.len() >= *pos + 4 && &bytes[*pos..*pos + 4] == b"true" {
745                *pos += 4;
746            } else {
747                return Err(JsonErrorKind::UnexpectedCharacter('t'));
748            }
749        }
750        b'f' => {
751            // Expect "false"
752            if bytes.len() >= *pos + 5 && &bytes[*pos..*pos + 5] == b"false" {
753                *pos += 5;
754            } else {
755                return Err(JsonErrorKind::UnexpectedCharacter('f'));
756            }
757        }
758        b'n' => {
759            // Expect "null"
760            if bytes.len() >= *pos + 4 && &bytes[*pos..*pos + 4] == b"null" {
761                *pos += 4;
762            } else {
763                return Err(JsonErrorKind::UnexpectedCharacter('n'));
764            }
765        }
766        b'-' | b'0'..=b'9' => {
767            // Skip a number: -?\d+(\.\d+)?([eE][+-]?\d+)?
768            let start = *pos;
769            if bytes[*pos] == b'-' {
770                *pos += 1;
771            }
772            if *pos < bytes.len() && bytes[*pos] == b'0' {
773                *pos += 1;
774            } else {
775                while *pos < bytes.len() && (bytes[*pos] as char).is_ascii_digit() {
776                    *pos += 1;
777                }
778            }
779            if *pos < bytes.len() && bytes[*pos] == b'.' {
780                *pos += 1;
781                let mut has_digit = false;
782                while *pos < bytes.len() && (bytes[*pos] as char).is_ascii_digit() {
783                    *pos += 1;
784                    has_digit = true;
785                }
786                if !has_digit {
787                    return Err(JsonErrorKind::UnexpectedCharacter('.'));
788                }
789            }
790            if *pos < bytes.len() && (bytes[*pos] == b'e' || bytes[*pos] == b'E') {
791                *pos += 1;
792                if *pos < bytes.len() && (bytes[*pos] == b'+' || bytes[*pos] == b'-') {
793                    *pos += 1;
794                }
795                let mut has_digit = false;
796                while *pos < bytes.len() && (bytes[*pos] as char).is_ascii_digit() {
797                    *pos += 1;
798                    has_digit = true;
799                }
800                if !has_digit {
801                    return Err(JsonErrorKind::UnexpectedCharacter('e'));
802                }
803            }
804            if *pos == start {
805                return Err(JsonErrorKind::UnexpectedCharacter(bytes[start] as char));
806            }
807        }
808        _ => {
809            return Err(JsonErrorKind::UnexpectedCharacter(bytes[*pos] as char));
810        }
811    }
812    Ok(())
813}