cassandra_protocol/
types.rs

1use self::cassandra_type::CassandraType;
2use crate::error::{column_is_empty_err, Error as CdrsError, Result as CDRSResult};
3use crate::frame::traits::FromCursor;
4use crate::frame::{Serialize, Version};
5use crate::types::data_serialization_types::*;
6use derive_more::Constructor;
7use std::convert::TryInto;
8use std::io::{self, Write};
9use std::io::{Cursor, Read};
10use std::net::{IpAddr, SocketAddr};
11
12pub const SHORT_LEN: usize = 2;
13pub const INT_LEN: usize = 4;
14pub const LONG_LEN: usize = 8;
15pub const UUID_LEN: usize = 16;
16
17const NULL_INT_LEN: CInt = -1;
18const NULL_SHORT_LEN: CIntShort = -1;
19
20#[macro_use]
21pub mod blob;
22pub mod cassandra_type;
23pub mod data_serialization_types;
24pub mod decimal;
25pub mod duration;
26pub mod from_cdrs;
27pub mod list;
28pub mod map;
29pub mod rows;
30pub mod tuple;
31pub mod udt;
32pub mod value;
33pub mod vector;
34
35pub mod prelude {
36    pub use crate::error::{Error, Result};
37    pub use crate::frame::{TryFromRow, TryFromUdt};
38    pub use crate::types::blob::Blob;
39    pub use crate::types::decimal::Decimal;
40    pub use crate::types::duration::Duration;
41    pub use crate::types::list::List;
42    pub use crate::types::map::Map;
43    pub use crate::types::rows::Row;
44    pub use crate::types::tuple::Tuple;
45    pub use crate::types::udt::Udt;
46    pub use crate::types::value::{Bytes, Value};
47    pub use crate::types::AsRustType;
48}
49
50pub trait AsCassandraType {
51    fn as_cassandra_type(&self) -> CDRSResult<Option<CassandraType>>;
52}
53
54/// Should be used to represent a single column as a Rust value.
55pub trait AsRustType<T> {
56    fn as_rust_type(&self) -> CDRSResult<Option<T>>;
57
58    fn as_r_type(&self) -> CDRSResult<T> {
59        self.as_rust_type()
60            .and_then(|op| op.ok_or_else(|| CdrsError::from("Value is null or non-set")))
61    }
62}
63
64pub trait AsRust {
65    fn as_rust<R>(&self) -> CDRSResult<Option<R>>
66    where
67        Self: AsRustType<R>,
68    {
69        self.as_rust_type()
70    }
71
72    fn as_r_rust<T>(&self) -> CDRSResult<T>
73    where
74        Self: AsRustType<T>,
75    {
76        self.as_rust()
77            .and_then(|op| op.ok_or_else(|| "Value is null or non-set".into()))
78    }
79}
80
81/// Should be used to return a single column as Rust value by its name.
82pub trait IntoRustByName<R> {
83    fn get_by_name(&self, name: &str) -> CDRSResult<Option<R>>;
84
85    fn get_r_by_name(&self, name: &str) -> CDRSResult<R> {
86        self.get_by_name(name)
87            .and_then(|op| op.ok_or_else(|| column_is_empty_err(name)))
88    }
89}
90
91pub trait ByName {
92    fn by_name<R>(&self, name: &str) -> CDRSResult<Option<R>>
93    where
94        Self: IntoRustByName<R>,
95    {
96        self.get_by_name(name)
97    }
98
99    fn r_by_name<R>(&self, name: &str) -> CDRSResult<R>
100    where
101        Self: IntoRustByName<R>,
102    {
103        self.by_name(name)
104            .and_then(|op| op.ok_or_else(|| column_is_empty_err(name)))
105    }
106}
107
108/// Should be used to return a single column as Rust value by its name.
109pub trait IntoRustByIndex<R> {
110    fn get_by_index(&self, index: usize) -> CDRSResult<Option<R>>;
111
112    fn get_r_by_index(&self, index: usize) -> CDRSResult<R> {
113        self.get_by_index(index)
114            .and_then(|op| op.ok_or_else(|| column_is_empty_err(index)))
115    }
116}
117
118pub trait ByIndex {
119    fn by_index<R>(&self, index: usize) -> CDRSResult<Option<R>>
120    where
121        Self: IntoRustByIndex<R>,
122    {
123        self.get_by_index(index)
124    }
125
126    fn r_by_index<R>(&self, index: usize) -> CDRSResult<R>
127    where
128        Self: IntoRustByIndex<R>,
129    {
130        self.by_index(index)
131            .and_then(|op| op.ok_or_else(|| column_is_empty_err(index)))
132    }
133}
134
135#[inline]
136fn convert_to_array<const S: usize>(bytes: &[u8]) -> Result<[u8; S], io::Error> {
137    bytes
138        .try_into()
139        .map_err(|error| io::Error::new(io::ErrorKind::UnexpectedEof, error))
140}
141
142#[inline]
143pub fn try_u64_from_bytes(bytes: &[u8]) -> Result<u64, io::Error> {
144    convert_to_array(bytes).map(u64::from_be_bytes)
145}
146
147#[inline]
148pub fn try_i64_from_bytes(bytes: &[u8]) -> Result<i64, io::Error> {
149    convert_to_array(bytes).map(i64::from_be_bytes)
150}
151
152#[inline]
153pub fn try_i32_from_bytes(bytes: &[u8]) -> Result<i32, io::Error> {
154    convert_to_array(bytes).map(i32::from_be_bytes)
155}
156
157#[inline]
158pub fn try_i16_from_bytes(bytes: &[u8]) -> Result<i16, io::Error> {
159    convert_to_array(bytes).map(i16::from_be_bytes)
160}
161
162#[inline]
163pub fn try_f32_from_bytes(bytes: &[u8]) -> Result<f32, io::Error> {
164    convert_to_array(bytes).map(f32::from_be_bytes)
165}
166
167#[inline]
168pub fn try_f64_from_bytes(bytes: &[u8]) -> Result<f64, io::Error> {
169    convert_to_array(bytes).map(f64::from_be_bytes)
170}
171
172#[inline]
173pub fn u16_from_bytes(bytes: [u8; 2]) -> u16 {
174    u16::from_be_bytes(bytes)
175}
176
177#[inline]
178pub fn to_short(int: i16) -> Vec<u8> {
179    int.to_be_bytes().into()
180}
181
182#[inline]
183pub fn to_int(int: i32) -> Vec<u8> {
184    int.to_be_bytes().into()
185}
186
187#[inline]
188pub fn to_bigint(int: i64) -> Vec<u8> {
189    int.to_be_bytes().into()
190}
191
192#[inline]
193pub fn to_u_short(int: u16) -> Vec<u8> {
194    int.to_be_bytes().into()
195}
196
197#[inline]
198pub fn to_u_int(int: u32) -> Vec<u8> {
199    int.to_be_bytes().into()
200}
201
202#[inline]
203pub fn to_u_big(int: u64) -> Vec<u8> {
204    int.to_be_bytes().into()
205}
206
207#[inline]
208pub fn to_float(f: f32) -> Vec<u8> {
209    f.to_be_bytes().into()
210}
211
212#[inline]
213pub fn to_float_big(f: f64) -> Vec<u8> {
214    f.to_be_bytes().into()
215}
216
217pub fn serialize_str(cursor: &mut Cursor<&mut Vec<u8>>, value: &str, version: Version) {
218    let len = value.len() as CIntShort;
219    len.serialize(cursor, version);
220    let _ = cursor.write(value.as_bytes());
221}
222
223pub(crate) fn serialize_str_long(cursor: &mut Cursor<&mut Vec<u8>>, value: &str, version: Version) {
224    let len = value.len() as CInt;
225    len.serialize(cursor, version);
226    let _ = cursor.write(value.as_bytes());
227}
228
229pub(crate) fn from_cursor_str<'a>(cursor: &mut Cursor<&'a [u8]>) -> CDRSResult<&'a str> {
230    let mut buff = [0; SHORT_LEN];
231    cursor.read_exact(&mut buff)?;
232
233    let len = CIntShort::from_be_bytes(buff);
234    let body_bytes = cursor_next_value_ref(cursor, len as usize)?;
235
236    std::str::from_utf8(body_bytes).map_err(Into::into)
237}
238
239pub(crate) fn from_cursor_str_long<'a>(cursor: &mut Cursor<&'a [u8]>) -> CDRSResult<&'a str> {
240    let mut buff = [0; INT_LEN];
241    cursor.read_exact(&mut buff)?;
242
243    let len = CInt::from_be_bytes(buff);
244    let body_bytes = cursor_next_value_ref(cursor, len as usize)?;
245
246    std::str::from_utf8(body_bytes).map_err(Into::into)
247}
248
249pub(crate) fn serialize_str_list<'a>(
250    cursor: &mut Cursor<&mut Vec<u8>>,
251    list: impl ExactSizeIterator<Item = &'a str>,
252    version: Version,
253) {
254    let len = list.len() as CIntShort;
255    len.serialize(cursor, version);
256
257    for string in list {
258        serialize_str(cursor, string, version);
259    }
260}
261
262pub fn from_cursor_string_list(cursor: &mut Cursor<&[u8]>) -> CDRSResult<Vec<String>> {
263    let mut buff = [0; SHORT_LEN];
264    cursor.read_exact(&mut buff)?;
265
266    let len = i16::from_be_bytes(buff);
267    let mut list = Vec::with_capacity(len as usize);
268    for _ in 0..len {
269        list.push(from_cursor_str(cursor)?.to_string());
270    }
271
272    Ok(list)
273}
274
275#[derive(Debug, Clone, Hash, PartialEq, Eq, Ord, PartialOrd)]
276/// The structure that represents Cassandra byte type.
277pub struct CBytes {
278    bytes: Option<Vec<u8>>,
279}
280
281impl CBytes {
282    #[inline]
283    pub fn new(bytes: Vec<u8>) -> CBytes {
284        CBytes { bytes: Some(bytes) }
285    }
286
287    /// Creates Cassandra bytes that represent null value
288    #[inline]
289    pub fn new_null() -> CBytes {
290        CBytes { bytes: None }
291    }
292
293    /// Converts `CBytes` into a plain array of bytes
294    #[inline]
295    pub fn into_bytes(self) -> Option<Vec<u8>> {
296        self.bytes
297    }
298
299    #[inline]
300    pub fn as_slice(&self) -> Option<&[u8]> {
301        self.bytes.as_deref()
302    }
303
304    #[inline]
305    pub fn is_null_or_empty(&self) -> bool {
306        match &self.bytes {
307            None => true,
308            Some(bytes) => bytes.is_empty(),
309        }
310    }
311
312    #[inline]
313    #[deprecated(note = "Use into_bytes().")]
314    pub fn into_plain(self) -> Option<Vec<u8>> {
315        self.bytes
316    }
317}
318
319impl FromCursor for CBytes {
320    fn from_cursor(cursor: &mut Cursor<&[u8]>, version: Version) -> CDRSResult<CBytes> {
321        let len = CInt::from_cursor(cursor, version)?;
322        // null or not set value
323        if len < 0 {
324            return Ok(CBytes { bytes: None });
325        }
326
327        cursor_next_value(cursor, len as usize).map(CBytes::new)
328    }
329}
330
331impl Serialize for CBytes {
332    fn serialize(&self, cursor: &mut Cursor<&mut Vec<u8>>, version: Version) {
333        match &self.bytes {
334            Some(bytes) => {
335                let len = bytes.len() as CInt;
336                len.serialize(cursor, version);
337                bytes.serialize(cursor, version);
338            }
339            None => NULL_INT_LEN.serialize(cursor, version),
340        }
341    }
342}
343
344/// Cassandra short bytes
345#[derive(Debug, Clone, Ord, PartialOrd, Eq, PartialEq, Hash, Default)]
346pub struct CBytesShort {
347    bytes: Option<Vec<u8>>,
348}
349
350impl CBytesShort {
351    #[inline]
352    pub fn new(bytes: Vec<u8>) -> CBytesShort {
353        CBytesShort { bytes: Some(bytes) }
354    }
355
356    /// Converts `CBytesShort` into plain vector of bytes
357    #[inline]
358    pub fn into_bytes(self) -> Option<Vec<u8>> {
359        self.bytes
360    }
361
362    #[inline]
363    pub fn serialized_len(&self) -> usize {
364        SHORT_LEN
365            + if let Some(bytes) = &self.bytes {
366                bytes.len()
367            } else {
368                0
369            }
370    }
371
372    #[inline]
373    #[deprecated(note = "Use into_bytes().")]
374    pub fn into_plain(self) -> Option<Vec<u8>> {
375        self.bytes
376    }
377}
378
379impl FromCursor for CBytesShort {
380    /// from_cursor gets Cursor who's position is set such that it should be a start of bytes.
381    /// It reads required number of bytes and returns a CBytes
382    fn from_cursor(cursor: &mut Cursor<&[u8]>, version: Version) -> CDRSResult<CBytesShort> {
383        let len = CIntShort::from_cursor(cursor, version)?;
384
385        if len < 0 {
386            return Ok(CBytesShort { bytes: None });
387        }
388
389        cursor_next_value(cursor, len as usize)
390            .map(CBytesShort::new)
391            .map_err(Into::into)
392    }
393}
394
395impl Serialize for CBytesShort {
396    fn serialize(&self, cursor: &mut Cursor<&mut Vec<u8>>, version: Version) {
397        match &self.bytes {
398            Some(bytes) => {
399                let len = bytes.len() as CIntShort;
400                len.serialize(cursor, version);
401                bytes.serialize(cursor, version);
402            }
403            None => NULL_SHORT_LEN.serialize(cursor, version),
404        }
405    }
406}
407
408/// Cassandra int type.
409pub type CInt = i32;
410
411impl FromCursor for CInt {
412    fn from_cursor(cursor: &mut Cursor<&[u8]>, _version: Version) -> CDRSResult<CInt> {
413        let mut buff = [0; INT_LEN];
414        cursor.read_exact(&mut buff)?;
415
416        Ok(CInt::from_be_bytes(buff))
417    }
418}
419
420/// Cassandra int short type.
421pub type CIntShort = i16;
422
423impl FromCursor for CIntShort {
424    fn from_cursor(cursor: &mut Cursor<&[u8]>, _version: Version) -> CDRSResult<CIntShort> {
425        let mut buff = [0; SHORT_LEN];
426        cursor.read_exact(&mut buff)?;
427
428        Ok(CIntShort::from_be_bytes(buff))
429    }
430}
431
432/// Cassandra long type.
433pub type CLong = i64;
434
435impl FromCursor for CLong {
436    fn from_cursor(cursor: &mut Cursor<&[u8]>, _version: Version) -> CDRSResult<Self> {
437        let mut buff = [0; LONG_LEN];
438        cursor.read_exact(&mut buff)?;
439
440        Ok(CLong::from_be_bytes(buff))
441    }
442}
443
444impl Serialize for SocketAddr {
445    fn serialize(&self, cursor: &mut Cursor<&mut Vec<u8>>, version: Version) {
446        match self.ip() {
447            IpAddr::V4(v4) => {
448                [4].serialize(cursor, version);
449                v4.octets().serialize(cursor, version);
450            }
451            IpAddr::V6(v6) => {
452                [16].serialize(cursor, version);
453                v6.octets().serialize(cursor, version);
454            }
455        }
456
457        to_int(self.port().into()).serialize(cursor, version);
458    }
459}
460
461impl FromCursor for SocketAddr {
462    fn from_cursor(cursor: &mut Cursor<&[u8]>, version: Version) -> CDRSResult<Self> {
463        let mut buff = [0];
464        cursor.read_exact(&mut buff)?;
465
466        let n = buff[0];
467
468        let ip = decode_inet(cursor_next_value(cursor, n as usize)?.as_slice())?;
469        let port = CInt::from_cursor(cursor, version)?;
470        Ok(SocketAddr::new(ip, port as u16))
471    }
472}
473
474pub fn cursor_next_value(cursor: &mut Cursor<&[u8]>, len: usize) -> CDRSResult<Vec<u8>> {
475    let mut buff = vec![0u8; len];
476    cursor.read_exact(&mut buff)?;
477    Ok(buff)
478}
479
480pub fn cursor_next_value_ref<'a>(
481    cursor: &mut Cursor<&'a [u8]>,
482    len: usize,
483) -> CDRSResult<&'a [u8]> {
484    let start = cursor.position() as usize;
485    let result = &cursor.get_ref()[start..start + len];
486    cursor.set_position(cursor.position() + len as u64);
487
488    if result.len() != len {
489        Err(CdrsError::General(
490            "cursor_next_value_ref could not retrieve a full slice".into(),
491        ))
492    } else {
493        Ok(result)
494    }
495}
496
497#[cfg(test)]
498mod tests {
499    use super::*;
500    use crate::frame::traits::FromCursor;
501    use num_bigint::BigInt;
502    use std::io::Cursor;
503
504    fn from_i_bytes(bytes: &[u8]) -> i64 {
505        try_i64_from_bytes(bytes).unwrap()
506    }
507
508    fn try_u16_from_bytes(bytes: &[u8]) -> Result<u16, io::Error> {
509        Ok(u16::from_be_bytes(convert_to_array(bytes)?))
510    }
511
512    fn to_varint(int: BigInt) -> Vec<u8> {
513        int.to_signed_bytes_be()
514    }
515
516    #[test]
517    fn test_from_cursor_str() {
518        let a = &[0, 3, 102, 111, 111, 0];
519        let mut cursor: Cursor<&[u8]> = Cursor::new(a);
520        let cstring = from_cursor_str(&mut cursor).unwrap();
521        assert_eq!(cstring, "foo");
522    }
523
524    #[test]
525    fn test_from_cursor_str_long() {
526        let a = &[0, 0, 0, 3, 102, 111, 111, 0];
527        let mut cursor: Cursor<&[u8]> = Cursor::new(a);
528        let cstring = from_cursor_str_long(&mut cursor).unwrap();
529        assert_eq!(cstring, "foo");
530    }
531
532    #[test]
533    fn test_serialize_str() {
534        let input = "foo";
535
536        let mut buf = vec![];
537        serialize_str(&mut Cursor::new(&mut buf), input, Version::V4);
538
539        assert_eq!(buf, &[0, 3, 102, 111, 111]);
540    }
541
542    #[test]
543    fn test_serialize_str_long() {
544        let input = "foo";
545
546        let mut buf = vec![];
547        serialize_str_long(&mut Cursor::new(&mut buf), input, Version::V4);
548
549        assert_eq!(buf, &[0, 0, 0, 3, 102, 111, 111]);
550    }
551
552    #[test]
553    fn test_cstringlist() {
554        let a = &[0, 2, 0, 3, 102, 111, 111, 0, 3, 102, 111, 112];
555        let mut cursor: Cursor<&[u8]> = Cursor::new(a);
556        let list = from_cursor_string_list(&mut cursor).unwrap();
557
558        assert_eq!(list, vec!("foo".to_string(), "fop".to_string()));
559    }
560
561    // CBytes
562    #[test]
563    fn test_cbytes_new() {
564        let bytes_vec = vec![1, 2, 3];
565        let _ = CBytes::new(bytes_vec);
566    }
567
568    #[test]
569    fn test_cbytes_into_bytes() {
570        let cbytes = CBytes::new(vec![1, 2, 3]);
571        assert_eq!(cbytes.into_bytes().unwrap(), &[1, 2, 3]);
572    }
573
574    #[test]
575    fn test_cbytes_from_cursor() {
576        let a = &[0, 0, 0, 3, 1, 2, 3];
577        let mut cursor: Cursor<&[u8]> = Cursor::new(a);
578        let cbytes = CBytes::from_cursor(&mut cursor, Version::V4).unwrap();
579        assert_eq!(cbytes.into_bytes().unwrap(), vec![1, 2, 3]);
580    }
581
582    #[test]
583    fn test_cbytes_serialize() {
584        let bytes_vec = vec![1, 2, 3];
585        let cbytes = CBytes::new(bytes_vec);
586        assert_eq!(
587            cbytes.serialize_to_vec(Version::V4),
588            vec![0, 0, 0, 3, 1, 2, 3]
589        );
590    }
591
592    // CBytesShort
593    #[test]
594    fn test_cbytesshort_new() {
595        let bytes_vec = vec![1, 2, 3];
596        let _ = CBytesShort::new(bytes_vec);
597    }
598
599    #[test]
600    fn test_cbytesshort_into_bytes() {
601        let cbytes = CBytesShort::new(vec![1, 2, 3]);
602        assert_eq!(cbytes.into_bytes().unwrap(), vec![1, 2, 3]);
603    }
604
605    #[test]
606    fn test_cbytesshort_from_cursor() {
607        let a = &[0, 3, 1, 2, 3];
608        let mut cursor: Cursor<&[u8]> = Cursor::new(a);
609        let cbytes = CBytesShort::from_cursor(&mut cursor, Version::V4).unwrap();
610        assert_eq!(cbytes.into_bytes().unwrap(), vec![1, 2, 3]);
611    }
612
613    #[test]
614    fn test_cbytesshort_serialize() {
615        let bytes_vec: Vec<u8> = vec![1, 2, 3];
616        let cbytes = CBytesShort::new(bytes_vec);
617        assert_eq!(cbytes.serialize_to_vec(Version::V4), vec![0, 3, 1, 2, 3]);
618    }
619
620    #[test]
621    fn test_cint_from_cursor() {
622        let a = &[0, 0, 0, 5];
623        let mut cursor: Cursor<&[u8]> = Cursor::new(a);
624        let i = CInt::from_cursor(&mut cursor, Version::V4).unwrap();
625        assert_eq!(i, 5);
626    }
627
628    #[test]
629    fn test_cintshort_from_cursor() {
630        let a = &[0, 5];
631        let mut cursor: Cursor<&[u8]> = Cursor::new(a);
632        let i = CIntShort::from_cursor(&mut cursor, Version::V4).unwrap();
633        assert_eq!(i, 5);
634    }
635
636    #[test]
637    fn test_cursor_next_value() {
638        let a = &[0, 1, 2, 3, 4];
639        let mut cursor: Cursor<&[u8]> = Cursor::new(a);
640        let l = 3;
641        let val = cursor_next_value(&mut cursor, l).unwrap();
642        assert_eq!(val, vec![0, 1, 2]);
643    }
644
645    #[test]
646    fn test_try_u16_from_bytes() {
647        let bytes: [u8; 2] = [0, 12]; // or .to_le()
648        let val = try_u16_from_bytes(&bytes);
649        assert_eq!(val.unwrap(), 12u16);
650    }
651
652    #[test]
653    fn test_from_i_bytes() {
654        let bytes: [u8; 8] = [0, 0, 0, 0, 0, 0, 0, 12]; // or .to_le()
655        let val = from_i_bytes(&bytes);
656        assert_eq!(val, 12i64);
657    }
658
659    #[test]
660    fn test_to_varint() {
661        assert_eq!(to_varint(0.into()), vec![0x00]);
662        assert_eq!(to_varint(1.into()), vec![0x01]);
663        assert_eq!(to_varint(127.into()), vec![0x7F]);
664        assert_eq!(to_varint(128.into()), vec![0x00, 0x80]);
665        assert_eq!(to_varint(129.into()), vec![0x00, 0x81]);
666        assert_eq!(to_varint(BigInt::from(-1)), vec![0xFF]);
667        assert_eq!(to_varint(BigInt::from(-128)), vec![0x80]);
668        assert_eq!(to_varint(BigInt::from(-129)), vec![0xFF, 0x7F]);
669    }
670}