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 {
293 match json {
294 JsonValue::Null => Value::Void,
295 JsonValue::Bool(b) => Value::Bool(b),
296 JsonValue::Number(n) => {
297 if n.fract() == 0.0 && n >= i64::MIN as f64 && n <= i64::MAX as f64 {
299 Value::Int(n as i64)
300 } else {
301 Value::Float(n)
302 }
303 }
304 JsonValue::String(s) => Value::String(Rc::new(s)),
305 JsonValue::Array(items) => {
306 let vals: Vec<Value> = items.into_iter().map(json_to_value).collect();
307 Value::Array(Rc::new(vals))
308 }
309 JsonValue::Object(map) => {
310 let mut fields = std::collections::BTreeMap::new();
311 for (key, val) in map {
312 fields.insert(key, json_to_value(val));
313 }
314 Value::Struct {
315 name: "Json".to_string(),
316 fields,
317 }
318 }
319 }
320}
321
322fn value_to_json(value: &Value) -> Result<JsonValue, String> {
323 match value {
324 Value::Void => Ok(JsonValue::Null),
325 Value::Bool(b) => Ok(JsonValue::Bool(*b)),
326 Value::Int(n) => Ok(JsonValue::Number(*n as f64)),
327 Value::Float(n) => {
328 if n.is_nan() || n.is_infinite() {
329 Ok(JsonValue::Null) } else {
331 Ok(JsonValue::Number(*n))
332 }
333 }
334 Value::String(s) => Ok(JsonValue::String((**s).clone())),
335 Value::Array(arr) => {
336 let items: Result<Vec<JsonValue>, String> =
337 arr.iter().map(value_to_json).collect();
338 Ok(JsonValue::Array(items?))
339 }
340 Value::Struct { fields, .. } => {
341 let mut map = BTreeMap::new();
342 let mut sorted_keys: Vec<&String> = fields.keys().collect();
344 sorted_keys.sort();
345 for key in sorted_keys {
346 if let Some(val) = fields.get(key) {
347 map.insert(key.clone(), value_to_json(val)?);
348 }
349 }
350 Ok(JsonValue::Object(map))
351 }
352 Value::Tuple(items) => {
353 let json_items: Result<Vec<JsonValue>, String> =
354 items.iter().map(value_to_json).collect();
355 Ok(JsonValue::Array(json_items?))
356 }
357 _ => Err(format!("cannot convert {} to JSON", value.type_name())),
358 }
359}
360
361fn emit_json(json: &JsonValue) -> String {
366 let mut out = String::new();
367 emit_value(&mut out, json);
368 out
369}
370
371fn emit_value(out: &mut String, json: &JsonValue) {
372 match json {
373 JsonValue::Null => out.push_str("null"),
374 JsonValue::Bool(true) => out.push_str("true"),
375 JsonValue::Bool(false) => out.push_str("false"),
376 JsonValue::Number(n) => {
377 if n.fract() == 0.0 && n.abs() < 1e15 {
378 out.push_str(&format!("{}", *n as i64));
380 } else {
381 out.push_str(&format!("{}", n));
382 }
383 }
384 JsonValue::String(s) => emit_string(out, s),
385 JsonValue::Array(items) => {
386 out.push('[');
387 for (i, item) in items.iter().enumerate() {
388 if i > 0 {
389 out.push(',');
390 }
391 emit_value(out, item);
392 }
393 out.push(']');
394 }
395 JsonValue::Object(map) => {
396 out.push('{');
397 for (i, (key, val)) in map.iter().enumerate() {
399 if i > 0 {
400 out.push(',');
401 }
402 emit_string(out, key);
403 out.push(':');
404 emit_value(out, val);
405 }
406 out.push('}');
407 }
408 }
409}
410
411fn emit_string(out: &mut String, s: &str) {
412 out.push('"');
413 for ch in s.chars() {
414 match ch {
415 '"' => out.push_str("\\\""),
416 '\\' => out.push_str("\\\\"),
417 '\n' => out.push_str("\\n"),
418 '\r' => out.push_str("\\r"),
419 '\t' => out.push_str("\\t"),
420 '\u{0008}' => out.push_str("\\b"),
421 '\u{000C}' => out.push_str("\\f"),
422 c if c < '\u{0020}' => {
423 out.push_str(&format!("\\u{:04x}", c as u32));
424 }
425 c => out.push(c),
426 }
427 }
428 out.push('"');
429}
430
431#[cfg(test)]
436mod tests {
437 use super::*;
438
439 #[test]
440 fn test_parse_null() {
441 let v = json_parse("null").unwrap();
442 assert!(matches!(v, Value::Void));
443 }
444
445 #[test]
446 fn test_parse_bool() {
447 assert!(matches!(json_parse("true").unwrap(), Value::Bool(true)));
448 assert!(matches!(json_parse("false").unwrap(), Value::Bool(false)));
449 }
450
451 #[test]
452 fn test_parse_integer() {
453 match json_parse("42").unwrap() {
454 Value::Int(n) => assert_eq!(n, 42),
455 other => panic!("expected Int, got {:?}", other),
456 }
457 }
458
459 #[test]
460 fn test_parse_float() {
461 match json_parse("3.14").unwrap() {
462 Value::Float(n) => assert!((n - 3.14).abs() < 1e-10),
463 other => panic!("expected Float, got {:?}", other),
464 }
465 }
466
467 #[test]
468 fn test_parse_string() {
469 match json_parse(r#""hello world""#).unwrap() {
470 Value::String(s) => assert_eq!(&*s, "hello world"),
471 other => panic!("expected String, got {:?}", other),
472 }
473 }
474
475 #[test]
476 fn test_parse_string_escapes() {
477 match json_parse(r#""line\nbreak\ttab""#).unwrap() {
478 Value::String(s) => assert_eq!(&*s, "line\nbreak\ttab"),
479 other => panic!("expected String, got {:?}", other),
480 }
481 }
482
483 #[test]
484 fn test_parse_array() {
485 let v = json_parse("[1, 2, 3]").unwrap();
486 match v {
487 Value::Array(arr) => {
488 assert_eq!(arr.len(), 3);
489 assert!(matches!(arr[0], Value::Int(1)));
490 assert!(matches!(arr[1], Value::Int(2)));
491 assert!(matches!(arr[2], Value::Int(3)));
492 }
493 other => panic!("expected Array, got {:?}", other),
494 }
495 }
496
497 #[test]
498 fn test_parse_object_sorted_keys() {
499 let v = json_parse(r#"{"z": 1, "a": 2, "m": 3}"#).unwrap();
500 match v {
501 Value::Struct { name, fields } => {
502 assert_eq!(name, "Json");
503 assert_eq!(fields.len(), 3);
504 assert!(matches!(fields.get("a"), Some(Value::Int(2))));
505 assert!(matches!(fields.get("z"), Some(Value::Int(1))));
506 }
507 other => panic!("expected Struct, got {:?}", other),
508 }
509 }
510
511 #[test]
512 fn test_parse_nested() {
513 let v = json_parse(r#"{"items": [1, {"nested": true}]}"#).unwrap();
514 match v {
515 Value::Struct { fields, .. } => {
516 match fields.get("items") {
517 Some(Value::Array(arr)) => {
518 assert_eq!(arr.len(), 2);
519 }
520 other => panic!("expected Array in items, got {:?}", other),
521 }
522 }
523 other => panic!("expected Struct, got {:?}", other),
524 }
525 }
526
527 #[test]
528 fn test_stringify_roundtrip() {
529 let input = r#"{"a":1,"b":"hello","c":[true,null]}"#;
530 let v = json_parse(input).unwrap();
531 let output = json_stringify(&v).unwrap();
532 assert_eq!(output, input);
533 }
534
535 #[test]
536 fn test_stringify_sorted_keys() {
537 let v = json_parse(r#"{"z":1,"a":2}"#).unwrap();
539 let output = json_stringify(&v).unwrap();
540 assert_eq!(output, r#"{"a":2,"z":1}"#);
541 }
542
543 #[test]
544 fn test_roundtrip_empty_object() {
545 let v = json_parse("{}").unwrap();
546 let output = json_stringify(&v).unwrap();
547 assert_eq!(output, "{}");
548 }
549
550 #[test]
551 fn test_roundtrip_empty_array() {
552 let v = json_parse("[]").unwrap();
553 let output = json_stringify(&v).unwrap();
554 assert_eq!(output, "[]");
555 }
556
557 #[test]
558 fn test_parse_negative_number() {
559 match json_parse("-42").unwrap() {
560 Value::Int(n) => assert_eq!(n, -42),
561 other => panic!("expected Int, got {:?}", other),
562 }
563 }
564
565 #[test]
566 fn test_parse_scientific_notation() {
567 match json_parse("1.5e2").unwrap() {
568 Value::Int(n) => assert_eq!(n, 150),
569 other => panic!("expected Int(150), got {:?}", other),
570 }
571 }
572
573 #[test]
574 fn test_stringify_nan_becomes_null() {
575 let output = json_stringify(&Value::Float(f64::NAN)).unwrap();
576 assert_eq!(output, "null");
577 }
578}