Skip to main content

cdrs/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 {
65            version: version,
66            flags: vec![flag],
67            stream: stream,
68            opcode: opcode,
69            body: body.into_cbytes(),
70            // for request frames it's always None
71            tracing_id: None,
72            warnings: vec![],
73        }
74    }
75}
76
77#[cfg(test)]
78mod test {
79    use super::*;
80    use crate::frame::{Flag, Frame, Opcode, Version};
81
82    #[test]
83    fn new_body_req_startup_some_compression() {
84        let compression = "test_compression";
85        let body = BodyReqStartup::new(Some(compression));
86        assert_eq!(body.map.get("CQL_VERSION"), Some(&"3.0.0"));
87        assert_eq!(body.map.get("COMPRESSION"), Some(&compression));
88        assert_eq!(body.map.len(), 2);
89    }
90
91    #[test]
92    fn new_body_req_startup_none_compression() {
93        let body = BodyReqStartup::new(None);
94        assert_eq!(body.map.get("CQL_VERSION"), Some(&"3.0.0"));
95        assert_eq!(body.map.len(), 1);
96    }
97
98    #[test]
99    fn new_req_startup() {
100        let compression = Some("test_compression");
101        let frame = Frame::new_req_startup(compression);
102        assert_eq!(frame.version, Version::Request);
103        assert_eq!(frame.flags, vec![Flag::Ignore]);
104        assert_eq!(frame.opcode, Opcode::Startup);
105        assert_eq!(frame.tracing_id, None);
106        assert_eq!(frame.warnings, vec![] as Vec<String>);
107    }
108}