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 a 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 a 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 a 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
313impl FromCursor for CBytes {
314    fn from_cursor(cursor: &mut Cursor<&[u8]>, version: Version) -> CDRSResult<CBytes> {
315        let len = CInt::from_cursor(cursor, version)?;
316        // null or not set value
317        if len < 0 {
318            return Ok(CBytes { bytes: None });
319        }
320
321        cursor_next_value(cursor, len as usize).map(CBytes::new)
322    }
323}
324
325impl Serialize for CBytes {
326    fn serialize(&self, cursor: &mut Cursor<&mut Vec<u8>>, version: Version) {
327        match &self.bytes {
328            Some(bytes) => {
329                let len = bytes.len() as CInt;
330                len.serialize(cursor, version);
331                bytes.serialize(cursor, version);
332            }
333            None => NULL_INT_LEN.serialize(cursor, version),
334        }
335    }
336}
337
338/// Cassandra short bytes
339#[derive(Debug, Clone, Ord, PartialOrd, Eq, PartialEq, Hash, Default)]
340pub struct CBytesShort {
341    bytes: Option<Vec<u8>>,
342}
343
344impl CBytesShort {
345    #[inline]
346    pub fn new(bytes: Vec<u8>) -> CBytesShort {
347        CBytesShort { bytes: Some(bytes) }
348    }
349
350    /// Converts `CBytesShort` into a plain vector of bytes
351    #[inline]
352    pub fn into_bytes(self) -> Option<Vec<u8>> {
353        self.bytes
354    }
355
356    #[inline]
357    pub fn serialized_len(&self) -> usize {
358        SHORT_LEN
359            + if let Some(bytes) = &self.bytes {
360                bytes.len()
361            } else {
362                0
363            }
364    }
365}
366
367impl FromCursor for CBytesShort {
368    /// `from_cursor` gets the Cursor whose position is set such that it should be a start of bytes.
369    /// It reads the required number of bytes and returns a CBytes
370    fn from_cursor(cursor: &mut Cursor<&[u8]>, version: Version) -> CDRSResult<CBytesShort> {
371        let len = CIntShort::from_cursor(cursor, version)?;
372
373        if len < 0 {
374            return Ok(CBytesShort { bytes: None });
375        }
376
377        cursor_next_value(cursor, len as usize).map(CBytesShort::new)
378    }
379}
380
381impl Serialize for CBytesShort {
382    fn serialize(&self, cursor: &mut Cursor<&mut Vec<u8>>, version: Version) {
383        match &self.bytes {
384            Some(bytes) => {
385                let len = bytes.len() as CIntShort;
386                len.serialize(cursor, version);
387                bytes.serialize(cursor, version);
388            }
389            None => NULL_SHORT_LEN.serialize(cursor, version),
390        }
391    }
392}
393
394/// Cassandra int type.
395pub type CInt = i32;
396
397impl FromCursor for CInt {
398    fn from_cursor(cursor: &mut Cursor<&[u8]>, _version: Version) -> CDRSResult<CInt> {
399        let mut buff = [0; INT_LEN];
400        cursor.read_exact(&mut buff)?;
401
402        Ok(CInt::from_be_bytes(buff))
403    }
404}
405
406/// Cassandra int short type.
407pub type CIntShort = i16;
408
409impl FromCursor for CIntShort {
410    fn from_cursor(cursor: &mut Cursor<&[u8]>, _version: Version) -> CDRSResult<CIntShort> {
411        let mut buff = [0; SHORT_LEN];
412        cursor.read_exact(&mut buff)?;
413
414        Ok(CIntShort::from_be_bytes(buff))
415    }
416}
417
418/// Cassandra long type.
419pub type CLong = i64;
420
421impl FromCursor for CLong {
422    fn from_cursor(cursor: &mut Cursor<&[u8]>, _version: Version) -> CDRSResult<Self> {
423        let mut buff = [0; LONG_LEN];
424        cursor.read_exact(&mut buff)?;
425
426        Ok(CLong::from_be_bytes(buff))
427    }
428}
429
430impl Serialize for SocketAddr {
431    fn serialize(&self, cursor: &mut Cursor<&mut Vec<u8>>, version: Version) {
432        match self.ip() {
433            IpAddr::V4(v4) => {
434                [4].serialize(cursor, version);
435                v4.octets().serialize(cursor, version);
436            }
437            IpAddr::V6(v6) => {
438                [16].serialize(cursor, version);
439                v6.octets().serialize(cursor, version);
440            }
441        }
442
443        to_int(self.port().into()).serialize(cursor, version);
444    }
445}
446
447impl FromCursor for SocketAddr {
448    fn from_cursor(cursor: &mut Cursor<&[u8]>, version: Version) -> CDRSResult<Self> {
449        let mut buff = [0];
450        cursor.read_exact(&mut buff)?;
451
452        let n = buff[0];
453
454        let ip = decode_inet(cursor_next_value(cursor, n as usize)?.as_slice())?;
455        let port = CInt::from_cursor(cursor, version)?;
456        Ok(SocketAddr::new(ip, port as u16))
457    }
458}
459
460pub fn cursor_next_value(cursor: &mut Cursor<&[u8]>, len: usize) -> CDRSResult<Vec<u8>> {
461    let mut buff = vec![0u8; len];
462    cursor.read_exact(&mut buff)?;
463    Ok(buff)
464}
465
466pub fn cursor_next_value_ref<'a>(
467    cursor: &mut Cursor<&'a [u8]>,
468    len: usize,
469) -> CDRSResult<&'a [u8]> {
470    let start = cursor.position() as usize;
471    let result = &cursor.get_ref()[start..start + len];
472    cursor.set_position(cursor.position() + len as u64);
473
474    if result.len() != len {
475        Err(CdrsError::General(
476            "cursor_next_value_ref could not retrieve a full slice".into(),
477        ))
478    } else {
479        Ok(result)
480    }
481}
482
483#[cfg(test)]
484mod tests {
485    use super::*;
486    use crate::frame::traits::FromCursor;
487    use num_bigint::BigInt;
488    use std::io::Cursor;
489
490    fn from_i_bytes(bytes: &[u8]) -> i64 {
491        try_i64_from_bytes(bytes).unwrap()
492    }
493
494    fn try_u16_from_bytes(bytes: &[u8]) -> Result<u16, io::Error> {
495        Ok(u16::from_be_bytes(convert_to_array(bytes)?))
496    }
497
498    fn to_varint(int: BigInt) -> Vec<u8> {
499        int.to_signed_bytes_be()
500    }
501
502    #[test]
503    fn test_from_cursor_str() {
504        let a = &[0, 3, 102, 111, 111, 0];
505        let mut cursor: Cursor<&[u8]> = Cursor::new(a);
506        let cstring = from_cursor_str(&mut cursor).unwrap();
507        assert_eq!(cstring, "foo");
508    }
509
510    #[test]
511    fn test_from_cursor_str_long() {
512        let a = &[0, 0, 0, 3, 102, 111, 111, 0];
513        let mut cursor: Cursor<&[u8]> = Cursor::new(a);
514        let cstring = from_cursor_str_long(&mut cursor).unwrap();
515        assert_eq!(cstring, "foo");
516    }
517
518    #[test]
519    fn test_serialize_str() {
520        let input = "foo";
521
522        let mut buf = vec![];
523        serialize_str(&mut Cursor::new(&mut buf), input, Version::V4);
524
525        assert_eq!(buf, &[0, 3, 102, 111, 111]);
526    }
527
528    #[test]
529    fn test_serialize_str_long() {
530        let input = "foo";
531
532        let mut buf = vec![];
533        serialize_str_long(&mut Cursor::new(&mut buf), input, Version::V4);
534
535        assert_eq!(buf, &[0, 0, 0, 3, 102, 111, 111]);
536    }
537
538    #[test]
539    fn test_cstringlist() {
540        let a = &[0, 2, 0, 3, 102, 111, 111, 0, 3, 102, 111, 112];
541        let mut cursor: Cursor<&[u8]> = Cursor::new(a);
542        let list = from_cursor_string_list(&mut cursor).unwrap();
543
544        assert_eq!(list, vec!("foo".to_string(), "fop".to_string()));
545    }
546
547    // CBytes
548    #[test]
549    fn test_cbytes_new() {
550        let bytes_vec = vec![1, 2, 3];
551        let _ = CBytes::new(bytes_vec);
552    }
553
554    #[test]
555    fn test_cbytes_into_bytes() {
556        let cbytes = CBytes::new(vec![1, 2, 3]);
557        assert_eq!(cbytes.into_bytes().unwrap(), &[1, 2, 3]);
558    }
559
560    #[test]
561    fn test_cbytes_from_cursor() {
562        let a = &[0, 0, 0, 3, 1, 2, 3];
563        let mut cursor: Cursor<&[u8]> = Cursor::new(a);
564        let cbytes = CBytes::from_cursor(&mut cursor, Version::V4).unwrap();
565        assert_eq!(cbytes.into_bytes().unwrap(), vec![1, 2, 3]);
566    }
567
568    #[test]
569    fn test_cbytes_serialize() {
570        let bytes_vec = vec![1, 2, 3];
571        let cbytes = CBytes::new(bytes_vec);
572        assert_eq!(
573            cbytes.serialize_to_vec(Version::V4),
574            vec![0, 0, 0, 3, 1, 2, 3]
575        );
576    }
577
578    // CBytesShort
579    #[test]
580    fn test_cbytesshort_new() {
581        let bytes_vec = vec![1, 2, 3];
582        let _ = CBytesShort::new(bytes_vec);
583    }
584
585    #[test]
586    fn test_cbytesshort_into_bytes() {
587        let cbytes = CBytesShort::new(vec![1, 2, 3]);
588        assert_eq!(cbytes.into_bytes().unwrap(), vec![1, 2, 3]);
589    }
590
591    #[test]
592    fn test_cbytesshort_from_cursor() {
593        let a = &[0, 3, 1, 2, 3];
594        let mut cursor: Cursor<&[u8]> = Cursor::new(a);
595        let cbytes = CBytesShort::from_cursor(&mut cursor, Version::V4).unwrap();
596        assert_eq!(cbytes.into_bytes().unwrap(), vec![1, 2, 3]);
597    }
598
599    #[test]
600    fn test_cbytesshort_serialize() {
601        let bytes_vec: Vec<u8> = vec![1, 2, 3];
602        let cbytes = CBytesShort::new(bytes_vec);
603        assert_eq!(cbytes.serialize_to_vec(Version::V4), vec![0, 3, 1, 2, 3]);
604    }
605
606    #[test]
607    fn test_cint_from_cursor() {
608        let a = &[0, 0, 0, 5];
609        let mut cursor: Cursor<&[u8]> = Cursor::new(a);
610        let i = CInt::from_cursor(&mut cursor, Version::V4).unwrap();
611        assert_eq!(i, 5);
612    }
613
614    #[test]
615    fn test_cintshort_from_cursor() {
616        let a = &[0, 5];
617        let mut cursor: Cursor<&[u8]> = Cursor::new(a);
618        let i = CIntShort::from_cursor(&mut cursor, Version::V4).unwrap();
619        assert_eq!(i, 5);
620    }
621
622    #[test]
623    fn test_cursor_next_value() {
624        let a = &[0, 1, 2, 3, 4];
625        let mut cursor: Cursor<&[u8]> = Cursor::new(a);
626        let l = 3;
627        let val = cursor_next_value(&mut cursor, l).unwrap();
628        assert_eq!(val, vec![0, 1, 2]);
629    }
630
631    #[test]
632    fn test_try_u16_from_bytes() {
633        let bytes: [u8; 2] = [0, 12]; // or .to_le()
634        let val = try_u16_from_bytes(&bytes);
635        assert_eq!(val.unwrap(), 12u16);
636    }
637
638    #[test]
639    fn test_from_i_bytes() {
640        let bytes: [u8; 8] = [0, 0, 0, 0, 0, 0, 0, 12]; // or .to_le()
641        let val = from_i_bytes(&bytes);
642        assert_eq!(val, 12i64);
643    }
644
645    #[test]
646    fn test_to_varint() {
647        assert_eq!(to_varint(0.into()), vec![0x00]);
648        assert_eq!(to_varint(1.into()), vec![0x01]);
649        assert_eq!(to_varint(127.into()), vec![0x7F]);
650        assert_eq!(to_varint(128.into()), vec![0x00, 0x80]);
651        assert_eq!(to_varint(129.into()), vec![0x00, 0x81]);
652        assert_eq!(to_varint(BigInt::from(-1)), vec![0xFF]);
653        assert_eq!(to_varint(BigInt::from(-128)), vec![0x80]);
654        assert_eq!(to_varint(BigInt::from(-129)), vec![0xFF, 0x7F]);
655    }
656}