1use crate::error::{err, ErrorCode, Result};
8use core::cmp::Ordering;
9
10pub const MAX_DEPTH: usize = 64;
12
13#[derive(Clone, Debug, PartialEq)]
15pub struct Number {
16 text: String,
17 value: f64,
18}
19
20impl Number {
21 pub fn text(&self) -> &str {
23 &self.text
24 }
25
26 pub fn value(&self) -> f64 {
28 self.value
29 }
30
31 pub fn from_f64(value: f64) -> Option<Number> {
33 if value.is_finite() {
34 Some(Number { text: format_number(value), value })
35 } else {
36 None
37 }
38 }
39}
40
41#[derive(Clone, Debug, PartialEq)]
43pub enum Value {
44 Null,
46 Bool(bool),
48 Number(Number),
50 String(String),
52 Array(Vec<Value>),
54 Object(Vec<(String, Value)>),
56}
57
58impl Value {
59 pub fn get(&self, name: &str) -> Option<&Value> {
61 match self {
62 Value::Object(m) => m.iter().find(|(k, _)| k == name).map(|(_, v)| v),
63 _ => None,
64 }
65 }
66
67 pub fn as_str(&self) -> Option<&str> {
69 match self {
70 Value::String(s) => Some(s),
71 _ => None,
72 }
73 }
74
75 pub fn as_object(&self) -> Option<&[(String, Value)]> {
77 match self {
78 Value::Object(m) => Some(m),
79 _ => None,
80 }
81 }
82
83 pub(crate) fn kind(&self) -> &'static str {
85 match self {
86 Value::Null => "null",
87 Value::Bool(_) => "a boolean",
88 Value::Number(_) => "a number",
89 Value::String(_) => "a string",
90 Value::Array(_) => "an array",
91 Value::Object(_) => "an object",
92 }
93 }
94
95 pub fn to_jcs(&self) -> Vec<u8> {
97 let mut out = String::new();
98 write_jcs(self, &mut out);
99 out.into_bytes()
100 }
101
102 pub fn to_jcs_string(&self) -> String {
104 let mut out = String::new();
105 write_jcs(self, &mut out);
106 out
107 }
108}
109
110pub(crate) fn jcs_sorted(members: &[(String, Value)]) -> Vec<&(String, Value)> {
112 let mut v: Vec<&(String, Value)> = members.iter().collect();
113 v.sort_by(|a, b| utf16_cmp(&a.0, &b.0));
114 v
115}
116
117pub(crate) fn utf16_cmp(a: &str, b: &str) -> Ordering {
119 a.encode_utf16().cmp(b.encode_utf16())
120}
121
122pub fn parse(bytes: &[u8]) -> Result<Value> {
129 if bytes.starts_with(&[0xEF, 0xBB, 0xBF]) {
130 return err(ErrorCode::ParseJson, "$", "byte order mark");
131 }
132 let text = match core::str::from_utf8(bytes) {
133 Ok(t) => t,
134 Err(e) => return err(ErrorCode::ParseJson, "$", format!("invalid UTF-8 at byte {}", e.valid_up_to())),
135 };
136 check_depth(text.as_bytes())?;
137 let mut p = Parser { b: text.as_bytes(), i: 0, lone_surrogate: false };
138 p.ws();
139 let v = p.value()?;
140 p.ws();
141 if p.i != p.b.len() {
142 return p.syntax("extra data after the value");
143 }
144 if p.lone_surrogate {
145 return err(ErrorCode::ParseJson, "$", "lone surrogate");
146 }
147 Ok(v)
148}
149
150pub fn canonicalize_json(bytes: &[u8]) -> Result<Vec<u8>> {
152 Ok(parse(bytes)?.to_jcs())
153}
154
155fn check_depth(b: &[u8]) -> Result<()> {
156 let mut depth: usize = 0;
157 let mut in_str = false;
158 let mut esc = false;
159 for &c in b {
160 if in_str {
161 if esc {
162 esc = false;
163 } else if c == b'\\' {
164 esc = true;
165 } else if c == b'"' {
166 in_str = false;
167 }
168 continue;
169 }
170 match c {
171 b'"' => in_str = true,
172 b'[' | b'{' => {
173 depth += 1;
174 if depth > MAX_DEPTH {
175 return err(ErrorCode::ParseJson, "$", format!("nested deeper than {MAX_DEPTH} levels"));
176 }
177 }
178 b']' | b'}' => depth = depth.saturating_sub(1),
179 _ => {}
180 }
181 }
182 Ok(())
183}
184
185struct Parser<'a> {
186 b: &'a [u8],
187 i: usize,
188 lone_surrogate: bool,
189}
190
191impl Parser<'_> {
192 fn syntax<T>(&self, what: &str) -> Result<T> {
193 err(ErrorCode::ParseJson, "$", format!("{what} at byte {}", self.i))
194 }
195
196 fn peek(&self) -> Option<u8> {
197 self.b.get(self.i).copied()
198 }
199
200 fn ws(&mut self) {
201 while let Some(b' ' | b'\t' | b'\n' | b'\r') = self.peek() {
202 self.i += 1;
203 }
204 }
205
206 fn lit(&mut self, word: &[u8], v: Value) -> Result<Value> {
207 if self.b.get(self.i..self.i + word.len()) == Some(word) {
208 self.i += word.len();
209 Ok(v)
210 } else {
211 self.syntax("invalid literal")
212 }
213 }
214
215 fn value(&mut self) -> Result<Value> {
217 match self.peek() {
218 Some(b'{') => self.object(),
219 Some(b'[') => self.array(),
220 Some(b'"') => Ok(Value::String(self.string()?.0)),
221 Some(b't') => self.lit(b"true", Value::Bool(true)),
222 Some(b'f') => self.lit(b"false", Value::Bool(false)),
223 Some(b'n') => self.lit(b"null", Value::Null),
224 Some(b'-' | b'0'..=b'9') => self.number(),
225 Some(_) => self.syntax("unexpected character"),
226 None => self.syntax("unexpected end of text"),
227 }
228 }
229
230 fn array(&mut self) -> Result<Value> {
231 self.i += 1;
232 let mut items = Vec::new();
233 self.ws();
234 if self.peek() == Some(b']') {
235 self.i += 1;
236 return Ok(Value::Array(items));
237 }
238 loop {
239 self.ws();
240 items.push(self.value()?);
241 self.ws();
242 match self.peek() {
243 Some(b',') => self.i += 1,
244 Some(b']') => {
245 self.i += 1;
246 return Ok(Value::Array(items));
247 }
248 _ => return self.syntax("expected ',' or ']'"),
249 }
250 }
251 }
252
253 fn object(&mut self) -> Result<Value> {
254 self.i += 1;
255 let mut members: Vec<(String, Value)> = Vec::new();
256 let mut units: Vec<Vec<u16>> = Vec::new();
257 self.ws();
258 if self.peek() == Some(b'}') {
259 self.i += 1;
260 return Ok(Value::Object(members));
261 }
262 loop {
263 self.ws();
264 if self.peek() != Some(b'"') {
265 return self.syntax("expected a member name");
266 }
267 let (name, name_units) = self.string()?;
268 self.ws();
269 if self.peek() != Some(b':') {
270 return self.syntax("expected ':'");
271 }
272 self.i += 1;
273 self.ws();
274 let v = self.value()?;
275 members.push((name, v));
276 units.push(name_units);
277 self.ws();
278 match self.peek() {
279 Some(b',') => self.i += 1,
280 Some(b'}') => {
281 self.i += 1;
282 break;
283 }
284 _ => return self.syntax("expected ',' or '}'"),
285 }
286 }
287 let mut order: Vec<usize> = (0..units.len()).collect();
289 order.sort_by(|&a, &b| units[a].cmp(&units[b]).then(a.cmp(&b)));
290 let mut dup: Option<usize> = None;
291 for w in order.windows(2) {
292 if units[w[0]] == units[w[1]] {
293 let second = w[0].max(w[1]);
294 dup = Some(dup.map_or(second, |d| d.min(second)));
295 }
296 }
297 if let Some(d) = dup {
298 let name = members.get(d).map(|m| m.0.as_str()).unwrap_or("");
299 return err(ErrorCode::ParseDuplicateKey, "$", format!("duplicate member '{name}'"));
300 }
301 Ok(Value::Object(members))
302 }
303
304 fn hex4(&mut self) -> Result<u16> {
305 let mut v: u16 = 0;
306 for _ in 0..4 {
307 let d = match self.peek() {
308 Some(c @ b'0'..=b'9') => c - b'0',
309 Some(c @ b'a'..=b'f') => c - b'a' + 10,
310 Some(c @ b'A'..=b'F') => c - b'A' + 10,
311 _ => return self.syntax("invalid \\u escape"),
312 };
313 v = (v << 4) | u16::from(d);
314 self.i += 1;
315 }
316 Ok(v)
317 }
318
319 fn string(&mut self) -> Result<(String, Vec<u16>)> {
322 self.i += 1;
323 let mut units: Vec<u16> = Vec::new();
324 loop {
325 let c = match self.peek() {
326 None => return self.syntax("unterminated string"),
327 Some(c) => c,
328 };
329 match c {
330 b'"' => {
331 self.i += 1;
332 break;
333 }
334 b'\\' => {
335 self.i += 1;
336 let e = match self.peek() {
337 Some(e) => e,
338 None => return self.syntax("unterminated string"),
339 };
340 self.i += 1;
341 let u = match e {
342 b'"' => 0x22,
343 b'\\' => 0x5C,
344 b'/' => 0x2F,
345 b'b' => 0x08,
346 b'f' => 0x0C,
347 b'n' => 0x0A,
348 b'r' => 0x0D,
349 b't' => 0x09,
350 b'u' => self.hex4()?,
351 _ => {
352 self.i -= 1;
353 return self.syntax("invalid escape");
354 }
355 };
356 units.push(u);
357 }
358 0x00..=0x1F => return self.syntax("control character in string"),
359 _ => {
360 let len = match c {
362 0x00..=0x7F => 1,
363 0xC0..=0xDF => 2,
364 0xE0..=0xEF => 3,
365 _ => 4,
366 };
367 let chunk = self.b.get(self.i..self.i + len).unwrap_or(&[]);
368 match core::str::from_utf8(chunk).ok().and_then(|s| s.chars().next()) {
369 Some(ch) => {
370 let mut buf = [0u16; 2];
371 units.extend_from_slice(ch.encode_utf16(&mut buf));
372 }
373 None => return self.syntax("invalid UTF-8"),
374 }
375 self.i += len;
376 }
377 }
378 }
379 let mut s = String::with_capacity(units.len());
380 for r in char::decode_utf16(units.iter().copied()) {
381 match r {
382 Ok(ch) => s.push(ch),
383 Err(_) => {
384 self.lone_surrogate = true;
385 s.push('\u{FFFD}');
386 }
387 }
388 }
389 Ok((s, units))
390 }
391
392 fn number(&mut self) -> Result<Value> {
393 let start = self.i;
394 if self.peek() == Some(b'-') {
395 self.i += 1;
396 }
397 match self.peek() {
398 Some(b'0') => self.i += 1,
399 Some(b'1'..=b'9') => {
400 while let Some(b'0'..=b'9') = self.peek() {
401 self.i += 1;
402 }
403 }
404 _ => return self.syntax("invalid number"),
405 }
406 if self.peek() == Some(b'.') {
407 self.i += 1;
408 if !matches!(self.peek(), Some(b'0'..=b'9')) {
409 return self.syntax("invalid number");
410 }
411 while let Some(b'0'..=b'9') = self.peek() {
412 self.i += 1;
413 }
414 }
415 if let Some(b'e' | b'E') = self.peek() {
416 self.i += 1;
417 if let Some(b'+' | b'-') = self.peek() {
418 self.i += 1;
419 }
420 if !matches!(self.peek(), Some(b'0'..=b'9')) {
421 return self.syntax("invalid number");
422 }
423 while let Some(b'0'..=b'9') = self.peek() {
424 self.i += 1;
425 }
426 }
427 let text = core::str::from_utf8(self.b.get(start..self.i).unwrap_or(&[])).unwrap_or("");
428 let value: f64 = match text.parse() {
429 Ok(v) => v,
430 Err(_) => return self.syntax("invalid number"),
431 };
432 if !value.is_finite() {
433 return err(ErrorCode::ParseJson, "$", format!("number out of IEEE 754 range: {text}"));
434 }
435 Ok(Value::Number(Number { text: text.to_string(), value }))
436 }
437}
438
439enum Piece<'a> {
440 Value(&'a Value),
441 Text(&'static str),
442 Key(&'a str),
443}
444
445fn write_jcs(v: &Value, out: &mut String) {
447 let mut stack = vec![Piece::Value(v)];
448 while let Some(p) = stack.pop() {
449 match p {
450 Piece::Text(t) => out.push_str(t),
451 Piece::Key(k) => {
452 write_string(k, out);
453 out.push(':');
454 }
455 Piece::Value(Value::Null) => out.push_str("null"),
456 Piece::Value(Value::Bool(true)) => out.push_str("true"),
457 Piece::Value(Value::Bool(false)) => out.push_str("false"),
458 Piece::Value(Value::Number(n)) => out.push_str(&format_number(n.value)),
459 Piece::Value(Value::String(s)) => write_string(s, out),
460 Piece::Value(Value::Array(items)) => {
461 out.push('[');
462 stack.push(Piece::Text("]"));
463 for (i, item) in items.iter().enumerate().rev() {
464 stack.push(Piece::Value(item));
465 if i > 0 {
466 stack.push(Piece::Text(","));
467 }
468 }
469 }
470 Piece::Value(Value::Object(members)) => {
471 out.push('{');
472 stack.push(Piece::Text("}"));
473 for (i, (k, val)) in jcs_sorted(members).into_iter().enumerate().rev() {
474 stack.push(Piece::Value(val));
475 stack.push(Piece::Key(k));
476 if i > 0 {
477 stack.push(Piece::Text(","));
478 }
479 }
480 }
481 }
482 }
483}
484
485pub fn check_value_depth(v: &Value) -> Result<()> {
488 let mut stack: Vec<(&Value, usize)> = vec![(v, 0)];
489 while let Some((v, d)) = stack.pop() {
490 let children: Box<dyn Iterator<Item = &Value>> = match v {
491 Value::Array(items) => Box::new(items.iter()),
492 Value::Object(members) => Box::new(members.iter().map(|(_, x)| x)),
493 _ => continue,
494 };
495 if d + 1 > MAX_DEPTH {
496 return err(ErrorCode::ParseJson, "$", format!("nested deeper than {MAX_DEPTH} levels"));
497 }
498 stack.extend(children.map(|c| (c, d + 1)));
499 }
500 Ok(())
501}
502
503pub(crate) fn write_string(s: &str, out: &mut String) {
505 out.push('"');
506 for c in s.chars() {
507 match c {
508 '"' => out.push_str("\\\""),
509 '\\' => out.push_str("\\\\"),
510 '\u{08}' => out.push_str("\\b"),
511 '\u{09}' => out.push_str("\\t"),
512 '\u{0A}' => out.push_str("\\n"),
513 '\u{0C}' => out.push_str("\\f"),
514 '\u{0D}' => out.push_str("\\r"),
515 c if (c as u32) < 0x20 => {
516 const HEX: &[u8; 16] = b"0123456789abcdef";
517 let n = c as usize;
518 out.push_str("\\u00");
519 out.push(char::from(HEX[(n >> 4) & 0xF]));
520 out.push(char::from(HEX[n & 0xF]));
521 }
522 c => out.push(c),
523 }
524 }
525 out.push('"');
526}
527
528fn split_sci(sci: &str) -> (String, i64) {
529 let (mantissa, exp) = sci.split_once('e').unwrap_or((sci, "0"));
530 (mantissa.chars().filter(char::is_ascii_digit).collect(), exp.parse().unwrap_or(0))
531}
532
533fn shortest_digits(v: f64) -> (String, i64) {
539 let shortest = split_sci(&format!("{v:e}"));
540 let k = shortest.0.len();
541 let exact_text = format!("{:.*e}", k.saturating_sub(1), v);
542 if exact_text.parse::<f64>() == Ok(v) {
543 let exact = split_sci(&exact_text);
544 if exact.0.len() == k {
545 return exact;
546 }
547 }
548 shortest
549}
550
551pub fn format_number(v: f64) -> String {
556 if v == 0.0 || !v.is_finite() {
557 return "0".to_string();
559 }
560 let mut out = String::new();
561 if v < 0.0 {
562 out.push('-');
563 }
564 let (digits, exp) = shortest_digits(v.abs());
565 let k = digits.len() as i64;
566 let n = exp + 1;
567 if k <= n && n <= 21 {
568 out.push_str(&digits);
569 for _ in 0..(n - k) {
570 out.push('0');
571 }
572 } else if 0 < n && n <= 21 {
573 let (a, b) = digits.split_at(n as usize);
574 out.push_str(a);
575 out.push('.');
576 out.push_str(b);
577 } else if -6 < n && n <= 0 {
578 out.push_str("0.");
579 for _ in 0..(-n) {
580 out.push('0');
581 }
582 out.push_str(&digits);
583 } else {
584 let (a, b) = digits.split_at(1);
585 out.push_str(a);
586 if !b.is_empty() {
587 out.push('.');
588 out.push_str(b);
589 }
590 out.push('e');
591 let e = n - 1;
592 out.push(if e < 0 { '-' } else { '+' });
593 out.push_str(&e.abs().to_string());
594 }
595 out
596}