From 544924aa9d8c08d1d09b555bc431a450e2131f36 Mon Sep 17 00:00:00 2001
From: Romain Porte <microjoe@microjoe.org>
Date: Wed, 26 Jul 2017 15:49:24 +0200
Subject: [PATCH] Added ContentFormat support

---
 Cargo.toml            |  1 +
 src/lib.rs            |  2 ++
 src/message/packet.rs | 50 +++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 53 insertions(+)

diff --git a/Cargo.toml b/Cargo.toml
index 32cacc6..0cb16f9 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -18,6 +18,7 @@ num = "0.1"
 rand = "0.3"
 log = "0.3"
 threadpool = "1.3"
+enum_primitive = "0.1.1"
 
 [dev-dependencies]
 quickcheck = "0.2.27"
diff --git a/src/lib.rs b/src/lib.rs
index 3e04e3e..0768f03 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -74,6 +74,8 @@ extern crate url;
 extern crate num;
 extern crate rand;
 extern crate threadpool;
+#[macro_use] extern crate enum_primitive;
+
 #[cfg(test)]
 extern crate quickcheck;
 
diff --git a/src/message/packet.rs b/src/message/packet.rs
index a2e4010..83d6217 100644
--- a/src/message/packet.rs
+++ b/src/message/packet.rs
@@ -2,6 +2,8 @@ use bincode;
 use std::collections::BTreeMap;
 use std::collections::LinkedList;
 
+use num::FromPrimitive;
+
 use message::header;
 
 macro_rules! u8_to_unsigned_be {
@@ -32,6 +34,18 @@ pub enum CoAPOption {
     Size1,
 }
 
+enum_from_primitive! {
+#[derive(PartialEq, Eq, Debug)]
+pub enum ContentFormat {
+    TextPlain = 0,
+    ApplicationLinkFormat = 40,
+    ApplicationXML = 41,
+    ApplicationOctetStream = 42,
+    ApplicationEXI = 47,
+    ApplicationJSON = 50,
+}
+}
+
 #[derive(Debug)]
 pub enum PackageError {
     InvalidHeader,
@@ -78,6 +92,15 @@ impl Packet {
         self.options.insert(num, value);
     }
 
+    pub fn set_content_format(&mut self, cf: ContentFormat) {
+        let content_format = cf as u16;
+        let msb = (content_format >> 8) as u8;
+        let lsb = (content_format & 0xFF) as u8;
+
+        let content_format: Vec<u8> = vec![msb, lsb];
+        self.add_option(CoAPOption::ContentFormat, content_format);
+    }
+
     pub fn set_payload(&mut self, payload: Vec<u8>) {
         self.payload = payload;
     }
@@ -105,6 +128,20 @@ impl Packet {
         }
     }
 
+    pub fn get_content_format(&self) -> Option<ContentFormat> {
+        if let Some(list) = self.get_option(CoAPOption::ContentFormat) {
+            if let Some(vector) = list.front() {
+                let msb = vector[0] as u16;
+                let lsb = vector[1] as u16;
+                let number = (msb << 8) + lsb;
+
+                return ContentFormat::from_u16(number);
+            }
+        }
+
+        None
+    }
+
     /// Decodes a byte slice and construct the equivalent Packet.
     pub fn from_bytes(buf: &[u8]) -> Result<Packet, ParseError> {
         let header_result: bincode::DecodingResult<header::HeaderRaw> = bincode::decode(buf);
@@ -442,6 +479,19 @@ mod test {
                         0x6C, 0x6F]);
     }
 
+    #[test]
+    fn test_encode_decode_content_format() {
+        let mut packet = Packet::new();
+        packet.set_content_format(ContentFormat::ApplicationJSON);
+        assert_eq!(ContentFormat::ApplicationJSON, packet.get_content_format().unwrap())
+    }
+
+    #[test]
+    fn test_decode_empty_content_format() {
+        let packet = Packet::new();
+        assert!(packet.get_content_format().is_none());
+    }
+
     #[test]
     fn test_malicious_packet() {
         use rand;
-- 
GitLab