struct_map/
value.rs

1use crate::error::StructMapError;
2use std::collections::HashMap;
3use std::result::Result;
4use std::vec::Vec;
5pub use to_hash_map::*;
6
7#[derive(Debug, Clone)]
8pub enum FieldValue {
9    Null,
10    Bool(bool),
11    Int(i64),
12    Float(f64),
13    String(String),
14    Array(Vec<FieldValue>),
15    Map(HashMap<String, FieldValue>),
16}
17
18impl ToString for FieldValue {
19    fn to_string(&self) -> String {
20        match self {
21            FieldValue::Null => "".to_owned(),
22            FieldValue::Bool(value) => value.to_string(),
23            FieldValue::Int(value) => value.to_string(),
24            FieldValue::Float(value) => value.to_string(),
25            FieldValue::String(value) => value.to_string(),
26            FieldValue::Array(value) => {
27                let mut res = String::new();
28                for val in value.iter() {
29                    let v = val.to_string();
30                    res.push_str(v.as_str());
31                }
32                res
33            }
34            FieldValue::Map(value) => {
35                let mut res = String::new();
36                for (key, val) in value {
37                    res.push_str(key.as_str());
38                    let v = val.to_string();
39                    res.push_str(v.as_str());
40                }
41                res
42            }
43        }
44    }
45}
46
47pub trait Converter: Sized {
48    fn to_field_value(&self) -> FieldValue;
49    fn to_primitive(fv: FieldValue) -> Result<Self, StructMapError>;
50}
51
52impl Converter for String {
53    fn to_field_value(&self) -> FieldValue {
54        FieldValue::String(self.to_string())
55    }
56    fn to_primitive(fv: FieldValue) -> Result<Self, StructMapError> {
57        match fv {
58            FieldValue::String(value) => Ok(value),
59            _ => Err(StructMapError::new("invalid type: String")),
60        }
61    }
62}
63
64impl Converter for char {
65    fn to_field_value(&self) -> FieldValue {
66        FieldValue::String(self.to_string())
67    }
68    fn to_primitive(fv: FieldValue) -> Result<Self, StructMapError> {
69        match fv {
70            FieldValue::String(value) => {
71                let chars: Vec<char> = value.chars().collect();
72                if chars.len() != 1 {
73                    return Err(StructMapError::new("invalid type: char"));
74                }
75                Ok(chars[0])
76            }
77            _ => Err(StructMapError::new("invalid type: char")),
78        }
79    }
80}
81impl Converter for bool {
82    fn to_field_value(&self) -> FieldValue {
83        FieldValue::Bool(*self)
84    }
85
86    fn to_primitive(fv: FieldValue) -> Result<Self, StructMapError> {
87        match fv {
88            FieldValue::Bool(value) => Ok(value),
89            _ => Err(StructMapError::new("invalid type: bool")),
90        }
91    }
92}
93
94macro_rules! integer_impls {
95    ($ ($type:ty) +) => {
96        $(
97            impl Converter for $type {
98                #[inline]
99                fn to_field_value(&self) -> FieldValue {
100                    FieldValue::Int(*self as i64)
101                }
102
103                #[inline]
104                fn to_primitive(fv: FieldValue) ->Result<Self, StructMapError> {
105                    match fv {
106                        FieldValue::Int(value)=>{
107                            if let Ok(value) = <$type>::try_from(value) {
108                                return Ok(value);
109                            }
110                            return Err(StructMapError::new(format!("invalid type: {}",stringify!($type).to_owned())))
111                        },
112                        _=> Err(StructMapError::new(format!("invalid type: {}",stringify!($type).to_owned()))),
113                    }
114                }
115            }
116        )+
117    }
118}
119
120integer_impls!(i8 i16 i32 i64 isize u8 u16 u32);
121
122impl Converter for f32 {
123    fn to_field_value(&self) -> FieldValue {
124        FieldValue::Float(*self as f64)
125    }
126    fn to_primitive(fv: FieldValue) -> Result<Self, StructMapError> {
127        match fv {
128            FieldValue::Float(value) => Ok(value as f32),
129            _ => Err(StructMapError::new("invalid type: f32")),
130        }
131    }
132}
133
134impl Converter for f64 {
135    fn to_field_value(&self) -> FieldValue {
136        FieldValue::Float(*self)
137    }
138    fn to_primitive(fv: FieldValue) -> Result<Self, StructMapError> {
139        match fv {
140            FieldValue::Float(value) => Ok(value),
141            _ => Err(StructMapError::new("invalid type: f64")),
142        }
143    }
144}
145
146impl<T> Converter for Option<T>
147where
148    T: Converter,
149{
150    fn to_field_value(&self) -> FieldValue {
151        match self {
152            Some(some) => some.to_field_value(),
153            None => FieldValue::Null,
154        }
155    }
156
157    fn to_primitive(fv: FieldValue) -> Result<Self, StructMapError> {
158        match fv {
159            FieldValue::Null => Ok(None),
160            _ => Ok(Some(T::to_primitive(fv)?)),
161        }
162    }
163}
164
165impl<T> Converter for Vec<T>
166where
167    T: Converter,
168{
169    fn to_field_value(&self) -> FieldValue {
170        FieldValue::Array(self.iter().map(|v| v.to_field_value()).collect())
171    }
172
173    fn to_primitive(fv: FieldValue) -> Result<Self, StructMapError> {
174        match fv {
175            FieldValue::Array(value) => value
176                .into_iter()
177                .map(|v| T::to_primitive(v))
178                .collect::<Result<Vec<T>, StructMapError>>(),
179            _ => Err(StructMapError::new("invalid type: Vec<T>")),
180        }
181    }
182}
183
184impl<K, V> Converter for HashMap<K, V>
185where
186    K: ToString + From<String> + std::cmp::Eq + std::hash::Hash,
187    V: Converter,
188{
189    fn to_field_value(&self) -> FieldValue {
190        FieldValue::Map(
191            self.iter()
192                .map(|(key, value)| (key.to_string(), value.to_field_value()))
193                .collect(),
194        )
195    }
196
197    fn to_primitive(fv: FieldValue) -> Result<Self, StructMapError> {
198        match fv {
199            FieldValue::Map(value) => {
200                let mut result = HashMap::with_capacity(value.len());
201                for (k, v) in value {
202                    if let Ok(k) = K::try_from(k) {
203                        result.insert(k, V::to_primitive(v)?);
204                    } else {
205                        return Err(StructMapError::new("invalid type: HashMap<K, V>"));
206                    }
207                }
208                Ok(result)
209            }
210            _ => Err(StructMapError::new("invalid type: HashMap<K, V>")),
211        }
212    }
213}
214
215pub trait ToHashMap {
216    fn to_map(&self) -> HashMap<String, FieldValue>;
217    fn from_map(map: HashMap<String, FieldValue>) -> Result<Self, StructMapError>
218    where
219        Self: std::marker::Sized;
220}
221
222impl<T> Converter for T
223where
224    T: ToHashMap,
225{
226    fn to_field_value(&self) -> FieldValue {
227        FieldValue::Map(self.to_map())
228    }
229
230    fn to_primitive(fv: FieldValue) -> Result<Self, StructMapError> {
231        match fv {
232            FieldValue::Map(value) => Ok(T::from_map(value)?),
233            _ => Err(StructMapError::new("invalid type: Mapper")),
234        }
235    }
236}