(chars: &[char], pos: &mut usize)
| 197 | } |
| 198 | |
| 199 | fn parse_array(chars: &[char], pos: &mut usize) -> Result<Vec<Value>, SqlError> { |
| 200 | // Expect '[' |
| 201 | if *pos >= chars.len() || chars[*pos] != '[' { |
| 202 | return Err(SqlError::Parse { |
| 203 | detail: format!( |
| 204 | "expected '[' at position {pos}, found {:?}", |
| 205 | chars.get(*pos) |
| 206 | ), |
| 207 | }); |
| 208 | } |
| 209 | *pos += 1; // consume '[' |
| 210 | let mut items = Vec::new(); |
| 211 | loop { |
| 212 | skip_ws(chars, pos); |
| 213 | if *pos >= chars.len() { |
| 214 | return Err(SqlError::Parse { |
| 215 | detail: "unterminated array literal".to_string(), |
| 216 | }); |
| 217 | } |
| 218 | if chars[*pos] == ']' { |
| 219 | *pos += 1; // consume ']' |
| 220 | break; |
| 221 | } |
| 222 | // trailing comma already consumed; skip it |
| 223 | if chars[*pos] == ',' { |
| 224 | *pos += 1; |
| 225 | continue; |
| 226 | } |
| 227 | let val = parse_value(chars, pos)?; |
| 228 | items.push(val); |
| 229 | skip_ws(chars, pos); |
| 230 | if *pos < chars.len() && chars[*pos] == ',' { |
| 231 | *pos += 1; // consume ',' |
| 232 | } |
| 233 | } |
| 234 | Ok(items) |
| 235 | } |
| 236 | |
| 237 | fn parse_object(chars: &[char], pos: &mut usize) -> Result<HashMap<String, Value>, SqlError> { |
| 238 | // Expect '{' |
no test coverage detected