1
#[cfg(feature = "alloc")]
2
use alloc::string::String;
3
use core::cmp::Ordering;
4
use core::fmt::{self, Debug, Display, Formatter, Write};
5
use core::hash;
6
use core::str::{CharIndices, Chars};
7

            
8
use crate::anystr::AnyStr;
9
use crate::error::{Error, ErrorKind};
10
use crate::parser::{ParseDelegate, Parser};
11

            
12
/// A JSON string.
13
///
14
/// Internally, this type may be represented by either an already escaped JSON
15
/// string or an unescaped string.
16
///
17
/// This type implements `Eq` and `PartialEq` such that the escapes are always
18
/// handled correctly. Consider the following examples:
19
///
20
/// ```rust
21
/// use justjson::JsonString;
22
///
23
/// let json = JsonString::from_json(r#""Check out this cat: \"\ud83d\ude39\"""#).unwrap();
24
/// assert_eq!(json, "Check out this cat: \"😹\"");
25
/// let alternate_form =
26
///     JsonString::from_json("\"Check out this cat: \\\"\u{1f639}\\\"\"").unwrap();
27
/// assert_eq!(json, alternate_form)
28
/// ```
29
///
30
/// When the underlying representation is an encoded JSON string, the
31
/// [`JsonStringInfo`] is stored from the parsing operation. This allows the
32
/// comparison implementations to perform quick length checks on the decoded
33
/// length to avoid comparing the bytes of strings that decode to different
34
/// lengths.
35
///
36
/// Additionally, this type implements `Ord`, `PartialOrd`, and `Hash` in ways
37
/// that are consistent regardless of whether the string has escape sequences or
38
/// not. If the underlying representation does not need extra processing, the
39
/// built-in implementations for `&str` are always used.
40
30
#[derive(Debug, Eq, Clone)]
41
pub struct JsonString<'a> {
42
    /// The JSON-source for the string.
43
    pub(crate) source: StringContents<'a>,
44
    pub(crate) info: JsonStringInfo,
45
}
46

            
47
impl<'a> JsonString<'a> {
48
    /// Parses `json`, expecting a single string value.
49
    ///
50
    /// # Errors
51
    ///
52
    /// Returns [`ErrorKind::ExpectedString`] if a non-string value is
53
    /// encountered.
54
73
    pub fn from_json(json: &'a str) -> Result<Self, Error> {
55
73
        Parser::parse_json(json, StringParser).map_err(Error::into_infallable)
56
73
    }
57

            
58
    /// Returns the contained string after decoding any escape sequences, if
59
    /// needed. If there are no escape sequences, the contents of the string are
60
    /// borrowed.
61
    ///
62
    /// This type keeps track of whether the underlying string contains escape
63
    /// sequences, so this function is nearly instananeous when there are no
64
    /// escape sequences.
65
    #[must_use]
66
    #[cfg(feature = "alloc")]
67
6
    pub fn decode_if_needed(&self) -> AnyStr<'a> {
68
6
        match &self.source {
69
4
            StringContents::Json(source) => {
70
4
                if self.info.has_escapes() {
71
1
                    AnyStr::Owned(self.decoded().collect())
72
                } else {
73
3
                    source.clone()
74
                }
75
            }
76
2
            StringContents::Raw(raw) => raw.clone(),
77
        }
78
6
    }
79

            
80
    /// Returns the contained string after escaping any characters, if needed.
81
    /// If the string is already internally represented as a JSON string, this
82
    /// function returns its source via borrowing and no additional processing.
83
    #[must_use]
84
    #[cfg(feature = "alloc")]
85
3
    pub fn escape_if_needed(&self) -> AnyStr<'a> {
86
3
        match &self.source {
87
1
            StringContents::Json(source) => source.clone(),
88
            StringContents::Raw(_) => {
89
                // We promote raw strings with no escapes to Json strings, which
90
                // means we will always need to escape this raw string.
91
2
                let mut json = String::with_capacity(self.info.expected_length());
92
2
                json.extend(AsJson::new(&self.source, self.info));
93
2
                AnyStr::Owned(json)
94
            }
95
        }
96
3
    }
97

            
98
    /// Returns the string after decoding any JSON escape sequences.
99
    #[must_use]
100
25
    pub fn decoded(&self) -> Decoded<'_> {
101
25
        Decoded::new(&self.source, self.info)
102
25
    }
103

            
104
    /// Returns the string after decoding any JSON escape sequences.
105
    #[must_use]
106
79
    pub fn as_json(&self) -> AsJson<'_> {
107
79
        AsJson::new(&self.source, self.info)
108
79
    }
109

            
110
    /// Returns a reference to the underlying storage of this string, if it's
111
    /// already encoded for use in a JSON string. This does not include the
112
    /// surrounding quotation marks.
113
    ///
114
    /// If None is returned, the string must be decoded using
115
    /// [`as_json()`](Self::as_json).
116
    #[must_use]
117
    pub fn as_json_str(&self) -> Option<&'_ AnyStr<'a>> {
118
3
        if let StringContents::Json(source) = &self.source {
119
1
            Some(source)
120
        } else {
121
2
            None
122
        }
123
3
    }
124

            
125
    /// Returns the length of this string when encoded as JSON.
126
    #[must_use]
127
11
    pub fn len(&self) -> usize {
128
11
        match &self.source {
129
9
            StringContents::Json(json) => json.len(),
130
2
            StringContents::Raw(_) => self.info.expected_length(),
131
        }
132
11
    }
133

            
134
    /// Returns true if this string is empty.
135
    #[must_use]
136
4
    pub fn is_empty(&self) -> bool {
137
4
        self.len() == 0
138
4
    }
139

            
140
    /// Returns the length of this string when decoded.
141
    #[must_use]
142
3
    pub fn decoded_len(&self) -> usize {
143
3
        match &self.source {
144
1
            StringContents::Json(_) => self.info.expected_length(),
145
2
            StringContents::Raw(raw) => raw.len(),
146
        }
147
3
    }
148

            
149
    /// Returns a reference to the contents of this value if the contained
150
    /// string does not have any escape sequences that must be decoded.
151
    #[must_use]
152
    #[inline]
153
    pub fn as_str(&self) -> Option<&str> {
154
4
        match &self.source {
155
4
            StringContents::Json(str) if !self.info.has_escapes() => Some(str),
156
1
            StringContents::Json(_) => None,
157
            StringContents::Raw(str) => Some(str),
158
        }
159
4
    }
160
}
161

            
162
impl<'a> From<&'a str> for JsonString<'a> {
163
50
    fn from(value: &'a str) -> Self {
164
50
        // Analyze the string for characters that need to be escaped.
165
50
        let source = StringContents::Raw(AnyStr::Borrowed(value));
166
50
        let mut escaped = AsJson::new(&source, JsonStringInfo::NONE);
167
231
        for _ in &mut escaped {}
168

            
169
50
        if escaped.info.has_escapes() {
170
14
            Self {
171
14
                info: escaped.info,
172
14
                source,
173
14
            }
174
        } else {
175
            // No escapes, we can promote to a JSON string.
176
36
            Self {
177
36
                source: StringContents::Json(AnyStr::Borrowed(value)),
178
36
                info: escaped.info,
179
36
            }
180
        }
181
50
    }
182
}
183

            
184
#[cfg(feature = "alloc")]
185
impl<'a> From<String> for JsonString<'a> {
186
3
    fn from(value: String) -> Self {
187
3
        // Analyze the string for characters that need to be escaped.
188
3
        let borrowed_contents = StringContents::Raw(AnyStr::Borrowed(&value));
189
3
        let mut escaped = AsJson::new(&borrowed_contents, JsonStringInfo::NONE);
190
27
        for _ in &mut escaped {}
191

            
192
3
        if escaped.info.has_escapes() {
193
1
            Self {
194
1
                info: escaped.info,
195
1
                source: StringContents::Raw(AnyStr::Owned(value)),
196
1
            }
197
        } else {
198
            // No escapes, we can promote to a JSON string.
199
2
            Self {
200
2
                info: escaped.info,
201
2
                source: StringContents::Json(AnyStr::Owned(value)),
202
2
            }
203
        }
204
3
    }
205
}
206

            
207
impl<'a, 'b> PartialEq<&'a str> for JsonString<'b> {
208
29
    fn eq(&self, other: &&'a str) -> bool {
209
29
        self.eq(*other)
210
29
    }
211
}
212

            
213
impl<'b> PartialEq<str> for JsonString<'b> {
214
40
    fn eq(&self, other: &str) -> bool {
215
40
        match &self.source {
216
37
            StringContents::Json(source) => {
217
37
                if self.info.has_escapes() {
218
                    // Quick check, if the decoded length differs, the strings can't be equal
219
9
                    if self.info.expected_length() != other.len() {
220
2
                        return false;
221
7
                    }
222
7

            
223
7
                    Decoded::new(&self.source, self.info)
224
7
                        .zip(other.chars())
225
18
                        .all(|(a, b)| a == b)
226
                } else {
227
                    // Direct string comparison excluding the quotes.
228
28
                    source == other
229
                }
230
            }
231
3
            StringContents::Raw(source) => source == other,
232
        }
233
40
    }
234
}
235

            
236
impl<'a, 'b> PartialEq<JsonString<'a>> for JsonString<'b> {
237
    fn eq(&self, other: &JsonString<'a>) -> bool {
238
113
        match (&self.source, &other.source) {
239
108
            (StringContents::Json(a), StringContents::Json(b)) => {
240
108
                match (self.info.has_escapes(), other.info.has_escapes()) {
241
                    (true, true) => {
242
4
                        if self.info.expected_length() == other.info.expected_length() {
243
3
                            Decoded::new(&self.source, self.info)
244
3
                                .zip(Decoded::new(&other.source, self.info))
245
20
                                .all(|(a, b)| a == b)
246
                        } else {
247
1
                            false
248
                        }
249
                    }
250
1
                    (true, false) => self == b.as_ref(),
251
1
                    (false, true) => other == a.as_ref(),
252
102
                    (false, false) => a.as_ref() == b.as_ref(),
253
                }
254
            }
255
1
            (StringContents::Raw(a), StringContents::Raw(b)) => a.as_ref() == b.as_ref(),
256
2
            (StringContents::Json(_), StringContents::Raw(b)) => {
257
2
                if other.info.expected_length() == self.len() {
258
1
                    self == b.as_ref()
259
                } else {
260
1
                    false
261
                }
262
            }
263
2
            (StringContents::Raw(a), _) => {
264
2
                if self.info.expected_length() == other.len() {
265
1
                    other == a.as_ref()
266
                } else {
267
1
                    false
268
                }
269
            }
270
        }
271
113
    }
272
}
273

            
274
1
#[test]
275
#[cfg(feature = "alloc")]
276
1
fn json_string_eq() {
277
1
    #[track_caller]
278
3
    fn test_json<'a, T>(json: &'a str, expected: T)
279
3
    where
280
3
        T: Debug,
281
3
        JsonString<'a>: PartialEq<T>,
282
3
    {
283
3
        assert_eq!(JsonString::from_json(json).unwrap(), expected);
284
3
    }
285
1

            
286
1
    #[track_caller]
287
5
    fn test_json_ne<'a, T>(json: &'a str, expected: T)
288
5
    where
289
5
        T: Debug,
290
5
        JsonString<'a>: PartialEq<T>,
291
5
    {
292
5
        assert_ne!(JsonString::from_json(json).unwrap(), expected);
293
5
    }
294
1

            
295
1
    // Test &str comparisons
296
1
    test_json(r#""Hello, World!""#, "Hello, World!");
297
1
    test_json(r#""\"\\\/\b\f\n\r\t\u25eF""#, "\"\\/\x07\x0c\n\r\t\u{25ef}");
298
1
    test_json("\"\u{25ef}\"", "\u{25ef}");
299
1
    // Test decoded length not being the same
300
1
    test_json_ne(r#""\n""#, "");
301
1
    // Test decoded char not matching
302
1
    test_json_ne(r#""\n""#, "x");
303
1
    // Test regular char not matching in decoded comparison
304
1
    test_json_ne(r#""\na""#, "\nx");
305
1

            
306
1
    // Test JsonString comparisons
307
1
    // Decoded length not being the same between two JsonStrings.
308
1
    test_json_ne(
309
1
        r#""\u0000""#,
310
1
        JsonString::from_json(r#""\u0000\u0000""#).unwrap(),
311
1
    );
312
1
    // Same decoded length, lhs doesn't have escapes, rhs does
313
1
    test_json_ne(r#""ab""#, JsonString::from_json(r#""\u0000""#).unwrap());
314
1
    // Raw strings in JsonString
315
1
    assert_eq!(JsonString::from("a"), "a");
316
1
    assert_eq!(JsonString::from("a"), JsonString::from("a"));
317
1
    assert_eq!(
318
1
        JsonString::from_json("\"a\"").unwrap(),
319
1
        JsonString::from("a")
320
1
    );
321
1
    assert_eq!(
322
1
        JsonString::from("a"),
323
1
        JsonString::from_json("\"a\"").unwrap()
324
1
    );
325

            
326
1
    assert_eq!(JsonString::from("\0"), "\0");
327
1
    assert_eq!(JsonString::from("\0"), JsonString::from("\0"));
328

            
329
1
    assert_eq!(
330
1
        JsonString::from_json(r#""\u0000""#).unwrap(),
331
1
        JsonString::from("\0"),
332
1
    );
333
1
    assert_eq!(
334
1
        JsonString::from("\0"),
335
1
        JsonString::from_json(r#""\u0000""#).unwrap(),
336
1
    );
337

            
338
1
    assert_ne!(
339
1
        JsonString::from_json(r#""\u0000""#).unwrap(),
340
1
        JsonString::from("\0 "),
341
1
    );
342
1
    assert_ne!(
343
1
        JsonString::from("\0 "),
344
1
        JsonString::from_json(r#""\u0000""#).unwrap(),
345
1
    );
346
1
}
347

            
348
impl<'b> PartialOrd<str> for JsonString<'b> {
349
    fn partial_cmp(&self, other: &str) -> Option<Ordering> {
350
10
        match &self.source {
351
10
            StringContents::Json(_) if self.info.has_escapes() => {
352
7
                let mut left_chars = self.decoded();
353
7
                let mut right_chars = other.chars();
354
                loop {
355
12
                    match (left_chars.next(), right_chars.next()) {
356
7
                        (Some(left), Some(right)) => match left.cmp(&right) {
357
5
                            Ordering::Equal => continue,
358
1
                            Ordering::Less => return Some(Ordering::Less),
359
1
                            Ordering::Greater => return Some(Ordering::Greater),
360
                        },
361
1
                        (Some(_), _) => return Some(Ordering::Greater),
362
3
                        (_, Some(_)) => return Some(Ordering::Less),
363
1
                        (None, None) => return Some(Ordering::Equal),
364
                    }
365
                }
366
            }
367
4
            StringContents::Json(left) | StringContents::Raw(left) => Some(left.cmp(other)),
368
        }
369
11
    }
370
}
371

            
372
impl<'a, 'b> PartialOrd<&'a str> for JsonString<'b> {
373
8
    fn partial_cmp(&self, other: &&'a str) -> Option<Ordering> {
374
8
        self.partial_cmp(*other)
375
8
    }
376
}
377

            
378
impl<'b> Ord for JsonString<'b> {
379
    fn cmp(&self, other: &Self) -> Ordering {
380
        // There aren't any shortcuts for comparisons
381
9
        match (&self.source, &other.source) {
382
6
            (StringContents::Json(left), StringContents::Json(right))
383
6
                if !self.info.has_escapes() && !other.info.has_escapes() =>
384
1
            {
385
1
                left.cmp(right)
386
            }
387
1
            (StringContents::Raw(left), StringContents::Raw(right)) => left.cmp(right),
388
1
            (StringContents::Json(_), StringContents::Raw(right)) => {
389
1
                self.partial_cmp(&&**right).expect("always some")
390
            }
391
1
            (StringContents::Raw(left), StringContents::Json(_)) => {
392
1
                other.partial_cmp(&&**left).expect("always some").reverse()
393
            }
394
            _ => {
395
5
                let mut left_chars = self.decoded();
396
5
                let mut right_chars = other.decoded();
397
                loop {
398
8
                    match (left_chars.next(), right_chars.next()) {
399
5
                        (Some(left), Some(right)) => match left.cmp(&right) {
400
3
                            Ordering::Equal => continue,
401
1
                            Ordering::Less => return Ordering::Less,
402
1
                            Ordering::Greater => return Ordering::Greater,
403
                        },
404
1
                        (Some(_), _) => return Ordering::Greater,
405
1
                        (_, Some(_)) => return Ordering::Less,
406
1
                        (None, None) => return Ordering::Equal,
407
                    }
408
                }
409
            }
410
        }
411
9
    }
412
}
413
impl<'a, 'b> PartialOrd<JsonString<'a>> for JsonString<'b> {
414
9
    fn partial_cmp(&self, other: &JsonString<'a>) -> Option<Ordering> {
415
9
        Some(self.cmp(other))
416
9
    }
417
}
418

            
419
#[cfg(feature = "alloc")]
420
#[cfg(test)]
421
macro_rules! jstr {
422
    ($src:literal) => {
423
        JsonString::from_json(concat!("\"", $src, "\"")).unwrap()
424
    };
425
}
426

            
427
1
#[test]
428
#[cfg(feature = "alloc")]
429
#[allow(clippy::cmp_owned)]
430
1
fn json_string_cmp() {
431
1
    macro_rules! assert_lt {
432
1
        ($left:expr, $right:expr) => {
433
1
            assert!($left < $right);
434
1
        };
435
1
    }
436
1

            
437
1
    macro_rules! assert_gt {
438
1
        ($left:expr, $right:expr) => {
439
1
            assert!($left > $right);
440
1
        };
441
1
    }
442
1

            
443
1
    macro_rules! assert_ord_eq {
444
1
        ($left:expr, $right:expr) => {
445
1
            assert_eq!($left.partial_cmp($right), Some(Ordering::Equal));
446
1
        };
447
1
    }
448
1

            
449
1
    // no escapes, which ends up using str.cmp
450
1
    assert_lt!(jstr!("a"), "b");
451
1
    assert_gt!(jstr!("b"), "a");
452
1
    assert_ord_eq!(jstr!("a"), "a");
453
1
    assert_ord_eq!(JsonString::from("\n"), "\n");
454

            
455
    // Escapes vs no escapes. Same as above, but encoding a/b as unicode escapes
456
1
    assert_lt!(jstr!(r#"\u0061"#), "b");
457
1
    assert_gt!(jstr!(r#"\u0062"#), "a");
458
1
    assert_ord_eq!(jstr!(r#"\u0061"#), "a");
459
    // differing lengths, but matching prefix
460
1
    assert_lt!(jstr!(r#"\u0061"#), "aa");
461
1
    assert_gt!(jstr!(r#"\u0061a"#), "a");
462

            
463
    // Same suite of tests, but with json strings on the right
464
    // Escapes vs no escapes. Same as above, but encoding a/b as unicode escapes
465
1
    assert_lt!(jstr!(r#"\u0061"#), JsonString::from("b"));
466
1
    assert_gt!(jstr!(r#"\u0062"#), JsonString::from("a"));
467
1
    assert_ord_eq!(jstr!(r#"\u0061"#), &JsonString::from("a"));
468
    // differing lengths, but matching prefix
469
1
    assert_lt!(jstr!(r#"\u0061"#), JsonString::from("aa"));
470
1
    assert_gt!(jstr!(r#"\u0061a"#), JsonString::from("a"));
471
    // Raw on both sides
472
1
    assert_ord_eq!(JsonString::from("\n"), &JsonString::from("\n"));
473
    // Raw either side
474
1
    assert_lt!(jstr!(r#"\n"#), JsonString::from("\na"));
475
1
    assert_gt!(JsonString::from("\na"), jstr!(r#"\n"#));
476
    // JSON no escapes both sides
477
1
    assert_lt!(jstr!("a"), JsonString::from("b"));
478
1
}
479

            
480
impl<'a> hash::Hash for JsonString<'a> {
481
    fn hash<H: hash::Hasher>(&self, state: &mut H) {
482
2
        match &self.source {
483
2
            StringContents::Json(_) if self.info.has_escapes() => {
484
1
                // The standard string hash writes out as bytes, but char
485
1
                // hashing is done by converting to u32. We're purposely
486
1
                // re-implementing Hasher::write_str via chars.
487
1
                let mut char_bytes = [0; 4];
488
1
                for ch in self.decoded() {
489
1
                    state.write(ch.encode_utf8(&mut char_bytes).as_bytes());
490
1
                }
491
1
                state.write_u8(0xff); // from Hasher::write_str
492
            }
493
2
            StringContents::Json(str) | StringContents::Raw(str) => str.hash(state),
494
        }
495
3
    }
496
}
497

            
498
1
#[test]
499
#[cfg(feature = "std")]
500
1
fn json_string_hash() {
501
1
    use core::hash::{BuildHasher, Hasher};
502
1
    use std::collections::hash_map::RandomState;
503
4
    fn hash(t: impl hash::Hash, state: &RandomState) -> u64 {
504
4
        let mut hasher = state.build_hasher();
505
4
        t.hash(&mut hasher);
506
4
        hasher.finish()
507
4
    }
508
1

            
509
1
    let state = RandomState::default();
510
1
    assert_eq!(
511
1
        hash(JsonString::from("\n"), &state),
512
1
        hash(jstr!("\\n"), &state)
513
1
    );
514
1
    assert_eq!(hash(jstr!("a"), &state), hash("a", &state));
515
1
}
516

            
517
impl<'a> Display for JsonString<'a> {
518
1
    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
519
1
        self.decoded().fmt(f)
520
1
    }
521
}
522

            
523
1
#[test]
524
#[cfg(feature = "alloc")]
525
1
fn display() {
526
1
    use std::string::ToString;
527
1
    let json = JsonString::from_json(r#""hello, world!""#).unwrap();
528
1
    assert_eq!(json.to_string(), "hello, world!");
529
1
}
530

            
531
1
#[test]
532
#[cfg(feature = "alloc")]
533
1
fn json_string_from_json() {
534
1
    assert_eq!(
535
1
        JsonString::from_json(r#""Hello, World!""#).unwrap(),
536
1
        JsonString {
537
1
            source: StringContents::Json(AnyStr::Borrowed("Hello, World!")),
538
1
            info: JsonStringInfo::new(false, 13),
539
1
        }
540
1
    );
541

            
542
1
    let expected_string = JsonString::from_json("true")
543
1
        .expect_err("shouldn't allow non-strings")
544
1
        .kind;
545
1
    assert!(matches!(expected_string, ErrorKind::ExpectedString));
546
1
}
547

            
548
1
#[test]
549
1
fn as_str() {
550
1
    let json_with_escapes = JsonString::from_json(r#""\n""#).unwrap();
551
1
    assert_eq!(json_with_escapes.as_str(), None);
552
1
    let json_no_escapes = JsonString::from_json(r#""hi""#).unwrap();
553
1
    assert_eq!(json_no_escapes.as_str(), Some("hi"));
554
1
    let raw = JsonString::from("hi");
555
1
    assert_eq!(raw.as_str(), Some("hi"));
556
1
}
557

            
558
1
#[test]
559
#[cfg(feature = "alloc")]
560
1
fn json_string_from_raw() {
561
1
    assert_eq!(JsonString::from(String::from("a")), JsonString::from("a"));
562
1
}
563

            
564
1
#[test]
565
#[cfg(feature = "alloc")]
566
1
fn decode_if_needed() {
567
1
    let empty = JsonString::from_json(r#""""#).unwrap();
568
1
    let AnyStr::Borrowed(string) = empty.decode_if_needed() else {
569
        unreachable!()
570
    };
571
1
    assert_eq!(string, "");
572
1
    let has_escapes = JsonString::from_json(r#""\r""#).unwrap();
573
1
    let AnyStr::Owned(string) = has_escapes.decode_if_needed() else {
574
        unreachable!()
575
    };
576
1
    assert_eq!(string, "\r");
577
1
    let decoded_via_display = alloc::format!("{}", has_escapes.decoded());
578
1
    assert_eq!(decoded_via_display, "\r");
579

            
580
1
    let raw_string = JsonString::from("raw string");
581
1
    let AnyStr::Borrowed(string) = raw_string.decode_if_needed() else {
582
        unreachable!()
583
    };
584
1
    assert_eq!(string, "raw string");
585

            
586
1
    let decoded_via_display = alloc::format!("{}", raw_string.decoded());
587
1
    assert_eq!(decoded_via_display, "raw string");
588
1
}
589

            
590
/// Information about a parsed [`JsonString`].
591
///
592
/// This type stores:
593
///
594
/// - Whether any escape sequences are in the source
595
/// - The length of the String if the escape sequences are decoded.
596
106
#[derive(Clone, Copy, Eq, PartialEq, Hash)]
597
pub struct JsonStringInfo(usize);
598

            
599
impl JsonStringInfo {
600
    const HAS_ESCAPES_MASK: usize = usize::MAX ^ Self::UNESCAPED_BYTES_MASK;
601
    /// Information with no escapes and 0 length.
602
    pub const NONE: Self = Self::new(false, 0);
603
    #[cfg(target_pointer_width = "32")]
604
    const UNESCAPED_BYTES_MASK: usize = 0x7FFF_FFFF;
605
    #[cfg(target_pointer_width = "64")]
606
    const UNESCAPED_BYTES_MASK: usize = 0x7FFF_FFFF_FFFF_FFFF;
607

            
608
    /// Returns a new instance with the initial values provided.
609
    #[must_use]
610
7
    pub const fn new(has_escapes: bool, unescaped_length: usize) -> Self {
611
7
        // Panics aren't allowed in const fns yet.
612
7
        // assert_eq!(
613
7
        //     unescaped_length & Self::HAS_ESCAPES_MASK,
614
7
        //     0,
615
7
        //     "too many bytes needed"
616
7
        // );
617
7

            
618
7
        if has_escapes {
619
1
            Self(Self::HAS_ESCAPES_MASK | unescaped_length)
620
        } else {
621
6
            Self(unescaped_length)
622
        }
623
7
    }
624

            
625
    /// Returns whether the string has any escape sequences.
626
    #[must_use]
627
370
    pub const fn has_escapes(self) -> bool {
628
370
        self.0 & Self::HAS_ESCAPES_MASK != 0
629
370
    }
630

            
631
    /// Returns the length of the string after decoding any escape sequences.
632
    #[must_use]
633
27
    pub const fn expected_length(self) -> usize {
634
27
        self.0 & Self::UNESCAPED_BYTES_MASK
635
27
    }
636

            
637
46631
    pub(crate) fn add_bytes(&mut self, bytes: usize) {
638
46631
        self.0 = self.0.checked_add(bytes).expect("too many extra bytes");
639
46631
    }
640

            
641
1676
    pub(crate) fn add_bytes_from_escape(&mut self, bytes: usize) {
642
1676
        self.0 = (Self::HAS_ESCAPES_MASK | self.0)
643
1676
            .checked_add(bytes)
644
1676
            .expect("too many extra bytes");
645
1676
    }
646
}
647

            
648
impl fmt::Debug for JsonStringInfo {
649
1
    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
650
1
        f.debug_struct("EscapeInfo")
651
1
            .field("has_escapes", &self.has_escapes())
652
1
            .field("unescaped_length", &self.expected_length())
653
1
            .finish()
654
1
    }
655
}
656

            
657
1
#[test]
658
#[cfg(feature = "alloc")]
659
1
fn test_string_info_debug() {
660
1
    let mut info = JsonStringInfo::NONE;
661
1
    info.add_bytes_from_escape(1);
662
1
    assert_eq!(
663
1
        alloc::format!("{info:?}"),
664
1
        "EscapeInfo { has_escapes: true, unescaped_length: 1 }"
665
1
    );
666
1
}
667

            
668
3
#[derive(Clone)]
669
pub struct Decoded<'a> {
670
    needs_decoding: bool,
671
    source: &'a str,
672
    chars: CharIndices<'a>,
673
}
674

            
675
impl<'a> Decoded<'a> {
676
38
    fn new(source: &'a StringContents<'a>, info: JsonStringInfo) -> Self {
677
38
        match source {
678
36
            StringContents::Json(source) => Self {
679
36
                needs_decoding: info.has_escapes(),
680
36
                source,
681
36
                chars: source.char_indices(),
682
36
            },
683
2
            StringContents::Raw(source) => Self {
684
2
                needs_decoding: false,
685
2
                source,
686
2
                chars: source.char_indices(),
687
2
            },
688
        }
689
38
    }
690
}
691

            
692
impl<'a> Iterator for Decoded<'a> {
693
    type Item = char;
694

            
695
    #[allow(unsafe_code)]
696
    #[inline]
697
153
    fn next(&mut self) -> Option<Self::Item> {
698
153
        let (_, ch) = self.chars.next()?;
699
129
        if self.needs_decoding && ch == '\\' {
700
72
            match self.chars.next().expect("already validated") {
701
7
                (_, 'r') => Some('\r'),
702
10
                (_, 'n') => Some('\n'),
703
5
                (_, 't') => Some('\t'),
704
5
                (_, 'b') => Some('\x07'),
705
5
                (_, 'f') => Some('\x0c'),
706
25
                (offset, 'u') => {
707
                    // four hex digits
708
125
                    for _ in 0..4 {
709
100
                        self.chars.next();
710
100
                    }
711
                    // We access the string slice directly rather than
712
                    // trying to rebuild via char indicies for speed.
713
25
                    let hex = &self.source[offset + 1..offset + 5];
714
25
                    let mut codepoint = u32::from_str_radix(hex, 16).expect("already validated");
715
25

            
716
25
                    if (HIGH_SURROGATE_MIN..=HIGH_SURROGATE_MAX).contains(&codepoint) {
717
                        // Surrogate pair, which has already been validated.
718
                        // Process another \uxxxx.
719
56
                        for _ in 0..6 {
720
48
                            self.chars.next();
721
48
                        }
722
8
                        let hex = &self.source[offset + 7..offset + 11];
723
8
                        let second_codepoint =
724
8
                            u32::from_str_radix(hex, 16).expect("already validated");
725
8
                        codepoint = merge_surrogate_pair(codepoint, second_codepoint);
726
17
                    }
727

            
728
                    // SAFETY: The JSON string has already had its UTF
729
                    // escapes validated.
730
25
                    Some(unsafe { char::from_u32_unchecked(codepoint) })
731
                }
732
15
                (_, other) => Some(other),
733
            }
734
        } else {
735
57
            Some(ch)
736
        }
737
153
    }
738
}
739

            
740
impl<'a> Display for Decoded<'a> {
741
3
    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
742
24
        for ch in self.clone() {
743
24
            f.write_char(ch)?;
744
        }
745

            
746
3
        Ok(())
747
3
    }
748
}
749

            
750
76
#[derive(Clone)]
751
pub struct AsJson<'a> {
752
    chars: Chars<'a>,
753
    state: EscapeState,
754
    info: JsonStringInfo,
755
}
756

            
757
impl<'a> Display for AsJson<'a> {
758
76
    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
759
176
        for ch in self.clone() {
760
176
            f.write_char(ch)?;
761
        }
762

            
763
76
        Ok(())
764
76
    }
765
}
766

            
767
76
#[derive(Clone)]
768
enum EscapeState {
769
    AlreadyEscaped,
770
    None,
771
    Single(u8),
772
    Unicode {
773
        current_nibble: Option<u8>,
774
        codepoint: u16,
775
    },
776
}
777

            
778
impl<'b, 'a> AsJson<'b> {
779
134
    fn new(value: &'b StringContents<'a>, info: JsonStringInfo) -> Self {
780
134
        match value {
781
77
            StringContents::Json(source) => Self {
782
77
                chars: source.chars(),
783
77
                state: EscapeState::AlreadyEscaped,
784
77
                info,
785
77
            },
786
57
            StringContents::Raw(source) => Self {
787
57
                chars: source.chars(),
788
57
                state: EscapeState::None,
789
57
                info,
790
57
            },
791
        }
792
134
    }
793
}
794

            
795
impl<'a> Iterator for AsJson<'a> {
796
    type Item = char;
797

            
798
    #[inline]
799
608
    fn next(&mut self) -> Option<Self::Item> {
800
608
        match &mut self.state {
801
258
            EscapeState::AlreadyEscaped => self.chars.next(),
802
            EscapeState::None => {
803
237
                let ch = self.chars.next()?;
804
180
                match u8::try_from(ch) {
805
174
                    Ok(b) if SAFE_STRING_BYTES[b as usize] => {
806
113
                        self.info.add_bytes(1);
807
113
                        Some(ch)
808
                    }
809
                    Ok(b'"' | b'\\' | b'/') => {
810
12
                        self.state = EscapeState::Single(ch as u8);
811
12
                        self.info.add_bytes_from_escape(2);
812
12
                        Some('\\')
813
                    }
814
                    Ok(b'\x07') => {
815
6
                        self.state = EscapeState::Single(b'b');
816
6
                        self.info.add_bytes_from_escape(2);
817
6
                        Some('\\')
818
                    }
819
                    Ok(b'\n') => {
820
12
                        self.state = EscapeState::Single(b'n');
821
12
                        self.info.add_bytes_from_escape(2);
822
12
                        Some('\\')
823
                    }
824
                    Ok(b'\r') => {
825
6
                        self.state = EscapeState::Single(b'r');
826
6
                        self.info.add_bytes_from_escape(2);
827
6
                        Some('\\')
828
                    }
829
                    Ok(b'\t') => {
830
6
                        self.state = EscapeState::Single(b't');
831
6
                        self.info.add_bytes_from_escape(2);
832
6
                        Some('\\')
833
                    }
834
                    Ok(b'\x0c') => {
835
6
                        self.state = EscapeState::Single(b'f');
836
6
                        self.info.add_bytes_from_escape(2);
837
6
                        Some('\\')
838
                    }
839
13
                    Ok(b) if (0..=31).contains(&b) => {
840
13
                        // Another control character, but it's not a common one.
841
13
                        // This must be encoded as a unicode escape.
842
13
                        self.state = EscapeState::Unicode {
843
13
                            current_nibble: None,
844
13
                            codepoint: u16::from(b),
845
13
                        };
846
13
                        self.info.add_bytes_from_escape(6);
847
13
                        Some('\\')
848
                    }
849
                    Err(_) => {
850
                        // A unicode character
851
6
                        self.info.add_bytes(ch.len_utf8());
852
6
                        Some(ch)
853
                    }
854
                    _ => unreachable!("SAFE_CHARACTERS prevents these"),
855
                }
856
            }
857
48
            EscapeState::Single(ch) => {
858
48
                let ch = *ch;
859
48
                self.state = EscapeState::None;
860
48
                Some(ch as char)
861
            }
862
            EscapeState::Unicode {
863
65
                current_nibble,
864
65
                codepoint,
865
65
            } => match current_nibble {
866
52
                Some(current_nibble) => {
867
52
                    #[allow(clippy::cast_possible_truncation)]
868
52
                    let bits = *codepoint as u8 & 0xF;
869
52
                    *codepoint >>= 4;
870
52
                    let ch = if bits < 10 { bits + b'0' } else { bits + b'a' };
871
52
                    *current_nibble += 1;
872
52
                    if *current_nibble == 4 {
873
13
                        self.state = EscapeState::None;
874
39
                    }
875
52
                    Some(ch as char)
876
                }
877
                None => {
878
13
                    *current_nibble = Some(0);
879
13
                    Some('u')
880
                }
881
            },
882
        }
883
608
    }
884

            
885
5
    fn size_hint(&self) -> (usize, Option<usize>) {
886
5
        self.chars.size_hint()
887
5
    }
888
}
889

            
890
#[allow(clippy::inconsistent_digit_grouping)]
891
pub(crate) static HEX_OFFSET_TABLE: [u8; 256] = {
892
    const ERR: u8 = u8::MAX;
893
    [
894
        ERR, ERR, ERR, ERR, ERR, ERR, ERR, ERR, ERR, ERR, ERR, ERR, ERR, ERR, ERR, ERR, // 0
895
        ERR, ERR, ERR, ERR, ERR, ERR, ERR, ERR, ERR, ERR, ERR, ERR, ERR, ERR, ERR, ERR, // 1
896
        ERR, ERR, ERR, ERR, ERR, ERR, ERR, ERR, ERR, ERR, ERR, ERR, ERR, ERR, ERR, ERR, // 2
897
        0__, 1__, 2__, 3__, 4__, 5__, 6__, 7__, 8__, 9__, ERR, ERR, ERR, ERR, ERR, ERR, // 3
898
        ERR, 10_, 11_, 12_, 13_, 14_, 15_, ERR, ERR, ERR, ERR, ERR, ERR, ERR, ERR, ERR, // 4
899
        ERR, ERR, ERR, ERR, ERR, ERR, ERR, ERR, ERR, ERR, ERR, ERR, ERR, ERR, ERR, ERR, // 5
900
        ERR, 10_, 11_, 12_, 13_, 14_, 15_, ERR, ERR, ERR, ERR, ERR, ERR, ERR, ERR, ERR, // 6
901
        ERR, ERR, ERR, ERR, ERR, ERR, ERR, ERR, ERR, ERR, ERR, ERR, ERR, ERR, ERR, ERR, // 7
902
        ERR, ERR, ERR, ERR, ERR, ERR, ERR, ERR, ERR, ERR, ERR, ERR, ERR, ERR, ERR, ERR, // 8
903
        ERR, ERR, ERR, ERR, ERR, ERR, ERR, ERR, ERR, ERR, ERR, ERR, ERR, ERR, ERR, ERR, // 9
904
        ERR, ERR, ERR, ERR, ERR, ERR, ERR, ERR, ERR, ERR, ERR, ERR, ERR, ERR, ERR, ERR, // A
905
        ERR, ERR, ERR, ERR, ERR, ERR, ERR, ERR, ERR, ERR, ERR, ERR, ERR, ERR, ERR, ERR, // B
906
        ERR, ERR, ERR, ERR, ERR, ERR, ERR, ERR, ERR, ERR, ERR, ERR, ERR, ERR, ERR, ERR, // C
907
        ERR, ERR, ERR, ERR, ERR, ERR, ERR, ERR, ERR, ERR, ERR, ERR, ERR, ERR, ERR, ERR, // D
908
        ERR, ERR, ERR, ERR, ERR, ERR, ERR, ERR, ERR, ERR, ERR, ERR, ERR, ERR, ERR, ERR, // E
909
        ERR, ERR, ERR, ERR, ERR, ERR, ERR, ERR, ERR, ERR, ERR, ERR, ERR, ERR, ERR, ERR, // F
910
    ]
911
};
912

            
913
pub(crate) static SAFE_STRING_BYTES: &[bool; 256] = {
914
    const ER: bool = false;
915
    const UC: bool = true;
916
    const BS: bool = false;
917
    const QU: bool = false;
918
    const __: bool = true;
919
    //  0   1   2   3   4   5   6   7   8   9   A   B   C    D   E   F
920
    &[
921
        ER, ER, ER, ER, ER, ER, ER, ER, ER, ER, ER, ER, ER, ER, ER, ER, // 0
922
        ER, ER, ER, ER, ER, ER, ER, ER, ER, ER, ER, ER, ER, ER, ER, ER, // 1
923
        __, __, QU, __, __, __, __, __, __, __, __, __, __, __, __, __, // 2
924
        __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, // 3
925
        __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, // 4
926
        __, __, __, __, __, __, __, __, __, __, __, __, BS, __, __, __, // 5
927
        __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, // 6
928
        __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, // 7
929
        UC, UC, UC, UC, UC, UC, UC, UC, UC, UC, UC, UC, UC, UC, UC, UC, // 8
930
        UC, UC, UC, UC, UC, UC, UC, UC, UC, UC, UC, UC, UC, UC, UC, UC, // 9
931
        UC, UC, UC, UC, UC, UC, UC, UC, UC, UC, UC, UC, UC, UC, UC, UC, // A
932
        UC, UC, UC, UC, UC, UC, UC, UC, UC, UC, UC, UC, UC, UC, UC, UC, // B
933
        UC, UC, UC, UC, UC, UC, UC, UC, UC, UC, UC, UC, UC, UC, UC, UC, // C
934
        UC, UC, UC, UC, UC, UC, UC, UC, UC, UC, UC, UC, UC, UC, UC, UC, // D
935
        UC, UC, UC, UC, UC, UC, UC, UC, UC, UC, UC, UC, UC, UC, UC, UC, // E
936
        UC, UC, UC, UC, UC, UC, UC, UC, UC, UC, UC, UC, UC, UC, UC, UC, // F
937
    ]
938
};
939

            
940
pub(crate) static SAFE_STRING_BYTES_VERIFY_UTF8: &[bool; 256] = {
941
    const ER: bool = false;
942
    const UC: bool = false;
943
    const BS: bool = false;
944
    const QU: bool = false;
945
    const __: bool = true;
946
    //  0   1   2   3   4   5   6   7   8   9   A   B   C    D   E   F
947
    &[
948
        ER, ER, ER, ER, ER, ER, ER, ER, ER, ER, ER, ER, ER, ER, ER, ER, // 0
949
        ER, ER, ER, ER, ER, ER, ER, ER, ER, ER, ER, ER, ER, ER, ER, ER, // 1
950
        __, __, QU, __, __, __, __, __, __, __, __, __, __, __, __, __, // 2
951
        __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, // 3
952
        __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, // 4
953
        __, __, __, __, __, __, __, __, __, __, __, __, BS, __, __, __, // 5
954
        __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, // 6
955
        __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, // 7
956
        UC, UC, UC, UC, UC, UC, UC, UC, UC, UC, UC, UC, UC, UC, UC, UC, // 8
957
        UC, UC, UC, UC, UC, UC, UC, UC, UC, UC, UC, UC, UC, UC, UC, UC, // 9
958
        UC, UC, UC, UC, UC, UC, UC, UC, UC, UC, UC, UC, UC, UC, UC, UC, // A
959
        UC, UC, UC, UC, UC, UC, UC, UC, UC, UC, UC, UC, UC, UC, UC, UC, // B
960
        UC, UC, UC, UC, UC, UC, UC, UC, UC, UC, UC, UC, UC, UC, UC, UC, // C
961
        UC, UC, UC, UC, UC, UC, UC, UC, UC, UC, UC, UC, UC, UC, UC, UC, // D
962
        UC, UC, UC, UC, UC, UC, UC, UC, UC, UC, UC, UC, UC, UC, UC, UC, // E
963
        UC, UC, UC, UC, UC, UC, UC, UC, UC, UC, UC, UC, UC, UC, UC, UC, // F
964
    ]
965
};
966

            
967
1
#[test]
968
1
fn is_empty() {
969
1
    assert!(JsonString::from("").is_empty());
970
1
    assert!(JsonString::from_json("\"\"").unwrap().is_empty());
971
1
    assert!(!JsonString::from(" ").is_empty());
972
1
    assert!(!JsonString::from_json("\" \"").unwrap().is_empty());
973
1
}
974

            
975
1
#[test]
976
#[cfg(feature = "alloc")]
977
1
fn escape() {
978
1
    let original = "\"\\/\u{07}\t\n\r\u{0c}\u{0}\u{25ef}";
979
1
    let escaped = "\\\"\\\\/\\b\\t\\n\\r\\f\\u0000\u{25ef}";
980
1
    let raw = JsonString::from(original);
981
1
    assert_eq!(raw.len(), escaped.len());
982
1
    assert_eq!(raw.decoded_len(), original.len());
983
1
    assert_eq!(raw, original);
984
1
    let decoded = raw.decoded().collect::<String>();
985
1
    assert_eq!(decoded, original);
986
1
    let decoded = raw.decode_if_needed();
987
1
    assert_eq!(decoded, original);
988
1
    let json = raw.as_json().collect::<String>();
989
1
    assert_eq!(json, escaped);
990
1
    let json = raw.escape_if_needed();
991
1
    assert_eq!(json, escaped);
992
1
    assert!(raw.as_json_str().is_none());
993

            
994
    // Test converting a String that needs encoding.
995
1
    let original = "\"\\/\u{07}\t\n\r\u{0c}\u{0}\u{25ef}";
996
1
    let escaped = "\\\"\\\\/\\b\\t\\n\\r\\f\\u0000\u{25ef}";
997
1
    let raw: JsonString<'static> = JsonString::from(String::from(original));
998
1
    assert_eq!(raw.len(), escaped.len());
999
1
    assert_eq!(raw.decoded_len(), original.len());
1
    assert_eq!(raw, original);
1
    let decoded = raw.decoded().collect::<String>();
1
    assert_eq!(decoded, original);
1
    let decoded = raw.decode_if_needed();
1
    assert_eq!(decoded, original);
1
    let json = raw.as_json().collect::<String>();
1
    assert_eq!(json, escaped);
1
    let json = raw.escape_if_needed();
1
    assert_eq!(json, escaped);
1
    assert!(raw.as_json_str().is_none());

            
    // Test with a raw string that doesn't need encoding
1
    let original = "hello";
1
    let raw = JsonString::from("hello");
1
    assert_eq!(raw.len(), original.len());
1
    assert_eq!(raw.decoded_len(), original.len());
1
    assert_eq!(raw, original);
1
    let decoded = raw.decoded().collect::<String>();
1
    assert_eq!(decoded, original);
1
    let decoded = raw.decode_if_needed();
1
    assert_eq!(decoded, original);
1
    let json = raw.as_json().collect::<String>();
1
    assert_eq!(json, original);
1
    let json = raw.escape_if_needed();
1
    assert_eq!(json, original);
1
    assert_eq!(raw.as_json_str().map(AnyStr::as_ref), Some("hello"));
1
}

            
30
#[derive(Debug, Clone, Eq, PartialEq, Hash)]
pub enum StringContents<'a> {
    Json(AnyStr<'a>),
    Raw(AnyStr<'a>),
}

            
pub(crate) const HIGH_SURROGATE_MIN: u32 = 0xD800;
pub(crate) const HIGH_SURROGATE_MAX: u32 = 0xDBFF;
pub(crate) const LOW_SURROGATE_MIN: u32 = 0xDC00;
pub(crate) const LOW_SURROGATE_MAX: u32 = 0xDFFF;
pub(crate) const DECODED_SURROGATE_BASE: u32 = 0x1_0000;

            
#[inline]
56
pub(crate) fn merge_surrogate_pair(high: u32, low: u32) -> u32 {
56
    DECODED_SURROGATE_BASE | ((high - HIGH_SURROGATE_MIN) * 0x400) | (low - LOW_SURROGATE_MIN)
56
}
struct StringParser;

            
impl<'a> ParseDelegate<'a> for StringParser {
    type Array = ();
    type Error = ErrorKind;
    type Key = ();
    type Object = ();
    type Value = JsonString<'a>;

            
1
    fn null(&mut self) -> Result<Self::Value, Self::Error> {
1
        Err(ErrorKind::ExpectedString)
1
    }

            
2
    fn boolean(&mut self, _value: bool) -> Result<Self::Value, Self::Error> {
2
        Err(ErrorKind::ExpectedString)
2
    }

            
1
    fn number(&mut self, _value: crate::JsonNumber<'a>) -> Result<Self::Value, Self::Error> {
1
        Err(ErrorKind::ExpectedString)
1
    }

            
67
    fn string(&mut self, value: JsonString<'a>) -> Result<Self::Value, Self::Error> {
67
        Ok(value)
67
    }

            
1
    fn begin_object(&mut self) -> Result<Self::Object, Self::Error> {
1
        Err(ErrorKind::ExpectedString)
1
    }

            
    fn object_key(
        &mut self,
        _object: &mut Self::Object,
        _key: crate::JsonString<'a>,
    ) -> Result<Self::Key, Self::Error> {
        unreachable!("error returned from begin_object")
    }

            
    fn object_value(
        &mut self,
        _object: &mut Self::Object,
        _key: Self::Key,
        _value: Self::Value,
    ) -> Result<(), Self::Error> {
        unreachable!("error returned from begin_object")
    }

            
    fn object_is_empty(&self, _object: &Self::Object) -> bool {
        unreachable!("error returned from begin_object")
    }

            
    fn end_object(&mut self, _object: Self::Object) -> Result<Self::Value, Self::Error> {
        unreachable!("error returned from begin_object")
    }

            
1
    fn begin_array(&mut self) -> Result<Self::Array, Self::Error> {
1
        Err(ErrorKind::ExpectedString)
1
    }

            
    fn array_value(
        &mut self,
        _array: &mut Self::Array,
        _value: Self::Value,
    ) -> Result<(), Self::Error> {
        unreachable!("error returned from array_value")
    }

            
    fn array_is_empty(&self, _array: &Self::Array) -> bool {
        unreachable!("error returned from array_value")
    }

            
    fn end_array(&mut self, _array: Self::Array) -> Result<Self::Value, Self::Error> {
        unreachable!("error returned from array_value")
    }

            
    fn kind_of(&self, _value: &Self::Value) -> crate::parser::JsonKind {
        unreachable!("allow_all_types_at_root is always true")
    }
}

            
1
#[test]
1
fn from_json_bad_types() {
1
    assert_eq!(
1
        JsonString::from_json("1").unwrap_err().kind,
1
        ErrorKind::ExpectedString
1
    );
1
    assert_eq!(
1
        JsonString::from_json("null").unwrap_err().kind,
1
        ErrorKind::ExpectedString
1
    );
1
    assert_eq!(
1
        JsonString::from_json("true").unwrap_err().kind,
1
        ErrorKind::ExpectedString
1
    );
1
    assert_eq!(
1
        JsonString::from_json("[]").unwrap_err().kind,
1
        ErrorKind::ExpectedString
1
    );
1
    assert_eq!(
1
        JsonString::from_json("{}").unwrap_err().kind,
1
        ErrorKind::ExpectedString
1
    );
1
}