1use std::collections::BTreeMap;
10use std::rc::Rc;
11
12use crate::Value;
13
14#[derive(Debug, Clone, PartialEq)]
20pub enum JsonValue {
21 Null,
22 Bool(bool),
23 Number(f64),
24 String(String),
25 Array(Vec<JsonValue>),
26 Object(BTreeMap<String, JsonValue>),
27}
28
29struct JsonParser<'a> {
35 input: &'a [u8],
36 pos: usize,
37}
38
39impl<'a> JsonParser<'a> {
40 fn new(input: &'a str) -> Self {
41 Self {
42 input: input.as_bytes(),
43 pos: 0,
44 }
45 }
46
47 fn peek(&self) -> Option<u8> {
48 self.input.get(self.pos).copied()
49 }
50
51 fn advance(&mut self) -> Option<u8> {
52 let ch = self.input.get(self.pos).copied();
53 if ch.is_some() {
54 self.pos += 1;
55 }
56 ch
57 }
58
59 fn skip_whitespace(&mut self) {
60 while let Some(ch) = self.peek() {
61 if ch == b' ' || ch == b'\t' || ch == b'\n' || ch == b'\r' {
62 self.pos += 1;
63 } else {
64 break;
65 }
66 }
67 }
68
69 fn expect(&mut self, expected: u8) -> Result<(), String> {
70 match self.advance() {
71 Some(ch) if ch == expected => Ok(()),
72 Some(ch) => Err(format!(
73 "expected '{}', found '{}' at position {}",
74 expected as char, ch as char, self.pos - 1
75 )),
76 None => Err(format!("unexpected end of input, expected '{}'", expected as char)),
77 }
78 }
79
80 fn parse_value(&mut self) -> Result<JsonValue, String> {
81 self.skip_whitespace();
82 match self.peek() {
83 None => Err("unexpected end of input".into()),
84 Some(b'"') => self.parse_string().map(JsonValue::String),
85 Some(b'{') => self.parse_object(),
86 Some(b'[') => self.parse_array(),
87 Some(b't') => self.parse_literal("true", JsonValue::Bool(true)),
88 Some(b'f') => self.parse_literal("false", JsonValue::Bool(false)),
89 Some(b'n') => self.parse_literal("null", JsonValue::Null),
90 Some(ch) if ch == b'-' || ch.is_ascii_digit() => self.parse_number(),
91 Some(ch) => Err(format!("unexpected character '{}' at position {}", ch as char, self.pos)),
92 }
93 }
94
95 fn parse_string(&mut self) -> Result<String, String> {
96 self.expect(b'"')?;
97 let mut result = String::new();
98 loop {
99 match self.advance() {
100 None => return Err("unterminated string".into()),
101 Some(b'"') => return Ok(result),
102 Some(b'\\') => {
103 match self.advance() {
104 Some(b'"') => result.push('"'),
105 Some(b'\\') => result.push('\\'),
106 Some(b'/') => result.push('/'),
107 Some(b'b') => result.push('\u{0008}'),
108 Some(b'f') => result.push('\u{000C}'),
109 Some(b'n') => result.push('\n'),
110 Some(b'r') => result.push('\r'),
111 Some(b't') => result.push('\t'),
112 Some(b'u') => {
113 let hex = self.parse_hex4()?;
114 if let Some(ch) = char::from_u32(hex) {
115 result.push(ch);
116 } else {
117 result.push('\u{FFFD}');
118 }
119 }
120 Some(ch) => return Err(format!("invalid escape '\\{}'", ch as char)),
121 None => return Err("unterminated escape sequence".into()),
122 }
123 }
124 Some(ch) => result.push(ch as char),
125 }
126 }
127 }
128
129 fn parse_hex4(&mut self) -> Result<u32, String> {
130 let mut value = 0u32;
131 for _ in 0..4 {
132 let ch = self.advance().ok_or("unexpected end in \\uXXXX")?;
133 let digit = match ch {
134 b'0'..=b'9' => (ch - b'0') as u32,
135 b'a'..=b'f' => (ch - b'a' + 10) as u32,
136 b'A'..=b'F' => (ch - b'A' + 10) as u32,
137 _ => return Err(format!("invalid hex digit '{}' in \\uXXXX", ch as char)),
138 };
139 value = value * 16 + digit;
140 }
141 Ok(value)
142 }
143
144 fn parse_number(&mut self) -> Result<JsonValue, String> {
145 let start = self.pos;
146 if self.peek() == Some(b'-') {
148 self.pos += 1;
149 }
150 if self.peek() == Some(b'0') {
152 self.pos += 1;
153 } else {
154 if !self.peek().map_or(false, |c| c.is_ascii_digit()) {
155 return Err("expected digit".into());
156 }
157 while self.peek().map_or(false, |c| c.is_ascii_digit()) {
158 self.pos += 1;
159 }
160 }
161 if self.peek() == Some(b'.') {
163 self.pos += 1;
164 while self.peek().map_or(false, |c| c.is_ascii_digit()) {
165 self.pos += 1;
166 }
167 }
168 if self.peek() == Some(b'e') || self.peek() == Some(b'E') {
170 self.pos += 1;
171 if self.peek() == Some(b'+') || self.peek() == Some(b'-') {
172 self.pos += 1;
173 }
174 while self.peek().map_or(false, |c| c.is_ascii_digit()) {
175 self.pos += 1;
176 }
177 }
178 let num_str = std::str::from_utf8(&self.input[start..self.pos])
179 .map_err(|_| "invalid UTF-8 in number")?;
180 let value: f64 = num_str
181 .parse()
182 .map_err(|_| format!("invalid number: {}", num_str))?;
183 Ok(JsonValue::Number(value))
184 }
185
186 fn parse_array(&mut self) -> Result<JsonValue, String> {
187 self.expect(b'[')?;
188 self.skip_whitespace();
189 let mut items = Vec::new();
190 if self.peek() == Some(b']') {
191 self.pos += 1;
192 return Ok(JsonValue::Array(items));
193 }
194 loop {
195 items.push(self.parse_value()?);
196 self.skip_whitespace();
197 match self.peek() {
198 Some(b',') => {
199 self.pos += 1;
200 }
201 Some(b']') => {
202 self.pos += 1;
203 return Ok(JsonValue::Array(items));
204 }
205 _ => return Err("expected ',' or ']' in array".into()),
206 }
207 }
208 }
209
210 fn parse_object(&mut self) -> Result<JsonValue, String> {
211 self.expect(b'{')?;
212 self.skip_whitespace();
213 let mut map = BTreeMap::new();
214 if self.peek() == Some(b'}') {
215 self.pos += 1;
216 return Ok(JsonValue::Object(map));
217 }
218 loop {
219 self.skip_whitespace();
220 let key = self.parse_string()?;
221 self.skip_whitespace();
222 self.expect(b':')?;
223 let value = self.parse_value()?;
224 map.insert(key, value);
225 self.skip_whitespace();
226 match self.peek() {
227 Some(b',') => {
228 self.pos += 1;
229 }
230 Some(b'}') => {
231 self.pos += 1;
232 return Ok(JsonValue::Object(map));
233 }
234 _ => return Err("expected ',' or '}' in object".into()),
235 }
236 }
237 }
238
239 fn parse_literal(&mut self, expected: &str, value: JsonValue) -> Result<JsonValue, String> {
240 for byte in expected.as_bytes() {
241 match self.advance() {
242 Some(ch) if ch == *byte => {}
243 _ => return Err(format!("expected '{}'", expected)),
244 }
245 }
246 Ok(value)
247 }
248}
249
250pub fn json_parse(input: &str) -> Result<Value, String> {
264 let mut parser = JsonParser::new(input);
265 let json = parser.parse_value()?;
266 parser.skip_whitespace();
267 if parser.pos < parser.input.len() {
268 return Err(format!(
269 "trailing content at position {}",
270 parser.pos
271 ));
272 }
273 Ok(json_to_value(json))
274}
275
276pub fn json_stringify(value: &Value) -> Result<String, String> {
278 let json = value_to_json(value)?;
279 Ok(emit_json(&json))
280}
281
282fn json_to_value(json: JsonValue) -> Value {
287 match json {
288 JsonValue::Null => Value::Void,
289 JsonValue::Bool(b) => Value::Bool(b),
290 JsonValue::Number(n) => {
291 if n.fract() == 0.0 && n >= i64::MIN as f64 && n <= i64::MAX as f64 {
293 Value::Int(n as i64)
294 } else {
295 Value::Float(n)
296 }
297 }
298 JsonValue::String(s) => Value::String(Rc::new(s)),
299 JsonValue::Array(items) => {
300 let vals: Vec<Value> = items.into_iter().map(json_to_value).collect();
301 Value::Array(Rc::new(vals))
302 }
303 JsonValue::Object(map) => {
304 let mut fields = std::collections::BTreeMap::new();
305 for (key, val) in map {
306 fields.insert(key, json_to_value(val));
307 }
308 Value::Struct {
309 name: "Json".to_string(),
310 fields,
311 }
312 }
313 }
314}
315
316fn value_to_json(value: &Value) -> Result<JsonValue, String> {
317 match value {
318 Value::Void => Ok(JsonValue::Null),
319 Value::Bool(b) => Ok(JsonValue::Bool(*b)),
320 Value::Int(n) => Ok(JsonValue::Number(*n as f64)),
321 Value::Float(n) => {
322 if n.is_nan() || n.is_infinite() {
323 Ok(JsonValue::Null) } else {
325 Ok(JsonValue::Number(*n))
326 }
327 }
328 Value::String(s) => Ok(JsonValue::String((**s).clone())),
329 Value::Array(arr) => {
330 let items: Result<Vec<JsonValue>, String> =
331 arr.iter().map(value_to_json).collect();
332 Ok(JsonValue::Array(items?))
333 }
334 Value::Struct { fields, .. } => {
335 let mut map = BTreeMap::new();
336 let mut sorted_keys: Vec<&String> = fields.keys().collect();
338 sorted_keys.sort();
339 for key in sorted_keys {
340 if let Some(val) = fields.get(key) {
341 map.insert(key.clone(), value_to_json(val)?);
342 }
343 }
344 Ok(JsonValue::Object(map))
345 }
346 Value::Tuple(items) => {
347 let json_items: Result<Vec<JsonValue>, String> =
348 items.iter().map(value_to_json).collect();
349 Ok(JsonValue::Array(json_items?))
350 }
351 _ => Err(format!("cannot convert {} to JSON", value.type_name())),
352 }
353}
354
355fn emit_json(json: &JsonValue) -> String {
360 let mut out = String::new();
361 emit_value(&mut out, json);
362 out
363}
364
365fn emit_value(out: &mut String, json: &JsonValue) {
366 match json {
367 JsonValue::Null => out.push_str("null"),
368 JsonValue::Bool(true) => out.push_str("true"),
369 JsonValue::Bool(false) => out.push_str("false"),
370 JsonValue::Number(n) => {
371 if n.fract() == 0.0 && n.abs() < 1e15 {
372 out.push_str(&format!("{}", *n as i64));
374 } else {
375 out.push_str(&format!("{}", n));
376 }
377 }
378 JsonValue::String(s) => emit_string(out, s),
379 JsonValue::Array(items) => {
380 out.push('[');
381 for (i, item) in items.iter().enumerate() {
382 if i > 0 {
383 out.push(',');
384 }
385 emit_value(out, item);
386 }
387 out.push(']');
388 }
389 JsonValue::Object(map) => {
390 out.push('{');
391 for (i, (key, val)) in map.iter().enumerate() {
393 if i > 0 {
394 out.push(',');
395 }
396 emit_string(out, key);
397 out.push(':');
398 emit_value(out, val);
399 }
400 out.push('}');
401 }
402 }
403}
404
405fn emit_string(out: &mut String, s: &str) {
406 out.push('"');
407 for ch in s.chars() {
408 match ch {
409 '"' => out.push_str("\\\""),
410 '\\' => out.push_str("\\\\"),
411 '\n' => out.push_str("\\n"),
412 '\r' => out.push_str("\\r"),
413 '\t' => out.push_str("\\t"),
414 '\u{0008}' => out.push_str("\\b"),
415 '\u{000C}' => out.push_str("\\f"),
416 c if c < '\u{0020}' => {
417 out.push_str(&format!("\\u{:04x}", c as u32));
418 }
419 c => out.push(c),
420 }
421 }
422 out.push('"');
423}
424
425#[cfg(test)]
430mod tests {
431 use super::*;
432
433 #[test]
434 fn test_parse_null() {
435 let v = json_parse("null").unwrap();
436 assert!(matches!(v, Value::Void));
437 }
438
439 #[test]
440 fn test_parse_bool() {
441 assert!(matches!(json_parse("true").unwrap(), Value::Bool(true)));
442 assert!(matches!(json_parse("false").unwrap(), Value::Bool(false)));
443 }
444
445 #[test]
446 fn test_parse_integer() {
447 match json_parse("42").unwrap() {
448 Value::Int(n) => assert_eq!(n, 42),
449 other => panic!("expected Int, got {:?}", other),
450 }
451 }
452
453 #[test]
454 fn test_parse_float() {
455 match json_parse("3.14").unwrap() {
456 Value::Float(n) => assert!((n - 3.14).abs() < 1e-10),
457 other => panic!("expected Float, got {:?}", other),
458 }
459 }
460
461 #[test]
462 fn test_parse_string() {
463 match json_parse(r#""hello world""#).unwrap() {
464 Value::String(s) => assert_eq!(&*s, "hello world"),
465 other => panic!("expected String, got {:?}", other),
466 }
467 }
468
469 #[test]
470 fn test_parse_string_escapes() {
471 match json_parse(r#""line\nbreak\ttab""#).unwrap() {
472 Value::String(s) => assert_eq!(&*s, "line\nbreak\ttab"),
473 other => panic!("expected String, got {:?}", other),
474 }
475 }
476
477 #[test]
478 fn test_parse_array() {
479 let v = json_parse("[1, 2, 3]").unwrap();
480 match v {
481 Value::Array(arr) => {
482 assert_eq!(arr.len(), 3);
483 assert!(matches!(arr[0], Value::Int(1)));
484 assert!(matches!(arr[1], Value::Int(2)));
485 assert!(matches!(arr[2], Value::Int(3)));
486 }
487 other => panic!("expected Array, got {:?}", other),
488 }
489 }
490
491 #[test]
492 fn test_parse_object_sorted_keys() {
493 let v = json_parse(r#"{"z": 1, "a": 2, "m": 3}"#).unwrap();
494 match v {
495 Value::Struct { name, fields } => {
496 assert_eq!(name, "Json");
497 assert_eq!(fields.len(), 3);
498 assert!(matches!(fields.get("a"), Some(Value::Int(2))));
499 assert!(matches!(fields.get("z"), Some(Value::Int(1))));
500 }
501 other => panic!("expected Struct, got {:?}", other),
502 }
503 }
504
505 #[test]
506 fn test_parse_nested() {
507 let v = json_parse(r#"{"items": [1, {"nested": true}]}"#).unwrap();
508 match v {
509 Value::Struct { fields, .. } => {
510 match fields.get("items") {
511 Some(Value::Array(arr)) => {
512 assert_eq!(arr.len(), 2);
513 }
514 other => panic!("expected Array in items, got {:?}", other),
515 }
516 }
517 other => panic!("expected Struct, got {:?}", other),
518 }
519 }
520
521 #[test]
522 fn test_stringify_roundtrip() {
523 let input = r#"{"a":1,"b":"hello","c":[true,null]}"#;
524 let v = json_parse(input).unwrap();
525 let output = json_stringify(&v).unwrap();
526 assert_eq!(output, input);
527 }
528
529 #[test]
530 fn test_stringify_sorted_keys() {
531 let v = json_parse(r#"{"z":1,"a":2}"#).unwrap();
533 let output = json_stringify(&v).unwrap();
534 assert_eq!(output, r#"{"a":2,"z":1}"#);
535 }
536
537 #[test]
538 fn test_roundtrip_empty_object() {
539 let v = json_parse("{}").unwrap();
540 let output = json_stringify(&v).unwrap();
541 assert_eq!(output, "{}");
542 }
543
544 #[test]
545 fn test_roundtrip_empty_array() {
546 let v = json_parse("[]").unwrap();
547 let output = json_stringify(&v).unwrap();
548 assert_eq!(output, "[]");
549 }
550
551 #[test]
552 fn test_parse_negative_number() {
553 match json_parse("-42").unwrap() {
554 Value::Int(n) => assert_eq!(n, -42),
555 other => panic!("expected Int, got {:?}", other),
556 }
557 }
558
559 #[test]
560 fn test_parse_scientific_notation() {
561 match json_parse("1.5e2").unwrap() {
562 Value::Int(n) => assert_eq!(n, 150),
563 other => panic!("expected Int(150), got {:?}", other),
564 }
565 }
566
567 #[test]
568 fn test_stringify_nan_becomes_null() {
569 let output = json_stringify(&Value::Float(f64::NAN)).unwrap();
570 assert_eq!(output, "null");
571 }
572}