| 207 | /// Process a single byte and return the transformed byte (if any) |
| 208 | #[inline] |
| 209 | fn process_byte(&mut self, byte: u8) -> Option<u8> { |
| 210 | match self.state { |
| 211 | JsonArrayState::Start => { |
| 212 | // Looking for the opening '[', skip whitespace |
| 213 | if byte == b'[' { |
| 214 | self.state = JsonArrayState::InArray; |
| 215 | } else if !byte.is_ascii_whitespace() { |
| 216 | self.has_leading_content = true; |
| 217 | } |
| 218 | None |
| 219 | } |
| 220 | JsonArrayState::InArray => { |
| 221 | // Handle escape sequences in strings |
| 222 | if self.escape_next { |
| 223 | self.escape_next = false; |
| 224 | return Some(byte); |
| 225 | } |
| 226 | |
| 227 | if self.in_string { |
| 228 | // Inside a string: handle escape and closing quote |
| 229 | match byte { |
| 230 | b'\\' => self.escape_next = true, |
| 231 | b'"' => self.in_string = false, |
| 232 | _ => {} |
| 233 | } |
| 234 | Some(byte) |
| 235 | } else { |
| 236 | // Outside strings: track depth and transform |
| 237 | match byte { |
| 238 | b'"' => { |
| 239 | self.in_string = true; |
| 240 | Some(byte) |
| 241 | } |
| 242 | b'{' | b'[' => { |
| 243 | self.depth += 1; |
| 244 | Some(byte) |
| 245 | } |
| 246 | b'}' => { |
| 247 | self.depth -= 1; |
| 248 | Some(byte) |
| 249 | } |
| 250 | b']' => { |
| 251 | if self.depth == 0 { |
| 252 | // Top-level ']' means end of array |
| 253 | self.state = JsonArrayState::Done; |
| 254 | None |
| 255 | } else { |
| 256 | // Nested ']' inside an object |
| 257 | self.depth -= 1; |
| 258 | Some(byte) |
| 259 | } |
| 260 | } |
| 261 | b',' if self.depth == 0 => { |
| 262 | // Top-level comma between objects → newline |
| 263 | Some(b'\n') |
| 264 | } |
| 265 | _ => { |
| 266 | // At depth 0, skip whitespace between objects |