clickhouse_client/value/
core.rs

1//! Core implementations
2
3use std::collections::{BTreeMap, HashMap};
4
5use impl_trait_for_tuples::impl_for_tuples;
6
7use super::{ChValue, Type, Value};
8use crate::error::Error;
9
10/// Implements the [Value] trait for built-in types
11macro_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
32// non-nullable std types
33impl_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);
47// nullable std types
48impl_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
63// &str
64impl 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
78// Vec<T>
79impl<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
105// HashMap<String, T>
106impl<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
136// BTreeMap<String, T>
137impl<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// (T1, T2, ...)
168#[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}