queen_core/wire_protocol/
header.rs

1use std::fmt;
2use std::io::{Read, Write};
3
4use byteorder::{LittleEndian, ReadBytesExt, WriteBytesExt};
5use super::error::Result;
6use super::error::Error::ResponseError;
7
8#[derive(Debug, Clone)]
9pub enum OpCode {
10    Request = 1,
11    Response = 2
12}
13
14impl OpCode {
15    pub fn from_i32(i: i32) -> Option<OpCode> {
16        match i {
17            1 => Some(OpCode::Request),
18            2 => Some(OpCode::Response),
19            _ => None
20        }
21    }
22}
23
24impl fmt::Display for OpCode {
25    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
26        match *self {
27            OpCode::Request => write!(fmt, "OP_REQUEST"),
28            OpCode::Response => write!(fmt, "OP_RESPONSE")
29        }
30    }
31}
32
33#[derive(Debug, Clone)]
34pub struct Header {
35    pub message_length: i32,
36    pub request_id: i32,
37    pub response_to: i32,
38    pub op_code: OpCode
39}
40
41impl Header {
42    pub fn new(message_length: i32, request_id: i32, response_to: i32, op_code: OpCode) -> Header {
43        Header {
44            message_length: message_length,
45            request_id: request_id,
46            response_to: response_to,
47            op_code: op_code
48        }
49    }
50
51    pub fn new_request(message_length: i32, request_id: i32) -> Header {
52        Header::new(message_length, request_id, 0, OpCode::Request)
53    }
54
55    pub fn new_response(message_length: i32, response_to: i32) -> Header {
56        Header::new(message_length, 0, response_to, OpCode::Response)
57    }
58
59    pub fn write<W: Write>(&self, buffer: &mut W) -> Result<()> {
60        buffer.write_i32::<LittleEndian>(self.message_length)?;
61        buffer.write_i32::<LittleEndian>(self.request_id)?;
62        buffer.write_i32::<LittleEndian>(self.response_to)?;
63        buffer.write_i32::<LittleEndian>(self.op_code.clone() as i32)?;
64
65        Ok(())
66    }
67
68    pub fn read<R: Read>(buffer: &mut R) -> Result<Header> {
69        let message_length = buffer.read_i32::<LittleEndian>()?;
70        let request_id = buffer.read_i32::<LittleEndian>()?;
71        let response_to = buffer.read_i32::<LittleEndian>()?;
72        let op_code_i32 = buffer.read_i32::<LittleEndian>()?;
73
74        let op_code = match OpCode::from_i32(op_code_i32) {
75            Some(code) => code,
76            _ => return Err(ResponseError(format!("Invalid header opcode from server: {}.", op_code_i32)))
77        };
78
79        Ok(Header::new(message_length, request_id, response_to, op_code))
80    }
81}