| 85 | } |
| 86 | |
| 87 | fn read_string(&mut self) -> Result<Token, JsonError> { |
| 88 | self.pos += 1; |
| 89 | let mut out = String::new(); |
| 90 | while self.pos < self.src.len() { |
| 91 | let c = self.src[self.pos]; |
| 92 | if c == b'"' { self.pos += 1; return Ok(Token::Str(out)); } |
| 93 | if c == b'\\' { |
| 94 | self.pos += 1; |
| 95 | if self.pos >= self.src.len() { return Err(self.err("dangling escape")); } |
| 96 | let esc = self.src[self.pos]; |
| 97 | self.pos += 1; |
| 98 | match esc { |
| 99 | b'"' => out.push('"'), |
| 100 | b'\\' => out.push('\\'), |
| 101 | b'/' => out.push('/'), |
| 102 | b'b' => out.push('\u{08}'), |
| 103 | b'f' => out.push('\u{0C}'), |
| 104 | b'n' => out.push('\n'), |
| 105 | b'r' => out.push('\r'), |
| 106 | b't' => out.push('\t'), |
| 107 | b'u' => { |
| 108 | let cp = self.read_hex4()?; |
| 109 | if (0xD800..=0xDBFF).contains(&cp) { |
| 110 | if self.src.len() < self.pos + 2 || self.src[self.pos] != b'\\' || self.src[self.pos + 1] != b'u' { |
| 111 | return Err(self.err("unpaired high surrogate")); |
| 112 | } |
| 113 | self.pos += 2; |
| 114 | let low = self.read_hex4()?; |
| 115 | if !(0xDC00..=0xDFFF).contains(&low) { |
| 116 | return Err(self.err("invalid low surrogate")); |
| 117 | } |
| 118 | let combined = 0x10000 + ((cp - 0xD800) << 10) + (low - 0xDC00); |
| 119 | out.push(char::from_u32(combined).ok_or_else(|| self.err("invalid surrogate pair"))?); |
| 120 | } else if (0xDC00..=0xDFFF).contains(&cp) { |
| 121 | return Err(self.err("unexpected low surrogate")); |
| 122 | } else { |
| 123 | out.push(char::from_u32(cp).ok_or_else(|| self.err("invalid unicode escape"))?); |
| 124 | } |
| 125 | } |
| 126 | _ => return Err(self.err("invalid escape")), |
| 127 | } |
| 128 | continue; |
| 129 | } |
| 130 | if c < 0x20 { return Err(self.err("control character in string")); } |
| 131 | let len = utf8_len(c).ok_or_else(|| self.err("invalid utf-8 lead byte"))?; |
| 132 | if self.pos + len > self.src.len() { return Err(self.err("truncated utf-8")); } |
| 133 | let bytes = &self.src[self.pos..self.pos + len]; |
| 134 | let s = core::str::from_utf8(bytes).map_err(|_| self.err("invalid utf-8"))?; |
| 135 | out.push_str(s); |
| 136 | self.pos += len; |
| 137 | } |
| 138 | Err(self.err("unterminated string")) |
| 139 | } |
| 140 | |
| 141 | fn read_hex4(&mut self) -> Result<u32, JsonError> { |
| 142 | if self.pos + 4 > self.src.len() { return Err(self.err("truncated \\u escape")); } |