1#[cfg(not(feature = "std"))]
2extern crate alloc;
3
4#[cfg(not(feature = "std"))]
5use alloc::vec::Vec;
6
7#[cfg(not(feature = "std"))]
8use alloc::string::ToString;
9
10use crate::traits::Serialize;
11
12#[cfg_attr(feature = "std", derive(Debug))]
13#[derive(Clone, PartialEq, Copy)]
14pub struct NumberValue {
15 pub integer: u64,
16 pub fraction: u64,
17 pub fraction_length: u32,
18 pub exponent: i32,
19 pub negative: bool,
20}
21
22impl NumberValue {
23 #[cfg(any(feature = "std", feature = "float"))]
25 pub fn to_f64(self) -> f64 {
26 self.into()
27 }
28}
29
30#[cfg(any(feature = "std", feature = "float"))]
31impl Into<f64> for NumberValue {
32 fn into(self) -> f64 {
33 #[cfg(not(feature = "std"))]
34 use num_traits::float::FloatCore as _;
35
36 let sign = if self.negative { -1.0 } else { 1.0 };
37 (self.integer as f64 + self.fraction as f64 / 10f64.powi(self.fraction_length as i32))
38 * 10f64.powi(self.exponent)
39 * sign
40 }
41}
42
43pub type JsonObject = Vec<(Vec<char>, JsonValue)>;
44
45#[cfg_attr(feature = "std", derive(Debug))]
46#[derive(Clone, PartialEq)]
47pub enum JsonValue {
48 Object(JsonObject),
49 Array(Vec<JsonValue>),
50 String(Vec<char>),
51 Number(NumberValue),
52 Boolean(bool),
53 Null,
54}
55
56impl JsonValue {
57 pub fn is_object(&self) -> bool {
59 match self {
60 JsonValue::Object(_) => true,
61 _ => false,
62 }
63 }
64
65 pub fn as_object(&self) -> Option<&[(Vec<char>, JsonValue)]> {
67 match self {
68 JsonValue::Object(obj) => Some(obj),
69 _ => None,
70 }
71 }
72
73 pub fn to_object(self) -> Option<JsonObject> {
75 match self {
76 JsonValue::Object(obj) => Some(obj),
77 _ => None,
78 }
79 }
80
81 pub fn is_array(&self) -> bool {
83 match self {
84 JsonValue::Array(_) => true,
85 _ => false,
86 }
87 }
88
89 pub fn as_array(&self) -> Option<&[JsonValue]> {
91 match self {
92 JsonValue::Array(arr) => Some(arr),
93 _ => None,
94 }
95 }
96
97 pub fn to_array(self) -> Option<Vec<JsonValue>> {
99 match self {
100 JsonValue::Array(arr) => Some(arr),
101 _ => None,
102 }
103 }
104
105 pub fn is_string(&self) -> bool {
107 match self {
108 JsonValue::String(_) => true,
109 _ => false,
110 }
111 }
112
113 pub fn as_string(&self) -> Option<&[char]> {
115 match self {
116 JsonValue::String(s) => Some(s),
117 _ => None,
118 }
119 }
120
121 pub fn to_string(self) -> Option<Vec<char>> {
123 match self {
124 JsonValue::String(s) => Some(s),
125 _ => None,
126 }
127 }
128
129 pub fn is_number(&self) -> bool {
131 match self {
132 JsonValue::Number(_) => true,
133 _ => false,
134 }
135 }
136
137 pub fn as_number(&self) -> Option<&NumberValue> {
139 match self {
140 JsonValue::Number(n) => Some(n),
141 _ => None,
142 }
143 }
144
145 pub fn to_number(self) -> Option<NumberValue> {
147 match self {
148 JsonValue::Number(n) => Some(n),
149 _ => None,
150 }
151 }
152
153 pub fn is_bool(&self) -> bool {
155 match self {
156 JsonValue::Boolean(_) => true,
157 _ => false,
158 }
159 }
160
161 pub fn as_bool(&self) -> Option<&bool> {
163 match self {
164 JsonValue::Boolean(b) => Some(b),
165 _ => None,
166 }
167 }
168
169 pub fn to_bool(self) -> Option<bool> {
171 match self {
172 JsonValue::Boolean(b) => Some(b),
173 _ => None,
174 }
175 }
176
177 pub fn is_null(&self) -> bool {
179 match self {
180 JsonValue::Null => true,
181 _ => false,
182 }
183 }
184}
185
186impl Serialize for NumberValue {
187 fn serialize_to(&self, buffer: &mut Vec<u8>, _indent: u32, _level: u32) {
188 if self.negative {
189 buffer.push(b'-');
190 }
191 buffer.extend_from_slice(self.integer.to_string().as_bytes());
192
193 if self.fraction > 0 {
194 buffer.push(b'.');
195
196 let fraction_nums = self.fraction.to_string();
197 let fraction_length = self.fraction_length as usize;
198 for _ in 0..fraction_length - fraction_nums.len() {
199 buffer.push(b'0');
200 }
201 buffer.extend_from_slice(fraction_nums.as_bytes())
202 }
203 if self.exponent != 0 {
204 buffer.push(b'e');
205 if self.exponent < 0 {
206 buffer.push(b'-');
207 }
208 buffer.extend_from_slice(self.exponent.abs().to_string().as_bytes());
209 }
210 }
211}
212
213fn push_string(buffer: &mut Vec<u8>, chars: &Vec<char>) {
214 buffer.push('"' as u8);
215 for ch in chars {
216 match ch {
217 '\x08' => buffer.extend_from_slice(br#"\b"#),
218 '\x0c' => buffer.extend_from_slice(br#"\f"#),
219 '\n' => buffer.extend_from_slice(br#"\n"#),
220 '\r' => buffer.extend_from_slice(br#"\r"#),
221 '\t' => buffer.extend_from_slice(br#"\t"#),
222 '\"' => buffer.extend_from_slice(br#"\""#),
223 '\\' => buffer.extend_from_slice(br#"\\"#),
224 _ => match ch.len_utf8() {
225 1 => {
226 let mut buff = [0u8; 1];
227 ch.encode_utf8(&mut buff);
228 buffer.push(buff[0]);
229 }
230 2 => {
231 let mut buff = [0u8; 2];
232 ch.encode_utf8(&mut buff);
233 buffer.extend_from_slice(&buff);
234 }
235 3 => {
236 let mut buff = [0u8; 3];
237 ch.encode_utf8(&mut buff);
238 buffer.extend_from_slice(&buff);
239 }
240 4 => {
241 let mut buff = [0u8; 4];
242 ch.encode_utf8(&mut buff);
243 buffer.extend_from_slice(&buff);
244 }
245 _ => panic!("Invalid UTF8 character"),
246 },
247 }
248 }
249 buffer.push('"' as u8);
250}
251
252fn push_new_line_indent(buffer: &mut Vec<u8>, indent: u32, level: u32) {
253 if indent > 0 {
254 buffer.push('\n' as u8);
255 }
256 let count = (indent * level) as usize;
257 buffer.reserve(count);
258 for _ in 0..count {
259 buffer.push(' ' as u8);
260 }
261}
262
263impl Serialize for JsonValue {
264 fn serialize_to(&self, buffer: &mut Vec<u8>, indent: u32, level: u32) {
265 match self {
266 JsonValue::Object(obj) => {
267 buffer.push('{' as u8);
268 if obj.len() > 0 {
269 push_new_line_indent(buffer, indent, level + 1);
270 push_string(buffer, &obj[0].0);
271 buffer.push(':' as u8);
272 if indent > 0 {
273 buffer.push(' ' as u8);
274 }
275 obj[0].1.serialize_to(buffer, indent, level + 1);
276 for (key, val) in obj.iter().skip(1) {
277 buffer.push(',' as u8);
278 push_new_line_indent(buffer, indent, level + 1);
279 push_string(buffer, key);
280 buffer.push(':' as u8);
281 if indent > 0 {
282 buffer.push(' ' as u8);
283 }
284 val.serialize_to(buffer, indent, level + 1);
285 }
286 push_new_line_indent(buffer, indent, level);
287 buffer.push('}' as u8);
288 } else {
289 buffer.push('}' as u8);
290 }
291 }
292 JsonValue::Array(arr) => {
293 buffer.push('[' as u8);
294 if arr.len() > 0 {
295 push_new_line_indent(buffer, indent, level + 1);
296 arr[0].serialize_to(buffer, indent, level + 1);
297 for val in arr.iter().skip(1) {
298 buffer.push(',' as u8);
299 push_new_line_indent(buffer, indent, level + 1);
300 val.serialize_to(buffer, indent, level);
301 }
302 push_new_line_indent(buffer, indent, level);
303 buffer.push(']' as u8);
304 } else {
305 buffer.push(']' as u8);
306 }
307 }
308 JsonValue::String(str) => push_string(buffer, str),
309 JsonValue::Number(num) => num.serialize_to(buffer, indent, level),
310 JsonValue::Boolean(true) => buffer.extend_from_slice(b"true"),
311 JsonValue::Boolean(false) => buffer.extend_from_slice(b"false"),
312 JsonValue::Null => buffer.extend_from_slice(b"null"),
313 }
314 }
315}
316
317#[cfg(test)]
318mod tests {
319 use super::*;
320
321 #[test]
322 fn json_value_convenience_methods() {
323 let obj = JsonValue::Object(vec![(vec![], JsonValue::Null)]);
324 assert!(obj.is_object());
325 assert_eq!(obj.as_object(), Some(&[(vec![], JsonValue::Null)][..]));
326 assert_eq!(obj.as_array(), None);
327 assert_eq!(obj.as_bool(), None);
328 assert_eq!(obj.as_number(), None);
329 assert_eq!(obj.as_string(), None);
330 assert_eq!(
331 obj.clone().to_object(),
332 Some(vec![(vec![], JsonValue::Null)]),
333 );
334 assert_eq!(obj.clone().to_array(), None);
335 assert_eq!(obj.clone().to_bool(), None);
336 assert_eq!(obj.clone().to_number(), None);
337 assert_eq!(obj.clone().to_string(), None);
338
339 let arr = JsonValue::Array(vec![JsonValue::Null]);
340 assert!(arr.is_array());
341 assert_eq!(arr.as_array(), Some(&[JsonValue::Null][..]));
342 assert_eq!(arr.as_object(), None);
343 assert_eq!(arr.as_bool(), None);
344 assert_eq!(arr.as_number(), None);
345 assert_eq!(arr.as_string(), None);
346 assert_eq!(arr.clone().to_array(), Some(vec![JsonValue::Null]));
347 assert_eq!(arr.clone().to_object(), None);
348 assert_eq!(arr.clone().to_bool(), None);
349 assert_eq!(arr.clone().to_number(), None);
350 assert_eq!(arr.clone().to_string(), None);
351
352 let s = JsonValue::String(vec!['a']);
353 assert!(s.is_string());
354 assert_eq!(s.as_string(), Some(&['a'][..]));
355 assert_eq!(s.as_object(), None);
356 assert_eq!(s.as_bool(), None);
357 assert_eq!(s.as_number(), None);
358 assert_eq!(s.as_array(), None);
359 assert_eq!(s.clone().to_string(), Some(vec!['a']));
360 assert_eq!(s.clone().to_object(), None);
361 assert_eq!(s.clone().to_bool(), None);
362 assert_eq!(s.clone().to_number(), None);
363 assert_eq!(s.clone().to_array(), None);
364
365 let n = JsonValue::Number(NumberValue {
366 integer: 0,
367 fraction: 0,
368 fraction_length: 0,
369 exponent: 0,
370 negative: false,
371 });
372 assert!(n.is_number());
373 assert_eq!(
374 n.as_number(),
375 Some(&NumberValue {
376 integer: 0,
377 fraction: 0,
378 fraction_length: 0,
379 exponent: 0,
380 negative: false,
381 }),
382 );
383 assert_eq!(n.as_object(), None);
384 assert_eq!(n.as_bool(), None);
385 assert_eq!(n.as_string(), None);
386 assert_eq!(n.as_array(), None);
387 assert_eq!(
388 n.clone().to_number(),
389 Some(NumberValue {
390 integer: 0,
391 fraction: 0,
392 fraction_length: 0,
393 exponent: 0,
394 negative: false,
395 }),
396 );
397 assert_eq!(n.clone().to_object(), None);
398 assert_eq!(n.clone().to_bool(), None);
399 assert_eq!(n.clone().to_string(), None);
400 assert_eq!(n.clone().to_array(), None);
401
402 let b = JsonValue::Boolean(false);
403 assert!(b.is_bool());
404 assert_eq!(b.as_bool(), Some(&false));
405 assert_eq!(b.as_object(), None);
406 assert_eq!(b.as_number(), None);
407 assert_eq!(b.as_string(), None);
408 assert_eq!(b.as_array(), None);
409 assert_eq!(b.clone().to_bool(), Some(false));
410 assert_eq!(b.clone().to_object(), None);
411 assert_eq!(b.clone().to_number(), None);
412 assert_eq!(b.clone().to_string(), None);
413 assert_eq!(b.clone().to_array(), None);
414
415 let null = JsonValue::Null;
416 assert!(null.is_null());
417 assert_eq!(null.as_array(), None);
418 assert_eq!(null.as_bool(), None);
419 assert_eq!(null.as_number(), None);
420 assert_eq!(null.as_object(), None);
421 assert_eq!(null.as_string(), None);
422 assert_eq!(null.clone().to_array(), None);
423 assert_eq!(null.clone().to_bool(), None);
424 assert_eq!(null.clone().to_number(), None);
425 assert_eq!(null.clone().to_object(), None);
426 assert_eq!(null.clone().to_string(), None);
427 }
428
429 #[test]
430 fn serialize_number_value() {
431 let val = NumberValue {
432 integer: 1234,
433 fraction: 0,
434 fraction_length: 0,
435 exponent: 0,
436 negative: false,
437 };
438 assert_eq!(val.serialize(), b"1234");
439
440 let val = NumberValue {
441 integer: 1234,
442 fraction: 0,
443 fraction_length: 0,
444 exponent: 0,
445 negative: true,
446 };
447 assert_eq!(val.serialize(), b"-1234");
448
449 let val = NumberValue {
450 integer: 1234,
451 fraction: 5678,
452 fraction_length: 4,
453 exponent: 0,
454 negative: true,
455 };
456 assert_eq!(val.serialize(), b"-1234.5678");
457
458 let val = NumberValue {
459 integer: 1234,
460 fraction: 1,
461 fraction_length: 3,
462 exponent: 0,
463 negative: false,
464 };
465 assert_eq!(val.serialize(), b"1234.001");
466
467 let val = NumberValue {
468 integer: 1234,
469 fraction: 0,
470 fraction_length: 0,
471 exponent: 3,
472 negative: false,
473 };
474 assert_eq!(val.serialize(), b"1234e3");
475
476 let val = NumberValue {
477 integer: 1234,
478 fraction: 0,
479 fraction_length: 0,
480 exponent: -5,
481 negative: false,
482 };
483 assert_eq!(val.serialize(), b"1234e-5");
484
485 let val = NumberValue {
486 integer: 1234,
487 fraction: 56,
488 fraction_length: 4,
489 exponent: -5,
490 negative: false,
491 };
492 assert_eq!(val.serialize(), b"1234.0056e-5");
493
494 let val = NumberValue {
495 integer: 1234,
496 fraction: 5,
497 fraction_length: 2,
498 exponent: 5,
499 negative: true,
500 };
501 assert_eq!(val.serialize(), b"-1234.05e5");
502 }
503
504 #[test]
505 fn serialize_works() {
506 let obj = JsonValue::Object(vec![(
507 "test\"123".chars().into_iter().collect(),
508 JsonValue::Null,
509 )]);
510 assert_eq!(
511 std::str::from_utf8(&obj.format(4)[..]).unwrap(),
512 r#"{
513 "test\"123": null
514}"#
515 );
516
517 let obj = JsonValue::Object(vec![
518 (
519 vec!['t', 'e', 's', 't'],
520 JsonValue::Number(NumberValue {
521 integer: 123,
522 fraction: 4,
523 fraction_length: 2,
524 exponent: 0,
525 negative: false,
526 }),
527 ),
528 (
529 vec!['t', 'e', 's', 't', '2'],
530 JsonValue::Array(vec![
531 JsonValue::Number(NumberValue {
532 integer: 1,
533 fraction: 0,
534 fraction_length: 0,
535 exponent: -4,
536 negative: false,
537 }),
538 JsonValue::Number(NumberValue {
539 integer: 2,
540 fraction: 41,
541 fraction_length: 3,
542 exponent: 2,
543 negative: false,
544 }),
545 JsonValue::Boolean(true),
546 JsonValue::Boolean(false),
547 JsonValue::Null,
548 JsonValue::String(vec!['\"', '1', 'n', '\"']),
549 JsonValue::Object(vec![]),
550 JsonValue::Array(vec![]),
551 ]),
552 ),
553 ]);
554
555 assert_eq!(
556 std::str::from_utf8(&obj.format(4)[..]).unwrap(),
557 r#"{
558 "test": 123.04,
559 "test2": [
560 1e-4,
561 2.041e2,
562 true,
563 false,
564 null,
565 "\"1n\"",
566 {},
567 []
568 ]
569}"#
570 );
571
572 assert_eq!(
573 std::str::from_utf8(&obj.serialize()[..]).unwrap(),
574 r#"{"test":123.04,"test2":[1e-4,2.041e2,true,false,null,"\"1n\"",{},[]]}"#
575 );
576 }
577
578 #[test]
579 fn to_f64_works() {
580 use assert_float_eq::*;
581
582 assert_f64_near!(
583 NumberValue {
584 integer: 1,
585 fraction: 5,
586 fraction_length: 1,
587 exponent: 0,
588 negative: true,
589 }
590 .to_f64(),
591 -1.5
592 );
593
594 assert_f64_near!(
595 NumberValue {
596 integer: 0,
597 fraction: 5,
598 fraction_length: 1,
599 exponent: 0,
600 negative: true,
601 }
602 .to_f64(),
603 -0.5
604 );
605
606 assert_f64_near!(
607 NumberValue {
608 integer: 0,
609 fraction: 5,
610 fraction_length: 1,
611 exponent: 0,
612 negative: false,
613 }
614 .to_f64(),
615 0.5
616 );
617
618 assert_f64_near!(
619 NumberValue {
620 integer: 1,
621 fraction: 15,
622 fraction_length: 3,
623 exponent: 1,
624 negative: false,
625 }
626 .to_f64(),
627 10.15
628 );
629
630 assert_f64_near!(
631 NumberValue {
632 integer: 1,
633 fraction: 15,
634 fraction_length: 3,
635 exponent: -1,
636 negative: true,
637 }
638 .to_f64(),
639 -0.1015
640 );
641 }
642}