diff --git a/src/packet.rs b/src/packet.rs index 103a54e50348fdb123f94bd04e1ebe020670b305..5581f952ffd96c07ad788165662a7a7a3e685695 100644 --- a/src/packet.rs +++ b/src/packet.rs @@ -18,13 +18,172 @@ pub enum PacketType { } #[derive(Default, Debug, RustcEncodable, RustcDecodable)] -pub struct PacketHeader { +pub struct PacketHeaderRaw { ver_type_tkl: u8, code: u8, message_id: u16 } +#[derive(Debug)] +pub struct PacketHeader { + ver_type_tkl: u8, + code: PacketClass, + message_id: u16 +} + +#[derive(Debug)] +pub enum PacketClass { + Empty, + Request(RequestRegistry), + Response(ResponseRegistry), + Reserved +} + +#[derive(Debug)] +pub enum RequestRegistry { + Get, + Post, + Put, + Delete +} + +#[derive(Debug)] +pub enum ResponseRegistry { + // 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 +} + +pub fn class_to_code(class: &PacketClass) -> u8 { + return match *class { + PacketClass::Empty => 0x00, + + PacketClass::Request(RequestRegistry::Get) => 0x01, + PacketClass::Request(RequestRegistry::Post) => 0x02, + PacketClass::Request(RequestRegistry::Put) => 0x03, + PacketClass::Request(RequestRegistry::Delete) => 0x04, + + PacketClass::Response(ResponseRegistry::Created) => 0x41, + PacketClass::Response(ResponseRegistry::Deleted) => 0x42, + PacketClass::Response(ResponseRegistry::Valid) => 0x43, + PacketClass::Response(ResponseRegistry::Changed) => 0x44, + PacketClass::Response(ResponseRegistry::Content) => 0x45, + + PacketClass::Response(ResponseRegistry::BadRequest) => 0x80, + PacketClass::Response(ResponseRegistry::Unauthorized) => 0x81, + PacketClass::Response(ResponseRegistry::BadOption) => 0x82, + PacketClass::Response(ResponseRegistry::Forbidden) => 0x83, + PacketClass::Response(ResponseRegistry::NotFound) => 0x84, + PacketClass::Response(ResponseRegistry::MethodNotAllowed) => 0x85, + PacketClass::Response(ResponseRegistry::NotAcceptable) => 0x86, + PacketClass::Response(ResponseRegistry::PreconditionFailed) => 0x8C, + PacketClass::Response(ResponseRegistry::RequestEntityTooLarge) => 0x8D, + PacketClass::Response(ResponseRegistry::UnsupportedContentFormat) => 0x8F, + + PacketClass::Response(ResponseRegistry::InternalServerError) => 0x90, + PacketClass::Response(ResponseRegistry::NotImplemented) => 0x91, + PacketClass::Response(ResponseRegistry::BadGateway) => 0x92, + PacketClass::Response(ResponseRegistry::ServiceUnavailable) => 0x93, + PacketClass::Response(ResponseRegistry::GatewayTimeout) => 0x94, + PacketClass::Response(ResponseRegistry::ProxyingNotSupported) => 0x95, + + _ => 0xFF, + } as u8 +} + +pub fn code_to_class(code: &u8) -> PacketClass { + match *code { + 0x00 => PacketClass::Empty, + + 0x01 => PacketClass::Request(RequestRegistry::Get), + 0x02 => PacketClass::Request(RequestRegistry::Post), + 0x03 => PacketClass::Request(RequestRegistry::Put), + 0x04 => PacketClass::Request(RequestRegistry::Delete), + + 0x41 => PacketClass::Response(ResponseRegistry::Created), + 0x42 => PacketClass::Response(ResponseRegistry::Deleted), + 0x43 => PacketClass::Response(ResponseRegistry::Valid), + 0x44 => PacketClass::Response(ResponseRegistry::Changed), + 0x45 => PacketClass::Response(ResponseRegistry::Content), + + 0x80 => PacketClass::Response(ResponseRegistry::BadRequest), + 0x81 => PacketClass::Response(ResponseRegistry::Unauthorized), + 0x82 => PacketClass::Response(ResponseRegistry::BadOption), + 0x83 => PacketClass::Response(ResponseRegistry::Forbidden), + 0x84 => PacketClass::Response(ResponseRegistry::NotFound), + 0x85 => PacketClass::Response(ResponseRegistry::MethodNotAllowed), + 0x86 => PacketClass::Response(ResponseRegistry::NotAcceptable), + 0x8C => PacketClass::Response(ResponseRegistry::PreconditionFailed), + 0x8D => PacketClass::Response(ResponseRegistry::RequestEntityTooLarge), + 0x8F => PacketClass::Response(ResponseRegistry::UnsupportedContentFormat), + + 0x90 => PacketClass::Response(ResponseRegistry::InternalServerError), + 0x91 => PacketClass::Response(ResponseRegistry::NotImplemented), + 0x92 => PacketClass::Response(ResponseRegistry::BadGateway), + 0x93 => PacketClass::Response(ResponseRegistry::ServiceUnavailable), + 0x94 => PacketClass::Response(ResponseRegistry::GatewayTimeout), + 0x95 => PacketClass::Response(ResponseRegistry::ProxyingNotSupported), + + _ => PacketClass::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: &PacketClass) -> String { + return code_to_str(&class_to_code(class)); +} + impl PacketHeader { + + pub fn new() -> PacketHeader { + return PacketHeader::from_raw(&PacketHeaderRaw::default()); + } + + pub fn from_raw(raw: &PacketHeaderRaw) -> PacketHeader { + return PacketHeader { + ver_type_tkl: raw.ver_type_tkl, + code: code_to_class(&raw.code), + message_id: raw.message_id, + } + } + + pub fn to_raw(&self) -> PacketHeaderRaw { + return PacketHeaderRaw { + 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; @@ -84,14 +243,11 @@ impl PacketHeader { assert_eq!(0xF8 & class_code, 0); assert_eq!(0xE0 & detail_code, 0); - self.code = class_code << 5 | detail_code; + self.code = code_to_class(&(class_code << 5 | detail_code)); } pub fn get_code(&self) -> String { - let class_code = (0xE0 & self.code) >> 5; - let detail_code = 0x1F & self.code; - - return format!("{}.{:02}", class_code, detail_code); + class_to_str(&self.code) } #[inline] @@ -152,7 +308,7 @@ pub struct Packet { impl Packet { pub fn new() -> Packet { Packet { - header: PacketHeader::default(), + header: PacketHeader::new(), token: Vec::new(), options: BTreeMap::new(), payload: Vec::new(), @@ -202,9 +358,10 @@ impl Packet { /// Decodes a byte slice and construct the equivalent Packet. pub fn from_bytes(buf: &[u8]) -> Result<Packet, ParseError> { - let header_result: bincode::DecodingResult<PacketHeader> = bincode::decode(buf); + let header_result: bincode::DecodingResult<PacketHeaderRaw> = bincode::decode(buf); match header_result { - Ok(header) => { + Ok(raw_header) => { + let header = PacketHeader::from_raw(&raw_header); let token_length = header.get_token_length(); let options_start: usize = 4 + token_length as usize; @@ -383,7 +540,7 @@ impl Packet { } let mut buf: Vec<u8> = Vec::with_capacity(buf_length); - let header_result: bincode::EncodingResult<()> = bincode::encode_into(&self.header, &mut buf, bincode::SizeLimit::Infinite); + let header_result: bincode::EncodingResult<()> = bincode::encode_into(&self.header.to_raw(), &mut buf, bincode::SizeLimit::Infinite); match header_result { Ok(_) => { buf.reserve(self.token.len() + options_bytes.len());