cassandra_proto/types/
mod.rs

1/// Cassandra types
2use std::io;
3use std::io::{Cursor, Read};
4use std::net::SocketAddr;
5
6use byteorder::{BigEndian, ByteOrder, ReadBytesExt, WriteBytesExt};
7use crate::error::{column_is_empty_err, Error as CDRSError, Result as CDRSResult};
8use crate::frame::traits::{FromBytes, FromCursor, IntoBytes};
9use crate::types::data_serialization_types::decode_inet;
10
11pub const LONG_STR_LEN: usize = 4;
12pub const SHORT_LEN: usize = 2;
13pub const INT_LEN: usize = 4;
14pub const UUID_LEN: usize = 16;
15
16#[macro_use]
17pub mod blob;
18pub mod data_serialization_types;
19pub mod decimal;
20pub mod from_cdrs;
21pub mod list;
22pub mod map;
23pub mod rows;
24pub mod tuple;
25pub mod udt;
26pub mod value;
27
28pub mod prelude {
29    pub use crate::error::{Error, Result};
30    pub use crate::frame::{TryFromRow, TryFromUDT};
31    pub use super::blob::Blob;
32    pub use super::decimal::Decimal;
33    pub use super::list::List;
34    pub use super::map::Map;
35    pub use super::rows::Row;
36    pub use super::tuple::Tuple;
37    pub use super::udt::UDT;
38    pub use super::value::{Bytes, Value};
39    pub use super::AsRustType;
40}
41
42/// Should be used to represent a single column as a Rust value.
43pub trait AsRustType<T> {
44    fn as_rust_type(&self) -> CDRSResult<Option<T>>;
45
46    fn as_r_type(&self) -> CDRSResult<T> {
47        self.as_rust_type()
48            .and_then(|op| op.ok_or(CDRSError::from("Value is null or non-set")))
49    }
50}
51
52pub trait AsRust {
53    fn as_rust<R>(&self) -> CDRSResult<Option<R>>
54    where
55        Self: AsRustType<R>,
56    {
57        self.as_rust_type()
58    }
59
60    fn as_r_rust<T>(&self) -> CDRSResult<T>
61    where
62        Self: AsRustType<T>,
63    {
64        self.as_rust()
65            .and_then(|op| op.ok_or("Value is null or non-set".into()))
66    }
67}
68
69/// Should be used to return a single column as Rust value by its name.
70pub trait IntoRustByName<R> {
71    fn get_by_name(&self, name: &str) -> CDRSResult<Option<R>>;
72
73    fn get_r_by_name(&self, name: &str) -> CDRSResult<R> {
74        self.get_by_name(name)
75            .and_then(|op| op.ok_or(column_is_empty_err(name)))
76    }
77}
78
79pub trait ByName {
80    fn by_name<R>(&self, name: &str) -> CDRSResult<Option<R>>
81    where
82        Self: IntoRustByName<R>,
83    {
84        self.get_by_name(name)
85    }
86
87    fn r_by_name<R>(&self, name: &str) -> CDRSResult<R>
88    where
89        Self: IntoRustByName<R>,
90    {
91        self.by_name(name)
92            .and_then(|op| op.ok_or(column_is_empty_err(name)))
93    }
94}
95
96/// Should be used to return a single column as Rust value by its name.
97pub trait IntoRustByIndex<R> {
98    fn get_by_index(&self, index: usize) -> CDRSResult<Option<R>>;
99
100    fn get_r_by_index(&self, index: usize) -> CDRSResult<R> {
101        self.get_by_index(index)
102            .and_then(|op| op.ok_or(column_is_empty_err(index)))
103    }
104}
105
106pub trait ByIndex {
107    fn by_index<R>(&self, index: usize) -> CDRSResult<Option<R>>
108    where
109        Self: IntoRustByIndex<R>,
110    {
111        self.get_by_index(index)
112    }
113
114    fn r_by_index<R>(&self, index: usize) -> CDRSResult<R>
115    where
116        Self: IntoRustByIndex<R>,
117    {
118        self.by_index(index)
119            .and_then(|op| op.ok_or(column_is_empty_err(index)))
120    }
121}
122
123/// Tries to converts u64 numerical value into array of n bytes.
124pub fn try_to_n_bytes(int: u64, n: usize) -> io::Result<Vec<u8>> {
125    let mut bytes = vec![];
126    bytes.write_uint::<BigEndian>(int, n)?;
127
128    Ok(bytes)
129}
130
131/// Converts u64 numerical value into array of n bytes
132///
133/// # Panics
134///
135/// It panics if given unisigned integer could not be converted in an array of n bytes
136pub fn to_n_bytes(int: u64, n: usize) -> Vec<u8> {
137    try_to_n_bytes(int, n).unwrap()
138}
139
140pub fn try_i_to_n_bytes(int: i64, n: usize) -> io::Result<Vec<u8>> {
141    let mut bytes = Vec::with_capacity(n);
142    unsafe {
143        bytes.set_len(n);
144    }
145    BigEndian::write_int(&mut bytes, int, n);
146
147    Ok(bytes)
148}
149
150/// Converts u64 numerical value into array of n bytes
151///
152/// # Panics
153///
154/// It panics if given integer could not be converted in an array of n bytes
155pub fn i_to_n_bytes(int: i64, n: usize) -> Vec<u8> {
156    try_i_to_n_bytes(int, n).unwrap()
157}
158
159/// Tryies to decode bytes array into `u64`.
160pub fn try_from_bytes(bytes: &[u8]) -> Result<u64, io::Error> {
161    let l = bytes.len();
162    let mut c = Cursor::new(bytes);
163    c.read_uint::<BigEndian>(l)
164}
165
166/// Tryies to decode bytes array into `u16`.
167pub fn try_u16_from_bytes(bytes: &[u8]) -> Result<u16, io::Error> {
168    let mut c = Cursor::new(bytes);
169    c.read_u16::<BigEndian>()
170}
171
172/// Tries to decode bytes array into `i64`.
173pub fn try_i_from_bytes(bytes: &[u8]) -> Result<i64, io::Error> {
174    let l = bytes.len();
175    let mut c = Cursor::new(bytes);
176    c.read_int::<BigEndian>(l)
177}
178
179/// Tries to decode bytes array into `i32`.
180pub fn try_i32_from_bytes(bytes: &[u8]) -> Result<i32, io::Error> {
181    let mut c = Cursor::new(bytes);
182    c.read_i32::<BigEndian>()
183}
184
185/// Tries to decode bytes array into `i16`.
186pub fn try_i16_from_bytes(bytes: &[u8]) -> Result<i16, io::Error> {
187    let mut c = Cursor::new(bytes);
188    c.read_i16::<BigEndian>()
189}
190
191/// Tries to decode bytes array into `f32`.
192pub fn try_f32_from_bytes(bytes: &[u8]) -> Result<f32, io::Error> {
193    let mut c = Cursor::new(bytes);
194    c.read_f32::<BigEndian>()
195}
196
197/// Tries to decode bytes array into `f64`.
198pub fn try_f64_from_bytes(bytes: &[u8]) -> Result<f64, io::Error> {
199    let mut c = Cursor::new(bytes);
200    c.read_f64::<BigEndian>()
201}
202
203/// Converts byte-array into u64
204///
205/// # Panics
206///
207/// It panics if given bytes could not be converted into `u64`
208pub fn from_bytes(bytes: &[u8]) -> u64 {
209    try_from_bytes(bytes).unwrap()
210}
211
212/// Converts byte-array into i64
213///
214/// # Panics
215///
216/// It panics if given bytes could not be converted into `i64`
217pub fn from_i_bytes(bytes: &[u8]) -> i64 {
218    try_i_from_bytes(bytes).unwrap()
219}
220
221/// Converts byte-array into u16
222///
223/// # Panics
224///
225/// It panics if given bytes could not be converted into `u16`
226pub fn from_u16_bytes(bytes: &[u8]) -> u16 {
227    try_u16_from_bytes(bytes).unwrap()
228}
229
230/// Converts number i16 into Cassandra's [short].
231///
232/// # Panics
233///
234/// It panics if given `i16` could not be converted into bytes
235pub fn to_short(int: i16) -> Vec<u8> {
236    let mut bytes = vec![];
237    // should not panic as input is i16
238    let _ = bytes.write_i16::<BigEndian>(int).unwrap();
239
240    bytes
241}
242
243/// Convers integer into Cassandra's [int]
244///
245/// # Panics
246///
247/// It panics if given `i32` could not be converted into bytes
248pub fn to_int(int: i32) -> Vec<u8> {
249    let mut bytes = vec![];
250    // should not panic as input is i16
251    let _ = bytes.write_i32::<BigEndian>(int).unwrap();
252
253    bytes
254}
255
256/// Convers integer into Cassandra's [int]
257///
258/// # Panics
259///
260/// It panics if given `i64` could not be converted into bytes
261pub fn to_bigint(int: i64) -> Vec<u8> {
262    let mut bytes = vec![];
263    // should not panic as input is i64
264    let _ = bytes.write_i64::<BigEndian>(int).unwrap();
265
266    bytes
267}
268
269/// Converts integer into Cassandra's [varint].
270pub fn to_varint(int: i64) -> Vec<u8> {
271    if int == 0 {
272        return vec![0];
273    }
274
275    let mut int_bytes = to_bigint(int);
276    match int.signum() {
277        1 => {
278            int_bytes = int_bytes.into_iter().skip_while(|b| *b == 0x00).collect();
279            if int_bytes
280                .get(0)
281                .map(|b| b.leading_zeros() == 0)
282                .unwrap_or(true)
283            {
284                int_bytes.insert(0, 0x00);
285            }
286        }
287        -1 => {
288            int_bytes = int_bytes.into_iter().skip_while(|b| *b == 0xFF).collect();
289            if int_bytes
290                .get(0)
291                .map(|b| b.leading_zeros() > 0)
292                .unwrap_or(true)
293            {
294                int_bytes.insert(0, 0xFF);
295            }
296        }
297        _ => unreachable!(),
298    }
299
300    int_bytes
301}
302
303/// Converts number i16 into Cassandra's `short`.
304///
305/// # Panics
306///
307/// It panics if given `u16` could not be converted into bytes
308pub fn to_u_short(int: u16) -> Vec<u8> {
309    let mut bytes = vec![];
310    // should not panic as input is i16
311    let _ = bytes.write_u16::<BigEndian>(int).unwrap();
312
313    bytes
314}
315
316/// Convers integer into Cassandra's [int]
317///
318/// # Panics
319///
320/// It panics if given `u32` could not be converted into bytes
321pub fn to_u(int: u32) -> Vec<u8> {
322    let mut bytes = vec![];
323    // should not panic as input is u64
324    let _ = bytes.write_u32::<BigEndian>(int).unwrap();
325
326    bytes
327}
328
329/// Convers integer into Cassandra's `int`
330///
331/// # Panics
332///
333/// It panics if given `u64` could not be converted into `u64`
334pub fn to_u_big(int: u64) -> Vec<u8> {
335    let mut bytes = vec![];
336    // should not panic as input is u64
337    let _ = bytes.write_u64::<BigEndian>(int).unwrap();
338
339    bytes
340}
341
342/// Converts `f32` into bytes
343///
344/// # Panics
345///
346/// It panics if given `f32` could not be converted into bytes
347pub fn to_float(f: f32) -> Vec<u8> {
348    let mut bytes = vec![];
349    // should not panic as input is f32
350    let _ = bytes.write_f32::<BigEndian>(f).unwrap();
351
352    bytes
353}
354
355/// Converts `f64` into array of bytes
356///
357/// # Panics
358///
359/// It panics if given `f63` could not be converted into bytes
360pub fn to_float_big(f: f64) -> Vec<u8> {
361    let mut bytes = vec![];
362    // should not panic as input is f64
363    let _ = bytes.write_f64::<BigEndian>(f).unwrap();
364
365    bytes
366}
367
368#[derive(Debug, Clone)]
369pub struct CString {
370    string: String,
371}
372
373impl CString {
374    pub fn new(string: String) -> CString {
375        CString { string: string }
376    }
377
378    /// Converts internal value into pointer of `str`.
379    pub fn as_str<'a>(&'a self) -> &'a str {
380        self.string.as_str()
381    }
382
383    /// Converts internal value into a plain `String`.
384    pub fn into_plain(self) -> String {
385        self.string
386    }
387
388    /// Represents internal value as a `String`.
389    pub fn as_plain(&self) -> String {
390        self.string.clone()
391    }
392}
393
394// Implementation for Rust std types
395// Use extended Rust string as Cassandra [string]
396impl IntoBytes for CString {
397    /// Converts into Cassandra byte representation of [string]
398    fn into_cbytes(&self) -> Vec<u8> {
399        let mut v: Vec<u8> = vec![];
400        let l = self.string.len() as i16;
401        v.extend_from_slice(to_short(l).as_slice());
402        v.extend_from_slice(self.string.as_bytes());
403        v
404    }
405}
406
407impl FromCursor for CString {
408    /// from_cursor gets Cursor who's position is set such that it should be a start of a [string].
409    /// It reads required number of bytes and returns a String
410    fn from_cursor(mut cursor: &mut Cursor<&[u8]>) -> CDRSResult<CString> {
411        let len_bytes = cursor_next_value(&mut cursor, SHORT_LEN as u64)?;
412        let len: u64 = try_from_bytes(len_bytes.as_slice())?;
413        let body_bytes = cursor_next_value(&mut cursor, len)?;
414
415        String::from_utf8(body_bytes)
416            .map_err(Into::into)
417            .map(CString::new)
418    }
419}
420
421#[derive(Debug, Clone)]
422pub struct CStringLong {
423    string: String,
424}
425
426impl CStringLong {
427    pub fn new(string: String) -> CStringLong {
428        CStringLong { string: string }
429    }
430
431    /// Converts internal value into pointer of `str`.
432    pub fn as_str<'a>(&'a self) -> &'a str {
433        self.string.as_str()
434    }
435
436    /// Converts internal value into a plain `String`.
437    pub fn into_plain(self) -> String {
438        self.string
439    }
440}
441
442// Implementation for Rust std types
443// Use extended Rust string as Cassandra [string]
444impl IntoBytes for CStringLong {
445    /// Converts into Cassandra byte representation of [string]
446    fn into_cbytes(&self) -> Vec<u8> {
447        let mut v: Vec<u8> = vec![];
448        let l = self.string.len() as i32;
449        v.extend_from_slice(to_int(l).as_slice());
450        v.extend_from_slice(self.string.as_bytes());
451        v
452    }
453}
454
455impl FromCursor for CStringLong {
456    /// from_cursor gets Cursor who's position is set such that it should be a start of a [string].
457    /// It reads required number of bytes and returns a String
458    fn from_cursor(mut cursor: &mut Cursor<&[u8]>) -> CDRSResult<CStringLong> {
459        let len_bytes = cursor_next_value(&mut cursor, INT_LEN as u64)?;
460        let len: u64 = try_from_bytes(len_bytes.as_slice())?;
461        let body_bytes = cursor_next_value(&mut cursor, len)?;
462
463        String::from_utf8(body_bytes)
464            .map_err(Into::into)
465            .map(CStringLong::new)
466    }
467}
468
469#[derive(Debug, Clone)]
470pub struct CStringList {
471    pub list: Vec<CString>,
472}
473
474impl CStringList {
475    pub fn into_plain(self) -> Vec<String> {
476        self.list
477            .iter()
478            .map(|string| string.clone().into_plain())
479            .collect()
480    }
481}
482
483impl IntoBytes for CStringList {
484    fn into_cbytes(&self) -> Vec<u8> {
485        let mut bytes = vec![];
486
487        let l = to_short(self.list.len() as i16);
488        bytes.extend_from_slice(l.as_slice());
489
490        bytes = self.list.iter().fold(bytes, |mut _bytes, cstring| {
491            _bytes.extend_from_slice(cstring.into_cbytes().as_slice());
492            _bytes
493        });
494
495        bytes
496    }
497}
498
499impl FromCursor for CStringList {
500    fn from_cursor(mut cursor: &mut Cursor<&[u8]>) -> CDRSResult<CStringList> {
501        // TODO: try to use slice instead
502        let mut len_bytes = [0; SHORT_LEN];
503        cursor.read_exact(&mut len_bytes)?;
504        let len = try_from_bytes(len_bytes.to_vec().as_slice())? as usize;
505        let mut list = Vec::with_capacity(len);
506        for _ in 0..len {
507            list.push(CString::from_cursor(&mut cursor)?);
508        }
509
510        Ok(CStringList { list: list })
511    }
512}
513
514//
515
516#[derive(Debug, Clone, Hash, PartialEq, Eq)]
517/// The structure that represents Cassandra byte type.
518pub struct CBytes {
519    bytes: Option<Vec<u8>>,
520}
521
522impl CBytes {
523    pub fn new(bytes: Vec<u8>) -> CBytes {
524        CBytes { bytes: Some(bytes) }
525    }
526
527    /// Creates Cassandra bytes that represent empty or null value
528    pub fn new_empty() -> CBytes {
529        CBytes { bytes: None }
530    }
531
532    /// Converts `CBytes` into a plain array of bytes
533    pub fn into_plain(self) -> Option<Vec<u8>> {
534        self.bytes
535    }
536
537    // TODO: try to replace usage of `as_plain` by `as_slice`
538    pub fn as_plain(&self) -> Option<Vec<u8>> {
539        self.bytes.clone()
540    }
541    pub fn as_slice(&self) -> Option<&[u8]> {
542        match self.bytes {
543            Some(ref v) => Some(v.as_slice()),
544            None => None,
545        }
546        // self.bytes.map(|v| v.as_slice())
547    }
548    pub fn is_empty(&self) -> bool {
549        self.bytes.is_some()
550    }
551}
552
553impl FromCursor for CBytes {
554    /// from_cursor gets Cursor who's position is set such that it should be a start of a [bytes].
555    /// It reads required number of bytes and returns a CBytes
556    fn from_cursor(mut cursor: &mut Cursor<&[u8]>) -> CDRSResult<CBytes> {
557        let len = CInt::from_cursor(&mut cursor)?;
558        // null or not set value
559        if len < 0 {
560            return Ok(CBytes { bytes: None });
561        }
562
563        cursor_next_value(&mut cursor, len as u64).map(CBytes::new)
564    }
565}
566
567// Use extended Rust Vec<u8> as Cassandra [bytes]
568impl IntoBytes for CBytes {
569    fn into_cbytes(&self) -> Vec<u8> {
570        match self.bytes {
571            Some(ref b) => {
572                let mut v: Vec<u8> = vec![];
573                let l = b.len() as i32;
574                v.extend_from_slice(to_int(l).as_slice());
575                v.extend_from_slice(b.as_slice());
576                v
577            }
578            None => vec![],
579        }
580    }
581}
582
583/// Cassandra short bytes
584#[derive(Debug, Clone)]
585pub struct CBytesShort {
586    bytes: Option<Vec<u8>>,
587}
588
589impl CBytesShort {
590    pub fn new(bytes: Vec<u8>) -> CBytesShort {
591        CBytesShort { bytes: Some(bytes) }
592    }
593    /// Converts `CBytesShort` into plain vector of bytes;
594    pub fn into_plain(self) -> Option<Vec<u8>> {
595        self.bytes
596    }
597}
598
599impl FromCursor for CBytesShort {
600    /// from_cursor gets Cursor who's position is set such that it should be a start of a [bytes].
601    /// It reads required number of bytes and returns a CBytes
602    fn from_cursor(mut cursor: &mut Cursor<&[u8]>) -> CDRSResult<CBytesShort> {
603        let len = CIntShort::from_cursor(&mut cursor)?;
604
605        if len < 0 {
606            return Ok(CBytesShort { bytes: None });
607        }
608
609        cursor_next_value(&mut cursor, len as u64)
610            .map(CBytesShort::new)
611            .map_err(Into::into)
612    }
613}
614
615// Use extended Rust Vec<u8> as Cassandra [bytes]
616impl IntoBytes for CBytesShort {
617    fn into_cbytes(&self) -> Vec<u8> {
618        match self.bytes {
619            Some(ref b) => {
620                let mut v: Vec<u8> = vec![];
621                let l = b.len() as i16;
622                v.extend_from_slice(to_short(l).as_slice());
623                v.extend_from_slice(b.as_slice());
624                v
625            }
626            None => vec![],
627        }
628    }
629}
630
631/// Cassandra int type.
632pub type CInt = i32;
633
634impl FromCursor for CInt {
635    fn from_cursor(mut cursor: &mut Cursor<&[u8]>) -> CDRSResult<CInt> {
636        let bytes = cursor_next_value(&mut cursor, INT_LEN as u64)?;
637        try_i32_from_bytes(bytes.as_slice()).map_err(Into::into)
638    }
639}
640
641/// Cassandra int short type.
642pub type CIntShort = i16;
643
644impl FromCursor for CIntShort {
645    fn from_cursor(mut cursor: &mut Cursor<&[u8]>) -> CDRSResult<CIntShort> {
646        let bytes = cursor_next_value(&mut cursor, SHORT_LEN as u64)?;
647        try_i16_from_bytes(bytes.as_slice()).map_err(Into::into)
648    }
649}
650
651// Use extended Rust Vec<u8> as Cassandra [bytes]
652impl FromBytes for Vec<u8> {
653    fn from_bytes(bytes: &[u8]) -> CDRSResult<Vec<u8>> {
654        let mut cursor = Cursor::new(bytes);
655        let len_bytes = cursor_next_value(&mut cursor, SHORT_LEN as u64)?;
656        let len: u64 = try_from_bytes(len_bytes.as_slice())?;
657
658        cursor_next_value(&mut cursor, len).map_err(Into::into)
659    }
660}
661
662/// The structure wich represets Cassandra [inet]
663/// (https://github.com/apache/cassandra/blob/trunk/doc/native_protocol_v4.spec#L222).
664#[derive(Debug)]
665pub struct CInet {
666    pub addr: SocketAddr,
667}
668
669impl FromCursor for CInet {
670    fn from_cursor(mut cursor: &mut Cursor<&[u8]>) -> CDRSResult<CInet> {
671        let n = CIntShort::from_cursor(&mut cursor)?;
672        let ip = decode_inet(cursor_next_value(&mut cursor, n as u64)?.as_slice())?;
673        let port = CInt::from_cursor(&mut cursor)?;
674        let socket_addr = SocketAddr::new(ip, port as u16);
675
676        Ok(CInet { addr: socket_addr })
677    }
678}
679
680pub fn cursor_next_value(cursor: &mut Cursor<&[u8]>, len: u64) -> CDRSResult<Vec<u8>> {
681    let l = len as usize;
682    let current_position = cursor.position();
683    let mut buff: Vec<u8> = Vec::with_capacity(l);
684    unsafe {
685        buff.set_len(l);
686    }
687    cursor.read_exact(&mut buff)?;
688    cursor.set_position(current_position + len);
689    Ok(buff)
690}
691
692#[cfg(test)]
693mod tests {
694    use super::*;
695    use crate::frame::traits::{FromCursor, IntoBytes};
696    use std::io::Cursor;
697    use std::mem::transmute;
698
699    // CString
700    #[test]
701    fn test_cstring_new() {
702        let foo = "foo".to_string();
703        let _ = CString::new(foo);
704    }
705
706    #[test]
707    fn test_cstring_as_str() {
708        let foo = "foo".to_string();
709        let cstring = CString::new(foo);
710
711        assert_eq!(cstring.as_str(), "foo");
712    }
713
714    #[test]
715    fn test_cstring_into_plain() {
716        let foo = "foo".to_string();
717        let cstring = CString::new(foo);
718
719        assert_eq!(cstring.into_plain(), "foo".to_string());
720    }
721
722    #[test]
723    fn test_cstring_into_cbytes() {
724        let foo = "foo".to_string();
725        let cstring = CString::new(foo);
726
727        assert_eq!(cstring.into_cbytes(), &[0, 3, 102, 111, 111]);
728    }
729
730    #[test]
731    fn test_cstring_from_cursor() {
732        let a = &[0, 3, 102, 111, 111, 0];
733        let mut cursor: Cursor<&[u8]> = Cursor::new(a);
734        let cstring = CString::from_cursor(&mut cursor).unwrap();
735        assert_eq!(cstring.as_str(), "foo");
736    }
737
738    // CStringLong
739    #[test]
740    fn test_cstringlong_new() {
741        let foo = "foo".to_string();
742        let _ = CStringLong::new(foo);
743    }
744
745    #[test]
746    fn test_cstringlong_as_str() {
747        let foo = "foo".to_string();
748        let cstring = CStringLong::new(foo);
749
750        assert_eq!(cstring.as_str(), "foo");
751    }
752
753    #[test]
754    fn test_cstringlong_into_plain() {
755        let foo = "foo".to_string();
756        let cstring = CStringLong::new(foo);
757
758        assert_eq!(cstring.into_plain(), "foo".to_string());
759    }
760
761    #[test]
762    fn test_cstringlong_into_cbytes() {
763        let foo = "foo".to_string();
764        let cstring = CStringLong::new(foo);
765
766        assert_eq!(cstring.into_cbytes(), &[0, 0, 0, 3, 102, 111, 111]);
767    }
768
769    #[test]
770    fn test_cstringlong_from_cursor() {
771        let a = &[0, 0, 0, 3, 102, 111, 111, 0];
772        let mut cursor: Cursor<&[u8]> = Cursor::new(a);
773        let cstring = CStringLong::from_cursor(&mut cursor).unwrap();
774        assert_eq!(cstring.as_str(), "foo");
775    }
776
777    // CStringList
778    #[test]
779    fn test_cstringlist() {
780        let a = &[0, 2, 0, 3, 102, 111, 111, 0, 3, 102, 111, 111];
781        let mut cursor: Cursor<&[u8]> = Cursor::new(a);
782        let list = CStringList::from_cursor(&mut cursor).unwrap();
783        let plain = list.into_plain();
784        assert_eq!(plain.len(), 2);
785        for s in plain.iter() {
786            assert_eq!(s.as_str(), "foo");
787        }
788    }
789
790    // CBytes
791    #[test]
792    fn test_cbytes_new() {
793        let bytes_vec = vec![1, 2, 3];
794        let _ = CBytes::new(bytes_vec);
795    }
796
797    #[test]
798    fn test_cbytes_into_plain() {
799        let cbytes = CBytes::new(vec![1, 2, 3]);
800        assert_eq!(cbytes.into_plain().unwrap(), &[1, 2, 3]);
801    }
802
803    #[test]
804    fn test_cbytes_from_cursor() {
805        let a = &[0, 0, 0, 3, 1, 2, 3];
806        let mut cursor: Cursor<&[u8]> = Cursor::new(a);
807        let cbytes = CBytes::from_cursor(&mut cursor).unwrap();
808        assert_eq!(cbytes.into_plain().unwrap(), vec![1, 2, 3]);
809    }
810
811    #[test]
812    fn test_cbytes_into_cbytes() {
813        let bytes_vec = vec![1, 2, 3];
814        let cbytes = CBytes::new(bytes_vec);
815        assert_eq!(cbytes.into_cbytes(), vec![0, 0, 0, 3, 1, 2, 3]);
816    }
817
818    // CBytesShort
819    #[test]
820    fn test_cbytesshort_new() {
821        let bytes_vec = vec![1, 2, 3];
822        let _ = CBytesShort::new(bytes_vec);
823    }
824
825    #[test]
826    fn test_cbytesshort_into_plain() {
827        let cbytes = CBytesShort::new(vec![1, 2, 3]);
828        assert_eq!(cbytes.into_plain().unwrap(), vec![1, 2, 3]);
829    }
830
831    #[test]
832    fn test_cbytesshort_from_cursor() {
833        let a = &[0, 3, 1, 2, 3];
834        let mut cursor: Cursor<&[u8]> = Cursor::new(a);
835        let cbytes = CBytesShort::from_cursor(&mut cursor).unwrap();
836        assert_eq!(cbytes.into_plain().unwrap(), vec![1, 2, 3]);
837    }
838
839    #[test]
840    fn test_cbytesshort_into_cbytes() {
841        let bytes_vec: Vec<u8> = vec![1, 2, 3];
842        let cbytes = CBytesShort::new(bytes_vec);
843        assert_eq!(cbytes.into_cbytes(), vec![0, 3, 1, 2, 3]);
844    }
845
846    // CInt
847    #[test]
848    fn test_cint_from_cursor() {
849        let a = &[0, 0, 0, 5];
850        let mut cursor: Cursor<&[u8]> = Cursor::new(a);
851        let i = CInt::from_cursor(&mut cursor).unwrap();
852        assert_eq!(i, 5);
853    }
854
855    // CIntShort
856    #[test]
857    fn test_cintshort_from_cursor() {
858        let a = &[0, 5];
859        let mut cursor: Cursor<&[u8]> = Cursor::new(a);
860        let i = CIntShort::from_cursor(&mut cursor).unwrap();
861        assert_eq!(i, 5);
862    }
863
864    // cursor_next_value
865    #[test]
866    fn test_cursor_next_value() {
867        let a = &[0, 1, 2, 3, 4];
868        let mut cursor: Cursor<&[u8]> = Cursor::new(a);
869        let l: u64 = 3;
870        let val = cursor_next_value(&mut cursor, l).unwrap();
871        assert_eq!(val, vec![0, 1, 2]);
872    }
873
874    #[test]
875    fn test_try_u16_from_bytes() {
876        let bytes: [u8; 2] = unsafe { transmute(12u16.to_be()) }; // or .to_le()
877        let val = try_u16_from_bytes(&bytes);
878        assert_eq!(val.unwrap(), 12u16);
879    }
880
881    #[test]
882    fn test_from_i_bytes() {
883        let bytes: [u8; 8] = unsafe { transmute(12i64.to_be()) }; // or .to_le()
884        let val = from_i_bytes(&bytes);
885        assert_eq!(val, 12i64);
886    }
887
888    #[test]
889    fn test_to_varint() {
890        assert_eq!(to_varint(0), vec![0x00]);
891        assert_eq!(to_varint(1), vec![0x01]);
892        assert_eq!(to_varint(127), vec![0x7F]);
893        assert_eq!(to_varint(128), vec![0x00, 0x80]);
894        assert_eq!(to_varint(129), vec![0x00, 0x81]);
895        assert_eq!(to_varint(-1), vec![0xFF]);
896        assert_eq!(to_varint(-128), vec![0x80]);
897        assert_eq!(to_varint(-129), vec![0xFF, 0x7F]);
898    }
899
900}