Skip to main content

json_bourne/
lexer.rs

1//! Stateless JSON lexer.
2//!
3//! `Lexer` is the byte-walking layer. It knows how to recognize and consume
4//! one JSON token at a time — strings, numbers, keywords, structural bytes
5//! — but it does not enforce the grammar that says "an array element is
6//! followed by `,` or `]`." That bookkeeping lives in `Parser`, which wraps
7//! a `Lexer` plus a `State` enum.
8//!
9//! The split exists because typed consumers (`Vec<T>::from_lex`,
10//! `Struct::from_lex`) already enforce the grammar by virtue of which
11//! method they call when. They walk the input recursively and don't need
12//! the `State` dispatch — calling it per element is pure overhead. By
13//! exposing the lexer directly, those consumers skip the state machine
14//! entirely; only streaming consumers using `Parser::next_event` pay for
15//! it.
16//!
17//! Container nesting is still tracked here (for depth limiting and matched
18//! `]`/`}` validation), but it's a plain push/pop on `Stack`, not a state
19//! machine.
20
21use crate::error::{Error, ErrorKind, Position};
22use crate::event::{Event, JsonNum, JsonStr, MAX_INPUT_LEN};
23
24/// `i64::MIN`'s magnitude as a `u64`: `i64::MAX as u64 + 1`. This is the
25/// largest `u64` value whose negation still fits in `i64`. Used by
26/// `parse_i64_value` to validate sign-aware bounds — `-9223372036854775808`
27/// is legal even though `+9223372036854775808` is not.
28const I64_MIN_MAGNITUDE: u64 = (i64::MAX as u64) + 1;
29
30/// Sign-aware bounds check shared by `parse_i64_value` and its inner
31/// digit loop. Maps an unsigned magnitude `acc` and a sign bit to the
32/// final `i64`, or returns `Err(())` if the magnitude doesn't fit.
33#[inline]
34fn i64_from_unsigned_magnitude(acc: u64, negative: bool) -> Result<i64, ()> {
35    if negative {
36        // `i64::MIN`'s magnitude is exactly `I64_MIN_MAGNITUDE`; any
37        // larger magnitude doesn't fit. `0i64.wrapping_sub_unsigned(acc)`
38        // produces `i64::MIN` when `acc == I64_MIN_MAGNITUDE`.
39        if acc <= I64_MIN_MAGNITUDE {
40            return Ok(0i64.wrapping_sub_unsigned(acc));
41        }
42        return Err(());
43    }
44    i64::try_from(acc).map_err(|_| ())
45}
46
47/// `i128::MIN`'s magnitude as a `u128`. Same trick as `I64_MIN_MAGNITUDE`,
48/// scaled up. `parse_i128_value` accumulates into `u128` so the negative
49/// edge case (`-170141183460469231731687303715884105728`) is representable
50/// during the lex pass before the sign-aware bounds check.
51const I128_MIN_MAGNITUDE: u128 = (i128::MAX as u128) + 1;
52
53/// `u128::MAX` is `2^128 - 1` ≈ 3.4 × 10^38, so 38 decimal digits always
54/// fit a `u128` without overflow check. The 39-digit boundary is exactly
55/// `10^38`–`u128::MAX`; from digit 39 onward we have to use checked
56/// arithmetic. Mirrors the 19-digit fast path in `parse_i64_value`.
57const U128_FAST_DIGITS: u32 = 38;
58
59/// Default maximum container nesting depth.
60///
61/// Guards against pathological inputs (e.g. millions of `[`s) that would
62/// otherwise drive recursive consumers into stack overflow. Override at
63/// compile time by parameterizing [`Lexer`] (and [`Parser`](crate::Parser))
64/// with a different `MAX_DEPTH`.
65pub const DEFAULT_MAX_DEPTH: usize = 128;
66
67#[derive(Copy, Clone, Debug, PartialEq, Eq)]
68#[allow(clippy::redundant_pub_crate)]
69pub(crate) enum Frame {
70    Array,
71    Object,
72}
73
74/// Fixed-capacity nesting stack. Avoids `alloc` for the parser itself.
75///
76/// Capacity is fixed at compile time by `Lexer`'s `MAX_DEPTH` parameter,
77/// so the inline array sized to it is also the depth bound.
78#[derive(Debug)]
79#[allow(clippy::redundant_pub_crate)]
80pub(crate) struct Stack<const MAX_DEPTH: usize> {
81    frames: [Frame; MAX_DEPTH],
82    len: usize,
83}
84
85impl<const MAX_DEPTH: usize> Stack<MAX_DEPTH> {
86    pub(crate) const fn new() -> Self {
87        Self {
88            frames: [Frame::Array; MAX_DEPTH],
89            len: 0,
90        }
91    }
92
93    pub(crate) const fn push(&mut self, frame: Frame) -> Result<(), ()> {
94        if self.len >= MAX_DEPTH {
95            return Err(());
96        }
97        self.frames[self.len] = frame;
98        self.len += 1;
99        Ok(())
100    }
101
102    pub(crate) const fn pop(&mut self) -> Option<Frame> {
103        if self.len == 0 {
104            None
105        } else {
106            self.len -= 1;
107            Some(self.frames[self.len])
108        }
109    }
110
111    pub(crate) const fn top(&self) -> Option<Frame> {
112        if self.len == 0 {
113            None
114        } else {
115            Some(self.frames[self.len - 1])
116        }
117    }
118
119    pub(crate) const fn len(&self) -> usize {
120        self.len
121    }
122
123    pub(crate) const fn truncate(&mut self, new_len: usize) {
124        if new_len <= self.len {
125            self.len = new_len;
126        }
127    }
128}
129
130enum ObjectPeek { Close, Quote, Comma, Other }
131
132/// Stateless JSON lexer over a borrowed byte slice.
133///
134/// Each `read_*` method consumes one syntactic token from the input. The
135/// caller is responsible for invoking the right method at the right time
136/// — there is no state machine that says "after reading a key, you must
137/// call `expect_byte(b':')` next." Typed consumers (`FromJson` impls) drive
138/// the lexer directly; streaming consumers go through `Parser` instead.
139#[derive(Debug)]
140pub struct Lexer<'input, const MAX_DEPTH: usize = DEFAULT_MAX_DEPTH> {
141    input: &'input [u8],
142    /// Byte offset of the next-to-read byte. Line and column are reconstructed
143    /// lazily from `input[..offset]` whenever a `Position` is needed (errors,
144    /// public `position()` calls). The hot path never touches them, which is
145    /// what lets `bump()` compile to a single increment.
146    offset: usize,
147    pub(crate) stack: Stack<MAX_DEPTH>,
148}
149
150/// Saved lexer position + nesting depth, restorable via [`Lexer::restore`].
151///
152/// Returned by [`Lexer::checkpoint`]. The two fields together capture
153/// everything a typed consumer might mutate while exploring an input
154/// speculatively — the byte cursor and the container-frame stack depth.
155/// Restoring rewinds both, putting the lexer back into the exact state it
156/// was in when the checkpoint was taken.
157///
158/// Used by enum dispatch for representations that must try a variant and
159/// retry another on failure (`#[bourne(untagged)]`) or that must locate a
160/// tag field before parsing the rest of the object
161/// (`#[bourne(tag = "...")]`).
162#[derive(Copy, Clone, Debug)]
163pub struct Checkpoint {
164    offset: usize,
165    stack_len: usize,
166}
167
168/// Result of `Lexer::peek_value_kind`. Tells a caller what kind of value
169/// will be produced by the next `read_*` call without committing to it.
170#[derive(Copy, Clone, Debug, PartialEq, Eq)]
171pub enum ValueKind {
172    Object,
173    Array,
174    String,
175    Number,
176    True,
177    False,
178    Null,
179}
180
181impl<'input, const MAX_DEPTH: usize> Lexer<'input, MAX_DEPTH> {
182    /// Construct a lexer over `input`.
183    ///
184    /// # Panics
185    ///
186    /// Panics if `input.len() > MAX_INPUT_LEN` (~2 GB). The packed offset
187    /// representation in `JsonStr`/`JsonNum` reserves the top bit of a `u32`
188    /// for `has_escapes`, so positions are limited to 31 bits. Real-world
189    /// JSON documents are far smaller than this; consumers needing larger
190    /// streams should chunk and parse incrementally.
191    #[must_use]
192    pub const fn new(input: &'input [u8]) -> Self {
193        assert!(input.len() <= MAX_INPUT_LEN, "input exceeds MAX_INPUT_LEN");
194        Self {
195            input,
196            offset: 0,
197            stack: Stack::new(),
198        }
199    }
200
201    #[must_use]
202    pub const fn position(&self) -> Position {
203        compute_position(self.input, self.offset)
204    }
205
206    /// The input slice the lexer was constructed with. Consumers use this
207    /// to materialize `&str`/`&[u8]` from `JsonStr` and `JsonNum`, which
208    /// store offsets rather than fat pointers.
209    #[must_use]
210    pub const fn input(&self) -> &'input [u8] {
211        self.input
212    }
213
214    #[must_use]
215    pub const fn offset(&self) -> usize {
216        self.offset
217    }
218
219    /// Snapshot the current cursor and nesting depth. Pair with
220    /// [`restore`](Self::restore) to roll the lexer back after a
221    /// speculative parse — typically used by `#[bourne(untagged)]` enum
222    /// dispatch to try variants in order.
223    ///
224    /// The returned [`Checkpoint`] is opaque: do not construct one yourself
225    /// or mix checkpoints across different `Lexer` instances.
226    #[must_use]
227    pub const fn checkpoint(&self) -> Checkpoint {
228        Checkpoint {
229            offset: self.offset,
230            stack_len: self.stack.len(),
231        }
232    }
233
234    /// Roll the lexer back to a previously taken [`Checkpoint`].
235    ///
236    /// Restores both the byte cursor and the container-frame stack depth.
237    /// Intended for the speculative-retry pattern: take a checkpoint,
238    /// attempt a parse, on `Err` call `restore` and try a different shape.
239    ///
240    /// The checkpoint must have been produced by `self.checkpoint()`. If
241    /// the checkpoint is from a different lexer or from after a `restore`
242    /// to a deeper depth, behavior is logically incoherent (the `truncate`
243    /// no-ops if asked to grow), though never memory-unsafe.
244    pub const fn restore(&mut self, cp: Checkpoint) {
245        self.offset = cp.offset;
246        self.stack.truncate(cp.stack_len);
247    }
248
249    /// Skip whitespace then peek at the next byte to determine the kind of
250    /// value that begins there. Does not consume the byte. Returns
251    /// `UnexpectedEof` if there is no next byte.
252    pub fn peek_value_kind(&mut self) -> Result<ValueKind, Error> {
253        self.skip_whitespace();
254        let b = self
255            .peek()
256            .ok_or_else(|| self.err(ErrorKind::UnexpectedEof))?;
257        match b {
258            b'{' => Ok(ValueKind::Object),
259            b'[' => Ok(ValueKind::Array),
260            b'"' => Ok(ValueKind::String),
261            b'-' | b'0'..=b'9' => Ok(ValueKind::Number),
262            b't' => Ok(ValueKind::True),
263            b'f' => Ok(ValueKind::False),
264            b'n' => Ok(ValueKind::Null),
265            other => Err(self.err(ErrorKind::UnexpectedByte(other))),
266        }
267    }
268
269    /// Skip whitespace then read one full JSON value, returning the matching
270    /// `Event`. For containers, opens the container (consuming `[` or `{`)
271    /// and pushes a frame onto the nesting stack — the caller is responsible
272    /// for matching `]`/`}` later via `read_array_continue` /
273    /// `read_object_continue` (or by going through `Parser`).
274    pub fn read_value(&mut self) -> Result<Event, Error> {
275        self.skip_whitespace();
276        let b = self
277            .peek()
278            .ok_or_else(|| self.err(ErrorKind::UnexpectedEof))?;
279        match b {
280            b'{' => {
281                self.bump();
282                self.push_frame(Frame::Object)?;
283                Ok(Event::StartObject)
284            }
285            b'[' => {
286                self.bump();
287                self.push_frame(Frame::Array)?;
288                Ok(Event::StartArray)
289            }
290            b'"' => self.read_string().map(Event::String),
291            b't' => self.read_keyword(b"true", Event::Bool(true)),
292            b'f' => self.read_keyword(b"false", Event::Bool(false)),
293            b'n' => self.read_keyword(b"null", Event::Null),
294            b'-' | b'0'..=b'9' => self.read_number().map(Event::Number),
295            other => Err(self.err(ErrorKind::UnexpectedByte(other))),
296        }
297    }
298
299    /// Pop a container frame; verifies the popped frame matches `expected`.
300    /// Caller has already consumed the closing `]` or `}`.
301    pub(crate) fn pop_frame(&mut self, expected: Frame) -> Result<(), Error> {
302        let popped = self
303            .stack
304            .pop()
305            .ok_or_else(|| self.err(ErrorKind::UnexpectedByte(b']')))?;
306        if popped != expected {
307            return Err(self.err(ErrorKind::TypeMismatch));
308        }
309        Ok(())
310    }
311
312    pub(crate) fn push_frame(&mut self, frame: Frame) -> Result<(), Error> {
313        self.stack
314            .push(frame)
315            .map_err(|()| self.err(ErrorKind::DepthLimitExceeded))
316    }
317
318    pub(crate) fn read_keyword(&mut self, kw: &[u8], event: Event) -> Result<Event, Error> {
319        for &expected in kw {
320            match self.peek() {
321                Some(b) if b == expected => self.bump(),
322                Some(b) => return Err(self.err(ErrorKind::UnexpectedByte(b))),
323                None => return Err(self.err(ErrorKind::UnexpectedEof)),
324            }
325        }
326        Ok(event)
327    }
328
329    /// Read a JSON string token. Cursor must be at the opening `"`. Returns
330    /// a `JsonStr` covering the bytes between the quotes (exclusive).
331    ///
332    /// When the body contains escape sequences, the deferred `validate_escapes`
333    /// pass runs before returning — every escape is checked for syntactic
334    /// validity (escape kind, hex digits, surrogate pairing). The contract
335    /// for stream/Event consumers: a returned `JsonStr` with
336    /// `has_escapes() == true` means the escapes are well-formed.
337    pub fn read_string(&mut self) -> Result<JsonStr, Error> {
338        self.read_string_inner(true)
339    }
340
341    /// Like [`read_string`](Self::read_string), but skip the deferred
342    /// `validate_escapes` pass. The caller commits to performing
343    /// equivalent validation as part of decoding (the typed `String`
344    /// / `Cow<str>` impls do exactly this).
345    ///
346    /// This exists because `validate_escapes` and an eager decoder do
347    /// overlapping work: the deferred validation walks the body checking
348    /// every escape; the decoder walks the body to actually emit the
349    /// decoded form, and naturally has to inspect every escape anyway.
350    /// On profile, the redundant `validate_escapes` walk was 42% of total
351    /// time on the `mixed_length_strings_with_escapes` corpus when going
352    /// to `Vec<String>`. Skipping it here gives the typed path a faster
353    /// route without weakening the stream-consumer contract.
354    pub fn read_string_no_validate(&mut self) -> Result<JsonStr, Error> {
355        self.read_string_inner(false)
356    }
357
358    fn read_string_inner(&mut self, validate: bool) -> Result<JsonStr, Error> {
359        debug_assert_eq!(self.peek(), Some(b'"'));
360        self.bump(); // opening quote
361        let start = self.offset;
362        let mut has_escapes = false;
363        loop {
364            let b = self
365                .peek()
366                .ok_or_else(|| self.err(ErrorKind::UnexpectedEof))?;
367            match b {
368                b'"' => {
369                    let end = self.offset;
370                    self.bump(); // closing quote
371                    if validate && has_escapes {
372                        let raw = &self.input[start..end];
373                        validate_escapes(raw).map_err(|kind| self.err(kind))?;
374                    }
375                    #[allow(clippy::cast_possible_truncation)]
376                    return Ok(JsonStr::new(start as u32, end as u32, has_escapes));
377                }
378                b'\\' => {
379                    has_escapes = true;
380                    self.bump();
381                    match self.peek() {
382                        Some(b'"' | b'\\' | b'/' | b'b' | b'f' | b'n' | b'r' | b't') => {
383                            self.bump();
384                        }
385                        Some(b'u') => {
386                            self.bump();
387                            for _ in 0..4 {
388                                match self.peek() {
389                                    Some(b) if b.is_ascii_hexdigit() => self.bump(),
390                                    Some(b) => return Err(self.err(ErrorKind::UnexpectedByte(b))),
391                                    None => return Err(self.err(ErrorKind::UnexpectedEof)),
392                                }
393                            }
394                        }
395                        Some(_) => return Err(self.err(ErrorKind::InvalidEscape)),
396                        None => return Err(self.err(ErrorKind::UnexpectedEof)),
397                    }
398                }
399                0..=0x1F => return Err(self.err(ErrorKind::ControlCharInString)),
400                0x20..=0x7F => self.scan_ascii_string_run(),
401                _ => self.consume_utf8_multibyte()?,
402            }
403        }
404    }
405
406    /// Read a JSON number token. Cursor must be at `-` or a digit. Returns a
407    /// `JsonNum` covering the literal.
408    #[inline]
409    pub fn read_number(&mut self) -> Result<JsonNum, Error> {
410        let start = self.offset;
411
412        if self.peek() == Some(b'-') {
413            self.bump();
414        }
415
416        match self.peek() {
417            Some(b'0') => {
418                self.bump();
419            }
420            Some(b'1'..=b'9') => {
421                self.bump();
422                self.scan_digit_run();
423            }
424            Some(b) => return Err(self.err(ErrorKind::UnexpectedByte(b))),
425            None => return Err(self.err(ErrorKind::UnexpectedEof)),
426        }
427
428        if self.peek() == Some(b'.') {
429            self.bump();
430            let frac_start = self.offset;
431            self.scan_digit_run();
432            if self.offset == frac_start {
433                return Err(self.err(ErrorKind::InvalidNumber));
434            }
435        }
436
437        if matches!(self.peek(), Some(b'e' | b'E')) {
438            self.bump();
439            if matches!(self.peek(), Some(b'+' | b'-')) {
440                self.bump();
441            }
442            let exp_start = self.offset;
443            self.scan_digit_run();
444            if self.offset == exp_start {
445                return Err(self.err(ErrorKind::InvalidNumber));
446            }
447        }
448
449        #[allow(clippy::cast_possible_truncation)]
450        let result = JsonNum::new(start as u32, self.offset as u32);
451        Ok(result)
452    }
453
454    /// Parse a JSON integer directly into `i64`, fusing lex and conversion.
455    ///
456    /// Caller must position the lexer at the first byte of the value
457    /// (after any whitespace). Returns the parsed `i64` and leaves the
458    /// cursor at the byte after the number. Rejects fractional and
459    /// exponent forms — those are not integers.
460    pub fn parse_i64_value(&mut self) -> Result<i64, Error> {
461        let start = self.offset;
462        let bytes = self.input;
463        let mut i = start;
464
465        let negative = matches!(bytes.get(i), Some(&b'-'));
466        if negative {
467            i += 1;
468        }
469
470        match bytes.get(i).copied() {
471            Some(b'0') => {
472                i += 1;
473                self.offset = i;
474                if matches!(bytes.get(i), Some(&b'.' | &b'e' | &b'E')) {
475                    return Err(self.err(ErrorKind::ExpectedNumber));
476                }
477                Ok(0)
478            }
479            Some(b'1'..=b'9') => self.parse_i64_digits(i, negative),
480            Some(b) => {
481                self.offset = i;
482                Err(self.err(ErrorKind::UnexpectedByte(b)))
483            }
484            None => {
485                self.offset = i;
486                Err(self.err(ErrorKind::UnexpectedEof))
487            }
488        }
489    }
490
491    /// Inner accumulation loop for `parse_i64_value` once a leading
492    /// `1..=9` digit has been confirmed at `start`. Walks digits as
493    /// `u64` (so positive `i64::MIN.unsigned_abs()` fits during the
494    /// lex pass) and then maps the magnitude to a signed result.
495    /// Splitting this out keeps `parse_i64_value` inside the project's
496    /// cyclomatic-complexity budget.
497    fn parse_i64_digits(&mut self, start: usize, negative: bool) -> Result<i64, Error> {
498        let bytes = self.input;
499        let end = bytes.len();
500        let mut i = start;
501        let mut acc: u64 = 0;
502        let mut count: u32 = 0;
503        while i < end {
504            let d = bytes[i].wrapping_sub(b'0');
505            if d >= 10 {
506                break;
507            }
508            if count < 19 {
509                // Up to 19 digits fit in u64 without overflow; the
510                // 20-digit boundary is u64::MAX.
511                acc = acc * 10 + u64::from(d);
512            } else {
513                acc = acc
514                    .checked_mul(10)
515                    .and_then(|v| v.checked_add(u64::from(d)))
516                    .ok_or_else(|| {
517                        self.offset = i;
518                        self.err(ErrorKind::NumberOutOfRange)
519                    })?;
520            }
521            i += 1;
522            count += 1;
523        }
524        self.offset = i;
525        if matches!(bytes.get(i), Some(&b'.' | &b'e' | &b'E')) {
526            return Err(self.err(ErrorKind::ExpectedNumber));
527        }
528        i64_from_unsigned_magnitude(acc, negative)
529            .map_err(|()| self.err(ErrorKind::NumberOutOfRange))
530    }
531
532    /// Parse a JSON integer directly into `i128`, fusing lex and conversion.
533    ///
534    /// Same shape as [`parse_i64_value`] but scaled to 128-bit. On profile,
535    /// routing `Vec<i128>` through `JsonNum::as_i128` (which calls
536    /// `str::parse::<i128>`) was 60% of the workload; the generic
537    /// `str::parse` path uses checked arithmetic on every digit. The
538    /// fast path here skips overflow checks for the first 38 digits
539    /// (which always fit a `u128`) and only pays them on the 39-digit
540    /// boundary case.
541    ///
542    /// Caller must position the lexer at the first byte of the value.
543    /// Rejects fractional and exponent forms.
544    ///
545    /// [`parse_i64_value`]: Self::parse_i64_value
546    pub fn parse_i128_value(&mut self) -> Result<i128, Error> {
547        let start = self.offset;
548        let bytes = self.input;
549        let end = bytes.len();
550        let mut i = start;
551
552        let negative = matches!(bytes.get(i), Some(&b'-'));
553        if negative {
554            i += 1;
555        }
556
557        let digits_start = i;
558        match bytes.get(i).copied() {
559            Some(b'0') => i += 1,
560            Some(b'1'..=b'9') => {
561                // Accumulate as u128 so the negative edge case
562                // (i128::MIN's magnitude = i128::MAX + 1) fits during
563                // the lex pass; sign-aware bounds check at the end.
564                let mut acc: u128 = 0;
565                let mut count: u32 = 0;
566                while i < end {
567                    let d = bytes[i].wrapping_sub(b'0');
568                    if d >= 10 {
569                        break;
570                    }
571                    if count < U128_FAST_DIGITS {
572                        acc = acc * 10 + u128::from(d);
573                    } else {
574                        acc = acc
575                            .checked_mul(10)
576                            .and_then(|v| v.checked_add(u128::from(d)))
577                            .ok_or_else(|| {
578                                self.offset = i;
579                                self.err(ErrorKind::NumberOutOfRange)
580                            })?;
581                    }
582                    i += 1;
583                    count += 1;
584                }
585                if i == digits_start {
586                    self.offset = i;
587                    return Err(self.err(ErrorKind::InvalidNumber));
588                }
589                self.offset = i;
590                if matches!(bytes.get(i), Some(&b'.' | &b'e' | &b'E')) {
591                    return Err(self.err(ErrorKind::ExpectedNumber));
592                }
593                if negative {
594                    if acc <= I128_MIN_MAGNITUDE {
595                        // Same wrapping_sub_unsigned trick as the i64
596                        // path — produces i128::MIN at the boundary,
597                        // correct negative i128 below it.
598                        return Ok(0i128.wrapping_sub_unsigned(acc));
599                    }
600                    return Err(self.err(ErrorKind::NumberOutOfRange));
601                }
602                if let Ok(n) = i128::try_from(acc) {
603                    return Ok(n);
604                }
605                return Err(self.err(ErrorKind::NumberOutOfRange));
606            }
607            Some(b) => {
608                self.offset = i;
609                return Err(self.err(ErrorKind::UnexpectedByte(b)));
610            }
611            None => {
612                self.offset = i;
613                return Err(self.err(ErrorKind::UnexpectedEof));
614            }
615        }
616        self.offset = i;
617        if matches!(bytes.get(i), Some(&b'.' | &b'e' | &b'E')) {
618            return Err(self.err(ErrorKind::ExpectedNumber));
619        }
620        Ok(0)
621    }
622
623    /// Parse a JSON unsigned integer directly into `u128`, fusing lex
624    /// and conversion. Rejects negative literals, fractional, and
625    /// exponent forms.
626    ///
627    /// Caller must position the lexer at the first byte of the value.
628    pub fn parse_u128_value(&mut self) -> Result<u128, Error> {
629        let start = self.offset;
630        let bytes = self.input;
631        let end = bytes.len();
632        let mut i = start;
633
634        // Unsigned: a leading `-` is rejected outright.
635        if matches!(bytes.get(i), Some(&b'-')) {
636            self.offset = i;
637            return Err(self.err(ErrorKind::NumberOutOfRange));
638        }
639
640        let digits_start = i;
641        match bytes.get(i).copied() {
642            Some(b'0') => i += 1,
643            Some(b'1'..=b'9') => {
644                let mut acc: u128 = 0;
645                let mut count: u32 = 0;
646                while i < end {
647                    let d = bytes[i].wrapping_sub(b'0');
648                    if d >= 10 {
649                        break;
650                    }
651                    if count < U128_FAST_DIGITS {
652                        acc = acc * 10 + u128::from(d);
653                    } else {
654                        acc = acc
655                            .checked_mul(10)
656                            .and_then(|v| v.checked_add(u128::from(d)))
657                            .ok_or_else(|| {
658                                self.offset = i;
659                                self.err(ErrorKind::NumberOutOfRange)
660                            })?;
661                    }
662                    i += 1;
663                    count += 1;
664                }
665                if i == digits_start {
666                    self.offset = i;
667                    return Err(self.err(ErrorKind::InvalidNumber));
668                }
669                self.offset = i;
670                if matches!(bytes.get(i), Some(&b'.' | &b'e' | &b'E')) {
671                    return Err(self.err(ErrorKind::ExpectedNumber));
672                }
673                return Ok(acc);
674            }
675            Some(b) => {
676                self.offset = i;
677                return Err(self.err(ErrorKind::UnexpectedByte(b)));
678            }
679            None => {
680                self.offset = i;
681                return Err(self.err(ErrorKind::UnexpectedEof));
682            }
683        }
684        self.offset = i;
685        if matches!(bytes.get(i), Some(&b'.' | &b'e' | &b'E')) {
686            return Err(self.err(ErrorKind::ExpectedNumber));
687        }
688        Ok(0)
689    }
690
691    /// Parse a JSON number directly into `f64`, fusing lex and decode.
692    ///
693    /// Caller must position the lexer at the first byte of the value
694    /// (after any whitespace). Skips the `JsonNum` middle layer that
695    /// `read_number()` + `JsonNum::as_f64` would build — saves one
696    /// `Option`-wrapped slice and the per-element struct construction.
697    /// On profile, `Vec<f64>` was ~50% slower than `Vec<i64>` largely
698    /// because of this missing fast path.
699    ///
700    /// Rejects non-finite results (out-of-range literals like `1e400`
701    /// decode to `±inf` from `str::parse::<f64>`, which JSON disallows).
702    pub fn parse_f64_value(&mut self) -> Result<f64, Error> {
703        let start = self.offset;
704        // Reuse the byte-walk of `read_number` (it already handles the
705        // `-?` integer + optional `.frac` + optional `e[+-]?digits`
706        // grammar correctly). Then slice the run we just walked and
707        // hand it to libcore's `str::parse::<f64>` — the same routine
708        // `JsonNum::as_f64` calls, just without the JsonNum struct.
709        let _span = self.read_number()?;
710        let end = self.offset;
711        // SAFETY: `read_number` only advances over the JSON number
712        // grammar's ASCII subset (`-`, digits, `.`, `e`, `E`, `+`).
713        // Always valid UTF-8.
714        #[allow(unsafe_code)]
715        let s = unsafe { core::str::from_utf8_unchecked(&self.input[start..end]) };
716        let v: f64 = s.parse().map_err(|_| self.err(ErrorKind::InvalidNumber))?;
717        if v.is_finite() {
718            Ok(v)
719        } else {
720            Err(self.err(ErrorKind::NumberOutOfRange))
721        }
722    }
723
724    /// Read a JSON string and return it as a borrowed `&'input str`. Errors
725    /// if the string contains escape sequences — those require a caller-owned
726    /// decode buffer, which `json-bourne` does not allocate.
727    ///
728    /// Caller must position the lexer at the opening `"`. On return the
729    /// cursor is past the closing `"`. The returned slice points into the
730    /// original input — zero copy.
731    pub fn parse_str_value(&mut self) -> Result<&'input str, Error> {
732        match self.peek() {
733            Some(b'"') => self.bump(),
734            Some(b) => return Err(self.err(ErrorKind::UnexpectedByte(b))),
735            None => return Err(self.err(ErrorKind::UnexpectedEof)),
736        }
737        let start = self.offset;
738        loop {
739            let b = self
740                .peek()
741                .ok_or_else(|| self.err(ErrorKind::UnexpectedEof))?;
742            match b {
743                b'"' => {
744                    let end = self.offset;
745                    self.bump();
746                    let raw = &self.input[start..end];
747                    // SAFETY: every byte was validated against the RFC 3629
748                    // ranges by the byte walk above (ASCII fast arm or
749                    // `consume_utf8_multibyte`).
750                    return Ok(unsafe { core::str::from_utf8_unchecked(raw) });
751                }
752                b'\\' => return Err(self.err(ErrorKind::InvalidEscape)),
753                0..=0x1F => return Err(self.err(ErrorKind::ControlCharInString)),
754                0x20..=0x7F => self.scan_ascii_string_run(),
755                _ => self.consume_utf8_multibyte()?,
756            }
757        }
758    }
759
760    /// Skip whitespace then expect `,` or the array-end byte. Returns
761    /// `true` if at end (caller should stop), `false` to continue with
762    /// another element.
763    ///
764    /// On `]` this also pops the matching frame from the nesting stack so
765    /// a subsequent operation resumes correctly in the enclosing context.
766    #[inline]
767    pub fn array_continue(&mut self, end_byte: u8) -> Result<bool, Error> {
768        self.skip_whitespace();
769        match self.peek() {
770            Some(b) if b == end_byte => {
771                self.bump();
772                let frame = if end_byte == b']' {
773                    Frame::Array
774                } else {
775                    Frame::Object
776                };
777                self.pop_frame(frame)?;
778                Ok(true)
779            }
780            Some(b',') => {
781                self.bump();
782                self.skip_whitespace();
783                Ok(false)
784            }
785            Some(b) => Err(self.err(ErrorKind::UnexpectedByte(b))),
786            None => Err(self.err(ErrorKind::UnexpectedEof)),
787        }
788    }
789
790    fn peek_object(&self) -> ObjectPeek {
791        match self.peek() {
792            Some(b'}') => ObjectPeek::Close,
793            Some(b'"') => ObjectPeek::Quote,
794            Some(b',') => ObjectPeek::Comma,
795            Some(_) | None => ObjectPeek::Other,
796        }
797    }
798
799    fn close_object(&mut self) -> Result<(), Error> {
800        self.bump();
801        self.pop_frame(Frame::Object)
802    }
803
804    fn expect_byte(&mut self, expected: u8) -> Result<(), Error> {
805        match self.peek() {
806            Some(b) if b == expected => { self.bump(); Ok(()) }
807            Some(b) => Err(self.err(ErrorKind::UnexpectedByte(b))),
808            None => Err(self.err(ErrorKind::UnexpectedEof)),
809        }
810    }
811
812    fn expect_colon(&mut self) -> Result<(), Error> {
813        self.skip_whitespace();
814        self.expect_byte(b':')?;
815        self.skip_whitespace();
816        Ok(())
817    }
818
819    fn advance_comma_to_quote(&mut self) -> Result<(), Error> {
820        self.bump();
821        self.skip_whitespace();
822        match self.peek_object() {
823            ObjectPeek::Quote => Ok(()),
824            _ => Err(self.unexpected_or_eof()),
825        }
826    }
827
828    /// After a `StartObject`, return the next key as a borrowed `&'input str`,
829    /// or `None` if the object closes immediately.
830    #[inline]
831    pub fn object_first_key(&mut self) -> Result<Option<&'input str>, Error> {
832        self.skip_whitespace();
833        match self.peek_object() {
834            ObjectPeek::Close => { self.close_object()?; Ok(None) }
835            ObjectPeek::Quote => {
836                let key = self.parse_str_value()?;
837                self.expect_colon()?;
838                Ok(Some(key))
839            }
840            ObjectPeek::Comma | ObjectPeek::Other => {
841                Err(self.unexpected_or_eof())
842            }
843        }
844    }
845
846    /// Like [`object_first_key`], but returns the key as a raw [`JsonStr`]
847    /// span.
848    ///
849    /// [`object_first_key`]: Self::object_first_key
850    #[inline]
851    pub fn object_first_key_lex(&mut self) -> Result<Option<JsonStr>, Error> {
852        self.skip_whitespace();
853        match self.peek_object() {
854            ObjectPeek::Close => { self.close_object()?; Ok(None) }
855            ObjectPeek::Quote => {
856                let key = self.read_string_no_validate()?;
857                self.expect_colon()?;
858                Ok(Some(key))
859            }
860            ObjectPeek::Comma | ObjectPeek::Other => {
861                Err(self.unexpected_or_eof())
862            }
863        }
864    }
865
866    /// After a field's value, advance to the next key or close the object.
867    #[inline]
868    pub fn object_next_key(&mut self) -> Result<Option<&'input str>, Error> {
869        self.skip_whitespace();
870        match self.peek_object() {
871            ObjectPeek::Close => { self.close_object()?; Ok(None) }
872            ObjectPeek::Comma => {
873                self.advance_comma_to_quote()?;
874                let key = self.parse_str_value()?;
875                self.expect_colon()?;
876                Ok(Some(key))
877            }
878            ObjectPeek::Quote | ObjectPeek::Other => {
879                Err(self.unexpected_or_eof())
880            }
881        }
882    }
883
884    /// Like [`object_next_key`], but returns the key as a raw [`JsonStr`]
885    /// span.
886    ///
887    /// [`object_next_key`]: Self::object_next_key
888    #[inline]
889    pub fn object_next_key_lex(&mut self) -> Result<Option<JsonStr>, Error> {
890        self.skip_whitespace();
891        match self.peek_object() {
892            ObjectPeek::Close => { self.close_object()?; Ok(None) }
893            ObjectPeek::Comma => {
894                self.advance_comma_to_quote()?;
895                let key = self.read_string_no_validate()?;
896                self.expect_colon()?;
897                Ok(Some(key))
898            }
899            ObjectPeek::Quote | ObjectPeek::Other => {
900                Err(self.unexpected_or_eof())
901            }
902        }
903    }
904
905    fn unexpected_or_eof(&self) -> Error {
906        self.peek().map_or_else(
907            || self.err(ErrorKind::UnexpectedEof),
908            |b| self.err(ErrorKind::UnexpectedByte(b)),
909        )
910    }
911
912    /// Expect the byte that opens an array (`[`), advance past it, push a
913    /// nesting frame, and skip whitespace to the first element (or `]`).
914    /// Returns `true` if the array is empty (the closing `]` has just been
915    /// consumed and the frame has been popped).
916    #[inline]
917    pub fn array_start(&mut self) -> Result<bool, Error> {
918        self.skip_whitespace();
919        match self.peek() {
920            Some(b'[') => {
921                self.bump();
922                self.push_frame(Frame::Array)?;
923                self.skip_whitespace();
924                if self.peek() == Some(b']') {
925                    self.bump();
926                    self.pop_frame(Frame::Array)?;
927                    Ok(true)
928                } else {
929                    Ok(false)
930                }
931            }
932            Some(b) => Err(self.err(ErrorKind::UnexpectedByte(b))),
933            None => Err(self.err(ErrorKind::UnexpectedEof)),
934        }
935    }
936
937    /// Expect the byte that opens an object (`{`), advance past it, push a
938    /// nesting frame, and skip whitespace. Does not consume any keys.
939    #[inline]
940    pub fn object_start(&mut self) -> Result<(), Error> {
941        self.skip_whitespace();
942        match self.peek() {
943            Some(b'{') => {
944                self.bump();
945                self.push_frame(Frame::Object)?;
946                self.skip_whitespace();
947                Ok(())
948            }
949            Some(b) => Err(self.err(ErrorKind::UnexpectedByte(b))),
950            None => Err(self.err(ErrorKind::UnexpectedEof)),
951        }
952    }
953
954    /// Require that no further (non-whitespace) data follows. Used by
955    /// the typed entry point to reject `"1 2"` and similar.
956    pub fn finish(&mut self) -> Result<(), Error> {
957        self.skip_whitespace();
958        if self.peek().is_some() {
959            Err(self.err(ErrorKind::TrailingData))
960        } else {
961            Ok(())
962        }
963    }
964
965    /// Consume one complete JSON value and discard it.
966    ///
967    /// Walks whatever value sits at the cursor — primitive, string,
968    /// number, array, or object — and advances past it. For composite
969    /// values, every nested element is also skipped. The structural
970    /// frame stack stays balanced: this method pushes and pops the
971    /// same frames `read_value` would.
972    ///
973    /// Validation is the same as `read_value`: malformed input
974    /// (control char in string, lone surrogate, malformed number,
975    /// etc.) still raises an `Error`. The "skip" here means "throw
976    /// away the value", not "throw away the parse". A lenient
977    /// `deny_unknown_fields = false` consumer wants the cursor
978    /// advanced, but it still wants the surrounding object to
979    /// parse correctly afterward — which requires lexing the skipped
980    /// value to find its end.
981    ///
982    /// Used by `#[derive(FromJson)]` when a struct opts into
983    /// `#[bourne(deny_unknown_fields = false)]` to consume the value
984    /// associated with an unrecognized key.
985    pub fn skip_value(&mut self) -> Result<(), Error> {
986        let event = self.read_value()?;
987        match event {
988            Event::StartArray => self.skip_array_body(),
989            Event::StartObject => self.skip_object_body(),
990            // Primitives consumed inline by `read_value`; nothing to
991            // do but return.
992            Event::String(_) | Event::Number(_) | Event::Bool(_) | Event::Null => Ok(()),
993            // `read_value` only returns Start*/scalar events. The
994            // End*/Key variants are produced by the streaming
995            // Parser, not the bare lexer, so they cannot appear
996            // here. Match exhaustively anyway so a future Event
997            // variant is a compile error rather than a silent skip.
998            Event::EndArray | Event::EndObject | Event::Key(_) => {
999                Err(self.err(ErrorKind::UnexpectedByte(b']')))
1000            }
1001        }
1002    }
1003
1004    /// Drive `array_continue` until the matching `]` closes the frame.
1005    /// `read_value` already consumed the opening `[` and pushed the
1006    /// frame; this finishes the job. Used only from `skip_value`.
1007    fn skip_array_body(&mut self) -> Result<(), Error> {
1008        // Empty array: `]` follows immediately, with the frame already
1009        // pushed by read_value. We need to consume `]` and pop. The
1010        // shared logic lives in array_continue, so peek and dispatch.
1011        self.skip_whitespace();
1012        if matches!(self.peek(), Some(b']')) {
1013            self.bump();
1014            return self.pop_frame(Frame::Array);
1015        }
1016        // Non-empty: at least one element, then either `,` (continue)
1017        // or `]` (done).
1018        self.skip_value()?;
1019        while !self.array_continue(b']')? {
1020            self.skip_value()?;
1021        }
1022        Ok(())
1023    }
1024
1025    /// Drive `object_first_key` / `object_next_key` until the matching
1026    /// `}` closes the frame. The keys themselves are consumed (we
1027    /// don't need them); only the values need explicit skipping.
1028    fn skip_object_body(&mut self) -> Result<(), Error> {
1029        let mut key = self.object_first_key()?;
1030        while key.is_some() {
1031            self.skip_value()?;
1032            key = self.object_next_key()?;
1033        }
1034        Ok(())
1035    }
1036
1037    // -------------------------------------------------------------------
1038    // byte-level helpers
1039    // -------------------------------------------------------------------
1040
1041    #[inline]
1042    fn scan_ascii_string_run(&mut self) {
1043        // x86_64 ABI guarantees SSE2 — no runtime detection needed.
1044        // The `bourne_no_simd` cfg disables the SIMD path; used by miri
1045        // (which doesn't model SSE2 intrinsics) and by curious users.
1046        #[cfg(all(target_arch = "x86_64", not(bourne_no_simd)))]
1047        // SAFETY: SSE2 is part of the x86_64 ABI baseline. Every x86_64
1048        // CPU has it; rustc's default target features include `+sse2`.
1049        // The intrinsics are `unsafe` by signature, not because we're
1050        // doing anything memory-unsafe — `_mm_loadu_si128` accepts
1051        // unaligned pointers and we walk only valid input bytes.
1052        unsafe {
1053            self.scan_ascii_string_run_sse2();
1054        }
1055        #[cfg(not(all(target_arch = "x86_64", not(bourne_no_simd))))]
1056        self.scan_ascii_string_run_scalar();
1057    }
1058
1059    /// Scalar fallback for the ASCII string scan. Used on non-x86_64 targets
1060    /// and as the inner loop's tail when fewer than 16 bytes remain.
1061    #[inline]
1062    fn scan_ascii_string_run_scalar(&mut self) {
1063        let bytes = self.input;
1064        let mut i = self.offset;
1065        let end = bytes.len();
1066        while i < end {
1067            let b = bytes[i];
1068            if b == b'"' || b == b'\\' || !(0x20..0x80).contains(&b) {
1069                break;
1070            }
1071            i += 1;
1072        }
1073        self.offset = i;
1074    }
1075
1076    /// SSE2-accelerated ASCII string scan. Walks 16 bytes at a time looking
1077    /// for the first "stop byte" (`"`, `\`, control char <0x20, or high-bit
1078    /// byte ≥0x80) and advances `self.offset` to it.
1079    ///
1080    /// Algorithm: load 16 bytes, build a 16-bit bitmask where bit `k` is set
1081    /// iff `bytes[i+k]` is a stop byte. If any bit is set, advance by the
1082    /// trailing-zero count to land on the first stop byte. Otherwise advance
1083    /// by 16 and continue.
1084    ///
1085    /// The "control or high-bit" test is fused into a single `cmplt_epi8`:
1086    /// reading bytes as `i8`, both `<0x20` (e.g. `0x05` = 5) and `≥0x80`
1087    /// (e.g. `0xC3` = -61) compare-less-than the constant 0x20. So one
1088    /// signed-compare instruction covers both stop categories.
1089    ///
1090    /// # Safety
1091    ///
1092    /// Only the SSE2 target feature is required. On `x86_64` it's part of the
1093    /// ABI baseline; the cfg gate at the call site enforces this.
1094    #[cfg(all(target_arch = "x86_64", not(bourne_no_simd)))]
1095    #[target_feature(enable = "sse2")]
1096    #[allow(clippy::cast_possible_wrap, clippy::cast_sign_loss)]
1097    unsafe fn scan_ascii_string_run_sse2(&mut self) {
1098        use core::arch::x86_64::{
1099            _mm_cmpeq_epi8, _mm_cmplt_epi8, _mm_loadu_si128, _mm_movemask_epi8, _mm_or_si128,
1100            _mm_set1_epi8,
1101        };
1102
1103        let bytes = self.input;
1104        let end = bytes.len();
1105        let mut i = self.offset;
1106
1107        // Splat constants. The `as i8` casts wrap by design — SSE2 byte
1108        // compares are always signed at the silicon level; we want the bit
1109        // patterns for `"`, `\`, and 0x20 regardless of sign interpretation.
1110        let quote = _mm_set1_epi8(b'"' as i8);
1111        let backslash = _mm_set1_epi8(b'\\' as i8);
1112        // `cmplt_epi8(b, 0x20)` flags both `b<0x20` (controls) AND `b>=0x80`
1113        // (high-bit bytes interpreted as negative i8). One compare, two stops.
1114        let lt_threshold = _mm_set1_epi8(0x20_i8);
1115
1116        while i + 16 <= end {
1117            // SAFETY: `i + 16 <= end` checked above; the pointer + 16 bytes
1118            // lie inside `bytes`. `_mm_loadu_si128` accepts unaligned addresses.
1119            let chunk = unsafe { _mm_loadu_si128(bytes.as_ptr().add(i).cast()) };
1120            let m_quote = _mm_cmpeq_epi8(chunk, quote);
1121            let m_back = _mm_cmpeq_epi8(chunk, backslash);
1122            let m_ctrl_or_hi = _mm_cmplt_epi8(chunk, lt_threshold);
1123            let mask = _mm_or_si128(_mm_or_si128(m_quote, m_back), m_ctrl_or_hi);
1124            // movemask returns i32 in [0, 0xFFFF]; cast to u32 is lossless.
1125            let bits = _mm_movemask_epi8(mask) as u32;
1126            if bits != 0 {
1127                i += bits.trailing_zeros() as usize;
1128                self.offset = i;
1129                return;
1130            }
1131            i += 16;
1132        }
1133
1134        // Tail: scalar walk for the final <16 bytes.
1135        self.offset = i;
1136        self.scan_ascii_string_run_scalar();
1137    }
1138
1139    #[inline]
1140    fn consume_utf8_multibyte(&mut self) -> Result<(), Error> {
1141        let leading = self
1142            .peek()
1143            .ok_or_else(|| self.err(ErrorKind::InvalidUtf8))?;
1144
1145        let (extra, second_lo, second_hi) =
1146            utf8_leading_byte_info(leading).ok_or_else(|| self.err(ErrorKind::InvalidUtf8))?;
1147        self.bump();
1148
1149        match self.peek() {
1150            Some(b) if b >= second_lo && b <= second_hi => self.bump(),
1151            _ => return Err(self.err(ErrorKind::InvalidUtf8)),
1152        }
1153        for _ in 1..extra {
1154            match self.peek() {
1155                Some(0x80..=0xBF) => self.bump(),
1156                _ => return Err(self.err(ErrorKind::InvalidUtf8)),
1157            }
1158        }
1159        Ok(())
1160    }
1161
1162    fn scan_digit_run(&mut self) {
1163        let bytes = self.input;
1164        let mut i = self.offset;
1165        let end = bytes.len();
1166        while i < end {
1167            let b = bytes[i];
1168            if b.wrapping_sub(b'0') >= 10 {
1169                break;
1170            }
1171            i += 1;
1172        }
1173        self.offset = i;
1174    }
1175
1176    pub(crate) fn skip_whitespace(&mut self) {
1177        let bytes = self.input;
1178        let mut i = self.offset;
1179        let end = bytes.len();
1180        while i < end {
1181            let b = bytes[i];
1182            if b == b' ' || b == b'\t' || b == b'\n' || b == b'\r' {
1183                i += 1;
1184            } else {
1185                break;
1186            }
1187        }
1188        self.offset = i;
1189    }
1190
1191    pub(crate) fn peek(&self) -> Option<u8> {
1192        self.input.get(self.offset).copied()
1193    }
1194
1195    pub(crate) fn bump(&mut self) {
1196        debug_assert!(self.offset < self.input.len());
1197        self.offset += 1;
1198    }
1199
1200    pub(crate) const fn err(&self, kind: ErrorKind) -> Error {
1201        Error::new(kind, compute_position(self.input, self.offset))
1202    }
1203}
1204
1205#[allow(clippy::cast_possible_truncation)]
1206const fn compute_position(_input: &[u8], offset: usize) -> Position {
1207    Position::new(offset as u32)
1208}
1209
1210/// Decode a UTF-8 leading byte into `(extra, lo, hi)` for the second byte.
1211/// Returns `None` for bytes that aren't valid UTF-8 sequence starters.
1212#[inline]
1213const fn utf8_leading_byte_info(b: u8) -> Option<(u8, u8, u8)> {
1214    match b {
1215        0xC2..=0xDF => Some((1, 0x80, 0xBF)),
1216        0xE0 => Some((2, 0xA0, 0xBF)),
1217        0xE1..=0xEC | 0xEE..=0xEF => Some((2, 0x80, 0xBF)),
1218        0xED => Some((2, 0x80, 0x9F)),
1219        0xF0 => Some((3, 0x90, 0xBF)),
1220        0xF1..=0xF3 => Some((3, 0x80, 0xBF)),
1221        0xF4 => Some((3, 0x80, 0x8F)),
1222        _ => None,
1223    }
1224}
1225
1226fn validate_escapes(raw: &[u8]) -> Result<(), ErrorKind> {
1227    let mut i = 0;
1228    while i < raw.len() {
1229        let b = raw[i];
1230        if b == b'\\' {
1231            i += 1;
1232            if i >= raw.len() {
1233                return Err(ErrorKind::InvalidEscape);
1234            }
1235            match raw[i] {
1236                b'"' | b'\\' | b'/' | b'b' | b'f' | b'n' | b'r' | b't' => i += 1,
1237                b'u' => {
1238                    if i + 5 > raw.len() {
1239                        return Err(ErrorKind::InvalidUnicodeEscape);
1240                    }
1241                    let cp = parse_hex4(&raw[i + 1..i + 5])?;
1242                    i += 5;
1243                    if (0xD800..=0xDBFF).contains(&cp) {
1244                        if i + 6 > raw.len() || raw[i] != b'\\' || raw[i + 1] != b'u' {
1245                            return Err(ErrorKind::UnpairedSurrogate);
1246                        }
1247                        let low = parse_hex4(&raw[i + 2..i + 6])?;
1248                        if !(0xDC00..=0xDFFF).contains(&low) {
1249                            return Err(ErrorKind::UnpairedSurrogate);
1250                        }
1251                        i += 6;
1252                    } else if (0xDC00..=0xDFFF).contains(&cp) {
1253                        return Err(ErrorKind::UnpairedSurrogate);
1254                    }
1255                }
1256                _ => return Err(ErrorKind::InvalidEscape),
1257            }
1258        } else if b < 0x20 {
1259            return Err(ErrorKind::ControlCharInString);
1260        } else {
1261            i += 1;
1262        }
1263    }
1264    Ok(())
1265}
1266
1267fn parse_hex4(bytes: &[u8]) -> Result<u32, ErrorKind> {
1268    let mut v: u32 = 0;
1269    for &b in bytes {
1270        let d = match b {
1271            b'0'..=b'9' => b - b'0',
1272            b'a'..=b'f' => b - b'a' + 10,
1273            b'A'..=b'F' => b - b'A' + 10,
1274            _ => return Err(ErrorKind::InvalidUnicodeEscape),
1275        };
1276        v = (v << 4) | u32::from(d);
1277    }
1278    Ok(v)
1279}