cassandra_protocol/types/
data_serialization_types.rs

1use integer_encoding::VarInt;
2use num_bigint::BigInt;
3use std::convert::TryInto;
4use std::io;
5use std::net;
6use std::string::FromUtf8Error;
7
8use super::blob::Blob;
9use super::decimal::Decimal;
10use super::duration::Duration;
11use crate::error;
12use crate::frame::{FromCursor, Version};
13use crate::types::{
14    try_f32_from_bytes, try_f64_from_bytes, try_i16_from_bytes, try_i32_from_bytes,
15    try_i64_from_bytes, CBytes, CInt, INT_LEN,
16};
17
18// https://github.com/apache/cassandra/blob/trunk/doc/native_protocol_v4.spec#L813
19
20const FALSE_BYTE: u8 = 0;
21
22// Decodes Cassandra `ascii` data (bytes)
23#[inline]
24pub fn decode_custom(bytes: &[u8]) -> Result<String, FromUtf8Error> {
25    Ok(String::from_utf8_lossy(bytes).into_owned())
26}
27
28// Decodes Cassandra `ascii` data (bytes)
29#[inline]
30pub fn decode_ascii(bytes: &[u8]) -> Result<String, FromUtf8Error> {
31    Ok(String::from_utf8_lossy(bytes).into_owned())
32}
33
34// Decodes Cassandra `varchar` data (bytes)
35#[inline]
36pub fn decode_varchar(bytes: &[u8]) -> Result<String, FromUtf8Error> {
37    Ok(String::from_utf8_lossy(bytes).into_owned())
38}
39
40// Decodes Cassandra `bigint` data (bytes)
41#[inline]
42pub fn decode_bigint(bytes: &[u8]) -> Result<i64, io::Error> {
43    try_i64_from_bytes(bytes)
44}
45
46// Decodes Cassandra `blob` data (bytes)
47#[inline]
48pub fn decode_blob(bytes: &[u8]) -> Result<Blob, io::Error> {
49    // in fact we just pass it through.
50    Ok(bytes.into())
51}
52
53// Decodes Cassandra `boolean` data (bytes)
54#[inline]
55pub fn decode_boolean(bytes: &[u8]) -> Result<bool, io::Error> {
56    if bytes.is_empty() {
57        Err(io::Error::new(
58            io::ErrorKind::UnexpectedEof,
59            "no bytes were found",
60        ))
61    } else {
62        Ok(bytes[0] != FALSE_BYTE)
63    }
64}
65
66// Decodes Cassandra `int` data (bytes)
67#[inline]
68pub fn decode_int(bytes: &[u8]) -> Result<i32, io::Error> {
69    try_i32_from_bytes(bytes)
70}
71
72// Decodes Cassandra `date` data (bytes)
73//    0: -5877641-06-23
74// 2^31: 1970-1-1
75// 2^32: 5881580-07-11
76#[inline]
77pub fn decode_date(bytes: &[u8]) -> Result<i32, io::Error> {
78    try_i32_from_bytes(bytes)
79}
80
81// Decodes Cassandra `decimal` data (bytes)
82pub fn decode_decimal(bytes: &[u8]) -> Result<Decimal, io::Error> {
83    let lr = bytes.split_at(INT_LEN);
84
85    let scale = try_i32_from_bytes(lr.0)?;
86    let unscaled = decode_varint(lr.1)?;
87
88    Ok(Decimal::new(unscaled, scale))
89}
90
91// Decodes Cassandra `double` data (bytes)
92#[inline]
93pub fn decode_double(bytes: &[u8]) -> Result<f64, io::Error> {
94    try_f64_from_bytes(bytes)
95}
96
97// Decodes Cassandra `float` data (bytes)
98#[inline]
99pub fn decode_float(bytes: &[u8]) -> Result<f32, io::Error> {
100    try_f32_from_bytes(bytes)
101}
102
103// Decodes Cassandra `inet` data (bytes)
104#[allow(clippy::many_single_char_names)]
105pub fn decode_inet(bytes: &[u8]) -> Result<net::IpAddr, io::Error> {
106    match bytes.len() {
107        // v4
108        4 => {
109            let array: [u8; 4] = bytes[0..4].try_into().unwrap();
110            Ok(net::IpAddr::V4(net::Ipv4Addr::from(array)))
111        }
112        // v6
113        16 => {
114            let array: [u8; 16] = bytes[0..16].try_into().unwrap();
115            Ok(net::IpAddr::V6(net::Ipv6Addr::from(array)))
116        }
117        _ => Err(io::Error::new(
118            io::ErrorKind::Other,
119            format!("Invalid Ip address {bytes:?}"),
120        )),
121    }
122}
123
124// Decodes Cassandra `timestamp` data (bytes) into Rust's `Result<i64, io::Error>`
125// `i32` represents a millisecond-precision
126//  offset from the unix epoch (00:00:00, January 1st, 1970).  Negative values
127//  represent a negative offset from the epoch.
128#[inline]
129pub fn decode_timestamp(bytes: &[u8]) -> Result<i64, io::Error> {
130    try_i64_from_bytes(bytes)
131}
132
133//noinspection DuplicatedCode
134// Decodes Cassandra `list` data (bytes)
135pub fn decode_list(bytes: &[u8], version: Version) -> Result<Vec<CBytes>, io::Error> {
136    let mut cursor = io::Cursor::new(bytes);
137    let l = CInt::from_cursor(&mut cursor, version)
138        .map_err(|e| io::Error::new(io::ErrorKind::InvalidData, e))?;
139    let mut list = Vec::with_capacity(l as usize);
140    for _ in 0..l {
141        let b = CBytes::from_cursor(&mut cursor, version)
142            .map_err(|err| io::Error::new(io::ErrorKind::InvalidData, err))?;
143        list.push(b);
144    }
145    Ok(list)
146}
147
148pub fn decode_float_vector(
149    bytes: &[u8],
150    _version: Version,
151    count: usize,
152) -> Result<Vec<CBytes>, io::Error> {
153    let type_size = 4;
154
155    let mut vector = Vec::with_capacity(count);
156    for i in (0..(count * type_size)).step_by(4) {
157        vector.push(CBytes::new(bytes[i..i + type_size].to_vec()));
158    }
159
160    Ok(vector)
161}
162
163// Decodes Cassandra `set` data (bytes)
164#[inline]
165pub fn decode_set(bytes: &[u8], version: Version) -> Result<Vec<CBytes>, io::Error> {
166    decode_list(bytes, version)
167}
168
169// Decodes Cassandra `map` data (bytes)
170pub fn decode_map(bytes: &[u8], version: Version) -> Result<Vec<(CBytes, CBytes)>, io::Error> {
171    let mut cursor = io::Cursor::new(bytes);
172    let l = CInt::from_cursor(&mut cursor, version)
173        .map_err(|err| io::Error::new(io::ErrorKind::InvalidData, err))?;
174    let mut map = Vec::with_capacity(l as usize);
175    for _ in 0..l {
176        let k = CBytes::from_cursor(&mut cursor, version)
177            .map_err(|err| io::Error::new(io::ErrorKind::InvalidData, err))?;
178        let v = CBytes::from_cursor(&mut cursor, version)
179            .map_err(|err| io::Error::new(io::ErrorKind::InvalidData, err))?;
180        map.push((k, v));
181    }
182    Ok(map)
183}
184
185// Decodes Cassandra `smallint` data (bytes)
186#[inline]
187pub fn decode_smallint(bytes: &[u8]) -> Result<i16, io::Error> {
188    try_i16_from_bytes(bytes)
189}
190
191// Decodes Cassandra `tinyint` data (bytes)
192#[inline]
193pub fn decode_tinyint(bytes: &[u8]) -> Result<i8, io::Error> {
194    Ok(bytes[0] as i8)
195}
196
197// Decodes Cassandra `text` data (bytes)
198#[inline]
199pub fn decode_text(bytes: &[u8]) -> Result<String, FromUtf8Error> {
200    Ok(String::from_utf8_lossy(bytes).into_owned())
201}
202
203// Decodes Cassandra `time` data (bytes)
204#[inline]
205pub fn decode_time(bytes: &[u8]) -> Result<i64, io::Error> {
206    try_i64_from_bytes(bytes)
207}
208
209// Decodes Cassandra `timeuuid` data (bytes)
210#[inline]
211pub fn decode_timeuuid(bytes: &[u8]) -> Result<uuid::Uuid, uuid::Error> {
212    uuid::Uuid::from_slice(bytes)
213}
214
215// Decodes Cassandra `varint` data (bytes)
216#[inline]
217pub fn decode_varint(bytes: &[u8]) -> Result<BigInt, io::Error> {
218    Ok(BigInt::from_signed_bytes_be(bytes))
219}
220
221// Decodes Cassandra `duration` data (bytes)
222#[inline]
223pub fn decode_duration(bytes: &[u8]) -> Result<Duration, io::Error> {
224    let (months, month_bytes_read) =
225        i32::decode_var(bytes).ok_or_else(|| io::Error::from(io::ErrorKind::InvalidData))?;
226
227    let (days, day_bytes_read) = i32::decode_var(&bytes[month_bytes_read..])
228        .ok_or_else(|| io::Error::from(io::ErrorKind::InvalidData))?;
229
230    let (nanoseconds, _) = i64::decode_var(&bytes[(month_bytes_read + day_bytes_read)..])
231        .ok_or_else(|| io::Error::from(io::ErrorKind::InvalidData))?;
232
233    Duration::new(months, days, nanoseconds)
234        .map_err(|err| io::Error::new(io::ErrorKind::InvalidData, err))
235}
236
237// Decodes Cassandra `Udt` data (bytes)
238pub fn decode_udt(bytes: &[u8], l: usize, version: Version) -> Result<Vec<CBytes>, io::Error> {
239    let mut cursor = io::Cursor::new(bytes);
240    let mut udt = Vec::with_capacity(l);
241    for _ in 0..l {
242        let v = CBytes::from_cursor(&mut cursor, version)
243            .or_else(|err| match err {
244                error::Error::Io(io_err) => {
245                    if io_err.kind() == io::ErrorKind::UnexpectedEof {
246                        Ok(CBytes::new_null())
247                    } else {
248                        Err(io_err.into())
249                    }
250                }
251                _ => Err(err),
252            })
253            .map_err(|err| io::Error::new(io::ErrorKind::InvalidData, err))?;
254        udt.push(v);
255    }
256    Ok(udt)
257}
258
259//noinspection DuplicatedCode
260// Decodes Cassandra `Tuple` data (bytes)
261pub fn decode_tuple(bytes: &[u8], l: usize, version: Version) -> Result<Vec<CBytes>, io::Error> {
262    let mut cursor = io::Cursor::new(bytes);
263    let mut tuple = Vec::with_capacity(l);
264    for _ in 0..l {
265        let v = CBytes::from_cursor(&mut cursor, version)
266            .map_err(|err| io::Error::new(io::ErrorKind::InvalidData, err))?;
267        tuple.push(v);
268    }
269    Ok(tuple)
270}
271
272//noinspection DuplicatedCode
273#[cfg(test)]
274mod tests {
275    use super::super::super::frame::message_result::*;
276    use super::*;
277    use crate::types::{to_float, to_float_big};
278    use float_eq::*;
279    use std::net::IpAddr;
280
281    #[test]
282    fn decode_custom_test() {
283        assert_eq!(decode_custom(b"abcd").unwrap(), "abcd".to_string());
284    }
285
286    #[test]
287    fn decode_ascii_test() {
288        assert_eq!(decode_ascii(b"abcd").unwrap(), "abcd".to_string());
289    }
290
291    #[test]
292    fn decode_varchar_test() {
293        assert_eq!(decode_varchar(b"abcd").unwrap(), "abcd".to_string());
294    }
295
296    #[test]
297    fn decode_bigint_test() {
298        assert_eq!(decode_bigint(&[0, 0, 0, 0, 0, 0, 0, 3]).unwrap(), 3);
299    }
300
301    #[test]
302    fn decode_blob_test() {
303        assert_eq!(
304            decode_blob(&[0, 0, 0, 3]).unwrap().into_vec(),
305            vec![0, 0, 0, 3]
306        );
307    }
308
309    #[test]
310    fn decode_boolean_test() {
311        assert!(!decode_boolean(&[0]).unwrap());
312        assert!(decode_boolean(&[1]).unwrap());
313        assert!(decode_boolean(&[]).is_err());
314    }
315
316    #[test]
317    fn decode_int_test() {
318        assert_eq!(decode_int(&[0, 0, 0, 3]).unwrap(), 3);
319    }
320
321    #[test]
322    fn decode_date_test() {
323        assert_eq!(decode_date(&[0, 0, 0, 3]).unwrap(), 3);
324    }
325
326    #[test]
327    fn decode_double_test() {
328        let bytes = to_float_big(0.3);
329        assert_float_eq!(
330            decode_double(bytes.as_slice()).unwrap(),
331            0.3,
332            abs <= f64::EPSILON
333        );
334    }
335
336    #[test]
337    fn decode_float_test() {
338        let bytes = to_float(0.3);
339        assert_float_eq!(
340            decode_float(bytes.as_slice()).unwrap(),
341            0.3,
342            abs <= f32::EPSILON
343        );
344    }
345
346    #[test]
347    fn decode_inet_test() {
348        let bytes_v4 = &[0, 0, 0, 0];
349        match decode_inet(bytes_v4) {
350            Ok(IpAddr::V4(ref ip)) => assert_eq!(ip.octets(), [0, 0, 0, 0]),
351            _ => panic!("wrong ip v4 address"),
352        }
353
354        let bytes_v6 = &[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0];
355        match decode_inet(bytes_v6) {
356            Ok(IpAddr::V6(ref ip)) => assert_eq!(ip.segments(), [0, 0, 0, 0, 0, 0, 0, 0]),
357            _ => panic!("wrong ip v6 address"),
358        };
359    }
360
361    #[test]
362    fn decode_timestamp_test() {
363        assert_eq!(decode_timestamp(&[0, 0, 0, 0, 0, 0, 0, 3]).unwrap(), 3);
364    }
365
366    #[test]
367    fn decode_list_test() {
368        let results = decode_list(&[0, 0, 0, 1, 0, 0, 0, 2, 1, 2], Version::V4).unwrap();
369        assert_eq!(results.len(), 1);
370        assert_eq!(results[0].as_slice().unwrap(), &[1, 2]);
371    }
372
373    #[test]
374    fn decode_duration_test() {
375        let result = decode_duration(&[200, 1, 144, 3, 216, 4]).unwrap();
376        assert_eq!(result, Duration::new(100, 200, 300).unwrap());
377    }
378
379    #[test]
380    fn decode_set_test() {
381        let results = decode_set(&[0, 0, 0, 1, 0, 0, 0, 2, 1, 2], Version::V4).unwrap();
382        assert_eq!(results.len(), 1);
383        assert_eq!(results[0].as_slice().unwrap(), &[1, 2]);
384    }
385
386    #[test]
387    fn decode_map_test() {
388        let results = decode_map(
389            &[0, 0, 0, 1, 0, 0, 0, 2, 1, 2, 0, 0, 0, 2, 2, 1],
390            Version::V4,
391        )
392        .unwrap();
393        assert_eq!(results.len(), 1);
394        assert_eq!(results[0].0.as_slice().unwrap(), &[1, 2]);
395        assert_eq!(results[0].1.as_slice().unwrap(), &[2, 1]);
396    }
397
398    #[test]
399    fn decode_smallint_test() {
400        assert_eq!(decode_smallint(&[0, 10]).unwrap(), 10);
401    }
402
403    #[test]
404    fn decode_tinyint_test() {
405        assert_eq!(decode_tinyint(&[10]).unwrap(), 10);
406    }
407
408    #[test]
409    fn decode_decimal_test() {
410        assert_eq!(
411            decode_decimal(&[0, 0, 0, 0, 10u8]).unwrap(),
412            Decimal::new(10.into(), 0)
413        );
414
415        assert_eq!(
416            decode_decimal(&[0, 0, 0, 0, 0x00, 0x81]).unwrap(),
417            Decimal::new(129.into(), 0)
418        );
419
420        assert_eq!(
421            decode_decimal(&[0, 0, 0, 0, 0xFF, 0x7F]).unwrap(),
422            Decimal::new(BigInt::from(-129), 0)
423        );
424
425        assert_eq!(
426            decode_decimal(&[0, 0, 0, 1, 0x00, 0x81]).unwrap(),
427            Decimal::new(129.into(), 1)
428        );
429
430        assert_eq!(
431            decode_decimal(&[0, 0, 0, 1, 0xFF, 0x7F]).unwrap(),
432            Decimal::new(BigInt::from(-129), 1)
433        );
434    }
435
436    #[test]
437    fn decode_text_test() {
438        assert_eq!(decode_text(b"abcba").unwrap(), "abcba");
439    }
440
441    #[test]
442    fn decode_time_test() {
443        assert_eq!(decode_time(&[0, 0, 0, 0, 0, 0, 0, 10]).unwrap(), 10);
444    }
445
446    #[test]
447    fn decode_timeuuid_test() {
448        assert_eq!(
449            decode_timeuuid(&[4, 54, 67, 12, 43, 2, 98, 76, 32, 50, 87, 5, 1, 33, 43, 87])
450                .unwrap()
451                .as_bytes(),
452            &[4, 54, 67, 12, 43, 2, 98, 76, 32, 50, 87, 5, 1, 33, 43, 87]
453        );
454    }
455
456    #[test]
457    fn decode_varint_test() {
458        assert_eq!(decode_varint(&[0x00]).unwrap(), 0.into());
459        assert_eq!(decode_varint(&[0x01]).unwrap(), 1.into());
460        assert_eq!(decode_varint(&[0x7F]).unwrap(), 127.into());
461        assert_eq!(decode_varint(&[0x00, 0x80]).unwrap(), 128.into());
462        assert_eq!(decode_varint(&[0x00, 0x81]).unwrap(), 129.into());
463        assert_eq!(decode_varint(&[0xFF]).unwrap(), BigInt::from(-1));
464        assert_eq!(decode_varint(&[0x80]).unwrap(), BigInt::from(-128));
465        assert_eq!(decode_varint(&[0xFF, 0x7F]).unwrap(), BigInt::from(-129));
466    }
467
468    #[test]
469    fn decode_udt_test() {
470        let udt = decode_udt(&[0, 0, 0, 2, 1, 2], 1, Version::V4).unwrap();
471        assert_eq!(udt.len(), 1);
472        assert_eq!(udt[0].as_slice().unwrap(), &[1, 2]);
473    }
474
475    #[test]
476    fn as_rust_blob_test() {
477        let d_type = ColTypeOption {
478            id: ColType::Blob,
479            value: None,
480        };
481        let data = CBytes::new(vec![1, 2, 3]);
482        assert_eq!(
483            as_rust_type!(d_type, data, Blob)
484                .unwrap()
485                .unwrap()
486                .into_vec(),
487            vec![1, 2, 3]
488        );
489        let wrong_type = ColTypeOption {
490            id: ColType::Map,
491            value: None,
492        };
493        assert!(as_rust_type!(wrong_type, data, Blob).is_err());
494    }
495
496    #[test]
497    fn as_rust_v4_blob_test() {
498        let d_type = ColTypeOption {
499            id: ColType::Custom,
500            value: Some(ColTypeOptionValue::CString(
501                "org.apache.cassandra.db.marshal.BytesType".into(),
502            )),
503        };
504        let data = CBytes::new(vec![1, 2, 3]);
505        assert_eq!(
506            as_rust_type!(d_type, data, Blob)
507                .unwrap()
508                .unwrap()
509                .into_vec(),
510            vec![1, 2, 3]
511        );
512    }
513
514    #[test]
515    fn as_rust_string_test() {
516        let type_custom = ColTypeOption {
517            id: ColType::Custom,
518            value: None,
519        };
520        let type_ascii = ColTypeOption {
521            id: ColType::Ascii,
522            value: None,
523        };
524        let type_varchar = ColTypeOption {
525            id: ColType::Varchar,
526            value: None,
527        };
528        let data = CBytes::new(b"abc".to_vec());
529        assert_eq!(
530            as_rust_type!(type_custom, data, String).unwrap().unwrap(),
531            "abc"
532        );
533        assert_eq!(
534            as_rust_type!(type_ascii, data, String).unwrap().unwrap(),
535            "abc"
536        );
537        assert_eq!(
538            as_rust_type!(type_varchar, data, String).unwrap().unwrap(),
539            "abc"
540        );
541        let wrong_type = ColTypeOption {
542            id: ColType::Map,
543            value: None,
544        };
545        assert!(as_rust_type!(wrong_type, data, String).is_err());
546    }
547
548    #[test]
549    fn as_rust_bool_test() {
550        let type_boolean = ColTypeOption {
551            id: ColType::Boolean,
552            value: None,
553        };
554        let data_true = CBytes::new(vec![1]);
555        let data_false = CBytes::new(vec![0]);
556        assert!(as_rust_type!(type_boolean, data_true, bool)
557            .unwrap()
558            .unwrap());
559        assert!(!as_rust_type!(type_boolean, data_false, bool)
560            .unwrap()
561            .unwrap());
562        let wrong_type = ColTypeOption {
563            id: ColType::Map,
564            value: None,
565        };
566        assert!(as_rust_type!(wrong_type, data_false, bool).is_err());
567    }
568
569    #[test]
570    fn as_rust_v4_bool_test() {
571        let type_boolean = ColTypeOption {
572            id: ColType::Custom,
573            value: Some(ColTypeOptionValue::CString(
574                "org.apache.cassandra.db.marshal.BooleanType".into(),
575            )),
576        };
577        let data_true = CBytes::new(vec![1]);
578        let data_false = CBytes::new(vec![0]);
579        assert!(as_rust_type!(type_boolean, data_true, bool)
580            .unwrap()
581            .unwrap());
582        assert!(!as_rust_type!(type_boolean, data_false, bool)
583            .unwrap()
584            .unwrap());
585    }
586
587    #[test]
588    fn as_rust_i64_test() {
589        let type_bigint = ColTypeOption {
590            id: ColType::Bigint,
591            value: None,
592        };
593        let type_timestamp = ColTypeOption {
594            id: ColType::Timestamp,
595            value: None,
596        };
597        let type_time = ColTypeOption {
598            id: ColType::Time,
599            value: None,
600        };
601        let data = CBytes::new(vec![0, 0, 0, 0, 0, 0, 0, 100]);
602        assert_eq!(as_rust_type!(type_bigint, data, i64).unwrap().unwrap(), 100);
603        assert_eq!(
604            as_rust_type!(type_timestamp, data, i64).unwrap().unwrap(),
605            100
606        );
607        assert_eq!(as_rust_type!(type_time, data, i64).unwrap().unwrap(), 100);
608        let wrong_type = ColTypeOption {
609            id: ColType::Map,
610            value: None,
611        };
612        assert!(as_rust_type!(wrong_type, data, i64).is_err());
613    }
614
615    #[test]
616    fn as_rust_v4_i64_test() {
617        let type_bigint = ColTypeOption {
618            id: ColType::Custom,
619            value: Some(ColTypeOptionValue::CString(
620                "org.apache.cassandra.db.marshal.LongType".into(),
621            )),
622        };
623        let type_timestamp = ColTypeOption {
624            id: ColType::Custom,
625            value: Some(ColTypeOptionValue::CString(
626                "org.apache.cassandra.db.marshal.TimestampType".into(),
627            )),
628        };
629        let type_time = ColTypeOption {
630            id: ColType::Custom,
631            value: Some(ColTypeOptionValue::CString(
632                "org.apache.cassandra.db.marshal.TimeType".into(),
633            )),
634        };
635        let data = CBytes::new(vec![0, 0, 0, 0, 0, 0, 0, 100]);
636        assert_eq!(as_rust_type!(type_bigint, data, i64).unwrap().unwrap(), 100);
637        assert_eq!(
638            as_rust_type!(type_timestamp, data, i64).unwrap().unwrap(),
639            100
640        );
641        assert_eq!(as_rust_type!(type_time, data, i64).unwrap().unwrap(), 100);
642    }
643
644    #[test]
645    fn as_rust_i32_test() {
646        let type_int = ColTypeOption {
647            id: ColType::Int,
648            value: None,
649        };
650        let type_date = ColTypeOption {
651            id: ColType::Date,
652            value: None,
653        };
654        let data = CBytes::new(vec![0, 0, 0, 100]);
655        assert_eq!(as_rust_type!(type_int, data, i32).unwrap().unwrap(), 100);
656        assert_eq!(as_rust_type!(type_date, data, i32).unwrap().unwrap(), 100);
657        let wrong_type = ColTypeOption {
658            id: ColType::Map,
659            value: None,
660        };
661        assert!(as_rust_type!(wrong_type, data, i32).is_err());
662    }
663
664    #[test]
665    fn as_rust_v4_i32_test() {
666        let type_int = ColTypeOption {
667            id: ColType::Custom,
668            value: Some(ColTypeOptionValue::CString(
669                "org.apache.cassandra.db.marshal.Int32Type".into(),
670            )),
671        };
672        let type_date = ColTypeOption {
673            id: ColType::Custom,
674            value: Some(ColTypeOptionValue::CString(
675                "org.apache.cassandra.db.marshal.SimpleDateType".into(),
676            )),
677        };
678        let data = CBytes::new(vec![0, 0, 0, 100]);
679        assert_eq!(as_rust_type!(type_int, data, i32).unwrap().unwrap(), 100);
680        assert_eq!(as_rust_type!(type_date, data, i32).unwrap().unwrap(), 100);
681    }
682
683    #[test]
684    fn as_rust_i16_test() {
685        let type_smallint = ColTypeOption {
686            id: ColType::Smallint,
687            value: None,
688        };
689        let data = CBytes::new(vec![0, 100]);
690        assert_eq!(
691            as_rust_type!(type_smallint, data, i16).unwrap().unwrap(),
692            100
693        );
694        let wrong_type = ColTypeOption {
695            id: ColType::Map,
696            value: None,
697        };
698        assert!(as_rust_type!(wrong_type, data, i16).is_err());
699    }
700
701    #[test]
702    fn as_rust_v4_i16_test() {
703        let type_smallint = ColTypeOption {
704            id: ColType::Custom,
705            value: Some(ColTypeOptionValue::CString(
706                "org.apache.cassandra.db.marshal.ShortType".into(),
707            )),
708        };
709        let data = CBytes::new(vec![0, 100]);
710        assert_eq!(
711            as_rust_type!(type_smallint, data, i16).unwrap().unwrap(),
712            100
713        );
714    }
715
716    #[test]
717    fn as_rust_i8_test() {
718        let type_tinyint = ColTypeOption {
719            id: ColType::Tinyint,
720            value: None,
721        };
722        let data = CBytes::new(vec![100]);
723        assert_eq!(as_rust_type!(type_tinyint, data, i8).unwrap().unwrap(), 100);
724        let wrong_type = ColTypeOption {
725            id: ColType::Map,
726            value: None,
727        };
728        assert!(as_rust_type!(wrong_type, data, i8).is_err());
729    }
730
731    #[test]
732    fn as_rust_v4_i8_test() {
733        let type_tinyint = ColTypeOption {
734            id: ColType::Custom,
735            value: Some(ColTypeOptionValue::CString(
736                "org.apache.cassandra.db.marshal.ByteType".into(),
737            )),
738        };
739        let data = CBytes::new(vec![100]);
740        assert_eq!(as_rust_type!(type_tinyint, data, i8).unwrap().unwrap(), 100);
741    }
742
743    #[test]
744    fn as_rust_f64_test() {
745        let type_double = ColTypeOption {
746            id: ColType::Double,
747            value: None,
748        };
749        let data = CBytes::new(to_float_big(0.1_f64));
750        assert_float_eq!(
751            as_rust_type!(type_double, data, f64).unwrap().unwrap(),
752            0.1,
753            abs <= f64::EPSILON
754        );
755        let wrong_type = ColTypeOption {
756            id: ColType::Map,
757            value: None,
758        };
759        assert!(as_rust_type!(wrong_type, data, f64).is_err());
760    }
761
762    #[test]
763    fn as_rust_v4_f64_test() {
764        let type_double = ColTypeOption {
765            id: ColType::Custom,
766            value: Some(ColTypeOptionValue::CString(
767                "org.apache.cassandra.db.marshal.DoubleType".into(),
768            )),
769        };
770        let data = CBytes::new(to_float_big(0.1_f64));
771        assert_float_eq!(
772            as_rust_type!(type_double, data, f64).unwrap().unwrap(),
773            0.1,
774            abs <= f64::EPSILON
775        );
776    }
777
778    #[test]
779    fn as_rust_f32_test() {
780        // let type_decimal = ColTypeOption { id: ColType::Decimal };
781        let type_float = ColTypeOption {
782            id: ColType::Float,
783            value: None,
784        };
785        let data = CBytes::new(to_float(0.1_f32));
786        // assert_eq!(as_rust_type!(type_decimal, data, f32).unwrap(), 100.0);
787        assert_float_eq!(
788            as_rust_type!(type_float, data, f32).unwrap().unwrap(),
789            0.1,
790            abs <= f32::EPSILON
791        );
792        let wrong_type = ColTypeOption {
793            id: ColType::Map,
794            value: None,
795        };
796        assert!(as_rust_type!(wrong_type, data, f32).is_err());
797    }
798
799    #[test]
800    fn as_rust_v4_f32_test() {
801        // let type_decimal = ColTypeOption { id: ColType::Decimal };
802        let type_float = ColTypeOption {
803            id: ColType::Custom,
804            value: Some(ColTypeOptionValue::CString(
805                "org.apache.cassandra.db.marshal.FloatType".into(),
806            )),
807        };
808        let data = CBytes::new(to_float(0.1_f32));
809        // assert_eq!(as_rust_type!(type_decimal, data, f32).unwrap(), 100.0);
810        assert_float_eq!(
811            as_rust_type!(type_float, data, f32).unwrap().unwrap(),
812            0.1,
813            abs <= f32::EPSILON
814        );
815    }
816
817    #[test]
818    fn as_rust_inet_test() {
819        let type_inet = ColTypeOption {
820            id: ColType::Inet,
821            value: None,
822        };
823        let data = CBytes::new(vec![0, 0, 0, 0]);
824
825        match as_rust_type!(type_inet, data, IpAddr) {
826            Ok(Some(IpAddr::V4(ref ip))) => assert_eq!(ip.octets(), [0, 0, 0, 0]),
827            _ => panic!("wrong ip v4 address"),
828        }
829        let wrong_type = ColTypeOption {
830            id: ColType::Map,
831            value: None,
832        };
833        assert!(as_rust_type!(wrong_type, data, f32).is_err());
834    }
835
836    #[test]
837    fn as_rust_v4_inet_test() {
838        let type_inet = ColTypeOption {
839            id: ColType::Custom,
840            value: Some(ColTypeOptionValue::CString(
841                "org.apache.cassandra.db.marshal.InetAddressType".into(),
842            )),
843        };
844        let data = CBytes::new(vec![0, 0, 0, 0]);
845
846        match as_rust_type!(type_inet, data, IpAddr) {
847            Ok(Some(IpAddr::V4(ref ip))) => assert_eq!(ip.octets(), [0, 0, 0, 0]),
848            _ => panic!("wrong ip v4 address"),
849        }
850    }
851}