cassandra_protocol/types/
cassandra_type.rs

1use num_bigint::BigInt;
2use std::collections::HashMap;
3use std::net::IpAddr;
4
5use super::prelude::{Blob, Decimal, Duration};
6use crate::error::Result as CDRSResult;
7use crate::frame::message_result::{ColType, ColTypeOption};
8use crate::frame::Version;
9use crate::types::CBytes;
10
11#[derive(Debug, PartialEq, Clone)]
12#[non_exhaustive]
13pub enum CassandraType {
14    Ascii(String),
15    Bigint(i64),
16    Blob(Blob),
17    Boolean(bool),
18    Counter(i64),
19    Decimal(Decimal),
20    Double(f64),
21    Float(f32),
22    Int(i32),
23    Timestamp(i64),
24    Uuid(uuid::Uuid),
25    Varchar(String),
26    Varint(BigInt),
27    Timeuuid(uuid::Uuid),
28    Inet(IpAddr),
29    Date(i32),
30    Time(i64),
31    Smallint(i16),
32    Tinyint(i8),
33    Duration(Duration),
34    List(Vec<CassandraType>),
35    Map(Vec<(CassandraType, CassandraType)>),
36    Set(Vec<CassandraType>),
37    Udt(HashMap<String, CassandraType>),
38    Tuple(Vec<CassandraType>),
39    Vector(Vec<CassandraType>),
40    Null,
41}
42
43/// Get a function to convert `CBytes` and `ColTypeOption` into a `CassandraType`
44pub fn wrapper_fn(
45    col_type: &ColType,
46) -> &'static dyn Fn(&CBytes, &ColTypeOption, Version) -> CDRSResult<CassandraType> {
47    match col_type {
48        ColType::Blob => &wrappers::blob,
49        ColType::Ascii => &wrappers::ascii,
50        ColType::Int => &wrappers::int,
51        ColType::List => &wrappers::list,
52        ColType::Custom => &wrappers::custom,
53        ColType::Bigint => &wrappers::bigint,
54        ColType::Boolean => &wrappers::bool,
55        ColType::Counter => &wrappers::counter,
56        ColType::Decimal => &wrappers::decimal,
57        ColType::Double => &wrappers::double,
58        ColType::Float => &wrappers::float,
59        ColType::Timestamp => &wrappers::timestamp,
60        ColType::Uuid => &wrappers::uuid,
61        ColType::Varchar => &wrappers::varchar,
62        ColType::Varint => &wrappers::varint,
63        ColType::Timeuuid => &wrappers::timeuuid,
64        ColType::Inet => &wrappers::inet,
65        ColType::Date => &wrappers::date,
66        ColType::Time => &wrappers::time,
67        ColType::Smallint => &wrappers::smallint,
68        ColType::Tinyint => &wrappers::tinyint,
69        ColType::Duration => &wrappers::duration,
70        ColType::Map => &wrappers::map,
71        ColType::Set => &wrappers::set,
72        ColType::Udt => &wrappers::udt,
73        ColType::Tuple => &wrappers::tuple,
74    }
75}
76
77pub mod wrappers {
78    use super::CassandraType;
79    use crate::error::Result as CDRSResult;
80    use crate::frame::message_result::{ColType, ColTypeOption, ColTypeOptionValue};
81    use crate::frame::Version;
82    use crate::types::data_serialization_types::*;
83    use crate::types::list::List;
84    use crate::types::vector::{get_vector_type_info, Vector, VectorInfo};
85    use crate::types::AsCassandraType;
86    use crate::types::CBytes;
87    use crate::types::{map::Map, tuple::Tuple, udt::Udt};
88
89    pub fn custom(
90        bytes: &CBytes,
91        col_type: &ColTypeOption,
92        version: Version,
93    ) -> CDRSResult<CassandraType> {
94        if let ColTypeOption {
95            id: ColType::Custom,
96            value: Some(value),
97        } = col_type
98        {
99            let VectorInfo {
100                internal_type: _,
101                count,
102            } = get_vector_type_info(value)?;
103
104            if let Some(actual_bytes) = bytes.as_slice() {
105                let vector = decode_float_vector(actual_bytes, version, count)
106                    .map(|data| Vector::new(col_type.clone(), data, version))?
107                    .as_cassandra_type()?
108                    .unwrap_or(CassandraType::Null);
109                return Ok(vector);
110            }
111        }
112
113        Ok(CassandraType::Null)
114    }
115
116    pub fn map(
117        bytes: &CBytes,
118        col_type: &ColTypeOption,
119        version: Version,
120    ) -> CDRSResult<CassandraType> {
121        if let Some(actual_bytes) = bytes.as_slice() {
122            let decoded_map = decode_map(actual_bytes, version)?;
123
124            Ok(Map::new(decoded_map, col_type.clone(), version)
125                .as_cassandra_type()?
126                .unwrap_or(CassandraType::Null))
127        } else {
128            Ok(CassandraType::Null)
129        }
130    }
131
132    pub fn set(
133        bytes: &CBytes,
134        col_type: &ColTypeOption,
135        version: Version,
136    ) -> CDRSResult<CassandraType> {
137        if let Some(actual_bytes) = bytes.as_slice() {
138            let decoded_set = decode_set(actual_bytes, version)?;
139
140            Ok(List::new(col_type.clone(), decoded_set, version)
141                .as_cassandra_type()?
142                .unwrap_or(CassandraType::Null))
143        } else {
144            Ok(CassandraType::Null)
145        }
146    }
147
148    pub fn udt(
149        bytes: &CBytes,
150        col_type: &ColTypeOption,
151        version: Version,
152    ) -> CDRSResult<CassandraType> {
153        if let Some(ColTypeOptionValue::UdtType(ref list_type_option)) = col_type.value {
154            if let Some(actual_bytes) = bytes.as_slice() {
155                let len = list_type_option.descriptions.len();
156                let decoded_udt = decode_udt(actual_bytes, len, version)?;
157
158                return Ok(Udt::new(decoded_udt, list_type_option, version)
159                    .as_cassandra_type()?
160                    .unwrap_or(CassandraType::Null));
161            }
162        }
163
164        Ok(CassandraType::Null)
165    }
166
167    pub fn tuple(
168        bytes: &CBytes,
169        col_type: &ColTypeOption,
170        version: Version,
171    ) -> CDRSResult<CassandraType> {
172        if let Some(ColTypeOptionValue::TupleType(ref list_type_option)) = col_type.value {
173            if let Some(actual_bytes) = bytes.as_slice() {
174                let len = list_type_option.types.len();
175                let decoded_tuple = decode_tuple(actual_bytes, len, version)?;
176
177                return Ok(Tuple::new(decoded_tuple, list_type_option, version)
178                    .as_cassandra_type()?
179                    .unwrap_or(CassandraType::Null));
180            }
181        }
182
183        Ok(CassandraType::Null)
184    }
185
186    pub fn null(
187        _: &CBytes,
188        _col_type: &ColTypeOption,
189        _version: Version,
190    ) -> CDRSResult<CassandraType> {
191        Ok(CassandraType::Null)
192    }
193
194    pub fn blob(
195        bytes: &CBytes,
196        col_type: &ColTypeOption,
197        _version: Version,
198    ) -> CDRSResult<CassandraType> {
199        let t = as_rust_type!(col_type, bytes, Blob)?;
200
201        Ok(match t {
202            Some(t) => CassandraType::Blob(t),
203            None => CassandraType::Null,
204        })
205    }
206
207    pub fn ascii(
208        bytes: &CBytes,
209        col_type: &ColTypeOption,
210        _version: Version,
211    ) -> CDRSResult<CassandraType> {
212        let t = as_rust_type!(col_type, bytes, String)?;
213
214        Ok(match t {
215            Some(t) => CassandraType::Ascii(t),
216            None => CassandraType::Null,
217        })
218    }
219
220    pub fn int(
221        bytes: &CBytes,
222        col_type: &ColTypeOption,
223        _version: Version,
224    ) -> CDRSResult<CassandraType> {
225        let t = as_rust_type!(col_type, bytes, i32)?;
226
227        Ok(match t {
228            Some(t) => CassandraType::Int(t),
229            None => CassandraType::Null,
230        })
231    }
232
233    pub fn list(
234        bytes: &CBytes,
235        col_type: &ColTypeOption,
236        version: Version,
237    ) -> CDRSResult<CassandraType> {
238        let list = as_rust_type!(col_type, bytes, version, List)?;
239        Ok(match list {
240            Some(t) => t.as_cassandra_type()?.unwrap_or(CassandraType::Null),
241            None => CassandraType::Null,
242        })
243    }
244
245    pub fn bigint(
246        bytes: &CBytes,
247        col_type: &ColTypeOption,
248        _version: Version,
249    ) -> CDRSResult<CassandraType> {
250        let t = as_rust_type!(col_type, bytes, i64)?;
251
252        Ok(match t {
253            Some(t) => CassandraType::Bigint(t),
254            None => CassandraType::Null,
255        })
256    }
257
258    pub fn counter(
259        bytes: &CBytes,
260        col_type: &ColTypeOption,
261        _version: Version,
262    ) -> CDRSResult<CassandraType> {
263        let t = as_rust_type!(col_type, bytes, i64)?;
264
265        Ok(match t {
266            Some(t) => CassandraType::Counter(t),
267            None => CassandraType::Null,
268        })
269    }
270
271    pub fn decimal(
272        bytes: &CBytes,
273        col_type: &ColTypeOption,
274        _version: Version,
275    ) -> CDRSResult<CassandraType> {
276        let t = as_rust_type!(col_type, bytes, Decimal)?;
277
278        Ok(match t {
279            Some(t) => CassandraType::Decimal(t),
280            None => CassandraType::Null,
281        })
282    }
283
284    pub fn double(
285        bytes: &CBytes,
286        col_type: &ColTypeOption,
287        _version: Version,
288    ) -> CDRSResult<CassandraType> {
289        let t = as_rust_type!(col_type, bytes, f64)?;
290
291        Ok(match t {
292            Some(t) => CassandraType::Double(t),
293            None => CassandraType::Null,
294        })
295    }
296
297    pub fn float(
298        bytes: &CBytes,
299        col_type: &ColTypeOption,
300        _version: Version,
301    ) -> CDRSResult<CassandraType> {
302        let t = as_rust_type!(col_type, bytes, f32)?;
303
304        Ok(match t {
305            Some(t) => CassandraType::Float(t),
306            None => CassandraType::Null,
307        })
308    }
309
310    pub fn timestamp(
311        bytes: &CBytes,
312        col_type: &ColTypeOption,
313        _version: Version,
314    ) -> CDRSResult<CassandraType> {
315        let t = as_rust_type!(col_type, bytes, i64)?;
316
317        Ok(match t {
318            Some(t) => CassandraType::Timestamp(t),
319            None => CassandraType::Null,
320        })
321    }
322
323    pub fn uuid(
324        bytes: &CBytes,
325        col_type: &ColTypeOption,
326        _version: Version,
327    ) -> CDRSResult<CassandraType> {
328        let t = as_rust_type!(col_type, bytes, Uuid)?;
329
330        Ok(match t {
331            Some(t) => CassandraType::Uuid(t),
332            None => CassandraType::Null,
333        })
334    }
335
336    pub fn varchar(
337        bytes: &CBytes,
338        col_type: &ColTypeOption,
339        _version: Version,
340    ) -> CDRSResult<CassandraType> {
341        let t = as_rust_type!(col_type, bytes, String)?;
342
343        Ok(match t {
344            Some(t) => CassandraType::Varchar(t),
345            None => CassandraType::Null,
346        })
347    }
348
349    pub fn varint(
350        bytes: &CBytes,
351        col_type: &ColTypeOption,
352        _version: Version,
353    ) -> CDRSResult<CassandraType> {
354        let t = as_rust_type!(col_type, bytes, BigInt)?;
355
356        Ok(match t {
357            Some(t) => CassandraType::Varint(t),
358            None => CassandraType::Null,
359        })
360    }
361
362    pub fn timeuuid(
363        bytes: &CBytes,
364        col_type: &ColTypeOption,
365        _version: Version,
366    ) -> CDRSResult<CassandraType> {
367        let t = as_rust_type!(col_type, bytes, Uuid)?;
368
369        Ok(match t {
370            Some(t) => CassandraType::Timeuuid(t),
371            None => CassandraType::Null,
372        })
373    }
374
375    pub fn inet(
376        bytes: &CBytes,
377        col_type: &ColTypeOption,
378        _version: Version,
379    ) -> CDRSResult<CassandraType> {
380        let t = as_rust_type!(col_type, bytes, IpAddr)?;
381
382        Ok(match t {
383            Some(t) => CassandraType::Inet(t),
384            None => CassandraType::Null,
385        })
386    }
387
388    pub fn date(
389        bytes: &CBytes,
390        col_type: &ColTypeOption,
391        _version: Version,
392    ) -> CDRSResult<CassandraType> {
393        let t = as_rust_type!(col_type, bytes, i32)?;
394
395        Ok(match t {
396            Some(t) => CassandraType::Date(t),
397            None => CassandraType::Null,
398        })
399    }
400
401    pub fn time(
402        bytes: &CBytes,
403        col_type: &ColTypeOption,
404        _version: Version,
405    ) -> CDRSResult<CassandraType> {
406        let t = as_rust_type!(col_type, bytes, i64)?;
407
408        Ok(match t {
409            Some(t) => CassandraType::Time(t),
410            None => CassandraType::Null,
411        })
412    }
413
414    pub fn smallint(
415        bytes: &CBytes,
416        col_type: &ColTypeOption,
417        _version: Version,
418    ) -> CDRSResult<CassandraType> {
419        let t = as_rust_type!(col_type, bytes, i16)?;
420
421        Ok(match t {
422            Some(t) => CassandraType::Smallint(t),
423            None => CassandraType::Null,
424        })
425    }
426
427    pub fn tinyint(
428        bytes: &CBytes,
429        col_type: &ColTypeOption,
430        _version: Version,
431    ) -> CDRSResult<CassandraType> {
432        let t = as_rust_type!(col_type, bytes, i8)?;
433
434        Ok(match t {
435            Some(t) => CassandraType::Tinyint(t),
436            None => CassandraType::Null,
437        })
438    }
439
440    pub fn bool(
441        bytes: &CBytes,
442        col_type: &ColTypeOption,
443        _version: Version,
444    ) -> CDRSResult<CassandraType> {
445        let t = as_rust_type!(col_type, bytes, bool)?;
446
447        Ok(match t {
448            Some(t) => CassandraType::Boolean(t),
449            None => CassandraType::Null,
450        })
451    }
452
453    pub fn duration(
454        bytes: &CBytes,
455        col_type: &ColTypeOption,
456        _version: Version,
457    ) -> CDRSResult<CassandraType> {
458        let t = as_rust_type!(col_type, bytes, Duration)?;
459
460        Ok(match t {
461            Some(t) => CassandraType::Duration(t),
462            None => CassandraType::Null,
463        })
464    }
465}