1use crate::{Config, Value};
2use smallvec::ToSmallVec;
3
4fn normalize_integer(s: &str) -> i64 {
5 let s = if let Some(rest) = s.strip_prefix('+') { rest } else { s };
6 if let Some(hex) = s.strip_prefix("0x").or_else(|| s.strip_prefix("0X")) {
7 i64::from_str_radix(hex, 16).unwrap_or_else(|_| {
8 panic!("unsupported: integer '{s}' does not fit in i64")
10 })
11 } else if let Some(hex) = s.strip_prefix("-0x").or_else(|| s.strip_prefix("-0X")) {
12 let abs = i64::from_str_radix(hex, 16).unwrap_or_else(|_| {
13 panic!("unsupported: integer '{s}' does not fit in i64")
15 });
16 abs.checked_neg().unwrap_or_else(|| {
17 panic!("unsupported: integer '{s}' does not fit in i64")
19 })
20 } else {
21 s.parse::<i64>().unwrap_or_else(|_| {
22 panic!("unsupported: integer '{s}' does not fit in i64")
24 })
25 }
26}
27
28impl<'s> Value<'s> {
29 pub fn to_json(&self) -> serde_json::Value {
30 match self {
31 Value::Bool(b) => serde_json::Value::Bool(*b),
32 Value::Integer(s) => {
33 let n = normalize_integer(s);
34 serde_json::Value::Number(n.into())
35 }
36 Value::String(s) => serde_json::Value::String((*s).to_owned()),
37 }
38 }
39}
40
41impl Config {
42 pub fn to_json(&self) -> serde_json::Value {
43 let mut map = serde_json::Map::new();
44 for &(group_start, count) in &self.group_order {
45 let (group_start, count) = (group_start as usize, count as usize);
46 let mut idxs: smallvec::SmallVec<[u32; 2]> =
47 { self.sorted_indices[group_start..(group_start + count)].to_smallvec() };
48 idxs.sort_unstable();
49 let key = &self.arena[self.entries[idxs[0] as usize].0];
50 if count == 1 {
51 let val = self.entries[idxs[0] as usize].1.to_value(&self.arena);
52 map.insert(key.to_owned(), val.to_json());
53 } else {
54 let arr: Vec<serde_json::Value> = idxs
55 .iter()
56 .map(|&i| {
57 let val = self.entries[i as usize].1.to_value(&self.arena);
58 val.to_json()
59 })
60 .collect();
61 map.insert(key.to_owned(), serde_json::Value::Array(arr));
62 }
63 }
64 serde_json::Value::Object(map)
65 }
66}
67
68#[cfg(test)]
69mod tests {
70 use super::normalize_integer;
71
72 #[test]
73 fn decimal() {
74 assert_eq!(normalize_integer("42"), 42);
75 assert_eq!(normalize_integer("0"), 0);
76 }
77
78 #[test]
79 fn signed() {
80 assert_eq!(normalize_integer("+7"), 7);
81 assert_eq!(normalize_integer("-10"), -10);
82 assert_eq!(normalize_integer("+0"), 0);
83 }
84
85 #[test]
86 fn hex() {
87 assert_eq!(normalize_integer("0xFF"), 255);
88 assert_eq!(normalize_integer("0XFF"), 255);
89 assert_eq!(normalize_integer("0x0"), 0);
90 }
91
92 #[test]
93 fn signed_hex() {
94 assert_eq!(normalize_integer("-0xFF"), -255);
95 assert_eq!(normalize_integer("-0XA"), -10);
96 }
97
98 #[test]
99 #[should_panic(expected = "unsupported")]
100 fn overflow_panics() {
101 normalize_integer("99999999999999999999");
102 }
103}