1use std::collections::{BTreeMap, HashMap};
4
5use impl_trait_for_tuples::impl_for_tuples;
6
7use super::{ChValue, Type, Value};
8use crate::error::Error;
9
10macro_rules! impl_ch_type {
12 ($TY:ty, $CH_TY:expr, $VAR:ident) => {
13 impl ChValue for $TY {
14 fn ch_type() -> Type {
15 $CH_TY
16 }
17
18 fn into_ch_value(self) -> Value {
19 Value::$VAR(self)
20 }
21
22 fn from_ch_value(value: Value) -> Result<Self, Error> {
23 match value {
24 Value::$VAR(v) => Ok(v),
25 _ => Err(Error::new("Cannot convert Value to base type")),
26 }
27 }
28 }
29 };
30}
31
32impl_ch_type!(u8, Type::UInt8, UInt8);
34impl_ch_type!(u16, Type::UInt16, UInt16);
35impl_ch_type!(u32, Type::UInt32, UInt32);
36impl_ch_type!(u64, Type::UInt64, UInt64);
37impl_ch_type!(u128, Type::UInt128, UInt128);
38impl_ch_type!(i8, Type::Int8, Int8);
39impl_ch_type!(i16, Type::Int16, Int16);
40impl_ch_type!(i32, Type::Int32, Int32);
41impl_ch_type!(i64, Type::Int64, Int64);
42impl_ch_type!(i128, Type::Int128, Int128);
43impl_ch_type!(f32, Type::Float32, Float32);
44impl_ch_type!(f64, Type::Float64, Float64);
45impl_ch_type!(bool, Type::Bool, Bool);
46impl_ch_type!(String, Type::String, String);
47impl_ch_type!(Option<u8>, Type::NullableUInt8, NullableUInt8);
49impl_ch_type!(Option<u16>, Type::NullableUInt16, NullableUInt16);
50impl_ch_type!(Option<u32>, Type::NullableUInt32, NullableUInt32);
51impl_ch_type!(Option<u64>, Type::NullableUInt64, NullableUInt64);
52impl_ch_type!(Option<u128>, Type::NullableUInt128, NullableUInt128);
53impl_ch_type!(Option<i8>, Type::NullableInt8, NullableInt8);
54impl_ch_type!(Option<i16>, Type::NullableInt16, NullableInt16);
55impl_ch_type!(Option<i32>, Type::NullableInt32, NullableInt32);
56impl_ch_type!(Option<i64>, Type::NullableInt64, NullableInt64);
57impl_ch_type!(Option<i128>, Type::NullableInt128, NullableInt128);
58impl_ch_type!(Option<f32>, Type::NullableFloat32, NullableFloat32);
59impl_ch_type!(Option<f64>, Type::NullableFloat64, NullableFloat64);
60impl_ch_type!(Option<bool>, Type::NullableBool, NullableBool);
61impl_ch_type!(Option<String>, Type::NullableString, NullableString);
62
63impl ChValue for &str {
65 fn ch_type() -> Type {
66 Type::String
67 }
68
69 fn into_ch_value(self) -> Value {
70 Value::String(self.to_string())
71 }
72
73 fn from_ch_value(_value: Value) -> Result<Self, Error> {
74 unreachable!("&str cannot be parsed from a value")
75 }
76}
77
78impl<T> ChValue for Vec<T>
80where
81 T: ChValue,
82{
83 fn ch_type() -> Type {
84 Type::Array(Box::new(T::ch_type()))
85 }
86
87 fn into_ch_value(self) -> Value {
88 Value::Array(self.into_iter().map(|v| v.into_ch_value()).collect())
89 }
90
91 fn from_ch_value(value: Value) -> Result<Self, Error> {
92 match value {
93 Value::Array(values) => {
94 let mut ts = vec![];
95 for value in values {
96 ts.push(T::from_ch_value(value)?);
97 }
98 Ok(ts)
99 }
100 _ => Err(Error::new("Cannot convert Value to array ")),
101 }
102 }
103}
104
105impl<T> ChValue for HashMap<String, T>
107where
108 T: ChValue,
109{
110 fn ch_type() -> Type {
111 Type::Map(Box::new(String::ch_type()), Box::new(T::ch_type()))
112 }
113
114 fn into_ch_value(self) -> Value {
115 Value::Map(
116 self.into_iter()
117 .map(|(k, v)| (k, v.into_ch_value()))
118 .collect(),
119 )
120 }
121
122 fn from_ch_value(value: Value) -> Result<Self, Error> {
123 match value {
124 Value::Map(values) => {
125 let mut map = HashMap::new();
126 for (key, value) in values {
127 map.insert(key, T::from_ch_value(value)?);
128 }
129 Ok(map)
130 }
131 _ => Err(Error::new("Cannot convert Value to array ")),
132 }
133 }
134}
135
136impl<T> ChValue for BTreeMap<String, T>
138where
139 T: ChValue,
140{
141 fn ch_type() -> Type {
142 Type::Map(Box::new(String::ch_type()), Box::new(T::ch_type()))
143 }
144
145 fn into_ch_value(self) -> Value {
146 Value::Map(
147 self.into_iter()
148 .map(|(k, v)| (k, v.into_ch_value()))
149 .collect(),
150 )
151 }
152
153 fn from_ch_value(value: Value) -> Result<Self, Error> {
154 match value {
155 Value::Map(values) => {
156 let mut map = BTreeMap::new();
157 for (key, value) in values {
158 map.insert(key, T::from_ch_value(value)?);
159 }
160 Ok(map)
161 }
162 _ => Err(Error::new("Cannot convert Value to array ")),
163 }
164 }
165}
166
167#[impl_for_tuples(1, 10)]
169impl ChValue for Tuple {
170 #[allow(clippy::vec_init_then_push)]
171 fn ch_type() -> Type {
172 let mut types = vec![];
173 for_tuples!( #( types.push(Tuple::ch_type()); )* );
174 Type::Tuple(types)
175 }
176
177 #[allow(clippy::vec_init_then_push)]
178 fn into_ch_value(self) -> Value {
179 let mut values = vec![];
180 for_tuples!( #( values.push(self.Tuple.into_ch_value()); )* );
181 Value::Tuple(values)
182 }
183
184 fn from_ch_value(value: Value) -> Result<Self, Error> {
185 match value {
186 Value::Tuple(values) => {
187 let mut iter = values.into_iter();
188 Ok((for_tuples!( #( Tuple::from_ch_value(iter.next().unwrap())?),* )))
189 }
190 _ => Err(Error::new("Cannot convert Value to array ")),
191 }
192 }
193}