Skip to content
Snippets Groups Projects
Select Git revision
  • cda8c9cae1be264227cf1a7b3da2f314ed4f34a0
  • master default
  • 0.5.1
  • 0.3.1
4 results

header.rs

Blame
  • header.rs 8.07 KiB
    #[derive(Default, Debug, RustcEncodable, RustcDecodable)]
    pub struct HeaderRaw {
        ver_type_tkl: u8,
        code: u8,
        message_id: u16,
    }
    
    #[derive(Debug)]
    pub struct Header {
        ver_type_tkl: u8,
        pub code: MessageClass,
        message_id: u16,
    }
    
    #[derive(Debug, PartialEq)]
    pub enum MessageClass {
        Empty,
        RequestType(Requests),
        ResponseType(Responses),
        Reserved,
    }
    
    #[derive(Debug, PartialEq)]
    pub enum Requests {
        Get,
        Post,
        Put,
        Delete,
    }
    
    #[derive(Debug, PartialEq)]
    pub enum Responses {
        // 200 Codes
        Created,
        Deleted,
        Valid,
        Changed,
        Content,
    
        // 400 Codes
        BadRequest,
        Unauthorized,
        BadOption,
        Forbidden,
        NotFound,
        MethodNotAllowed,
        NotAcceptable,
        PreconditionFailed,
        RequestEntityTooLarge,
        UnsupportedContentFormat,
    
        // 500 Codes
        InternalServerError,
        NotImplemented,
        BadGateway,
        ServiceUnavailable,
        GatewayTimeout,
        ProxyingNotSupported,
    }
    
    #[derive(PartialEq, Eq, Debug)]
    pub enum MessageType {
        Confirmable,
        NonConfirmable,
        Acknowledgement,
        Reset,
        Invalid,
    }
    
    impl Header {
        pub fn new() -> Header {
            return Header::from_raw(&HeaderRaw::default());
        }
    
        pub fn from_raw(raw: &HeaderRaw) -> Header {
            return Header {
                ver_type_tkl: raw.ver_type_tkl,
                code: code_to_class(&raw.code),
                message_id: raw.message_id,
            };
        }
    
        pub fn to_raw(&self) -> HeaderRaw {
            return HeaderRaw {
                ver_type_tkl: self.ver_type_tkl,
                code: class_to_code(&self.code),
                message_id: self.message_id,
            };
        }
    
        #[inline]
        pub fn set_version(&mut self, v: u8) {
            let type_tkl = 0x3F & self.ver_type_tkl;
            self.ver_type_tkl = v << 6 | type_tkl;
        }
    
        #[inline]
        pub fn get_version(&self) -> u8 {
            return self.ver_type_tkl >> 6;
        }
    
        #[inline]
        pub fn set_type(&mut self, t: MessageType) {
            let tn = match t {
                MessageType::Confirmable => 0,
                MessageType::NonConfirmable => 1,
                MessageType::Acknowledgement => 2,
                MessageType::Reset => 3,
                _ => unreachable!(),
            };
    
            let ver_tkl = 0xCF & self.ver_type_tkl;
            self.ver_type_tkl = tn << 4 | ver_tkl;
        }
    
        #[inline]
        pub fn get_type(&self) -> MessageType {
            let tn = (0x30 & self.ver_type_tkl) >> 4;
            match tn {
                0 => MessageType::Confirmable,
                1 => MessageType::NonConfirmable,
                2 => MessageType::Acknowledgement,
                3 => MessageType::Reset,
                _ => MessageType::Invalid,
            }
        }
    
        #[inline]
        pub fn set_token_length(&mut self, tkl: u8) {
            assert_eq!(0xF0 & tkl, 0);
    
            let ver_type = 0xF0 & self.ver_type_tkl;
            self.ver_type_tkl = tkl | ver_type;
        }
    
        #[inline]
        pub fn get_token_length(&self) -> u8 {
            return 0x0F & self.ver_type_tkl;
        }
    
        pub fn set_code(&mut self, code: &str) {
            let code_vec: Vec<&str> = code.split('.').collect();
            assert_eq!(code_vec.len(), 2);
    
            let class_code = code_vec[0].parse::<u8>().unwrap();
            let detail_code = code_vec[1].parse::<u8>().unwrap();
            assert_eq!(0xF8 & class_code, 0);
            assert_eq!(0xE0 & detail_code, 0);
    
            self.code = code_to_class(&(class_code << 5 | detail_code));
        }
    
        pub fn get_code(&self) -> String {
            class_to_str(&self.code)
        }
    
        #[inline]
        pub fn set_message_id(&mut self, message_id: u16) {
            self.message_id = message_id;
        }
    
        #[inline]
        pub fn get_message_id(&self) -> u16 {
            return self.message_id;
        }
    }
    
    pub fn class_to_code(class: &MessageClass) -> u8 {
        return match *class {
            MessageClass::Empty => 0x00,
    
            MessageClass::RequestType(Requests::Get) => 0x01,
            MessageClass::RequestType(Requests::Post) => 0x02,
            MessageClass::RequestType(Requests::Put) => 0x03,
            MessageClass::RequestType(Requests::Delete) => 0x04,
    
            MessageClass::ResponseType(Responses::Created) => 0x41,
            MessageClass::ResponseType(Responses::Deleted) => 0x42,
            MessageClass::ResponseType(Responses::Valid) => 0x43,
            MessageClass::ResponseType(Responses::Changed) => 0x44,
            MessageClass::ResponseType(Responses::Content) => 0x45,
    
            MessageClass::ResponseType(Responses::BadRequest) => 0x80,
            MessageClass::ResponseType(Responses::Unauthorized) => 0x81,
            MessageClass::ResponseType(Responses::BadOption) => 0x82,
            MessageClass::ResponseType(Responses::Forbidden) => 0x83,
            MessageClass::ResponseType(Responses::NotFound) => 0x84,
            MessageClass::ResponseType(Responses::MethodNotAllowed) => 0x85,
            MessageClass::ResponseType(Responses::NotAcceptable) => 0x86,
            MessageClass::ResponseType(Responses::PreconditionFailed) => 0x8C,
            MessageClass::ResponseType(Responses::RequestEntityTooLarge) => 0x8D,
            MessageClass::ResponseType(Responses::UnsupportedContentFormat) => 0x8F,
    
            MessageClass::ResponseType(Responses::InternalServerError) => 0x90,
            MessageClass::ResponseType(Responses::NotImplemented) => 0x91,
            MessageClass::ResponseType(Responses::BadGateway) => 0x92,
            MessageClass::ResponseType(Responses::ServiceUnavailable) => 0x93,
            MessageClass::ResponseType(Responses::GatewayTimeout) => 0x94,
            MessageClass::ResponseType(Responses::ProxyingNotSupported) => 0x95,
    
            _ => 0xFF,
        } as u8;
    }
    
    pub fn code_to_class(code: &u8) -> MessageClass {
        match *code {
            0x00 => MessageClass::Empty,
    
            0x01 => MessageClass::RequestType(Requests::Get),
            0x02 => MessageClass::RequestType(Requests::Post),
            0x03 => MessageClass::RequestType(Requests::Put),
            0x04 => MessageClass::RequestType(Requests::Delete),
    
            0x41 => MessageClass::ResponseType(Responses::Created),
            0x42 => MessageClass::ResponseType(Responses::Deleted),
            0x43 => MessageClass::ResponseType(Responses::Valid),
            0x44 => MessageClass::ResponseType(Responses::Changed),
            0x45 => MessageClass::ResponseType(Responses::Content),
    
            0x80 => MessageClass::ResponseType(Responses::BadRequest),
            0x81 => MessageClass::ResponseType(Responses::Unauthorized),
            0x82 => MessageClass::ResponseType(Responses::BadOption),
            0x83 => MessageClass::ResponseType(Responses::Forbidden),
            0x84 => MessageClass::ResponseType(Responses::NotFound),
            0x85 => MessageClass::ResponseType(Responses::MethodNotAllowed),
            0x86 => MessageClass::ResponseType(Responses::NotAcceptable),
            0x8C => MessageClass::ResponseType(Responses::PreconditionFailed),
            0x8D => MessageClass::ResponseType(Responses::RequestEntityTooLarge),
            0x8F => MessageClass::ResponseType(Responses::UnsupportedContentFormat),
    
            0x90 => MessageClass::ResponseType(Responses::InternalServerError),
            0x91 => MessageClass::ResponseType(Responses::NotImplemented),
            0x92 => MessageClass::ResponseType(Responses::BadGateway),
            0x93 => MessageClass::ResponseType(Responses::ServiceUnavailable),
            0x94 => MessageClass::ResponseType(Responses::GatewayTimeout),
            0x95 => MessageClass::ResponseType(Responses::ProxyingNotSupported),
    
            _ => MessageClass::Reserved,
        }
    }
    
    pub fn code_to_str(code: &u8) -> String {
        let class_code = (0xE0 & code) >> 5;
        let detail_code = 0x1F & code;
    
        return format!("{}.{:02}", class_code, detail_code);
    }
    
    pub fn class_to_str(class: &MessageClass) -> String {
        return code_to_str(&class_to_code(class));
    }
    
    #[cfg(test)]
    mod test {
        use message::header::*;
    
        #[test]
        fn test_header_codes() {
            for code in 0..255 {
                let class = code_to_class(&code);
                let code_str = code_to_str(&code);
                let class_str = class_to_str(&class);
    
                // Reserved class could technically be many codes
                //   so only check valid items
                if class != MessageClass::Reserved {
                    assert_eq!(class_to_code(&class), code);
                    assert_eq!(code_str, class_str);
                }
            }
        }
    }