dade/
json.rs

1use std::collections::BTreeMap;
2use std::num::{ParseFloatError, ParseIntError};
3use std::str::FromStr;
4
5use crate::dump::JsonDumper;
6use crate::error::{Error, Result};
7
8pub struct Number {
9    value: String,
10}
11
12impl Number {
13    pub fn new(value: String) -> Self {
14        Self { value }
15    }
16    pub fn parse<F: FromStr>(&self) -> std::result::Result<F, F::Err> {
17        self.value.parse()
18    }
19    pub fn from<T: std::string::ToString>(val: T) -> Self {
20        Self {
21            value: val.to_string(),
22        }
23    }
24}
25
26impl ToString for Number {
27    fn to_string(&self) -> String {
28        self.value.to_string()
29    }
30}
31
32/// Types for conforms JSON.
33pub enum JsonValue {
34    /// Correspond for null in JSON.
35    Null,
36    /// Correspond for boolean in JSON.
37    Bool(bool),
38    /// Correspond for number in JSON.
39    Number(Number),
40    /// Correspond for string in JSON.
41    String(String),
42    /// Correspond for array in JSON.
43    Array(Vec<JsonValue>),
44    /// Correspond for object in JSON.
45    Object(BTreeMap<String, JsonValue>),
46}
47
48impl ToString for JsonValue {
49    fn to_string(&self) -> String {
50        JsonDumper::new(false).dump(self)
51    }
52}
53
54/// A trait defines as the format to convert data to an instance.
55pub trait FromJsonValue: Sized {
56    fn from_json_value(value: &JsonValue) -> Result<Self>;
57}
58
59impl FromJsonValue for () {
60    fn from_json_value(value: &JsonValue) -> Result<Self> {
61        match value {
62            JsonValue::Null => Ok(()),
63            _ => Err(Error::validate_err("expect `JsonValue::Null`")),
64        }
65    }
66}
67
68macro_rules! from_json_value_for_int {
69    ( $( $i:ident ),* ) => {
70        $(
71            impl FromJsonValue for $i {
72                fn from_json_value(value: &JsonValue) -> Result<Self> {
73                    match value {
74                        JsonValue::Number(num) => num
75                            .value
76                            .parse()
77                            .map_err(|err: ParseIntError| Error::validate_err(err.to_string().as_str())),
78                        _ => Err(Error::validate_err("expect `JsonValue::Number`")),
79                    }
80                }
81            }
82        )*
83    };
84}
85
86from_json_value_for_int!(u8, u16, u32, u64, u128, usize, i8, i16, i32, i64, i128, isize);
87
88macro_rules! from_json_value_for_float {
89    ( $( $i:ident ),* ) => {
90        $(
91            impl FromJsonValue for $i {
92                fn from_json_value(value: &JsonValue) -> Result<Self> {
93                    match value {
94                        JsonValue::Number(num) => num
95                            .value
96                            .parse()
97                            .map_err(|err: ParseFloatError| Error::validate_err(err.to_string().as_str())),
98                        _ => Err(Error::validate_err("expect `JsonValue::Number`")),
99                    }
100                }
101            }
102        )*
103    };
104}
105
106from_json_value_for_float!(f32, f64);
107
108impl FromJsonValue for String {
109    fn from_json_value(value: &JsonValue) -> Result<Self> {
110        match value {
111            JsonValue::String(s) => Ok(s.to_string()),
112            _ => Err(Error::validate_err("expect `JsonValue::String`")),
113        }
114    }
115}
116
117impl FromJsonValue for bool {
118    fn from_json_value(value: &JsonValue) -> Result<Self> {
119        match value {
120            JsonValue::Bool(b) => Ok(*b),
121            _ => Err(Error::validate_err("expect `JsonValue::Bool`")),
122        }
123    }
124}
125
126impl<T: FromJsonValue> FromJsonValue for Vec<T> {
127    fn from_json_value(value: &JsonValue) -> Result<Self> {
128        match value {
129            JsonValue::Array(arr) => {
130                let mut buffer = Vec::with_capacity(arr.len());
131                for val in arr.iter() {
132                    buffer.push(FromJsonValue::from_json_value(val)?);
133                }
134                Ok(buffer)
135            }
136            _ => Err(Error::validate_err("expect `JsonValue::Array`")),
137        }
138    }
139}
140
141impl<T: FromJsonValue> FromJsonValue for Option<T> {
142    fn from_json_value(value: &JsonValue) -> Result<Self> {
143        match value {
144            JsonValue::Null => Ok(None),
145            _ => Ok(Some(FromJsonValue::from_json_value(value)?)),
146        }
147    }
148}
149
150impl<T: FromJsonValue> FromJsonValue for Box<T> {
151    fn from_json_value(value: &JsonValue) -> Result<Self> {
152        Ok(Box::new(FromJsonValue::from_json_value(value)?))
153    }
154}
155
156/// A trait defines as the format to get data from the instance.
157pub trait ToJsonValue {
158    fn to_json_value(&self) -> JsonValue;
159}
160
161impl ToJsonValue for () {
162    fn to_json_value(&self) -> JsonValue {
163        JsonValue::Null
164    }
165}
166
167macro_rules! to_json_value_for_num {
168    ( $( $i:ident ),* ) => {
169        $(
170            impl ToJsonValue for $i {
171                fn to_json_value(&self) -> JsonValue {
172                    JsonValue::Number(Number::new(self.to_string()))
173                }
174            }
175        )*
176    };
177}
178
179to_json_value_for_num!(u8, u16, u32, u64, u128, usize, i8, i16, i32, i64, i128, isize, f32, f64);
180
181impl ToJsonValue for String {
182    fn to_json_value(&self) -> JsonValue {
183        JsonValue::String(self.to_string())
184    }
185}
186
187impl ToJsonValue for bool {
188    fn to_json_value(&self) -> JsonValue {
189        JsonValue::Bool(*self)
190    }
191}
192
193impl<T: ToJsonValue> ToJsonValue for Vec<T> {
194    fn to_json_value(&self) -> JsonValue {
195        JsonValue::Array(
196            self.iter()
197                .map(|val| ToJsonValue::to_json_value(val))
198                .collect(),
199        )
200    }
201}
202
203impl<T: ToJsonValue> ToJsonValue for Option<T> {
204    fn to_json_value(&self) -> JsonValue {
205        match self {
206            None => JsonValue::Null,
207            Some(val) => ToJsonValue::to_json_value(val),
208        }
209    }
210}
211
212impl<T: ToJsonValue> ToJsonValue for Box<T> {
213    fn to_json_value(&self) -> JsonValue {
214        T::to_json_value(self)
215    }
216}