cassandra_proto/frame/
frame_startup.rs

1use std::collections::HashMap;
2
3use rand;
4
5use crate::frame::*;
6use crate::types::to_short;
7
8const CQL_VERSION: &'static str = "CQL_VERSION";
9const CQL_VERSION_VAL: &'static str = "3.0.0";
10const COMPRESSION: &'static str = "COMPRESSION";
11
12#[derive(Debug)]
13pub struct BodyReqStartup<'a> {
14    pub map: HashMap<&'static str, &'a str>,
15}
16
17impl<'a> BodyReqStartup<'a> {
18    pub fn new<'b>(compression: Option<&'b str>) -> BodyReqStartup<'b> {
19        let mut map = HashMap::new();
20        map.insert(CQL_VERSION, CQL_VERSION_VAL);
21        if let Some(c) = compression {
22            map.insert(COMPRESSION, c);
23        }
24        BodyReqStartup { map: map }
25    }
26
27    // should be [u8; 2]
28    // Number of key-value pairs
29    fn num(&self) -> Vec<u8> {
30        to_short(self.map.len() as i16)
31    }
32}
33
34impl<'a> IntoBytes for BodyReqStartup<'a> {
35    fn into_cbytes(&self) -> Vec<u8> {
36        let mut v = vec![];
37        // push number of key-value pairs
38        v.extend_from_slice(&self.num().as_slice());
39        for (key, val) in self.map.iter() {
40            // push key len
41            v.extend_from_slice(to_short(key.len() as i16).as_slice());
42            // push key itself
43            v.extend_from_slice(key.as_bytes());
44            // push val len
45            v.extend_from_slice(to_short(val.len() as i16).as_slice());
46            // push val itself
47            v.extend_from_slice(val.as_bytes());
48        }
49        v
50    }
51}
52
53// Frame implementation related to BodyReqStartup
54
55impl Frame {
56    /// Creates new frame of type `startup`.
57    pub fn new_req_startup(compression: Option<&str>) -> Frame {
58        let version = Version::Request;
59        let flag = Flag::Ignore;
60        let stream = rand::random::<u16>();
61        let opcode = Opcode::Startup;
62        let body = BodyReqStartup::new(compression);
63
64        Frame { version: version,
65                flags: vec![flag],
66                stream: stream,
67                opcode: opcode,
68                body: body.into_cbytes(),
69                // for request frames it's always None
70                tracing_id: None,
71                warnings: vec![], }
72    }
73}
74
75#[cfg(test)]
76mod test {
77    use super::*;
78    use crate::frame::{Flag, Frame, Opcode, Version};
79
80    #[test]
81    fn new_body_req_startup_some_compression() {
82        let compression = "test_compression";
83        let body = BodyReqStartup::new(Some(compression));
84        assert_eq!(body.map.get("CQL_VERSION"), Some(&"3.0.0"));
85        assert_eq!(body.map.get("COMPRESSION"), Some(&compression));
86        assert_eq!(body.map.len(), 2);
87    }
88
89    #[test]
90    fn new_body_req_startup_none_compression() {
91        let body = BodyReqStartup::new(None);
92        assert_eq!(body.map.get("CQL_VERSION"), Some(&"3.0.0"));
93        assert_eq!(body.map.len(), 1);
94    }
95
96    #[test]
97    fn new_req_startup() {
98        let compression = Some("test_compression");
99        let frame = Frame::new_req_startup(compression);
100        assert_eq!(frame.version, Version::Request);
101        assert_eq!(frame.flags, vec![Flag::Ignore]);
102        assert_eq!(frame.opcode, Opcode::Startup);
103        assert_eq!(frame.tracing_id, None);
104        assert_eq!(frame.warnings, vec![] as Vec<String>);
105    }
106}