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
43pub 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}