Coverage Report

Created: 2026-10-17 07:10

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/json/src/read.rs
Line
Count
Source
1
use crate::error::{Error, ErrorCode, Result};
2
use alloc::vec::Vec;
3
use core::cmp;
4
use core::mem;
5
use core::ops::Deref;
6
use core::str;
7
8
#[cfg(feature = "std")]
9
use crate::io;
10
#[cfg(feature = "std")]
11
use crate::iter::LineColIterator;
12
13
#[cfg(feature = "raw_value")]
14
use crate::raw::BorrowedRawDeserializer;
15
#[cfg(all(feature = "raw_value", feature = "std"))]
16
use crate::raw::OwnedRawDeserializer;
17
#[cfg(all(feature = "raw_value", feature = "std"))]
18
use alloc::string::String;
19
#[cfg(feature = "raw_value")]
20
use serde::de::Visitor;
21
22
/// Trait used by the deserializer for iterating over input. This is manually
23
/// "specialized" for iterating over `&[u8]`. Once feature(specialization) is
24
/// stable we can use actual specialization.
25
///
26
/// This trait is sealed and cannot be implemented for types outside of
27
/// `serde_json`.
28
pub trait Read<'de>: private::Sealed {
29
    #[doc(hidden)]
30
    fn next(&mut self) -> Result<Option<u8>>;
31
    #[doc(hidden)]
32
    fn peek(&mut self) -> Result<Option<u8>>;
33
34
    /// Only valid after a call to peek(). Discards the peeked byte.
35
    #[doc(hidden)]
36
    fn discard(&mut self);
37
38
    /// Position of the most recent call to next().
39
    ///
40
    /// The most recent call was probably next() and not peek(), but this method
41
    /// should try to return a sensible result if the most recent call was
42
    /// actually peek() because we don't always know.
43
    ///
44
    /// Only called in case of an error, so performance is not important.
45
    #[doc(hidden)]
46
    fn position(&self) -> Position;
47
48
    /// Position of the most recent call to peek().
49
    ///
50
    /// The most recent call was probably peek() and not next(), but this method
51
    /// should try to return a sensible result if the most recent call was
52
    /// actually next() because we don't always know.
53
    ///
54
    /// Only called in case of an error, so performance is not important.
55
    #[doc(hidden)]
56
    fn peek_position(&self) -> Position;
57
58
    /// Offset from the beginning of the input to the next byte that would be
59
    /// returned by next() or peek().
60
    #[doc(hidden)]
61
    fn byte_offset(&self) -> usize;
62
63
    /// Assumes the previous byte was a quotation mark. Parses a JSON-escaped
64
    /// string until the next quotation mark using the given scratch space if
65
    /// necessary. The scratch space is initially empty.
66
    #[doc(hidden)]
67
    fn parse_str<'s>(&'s mut self, scratch: &'s mut Vec<u8>) -> Result<Reference<'de, 's, str>>;
68
69
    /// Assumes the previous byte was a quotation mark. Parses a JSON-escaped
70
    /// string until the next quotation mark using the given scratch space if
71
    /// necessary. The scratch space is initially empty.
72
    ///
73
    /// This function returns the raw bytes in the string with escape sequences
74
    /// expanded but without performing unicode validation.
75
    #[doc(hidden)]
76
    fn parse_str_raw<'s>(
77
        &'s mut self,
78
        scratch: &'s mut Vec<u8>,
79
    ) -> Result<Reference<'de, 's, [u8]>>;
80
81
    /// Assumes the previous byte was a quotation mark. Parses a JSON-escaped
82
    /// string until the next quotation mark but discards the data.
83
    #[doc(hidden)]
84
    fn ignore_str(&mut self) -> Result<()>;
85
86
    /// Assumes the previous byte was a hex escape sequence ('\u') in a string.
87
    /// Parses next hexadecimal sequence.
88
    #[doc(hidden)]
89
    fn decode_hex_escape(&mut self) -> Result<u16>;
90
91
    /// Switch raw buffering mode on.
92
    ///
93
    /// This is used when deserializing `RawValue`.
94
    #[cfg(feature = "raw_value")]
95
    #[doc(hidden)]
96
    fn begin_raw_buffering(&mut self);
97
98
    /// Switch raw buffering mode off and provides the raw buffered data to the
99
    /// given visitor.
100
    #[cfg(feature = "raw_value")]
101
    #[doc(hidden)]
102
    fn end_raw_buffering<V>(&mut self, visitor: V) -> Result<V::Value>
103
    where
104
        V: Visitor<'de>;
105
106
    /// Whether StreamDeserializer::next needs to check the failed flag. True
107
    /// for IoRead, false for StrRead and SliceRead which can track failure by
108
    /// truncating their input slice to avoid the extra check on every next
109
    /// call.
110
    #[doc(hidden)]
111
    const should_early_return_if_failed: bool;
112
113
    /// Mark a persistent failure of StreamDeserializer, either by setting the
114
    /// flag or by truncating the input data.
115
    #[doc(hidden)]
116
    fn set_failed(&mut self, failed: &mut bool);
117
}
118
119
pub struct Position {
120
    pub line: usize,
121
    pub column: usize,
122
}
123
124
pub enum Reference<'b, 'c, T>
125
where
126
    T: ?Sized + 'static,
127
{
128
    Borrowed(&'b T),
129
    Copied(&'c T),
130
}
131
132
impl<'b, 'c, T> Deref for Reference<'b, 'c, T>
133
where
134
    T: ?Sized + 'static,
135
{
136
    type Target = T;
137
138
0
    fn deref(&self) -> &Self::Target {
139
0
        match *self {
140
0
            Reference::Borrowed(b) => b,
141
0
            Reference::Copied(c) => c,
142
        }
143
0
    }
144
}
145
146
/// JSON input source that reads from a std::io input stream.
147
#[cfg(feature = "std")]
148
#[cfg_attr(docsrs, doc(cfg(feature = "std")))]
149
pub struct IoRead<R>
150
where
151
    R: io::Read,
152
{
153
    iter: LineColIterator<io::Bytes<R>>,
154
    /// Temporary storage of peeked byte.
155
    ch: Option<u8>,
156
    #[cfg(feature = "raw_value")]
157
    raw_buffer: Option<Vec<u8>>,
158
    #[cfg(feature = "raw_value")]
159
    raw_buffering_start_position: Position,
160
}
161
162
/// JSON input source that reads from a slice of bytes.
163
//
164
// This is more efficient than other iterators because peek() can be read-only
165
// and we can compute line/col position only if an error happens.
166
pub struct SliceRead<'a> {
167
    slice: &'a [u8],
168
    /// Index of the *next* byte that will be returned by next() or peek().
169
    index: usize,
170
    #[cfg(feature = "raw_value")]
171
    raw_buffering_start_index: usize,
172
}
173
174
/// JSON input source that reads from a UTF-8 string.
175
//
176
// Able to elide UTF-8 checks by assuming that the input is valid UTF-8.
177
pub struct StrRead<'a> {
178
    delegate: SliceRead<'a>,
179
    #[cfg(feature = "raw_value")]
180
    data: &'a str,
181
}
182
183
// Prevent users from implementing the Read trait.
184
mod private {
185
    pub trait Sealed {}
186
}
187
188
//////////////////////////////////////////////////////////////////////////////
189
190
#[cfg(feature = "std")]
191
impl<R> IoRead<R>
192
where
193
    R: io::Read,
194
{
195
    /// Create a JSON input source to read from a std::io input stream.
196
    ///
197
    /// When reading from a source against which short reads are not efficient, such
198
    /// as a [`File`], you will want to apply your own buffering because serde_json
199
    /// will not buffer the input. See [`std::io::BufReader`].
200
    ///
201
    /// [`File`]: std::fs::File
202
    pub fn new(reader: R) -> Self {
203
        IoRead {
204
            iter: LineColIterator::new(reader.bytes()),
205
            ch: None,
206
            #[cfg(feature = "raw_value")]
207
            raw_buffer: None,
208
            #[cfg(feature = "raw_value")]
209
            raw_buffering_start_position: Position { line: 1, column: 0 },
210
        }
211
    }
212
}
213
214
#[cfg(feature = "std")]
215
impl<R> private::Sealed for IoRead<R> where R: io::Read {}
216
217
#[cfg(feature = "std")]
218
impl<R> IoRead<R>
219
where
220
    R: io::Read,
221
{
222
    fn parse_str_bytes<'s, T, F>(
223
        &'s mut self,
224
        scratch: &'s mut Vec<u8>,
225
        validate: bool,
226
        result: F,
227
    ) -> Result<T>
228
    where
229
        T: 's,
230
        F: FnOnce(&'s Self, &'s [u8]) -> Result<T>,
231
    {
232
        loop {
233
            let ch = tri!(next_or_eof(self));
234
            if !is_escape(ch, true) {
235
                scratch.push(ch);
236
                continue;
237
            }
238
            match ch {
239
                b'"' => {
240
                    return result(self, scratch);
241
                }
242
                b'\\' => {
243
                    tri!(parse_escape(self, validate, scratch));
244
                }
245
                _ => {
246
                    if validate {
247
                        return error(self, ErrorCode::ControlCharacterWhileParsingString);
248
                    }
249
                    scratch.push(ch);
250
                }
251
            }
252
        }
253
    }
254
}
255
256
#[cfg(feature = "std")]
257
impl<'de, R> Read<'de> for IoRead<R>
258
where
259
    R: io::Read,
260
{
261
    #[inline]
262
    fn next(&mut self) -> Result<Option<u8>> {
263
        match self.ch.take() {
264
            Some(ch) => {
265
                #[cfg(feature = "raw_value")]
266
                {
267
                    if let Some(buf) = &mut self.raw_buffer {
268
                        buf.push(ch);
269
                    }
270
                }
271
                Ok(Some(ch))
272
            }
273
            None => match self.iter.next() {
274
                Some(Err(err)) => Err(Error::io(err)),
275
                Some(Ok(ch)) => {
276
                    #[cfg(feature = "raw_value")]
277
                    {
278
                        if let Some(buf) = &mut self.raw_buffer {
279
                            buf.push(ch);
280
                        }
281
                    }
282
                    Ok(Some(ch))
283
                }
284
                None => Ok(None),
285
            },
286
        }
287
    }
288
289
    #[inline]
290
    fn peek(&mut self) -> Result<Option<u8>> {
291
        match self.ch {
292
            Some(ch) => Ok(Some(ch)),
293
            None => match self.iter.next() {
294
                Some(Err(err)) => Err(Error::io(err)),
295
                Some(Ok(ch)) => {
296
                    self.ch = Some(ch);
297
                    Ok(self.ch)
298
                }
299
                None => Ok(None),
300
            },
301
        }
302
    }
303
304
    #[cfg(not(feature = "raw_value"))]
305
    #[inline]
306
    fn discard(&mut self) {
307
        self.ch = None;
308
    }
309
310
    #[cfg(feature = "raw_value")]
311
    fn discard(&mut self) {
312
        if let Some(ch) = self.ch.take() {
313
            if let Some(buf) = &mut self.raw_buffer {
314
                buf.push(ch);
315
            }
316
        }
317
    }
318
319
    fn position(&self) -> Position {
320
        Position {
321
            line: self.iter.line(),
322
            column: self.iter.col(),
323
        }
324
    }
325
326
    fn peek_position(&self) -> Position {
327
        // The LineColIterator updates its position during peek() so it has the
328
        // right one here.
329
        self.position()
330
    }
331
332
    fn byte_offset(&self) -> usize {
333
        match self.ch {
334
            Some(_) => self.iter.byte_offset() - 1,
335
            None => self.iter.byte_offset(),
336
        }
337
    }
338
339
    fn parse_str<'s>(&'s mut self, scratch: &'s mut Vec<u8>) -> Result<Reference<'de, 's, str>> {
340
        self.parse_str_bytes(scratch, true, as_str)
341
            .map(Reference::Copied)
342
    }
343
344
    fn parse_str_raw<'s>(
345
        &'s mut self,
346
        scratch: &'s mut Vec<u8>,
347
    ) -> Result<Reference<'de, 's, [u8]>> {
348
        self.parse_str_bytes(scratch, false, |_, bytes| Ok(bytes))
349
            .map(Reference::Copied)
350
    }
351
352
    fn ignore_str(&mut self) -> Result<()> {
353
        loop {
354
            let ch = tri!(next_or_eof(self));
355
            if !is_escape(ch, true) {
356
                continue;
357
            }
358
            match ch {
359
                b'"' => {
360
                    return Ok(());
361
                }
362
                b'\\' => {
363
                    tri!(ignore_escape(self));
364
                }
365
                _ => {
366
                    return error(self, ErrorCode::ControlCharacterWhileParsingString);
367
                }
368
            }
369
        }
370
    }
371
372
    fn decode_hex_escape(&mut self) -> Result<u16> {
373
        let a = tri!(next_or_eof(self));
374
        let b = tri!(next_or_eof(self));
375
        let c = tri!(next_or_eof(self));
376
        let d = tri!(next_or_eof(self));
377
        match decode_four_hex_digits(a, b, c, d) {
378
            Some(val) => Ok(val),
379
            None => error(self, ErrorCode::InvalidEscape),
380
        }
381
    }
382
383
    #[cfg(feature = "raw_value")]
384
    fn begin_raw_buffering(&mut self) {
385
        let position = self.position();
386
        self.raw_buffering_start_position = Position {
387
            line: position.line,
388
            column: position.column - usize::from(self.ch.is_some()),
389
        };
390
        self.raw_buffer = Some(Vec::new());
391
    }
392
393
    #[cfg(feature = "raw_value")]
394
    fn end_raw_buffering<V>(&mut self, visitor: V) -> Result<V::Value>
395
    where
396
        V: Visitor<'de>,
397
    {
398
        let raw = self.raw_buffer.take().unwrap();
399
        let raw = match String::from_utf8(raw) {
400
            Ok(raw) => raw,
401
            Err(err) => {
402
                let prefix = &err.as_bytes()[..=err.utf8_error().valid_up_to()];
403
                let line;
404
                let column;
405
                if let Some(last_newline) = memchr::memrchr(b'\n', prefix) {
406
                    line = self.raw_buffering_start_position.line
407
                        + memchr::memchr_iter(b'\n', &prefix[..last_newline]).count()
408
                        + 1;
409
                    column = prefix.len() - last_newline - 1;
410
                } else {
411
                    line = self.raw_buffering_start_position.line;
412
                    column = self.raw_buffering_start_position.column + prefix.len();
413
                }
414
                return Err(Error::syntax(
415
                    ErrorCode::InvalidUnicodeCodePoint,
416
                    line,
417
                    column,
418
                ));
419
            }
420
        };
421
        visitor.visit_map(OwnedRawDeserializer {
422
            raw_value: Some(raw),
423
        })
424
    }
425
426
    const should_early_return_if_failed: bool = true;
427
428
    #[inline]
429
    #[cold]
430
    fn set_failed(&mut self, failed: &mut bool) {
431
        *failed = true;
432
    }
433
}
434
435
//////////////////////////////////////////////////////////////////////////////
436
437
impl<'a> SliceRead<'a> {
438
    /// Create a JSON input source to read from a slice of bytes.
439
6.13k
    pub fn new(slice: &'a [u8]) -> Self {
440
6.13k
        SliceRead {
441
6.13k
            slice,
442
6.13k
            index: 0,
443
6.13k
            #[cfg(feature = "raw_value")]
444
6.13k
            raw_buffering_start_index: 0,
445
6.13k
        }
446
6.13k
    }
447
448
35.0k
    fn position_of_index(&self, i: usize) -> Position {
449
35.0k
        let start_of_line = match memchr::memrchr(b'\n', &self.slice[..i]) {
450
22.9k
            Some(position) => position + 1,
451
12.1k
            None => 0,
452
        };
453
35.0k
        Position {
454
35.0k
            line: 1 + memchr::memchr_iter(b'\n', &self.slice[..start_of_line]).count(),
455
35.0k
            column: i - start_of_line,
456
35.0k
        }
457
35.0k
    }
458
459
728k
    fn skip_to_escape(&mut self, forbid_control_characters: bool) {
460
        // Immediately bail-out on empty strings and consecutive escapes (e.g. \u041b\u0435)
461
728k
        if self.index == self.slice.len()
462
728k
            || is_escape(self.slice[self.index], forbid_control_characters)
463
        {
464
189k
            return;
465
539k
        }
466
539k
        self.index += 1;
467
468
539k
        let rest = &self.slice[self.index..];
469
470
539k
        if !forbid_control_characters {
471
0
            self.index += memchr::memchr2(b'"', b'\\', rest).unwrap_or(rest.len());
472
0
            return;
473
539k
        }
474
475
        // We wish to find the first byte in range 0x00..=0x1F or " or \. Ideally, we'd use
476
        // something akin to memchr3, but the memchr crate does not support this at the moment.
477
        // Therefore, we use a variation on Mycroft's algorithm [1] to provide performance better
478
        // than a naive loop. It runs faster than equivalent two-pass memchr2+SWAR code on
479
        // benchmarks and it's cross-platform, so probably the right fit.
480
        // [1]: https://groups.google.com/forum/#!original/comp.lang.c/2HtQXvg7iKc/xOJeipH6KLMJ
481
482
        #[cfg(fast_arithmetic = "64")]
483
        type Chunk = u64;
484
        #[cfg(fast_arithmetic = "32")]
485
        type Chunk = u32;
486
487
        const STEP: usize = mem::size_of::<Chunk>();
488
        const ONE_BYTES: Chunk = Chunk::MAX / 255; // 0x0101...01
489
490
17.4M
        for chunk in rest.chunks_exact(STEP) {
491
17.4M
            let chars = Chunk::from_le_bytes(chunk.try_into().unwrap());
492
17.4M
            let contains_ctrl = chars.wrapping_sub(ONE_BYTES * 0x20) & !chars;
493
17.4M
            let chars_quote = chars ^ (ONE_BYTES * Chunk::from(b'"'));
494
17.4M
            let contains_quote = chars_quote.wrapping_sub(ONE_BYTES) & !chars_quote;
495
17.4M
            let chars_backslash = chars ^ (ONE_BYTES * Chunk::from(b'\\'));
496
17.4M
            let contains_backslash = chars_backslash.wrapping_sub(ONE_BYTES) & !chars_backslash;
497
17.4M
            let masked = (contains_ctrl | contains_quote | contains_backslash) & (ONE_BYTES << 7);
498
17.4M
            if masked != 0 {
499
                // SAFETY: chunk is in-bounds for slice
500
538k
                self.index = unsafe { chunk.as_ptr().offset_from(self.slice.as_ptr()) } as usize
501
538k
                    + masked.trailing_zeros() as usize / 8;
502
538k
                return;
503
16.9M
            }
504
        }
505
506
1.51k
        self.index += rest.len() / STEP * STEP;
507
1.51k
        self.skip_to_escape_slow();
508
728k
    }
509
510
    #[cold]
511
    #[inline(never)]
512
1.51k
    fn skip_to_escape_slow(&mut self) {
513
3.71k
        while self.index < self.slice.len() && !is_escape(self.slice[self.index], true) {
514
2.20k
            self.index += 1;
515
2.20k
        }
516
1.51k
    }
517
518
    /// The big optimization here over IoRead is that if the string contains no
519
    /// backslash escape sequences, the returned &str is a slice of the raw JSON
520
    /// data so we avoid copying into the scratch space.
521
410k
    fn parse_str_bytes<'s, T, F>(
522
410k
        &'s mut self,
523
410k
        scratch: &'s mut Vec<u8>,
524
410k
        validate: bool,
525
410k
        result: F,
526
410k
    ) -> Result<Reference<'a, 's, T>>
527
410k
    where
528
410k
        T: ?Sized + 's,
529
410k
        F: for<'f> FnOnce(&'s Self, &'f [u8]) -> Result<&'f T>,
530
    {
531
        // Index of the first byte not yet copied into the scratch space.
532
410k
        let mut start = self.index;
533
534
        loop {
535
728k
            self.skip_to_escape(validate);
536
728k
            if self.index == self.slice.len() {
537
921
                return error(self, ErrorCode::EofWhileParsingString);
538
728k
            }
539
728k
            match self.slice[self.index] {
540
                b'"' => {
541
408k
                    if scratch.is_empty() {
542
                        // Fast path: return a slice of the raw JSON without any
543
                        // copying.
544
381k
                        let borrowed = &self.slice[start..self.index];
545
381k
                        self.index += 1;
546
381k
                        return result(self, borrowed).map(Reference::Borrowed);
547
                    } else {
548
27.0k
                        scratch.extend_from_slice(&self.slice[start..self.index]);
549
27.0k
                        self.index += 1;
550
27.0k
                        return result(self, scratch).map(Reference::Copied);
551
                    }
552
                }
553
                b'\\' => {
554
319k
                    scratch.extend_from_slice(&self.slice[start..self.index]);
555
319k
                    self.index += 1;
556
319k
                    tri!(parse_escape(self, validate, scratch));
557
318k
                    start = self.index;
558
                }
559
                _ => {
560
253
                    self.index += 1;
561
253
                    return error(self, ErrorCode::ControlCharacterWhileParsingString);
562
                }
563
            }
564
        }
565
410k
    }
Unexecuted instantiation: <serde_json::read::SliceRead>::parse_str_bytes::<[u8], <serde_json::read::SliceRead as serde_json::read::Read>::parse_str_raw::{closure#0}>
<serde_json::read::SliceRead>::parse_str_bytes::<str, serde_json::read::as_str<serde_json::read::SliceRead>>
Line
Count
Source
521
410k
    fn parse_str_bytes<'s, T, F>(
522
410k
        &'s mut self,
523
410k
        scratch: &'s mut Vec<u8>,
524
410k
        validate: bool,
525
410k
        result: F,
526
410k
    ) -> Result<Reference<'a, 's, T>>
527
410k
    where
528
410k
        T: ?Sized + 's,
529
410k
        F: for<'f> FnOnce(&'s Self, &'f [u8]) -> Result<&'f T>,
530
    {
531
        // Index of the first byte not yet copied into the scratch space.
532
410k
        let mut start = self.index;
533
534
        loop {
535
728k
            self.skip_to_escape(validate);
536
728k
            if self.index == self.slice.len() {
537
921
                return error(self, ErrorCode::EofWhileParsingString);
538
728k
            }
539
728k
            match self.slice[self.index] {
540
                b'"' => {
541
408k
                    if scratch.is_empty() {
542
                        // Fast path: return a slice of the raw JSON without any
543
                        // copying.
544
381k
                        let borrowed = &self.slice[start..self.index];
545
381k
                        self.index += 1;
546
381k
                        return result(self, borrowed).map(Reference::Borrowed);
547
                    } else {
548
27.0k
                        scratch.extend_from_slice(&self.slice[start..self.index]);
549
27.0k
                        self.index += 1;
550
27.0k
                        return result(self, scratch).map(Reference::Copied);
551
                    }
552
                }
553
                b'\\' => {
554
319k
                    scratch.extend_from_slice(&self.slice[start..self.index]);
555
319k
                    self.index += 1;
556
319k
                    tri!(parse_escape(self, validate, scratch));
557
318k
                    start = self.index;
558
                }
559
                _ => {
560
253
                    self.index += 1;
561
253
                    return error(self, ErrorCode::ControlCharacterWhileParsingString);
562
                }
563
            }
564
        }
565
410k
    }
Unexecuted instantiation: <serde_json::read::SliceRead>::parse_str_bytes::<str, <serde_json::read::StrRead as serde_json::read::Read>::parse_str::{closure#0}>
566
}
567
568
impl<'a> private::Sealed for SliceRead<'a> {}
569
570
impl<'a> Read<'a> for SliceRead<'a> {
571
    #[inline]
572
2.21M
    fn next(&mut self) -> Result<Option<u8>> {
573
        // `Ok(self.slice.get(self.index).map(|ch| { self.index += 1; *ch }))`
574
        // is about 10% slower.
575
2.21M
        Ok(if self.index < self.slice.len() {
576
2.21M
            let ch = self.slice[self.index];
577
2.21M
            self.index += 1;
578
2.21M
            Some(ch)
579
        } else {
580
361
            None
581
        })
582
2.21M
    }
<serde_json::read::SliceRead as serde_json::read::Read>::next
Line
Count
Source
572
1.89M
    fn next(&mut self) -> Result<Option<u8>> {
573
        // `Ok(self.slice.get(self.index).map(|ch| { self.index += 1; *ch }))`
574
        // is about 10% slower.
575
1.89M
        Ok(if self.index < self.slice.len() {
576
1.89M
            let ch = self.slice[self.index];
577
1.89M
            self.index += 1;
578
1.89M
            Some(ch)
579
        } else {
580
169
            None
581
        })
582
1.89M
    }
<serde_json::read::SliceRead as serde_json::read::Read>::next
Line
Count
Source
572
319k
    fn next(&mut self) -> Result<Option<u8>> {
573
        // `Ok(self.slice.get(self.index).map(|ch| { self.index += 1; *ch }))`
574
        // is about 10% slower.
575
319k
        Ok(if self.index < self.slice.len() {
576
319k
            let ch = self.slice[self.index];
577
319k
            self.index += 1;
578
319k
            Some(ch)
579
        } else {
580
192
            None
581
        })
582
319k
    }
583
584
    #[inline]
585
29.5M
    fn peek(&mut self) -> Result<Option<u8>> {
586
        // `Ok(self.slice.get(self.index).map(|ch| *ch))` is about 10% slower
587
        // for some reason.
588
29.5M
        Ok(if self.index < self.slice.len() {
589
29.4M
            Some(self.slice[self.index])
590
        } else {
591
27.7k
            None
592
        })
593
29.5M
    }
<serde_json::read::SliceRead as serde_json::read::Read>::peek
Line
Count
Source
585
29.4M
    fn peek(&mut self) -> Result<Option<u8>> {
586
        // `Ok(self.slice.get(self.index).map(|ch| *ch))` is about 10% slower
587
        // for some reason.
588
29.4M
        Ok(if self.index < self.slice.len() {
589
29.4M
            Some(self.slice[self.index])
590
        } else {
591
27.7k
            None
592
        })
593
29.4M
    }
<serde_json::read::SliceRead as serde_json::read::Read>::peek
Line
Count
Source
585
40.8k
    fn peek(&mut self) -> Result<Option<u8>> {
586
        // `Ok(self.slice.get(self.index).map(|ch| *ch))` is about 10% slower
587
        // for some reason.
588
40.8k
        Ok(if self.index < self.slice.len() {
589
40.7k
            Some(self.slice[self.index])
590
        } else {
591
80
            None
592
        })
593
40.8k
    }
594
595
    #[inline]
596
23.1M
    fn discard(&mut self) {
597
23.1M
        self.index += 1;
598
23.1M
    }
<serde_json::read::SliceRead as serde_json::read::Read>::discard
Line
Count
Source
596
23.0M
    fn discard(&mut self) {
597
23.0M
        self.index += 1;
598
23.0M
    }
<serde_json::read::SliceRead as serde_json::read::Read>::discard
Line
Count
Source
596
40.7k
    fn discard(&mut self) {
597
40.7k
        self.index += 1;
598
40.7k
    }
599
600
2.90k
    fn position(&self) -> Position {
601
2.90k
        self.position_of_index(self.index)
602
2.90k
    }
603
604
32.1k
    fn peek_position(&self) -> Position {
605
        // Cap it at slice.len() just in case the most recent call was next()
606
        // and it returned the last byte.
607
32.1k
        self.position_of_index(cmp::min(self.slice.len(), self.index + 1))
608
32.1k
    }
609
610
0
    fn byte_offset(&self) -> usize {
611
0
        self.index
612
0
    }
613
614
410k
    fn parse_str<'s>(&'s mut self, scratch: &'s mut Vec<u8>) -> Result<Reference<'a, 's, str>> {
615
410k
        self.parse_str_bytes(scratch, true, as_str)
616
410k
    }
617
618
0
    fn parse_str_raw<'s>(
619
0
        &'s mut self,
620
0
        scratch: &'s mut Vec<u8>,
621
0
    ) -> Result<Reference<'a, 's, [u8]>> {
622
0
        self.parse_str_bytes(scratch, false, |_, bytes| Ok(bytes))
623
0
    }
624
625
0
    fn ignore_str(&mut self) -> Result<()> {
626
        loop {
627
0
            self.skip_to_escape(true);
628
0
            if self.index == self.slice.len() {
629
0
                return error(self, ErrorCode::EofWhileParsingString);
630
0
            }
631
0
            match self.slice[self.index] {
632
                b'"' => {
633
0
                    self.index += 1;
634
0
                    return Ok(());
635
                }
636
                b'\\' => {
637
0
                    self.index += 1;
638
0
                    tri!(ignore_escape(self));
639
                }
640
                _ => {
641
0
                    return error(self, ErrorCode::ControlCharacterWhileParsingString);
642
                }
643
            }
644
        }
645
0
    }
646
647
    #[inline]
648
76.5k
    fn decode_hex_escape(&mut self) -> Result<u16> {
649
76.5k
        match self.slice[self.index..] {
650
76.5k
            [a, b, c, d, ..] => {
651
76.5k
                self.index += 4;
652
76.5k
                match decode_four_hex_digits(a, b, c, d) {
653
76.4k
                    Some(val) => Ok(val),
654
74
                    None => error(self, ErrorCode::InvalidEscape),
655
                }
656
            }
657
            _ => {
658
86
                self.index = self.slice.len();
659
86
                error(self, ErrorCode::EofWhileParsingString)
660
            }
661
        }
662
76.5k
    }
663
664
    #[cfg(feature = "raw_value")]
665
    fn begin_raw_buffering(&mut self) {
666
        self.raw_buffering_start_index = self.index;
667
    }
668
669
    #[cfg(feature = "raw_value")]
670
    fn end_raw_buffering<V>(&mut self, visitor: V) -> Result<V::Value>
671
    where
672
        V: Visitor<'a>,
673
    {
674
        let raw = &self.slice[self.raw_buffering_start_index..self.index];
675
        let raw = match str::from_utf8(raw) {
676
            Ok(raw) => raw,
677
            Err(err) => {
678
                let at = self.raw_buffering_start_index + err.valid_up_to() + 1;
679
                let position = self.position_of_index(at);
680
                return Err(Error::syntax(
681
                    ErrorCode::InvalidUnicodeCodePoint,
682
                    position.line,
683
                    position.column,
684
                ));
685
            }
686
        };
687
        visitor.visit_map(BorrowedRawDeserializer {
688
            raw_value: Some(raw),
689
        })
690
    }
691
692
    const should_early_return_if_failed: bool = false;
693
694
    #[inline]
695
    #[cold]
696
    fn set_failed(&mut self, _failed: &mut bool) {
697
        self.slice = &self.slice[..self.index];
698
    }
699
}
700
701
//////////////////////////////////////////////////////////////////////////////
702
703
impl<'a> StrRead<'a> {
704
    /// Create a JSON input source to read from a UTF-8 string.
705
0
    pub fn new(s: &'a str) -> Self {
706
0
        StrRead {
707
0
            delegate: SliceRead::new(s.as_bytes()),
708
0
            #[cfg(feature = "raw_value")]
709
0
            data: s,
710
0
        }
711
0
    }
712
}
713
714
impl<'a> private::Sealed for StrRead<'a> {}
715
716
impl<'a> Read<'a> for StrRead<'a> {
717
    #[inline]
718
0
    fn next(&mut self) -> Result<Option<u8>> {
719
0
        self.delegate.next()
720
0
    }
721
722
    #[inline]
723
0
    fn peek(&mut self) -> Result<Option<u8>> {
724
0
        self.delegate.peek()
725
0
    }
726
727
    #[inline]
728
0
    fn discard(&mut self) {
729
0
        self.delegate.discard();
730
0
    }
731
732
0
    fn position(&self) -> Position {
733
0
        self.delegate.position()
734
0
    }
735
736
0
    fn peek_position(&self) -> Position {
737
0
        self.delegate.peek_position()
738
0
    }
739
740
0
    fn byte_offset(&self) -> usize {
741
0
        self.delegate.byte_offset()
742
0
    }
743
744
0
    fn parse_str<'s>(&'s mut self, scratch: &'s mut Vec<u8>) -> Result<Reference<'a, 's, str>> {
745
0
        self.delegate.parse_str_bytes(scratch, true, |_, bytes| {
746
            // The deserialization input came in as &str with a UTF-8 guarantee,
747
            // and the \u-escapes are checked along the way, so don't need to
748
            // check here.
749
0
            Ok(unsafe { str::from_utf8_unchecked(bytes) })
750
0
        })
751
0
    }
752
753
0
    fn parse_str_raw<'s>(
754
0
        &'s mut self,
755
0
        scratch: &'s mut Vec<u8>,
756
0
    ) -> Result<Reference<'a, 's, [u8]>> {
757
0
        self.delegate.parse_str_raw(scratch)
758
0
    }
759
760
0
    fn ignore_str(&mut self) -> Result<()> {
761
0
        self.delegate.ignore_str()
762
0
    }
763
764
0
    fn decode_hex_escape(&mut self) -> Result<u16> {
765
0
        self.delegate.decode_hex_escape()
766
0
    }
767
768
    #[cfg(feature = "raw_value")]
769
    fn begin_raw_buffering(&mut self) {
770
        self.delegate.begin_raw_buffering();
771
    }
772
773
    #[cfg(feature = "raw_value")]
774
    fn end_raw_buffering<V>(&mut self, visitor: V) -> Result<V::Value>
775
    where
776
        V: Visitor<'a>,
777
    {
778
        let raw = &self.data[self.delegate.raw_buffering_start_index..self.delegate.index];
779
        visitor.visit_map(BorrowedRawDeserializer {
780
            raw_value: Some(raw),
781
        })
782
    }
783
784
    const should_early_return_if_failed: bool = false;
785
786
    #[inline]
787
    #[cold]
788
    fn set_failed(&mut self, failed: &mut bool) {
789
        self.delegate.set_failed(failed);
790
    }
791
}
792
793
//////////////////////////////////////////////////////////////////////////////
794
795
impl<'de, R> private::Sealed for &mut R where R: Read<'de> {}
796
797
impl<'de, R> Read<'de> for &mut R
798
where
799
    R: Read<'de>,
800
{
801
    fn next(&mut self) -> Result<Option<u8>> {
802
        R::next(self)
803
    }
804
805
    fn peek(&mut self) -> Result<Option<u8>> {
806
        R::peek(self)
807
    }
808
809
    fn discard(&mut self) {
810
        R::discard(self);
811
    }
812
813
    fn position(&self) -> Position {
814
        R::position(self)
815
    }
816
817
    fn peek_position(&self) -> Position {
818
        R::peek_position(self)
819
    }
820
821
    fn byte_offset(&self) -> usize {
822
        R::byte_offset(self)
823
    }
824
825
    fn parse_str<'s>(&'s mut self, scratch: &'s mut Vec<u8>) -> Result<Reference<'de, 's, str>> {
826
        R::parse_str(self, scratch)
827
    }
828
829
    fn parse_str_raw<'s>(
830
        &'s mut self,
831
        scratch: &'s mut Vec<u8>,
832
    ) -> Result<Reference<'de, 's, [u8]>> {
833
        R::parse_str_raw(self, scratch)
834
    }
835
836
    fn ignore_str(&mut self) -> Result<()> {
837
        R::ignore_str(self)
838
    }
839
840
    fn decode_hex_escape(&mut self) -> Result<u16> {
841
        R::decode_hex_escape(self)
842
    }
843
844
    #[cfg(feature = "raw_value")]
845
    fn begin_raw_buffering(&mut self) {
846
        R::begin_raw_buffering(self);
847
    }
848
849
    #[cfg(feature = "raw_value")]
850
    fn end_raw_buffering<V>(&mut self, visitor: V) -> Result<V::Value>
851
    where
852
        V: Visitor<'de>,
853
    {
854
        R::end_raw_buffering(self, visitor)
855
    }
856
857
    const should_early_return_if_failed: bool = R::should_early_return_if_failed;
858
859
    fn set_failed(&mut self, failed: &mut bool) {
860
        R::set_failed(self, failed);
861
    }
862
}
863
864
//////////////////////////////////////////////////////////////////////////////
865
866
/// Marker for whether StreamDeserializer can implement FusedIterator.
867
pub trait Fused: private::Sealed {}
868
impl<'a> Fused for SliceRead<'a> {}
869
impl<'a> Fused for StrRead<'a> {}
870
871
731k
fn is_escape(ch: u8, including_control_characters: bool) -> bool {
872
731k
    ch == b'"' || ch == b'\\' || (including_control_characters && ch < 0x20)
873
731k
}
874
875
319k
fn next_or_eof<'de, R>(read: &mut R) -> Result<u8>
876
319k
where
877
319k
    R: ?Sized + Read<'de>,
878
{
879
319k
    match tri!(read.next()) {
880
319k
        Some(b) => Ok(b),
881
192
        None => error(read, ErrorCode::EofWhileParsingString),
882
    }
883
319k
}
884
885
40.8k
fn peek_or_eof<'de, R>(read: &mut R) -> Result<u8>
886
40.8k
where
887
40.8k
    R: ?Sized + Read<'de>,
888
{
889
40.8k
    match tri!(read.peek()) {
890
40.7k
        Some(b) => Ok(b),
891
80
        None => error(read, ErrorCode::EofWhileParsingString),
892
    }
893
40.8k
}
894
895
1.98k
fn error<'de, R, T>(read: &R, reason: ErrorCode) -> Result<T>
896
1.98k
where
897
1.98k
    R: ?Sized + Read<'de>,
898
{
899
1.98k
    let position = read.position();
900
1.98k
    Err(Error::syntax(reason, position.line, position.column))
901
1.98k
}
Unexecuted instantiation: serde_json::read::error::<serde_json::read::SliceRead, serde_json::read::Reference<[u8]>>
serde_json::read::error::<serde_json::read::SliceRead, serde_json::read::Reference<str>>
Line
Count
Source
895
1.17k
fn error<'de, R, T>(read: &R, reason: ErrorCode) -> Result<T>
896
1.17k
where
897
1.17k
    R: ?Sized + Read<'de>,
898
{
899
1.17k
    let position = read.position();
900
1.17k
    Err(Error::syntax(reason, position.line, position.column))
901
1.17k
}
serde_json::read::error::<serde_json::read::SliceRead, u8>
Line
Count
Source
895
272
fn error<'de, R, T>(read: &R, reason: ErrorCode) -> Result<T>
896
272
where
897
272
    R: ?Sized + Read<'de>,
898
{
899
272
    let position = read.position();
900
272
    Err(Error::syntax(reason, position.line, position.column))
901
272
}
serde_json::read::error::<serde_json::read::SliceRead, u16>
Line
Count
Source
895
160
fn error<'de, R, T>(read: &R, reason: ErrorCode) -> Result<T>
896
160
where
897
160
    R: ?Sized + Read<'de>,
898
{
899
160
    let position = read.position();
900
160
    Err(Error::syntax(reason, position.line, position.column))
901
160
}
serde_json::read::error::<serde_json::read::SliceRead, ()>
Line
Count
Source
895
383
fn error<'de, R, T>(read: &R, reason: ErrorCode) -> Result<T>
896
383
where
897
383
    R: ?Sized + Read<'de>,
898
{
899
383
    let position = read.position();
900
383
    Err(Error::syntax(reason, position.line, position.column))
901
383
}
902
903
408k
fn as_str<'de, 's, R: Read<'de>>(read: &R, slice: &'s [u8]) -> Result<&'s str> {
904
408k
    match str::from_utf8(slice) {
905
408k
        Ok(s) => Ok(s),
906
102
        Err(err) => {
907
            // Point at the first invalid UTF-8 byte. `read` is positioned at
908
            // the closing quote of the string whose content is `slice`. If the
909
            // JSON string contained escape sequences, the column position is
910
            // approximate.
911
102
            let position = read.position();
912
102
            Err(Error::syntax(
913
102
                ErrorCode::InvalidUnicodeCodePoint,
914
102
                position.line,
915
102
                position
916
102
                    .column
917
102
                    .saturating_sub(slice.len() - err.valid_up_to()),
918
102
            ))
919
        }
920
    }
921
408k
}
922
923
/// Parses a JSON escape sequence and appends it into the scratch space. Assumes
924
/// the previous byte read was a backslash.
925
319k
fn parse_escape<'de, R: Read<'de>>(
926
319k
    read: &mut R,
927
319k
    validate: bool,
928
319k
    scratch: &mut Vec<u8>,
929
319k
) -> Result<()> {
930
319k
    let ch = tri!(next_or_eof(read));
931
932
319k
    match ch {
933
7.83k
        b'"' => scratch.push(b'"'),
934
120k
        b'\\' => scratch.push(b'\\'),
935
3.87k
        b'/' => scratch.push(b'/'),
936
3.18k
        b'b' => scratch.push(b'\x08'),
937
62.7k
        b'f' => scratch.push(b'\x0c'),
938
28.1k
        b'n' => scratch.push(b'\n'),
939
6.78k
        b'r' => scratch.push(b'\r'),
940
29.1k
        b't' => scratch.push(b'\t'),
941
56.3k
        b'u' => return parse_unicode_escape(read, validate, scratch),
942
81
        _ => return error(read, ErrorCode::InvalidEscape),
943
    }
944
945
262k
    Ok(())
946
319k
}
947
948
/// Parses a JSON \u escape and appends it into the scratch space. Assumes `\u`
949
/// has just been read.
950
#[cold]
951
56.3k
fn parse_unicode_escape<'de, R: Read<'de>>(
952
56.3k
    read: &mut R,
953
56.3k
    validate: bool,
954
56.3k
    scratch: &mut Vec<u8>,
955
56.3k
) -> Result<()> {
956
56.3k
    let mut n = tri!(read.decode_hex_escape());
957
958
    // Non-BMP characters are encoded as a sequence of two hex escapes,
959
    // representing UTF-16 surrogates. If deserializing a utf-8 string the
960
    // surrogates are required to be paired, whereas deserializing a byte string
961
    // accepts lone surrogates.
962
56.1k
    if validate && n >= 0xDC00 && n <= 0xDFFF {
963
        // XXX: This is actually a trailing surrogate.
964
78
        return error(read, ErrorCode::LoneLeadingSurrogateInHexEscape);
965
56.1k
    }
966
967
    loop {
968
56.1k
        if n < 0xD800 || n > 0xDBFF {
969
            // Every u16 outside of the surrogate ranges is guaranteed to be a
970
            // legal char.
971
35.6k
            push_wtf8_codepoint(n as u32, scratch);
972
35.6k
            return Ok(());
973
20.4k
        }
974
975
        // n is a leading surrogate, we now expect a trailing surrogate.
976
20.4k
        let n1 = n;
977
978
20.4k
        if tri!(peek_or_eof(read)) == b'\\' {
979
20.3k
            read.discard();
980
20.3k
        } else {
981
63
            return if validate {
982
63
                read.discard();
983
63
                error(read, ErrorCode::UnexpectedEndOfHexEscape)
984
            } else {
985
0
                push_wtf8_codepoint(n1 as u32, scratch);
986
0
                Ok(())
987
            };
988
        }
989
990
20.3k
        if tri!(peek_or_eof(read)) == b'u' {
991
20.2k
            read.discard();
992
20.2k
        } else {
993
71
            return if validate {
994
71
                read.discard();
995
71
                error(read, ErrorCode::UnexpectedEndOfHexEscape)
996
            } else {
997
0
                push_wtf8_codepoint(n1 as u32, scratch);
998
                // The \ prior to this byte started an escape sequence, so we
999
                // need to parse that now. This recursive call does not blow the
1000
                // stack on malicious input because the escape is not \u, so it
1001
                // will be handled by one of the easy nonrecursive cases.
1002
0
                parse_escape(read, validate, scratch)
1003
            };
1004
        }
1005
1006
20.2k
        let n2 = tri!(read.decode_hex_escape());
1007
1008
20.2k
        if n2 < 0xDC00 || n2 > 0xDFFF {
1009
90
            if validate {
1010
90
                return error(read, ErrorCode::LoneLeadingSurrogateInHexEscape);
1011
0
            }
1012
0
            push_wtf8_codepoint(n1 as u32, scratch);
1013
            // If n2 is a leading surrogate, we need to restart.
1014
0
            n = n2;
1015
0
            continue;
1016
20.1k
        }
1017
1018
        // This value is in range U+10000..=U+10FFFF, which is always a valid
1019
        // codepoint.
1020
20.1k
        let n = ((((n1 - 0xD800) as u32) << 10) | (n2 - 0xDC00) as u32) + 0x1_0000;
1021
20.1k
        push_wtf8_codepoint(n, scratch);
1022
20.1k
        return Ok(());
1023
    }
1024
56.3k
}
1025
1026
/// Adds a WTF-8 codepoint to the end of the buffer. This is a more efficient
1027
/// implementation of String::push. The codepoint may be a surrogate.
1028
#[inline]
1029
55.7k
fn push_wtf8_codepoint(n: u32, scratch: &mut Vec<u8>) {
1030
55.7k
    if n < 0x80 {
1031
13.6k
        scratch.push(n as u8);
1032
13.6k
        return;
1033
42.0k
    }
1034
1035
42.0k
    scratch.reserve(4);
1036
1037
    // SAFETY: After the `reserve` call, `scratch` has at least 4 bytes of
1038
    // allocated but uninitialized memory after its last initialized byte, which
1039
    // is where `ptr` points. All reachable match arms write `encoded_len` bytes
1040
    // to that region and update the length accordingly, and `encoded_len` is
1041
    // always <= 4.
1042
    unsafe {
1043
42.0k
        let ptr = scratch.as_mut_ptr().add(scratch.len());
1044
1045
42.0k
        let encoded_len = match n {
1046
42.0k
            0..=0x7F => unreachable!(),
1047
42.0k
            0x80..=0x7FF => {
1048
2.03k
                ptr.write(((n >> 6) & 0b0001_1111) as u8 | 0b1100_0000);
1049
2.03k
                2
1050
            }
1051
40.0k
            0x800..=0xFFFF => {
1052
19.8k
                ptr.write(((n >> 12) & 0b0000_1111) as u8 | 0b1110_0000);
1053
19.8k
                ptr.add(1)
1054
19.8k
                    .write(((n >> 6) & 0b0011_1111) as u8 | 0b1000_0000);
1055
19.8k
                3
1056
            }
1057
20.1k
            0x1_0000..=0x10_FFFF => {
1058
20.1k
                ptr.write(((n >> 18) & 0b0000_0111) as u8 | 0b1111_0000);
1059
20.1k
                ptr.add(1)
1060
20.1k
                    .write(((n >> 12) & 0b0011_1111) as u8 | 0b1000_0000);
1061
20.1k
                ptr.add(2)
1062
20.1k
                    .write(((n >> 6) & 0b0011_1111) as u8 | 0b1000_0000);
1063
20.1k
                4
1064
            }
1065
0
            0x11_0000.. => unreachable!(),
1066
        };
1067
42.0k
        ptr.add(encoded_len - 1)
1068
42.0k
            .write((n & 0b0011_1111) as u8 | 0b1000_0000);
1069
1070
42.0k
        scratch.set_len(scratch.len() + encoded_len);
1071
    }
1072
55.7k
}
1073
1074
/// Parses a JSON escape sequence and discards the value. Assumes the previous
1075
/// byte read was a backslash.
1076
0
fn ignore_escape<'de, R>(read: &mut R) -> Result<()>
1077
0
where
1078
0
    R: ?Sized + Read<'de>,
1079
{
1080
0
    let ch = tri!(next_or_eof(read));
1081
1082
0
    match ch {
1083
0
        b'"' | b'\\' | b'/' | b'b' | b'f' | b'n' | b'r' | b't' => {}
1084
        b'u' => {
1085
            // At this point we don't care if the codepoint is valid. We just
1086
            // want to consume it. We don't actually know what is valid or not
1087
            // at this point, because that depends on if this string will
1088
            // ultimately be parsed into a string or a byte buffer in the "real"
1089
            // parse.
1090
1091
0
            tri!(read.decode_hex_escape());
1092
        }
1093
        _ => {
1094
0
            return error(read, ErrorCode::InvalidEscape);
1095
        }
1096
    }
1097
1098
0
    Ok(())
1099
0
}
1100
1101
const fn decode_hex_val_slow(val: u8) -> Option<u8> {
1102
    match val {
1103
        b'0'..=b'9' => Some(val - b'0'),
1104
        b'A'..=b'F' => Some(val - b'A' + 10),
1105
        b'a'..=b'f' => Some(val - b'a' + 10),
1106
        _ => None,
1107
    }
1108
}
1109
1110
const fn build_hex_table(shift: usize) -> [i16; 256] {
1111
    let mut table = [0; 256];
1112
    let mut ch = 0;
1113
    while ch < 256 {
1114
        table[ch] = match decode_hex_val_slow(ch as u8) {
1115
            Some(val) => (val as i16) << shift,
1116
            None => -1,
1117
        };
1118
        ch += 1;
1119
    }
1120
    table
1121
}
1122
1123
static HEX0: [i16; 256] = build_hex_table(0);
1124
static HEX1: [i16; 256] = build_hex_table(4);
1125
1126
76.5k
fn decode_four_hex_digits(a: u8, b: u8, c: u8, d: u8) -> Option<u16> {
1127
76.5k
    let a = HEX1[a as usize] as i32;
1128
76.5k
    let b = HEX0[b as usize] as i32;
1129
76.5k
    let c = HEX1[c as usize] as i32;
1130
76.5k
    let d = HEX0[d as usize] as i32;
1131
1132
76.5k
    let codepoint = ((a | b) << 8) | c | d;
1133
1134
    // A single sign bit check.
1135
76.5k
    if codepoint >= 0 {
1136
76.4k
        Some(codepoint as u16)
1137
    } else {
1138
74
        None
1139
    }
1140
76.5k
}