core_json_traits/
string.rs

1use crate::JsonSerialize;
2
3#[cfg(feature = "alloc")]
4use crate::{Read, Stack, JsonError, Value, JsonDeserialize};
5#[cfg(feature = "alloc")]
6impl JsonDeserialize for alloc::string::String {
7  fn deserialize<'read, 'parent, B: Read<'read>, S: Stack>(
8    value: Value<'read, 'parent, B, S>,
9  ) -> Result<Self, JsonError<'read, B, S>> {
10    value.to_str()?.collect()
11  }
12}
13
14struct CharIterator<I: Iterator<Item = char>> {
15  iter: I,
16  buf: [char; 12],
17  queued: usize,
18}
19impl<I: Iterator<Item = char>> Iterator for CharIterator<I> {
20  type Item = char;
21  fn next(&mut self) -> Option<Self::Item> {
22    // If we don't have a character in progress, fetch the next character
23    if self.queued == 0 {
24      let char = self.iter.next()?;
25
26      match u32::from(char) {
27        // Unescaped
28        0x20 ..= 0x21 | 0x23 ..= 0x5b | 0x5d ..= 0x10ffff => {
29          self.buf[self.buf.len() - 1] = char;
30          self.queued = 1;
31        }
32        // Escaped with a special case
33        #[allow(unreachable_patterns)]
34        0x22 | 0x5c | 0x2f | 0x62 | 0x66 | 0x6e | 0x72 | 0x74 => {
35          self.buf[self.buf.len() - 2] = '\\';
36          self.buf[self.buf.len() - 1] = match u32::from(char) {
37            // Handle characters whose aliases are distinct from them themselves
38            0x62 => 'b',
39            0x66 => 'f',
40            0x6e => 'n',
41            0x72 => 'r',
42            0x74 => 't',
43            // Handle characters whose aliases are equivalent to them themselves
44            _ => char,
45          };
46          self.queued = 2;
47        }
48        _ => {
49          // Encode this character as UTF-16
50          let mut elems = [0; 2];
51          let elems = char.encode_utf16(&mut elems);
52          for (i, b) in elems.iter().enumerate() {
53            // If we only have one element, write it to the second position
54            let i = (((2 - elems.len()) + i) * 6) + 2;
55            // Convert to hex
56            for n in 0 .. 4 {
57              // Safe to cast as this is masked with 0b1111 (a 4-bit value)
58              let nibble = (((*b) >> (16 - ((n + 1) * 4))) & 0b1111) as u8;
59              // Safe to cast as this will be `'0' ..= '9' | 'a' ..= 'f``
60              self.buf[i + n] = (if let Some(value) = nibble.checked_sub(10) {
61                b'a' + value
62              } else {
63                b'0' + nibble
64              }) as char;
65            }
66          }
67          self.queued = elems.len() * 6;
68        }
69      }
70    }
71
72    // Yield the next character queued
73    let res = self.buf[12 - self.queued];
74    // Increment
75    self.queued -= 1;
76    Some(res)
77  }
78}
79impl JsonSerialize for str {
80  fn serialize(&self) -> impl Iterator<Item = char> {
81    core::iter::once('"')
82      .chain(CharIterator {
83        iter: self.chars(),
84        buf: ['\\', 'u', 'F', 'F', 'F', 'F', '\\', 'u', 'F', 'F', 'F', 'F'],
85        queued: 0,
86      })
87      .chain(core::iter::once('"'))
88  }
89}
90
91#[cfg(feature = "alloc")]
92impl JsonSerialize for alloc::string::String {
93  fn serialize(&self) -> impl Iterator<Item = char> {
94    self.as_str().serialize()
95  }
96}