From 5d8fb84ef4185bc0ad87470b0da8e01f87c423b1 Mon Sep 17 00:00:00 2001 From: Apisit Ritruengroj Date: Mon, 11 Aug 2025 20:02:00 +0700 Subject: [PATCH 1/9] feat: intial declaration --- rust/signed_doc/Cargo.toml | 1 + rust/signed_doc/src/metadata/content_type.rs | 49 ++++++++++++-------- 2 files changed, 31 insertions(+), 19 deletions(-) diff --git a/rust/signed_doc/Cargo.toml b/rust/signed_doc/Cargo.toml index 25fb35586c5..4adbdb0c061 100644 --- a/rust/signed_doc/Cargo.toml +++ b/rust/signed_doc/Cargo.toml @@ -22,6 +22,7 @@ brotli = "7.0.0" ed25519-dalek = { version = "2.1.1", features = ["rand_core", "pem"] } hex = "0.4.3" strum = { version = "0.27.1", features = ["derive"] } +strum_macros = { version = "0.27.1" } clap = { version = "4.5.23", features = ["derive", "env"] } jsonschema = "0.28.3" jsonpath-rust = "0.7.5" diff --git a/rust/signed_doc/src/metadata/content_type.rs b/rust/signed_doc/src/metadata/content_type.rs index c2b4eba6679..6a32efdbabf 100644 --- a/rust/signed_doc/src/metadata/content_type.rs +++ b/rust/signed_doc/src/metadata/content_type.rs @@ -1,37 +1,48 @@ //! Document Payload Content Type. -use std::{ - fmt::{Display, Formatter}, - str::FromStr, -}; +use std::{str::FromStr, string::ToString}; use strum::VariantArray; /// Payload Content Type. -#[derive(Debug, Copy, Clone, PartialEq, Eq, VariantArray)] +#[derive(Debug, Copy, Clone, PartialEq, Eq, VariantArray, strum_macros::Display)] pub enum ContentType { /// `application/cbor` + #[strum(to_string = "application/cbor")] Cbor, /// `application/cddl` + #[strum(to_string = "application/cddl")] Cddl, /// `application/json` + #[strum(to_string = "application/json")] Json, /// `application/json+schema` + #[strum(to_string = "application/json+schema")] JsonSchema, -} - -impl Display for ContentType { - fn fmt( - &self, - f: &mut Formatter<'_>, - ) -> Result<(), std::fmt::Error> { - match self { - Self::Cbor => write!(f, "application/cbor"), - Self::Cddl => write!(f, "application/cddl"), - Self::Json => write!(f, "application/json"), - Self::JsonSchema => write!(f, "application/json+schema"), - } - } + /// `text/css; charset=utf-8` + #[strum(to_string = "text/css; charset=utf-8")] + Css, + /// `text/css; charset=utf-8; template=handlebars` + #[strum(to_string = "text/css; charset=utf-8; template=handlebars")] + CssTemplate, + /// `text/html; charset=utf-8` + #[strum(to_string = "text/html; charset=utf-8")] + Html, + /// `text/html; charset=utf-8; template=handlebars` + #[strum(to_string = "text/html; charset=utf-8; template=handlebars")] + HtmlTemplate, + /// `text/markdown; charset=utf-8` + #[strum(to_string = "text/markdown; charset=utf-8")] + Markdown, + /// `text/markdown; charset=utf-8; template=handlebars` + #[strum(to_string = "text/markdown; charset=utf-8; template=handlebars")] + MarkdownTemplate, + /// `text/plain; charset=utf-8` + #[strum(to_string = "text/plain; charset=utf-8")] + Text, + /// `text/plain; charset=utf-8; template=handlebars` + #[strum(to_string = "text/plain; charset=utf-8; template=handlebars")] + TextTemplate, } impl FromStr for ContentType { From 460b7201e7702f2ea30e92e334ab67e031254dbf Mon Sep 17 00:00:00 2001 From: Apisit Ritruengroj Date: Mon, 11 Aug 2025 20:25:30 +0700 Subject: [PATCH 2/9] feat: intial declaration --- rust/signed_doc/src/metadata/content_type.rs | 96 +++++++++++--------- 1 file changed, 52 insertions(+), 44 deletions(-) diff --git a/rust/signed_doc/src/metadata/content_type.rs b/rust/signed_doc/src/metadata/content_type.rs index 6a32efdbabf..65490479296 100644 --- a/rust/signed_doc/src/metadata/content_type.rs +++ b/rust/signed_doc/src/metadata/content_type.rs @@ -24,25 +24,25 @@ pub enum ContentType { Css, /// `text/css; charset=utf-8; template=handlebars` #[strum(to_string = "text/css; charset=utf-8; template=handlebars")] - CssTemplate, + CssHandlebars, /// `text/html; charset=utf-8` #[strum(to_string = "text/html; charset=utf-8")] Html, /// `text/html; charset=utf-8; template=handlebars` #[strum(to_string = "text/html; charset=utf-8; template=handlebars")] - HtmlTemplate, + HtmlHandlebars, /// `text/markdown; charset=utf-8` #[strum(to_string = "text/markdown; charset=utf-8")] Markdown, /// `text/markdown; charset=utf-8; template=handlebars` #[strum(to_string = "text/markdown; charset=utf-8; template=handlebars")] - MarkdownTemplate, + MarkdownHandlebars, /// `text/plain; charset=utf-8` #[strum(to_string = "text/plain; charset=utf-8")] - Text, + Plain, /// `text/plain; charset=utf-8; template=handlebars` #[strum(to_string = "text/plain; charset=utf-8; template=handlebars")] - TextTemplate, + PlainHandlebars, } impl FromStr for ContentType { @@ -53,7 +53,14 @@ impl FromStr for ContentType { "application/cbor" => Ok(Self::Cbor), "application/cddl" => Ok(Self::Cddl), "application/json" => Ok(Self::Json), - "application/json+schema" => Ok(Self::JsonSchema), + "text/css; charset=utf-8" => Ok(Self::Css), + "text/css; charset=utf-8; template=handlebars" => Ok(Self::CssHandlebars), + "text/html; charset=utf-8" => Ok(Self::Html), + "text/html; charset=utf-8; template=handlebars" => Ok(Self::HtmlHandlebars), + "text/markdown; charset=utf-8" => Ok(Self::Markdown), + "text/markdown; charset=utf-8; template=handlebars" => Ok(Self::MarkdownHandlebars), + "text/plain; charset=utf-8" => Ok(Self::Plain), + "text/plain; charset=utf-8; template=handlebars" => Ok(Self::PlainHandlebars), _ => { anyhow::bail!( "Unsupported Content Type: {s:?}, Supported only: {:?}", @@ -69,7 +76,9 @@ impl FromStr for ContentType { impl<'de> serde::Deserialize<'de> for ContentType { fn deserialize(deserializer: D) -> Result - where D: serde::Deserializer<'de> { + where + D: serde::Deserializer<'de>, + { let s = String::deserialize(deserializer)?; FromStr::from_str(&s).map_err(serde::de::Error::custom) } @@ -110,11 +119,9 @@ impl minicbor::Decode<'_, ()> for ContentType { Ok(val) if val == minicbor::data::Int::from(50_u8) => Ok(Self::Json), // CoAP Content Format CBOR Ok(val) if val == minicbor::data::Int::from(60_u8) => Ok(Self::Cbor), - Ok(val) => { - Err(minicbor::decode::Error::message(format!( - "unsupported CoAP Content Formats value: {val}" - ))) - }, + Ok(val) => Err(minicbor::decode::Error::message(format!( + "unsupported CoAP Content Formats value: {val}" + ))), Err(_) => { d.set_position(p); d.str()?.parse().map_err(minicbor::decode::Error::message) @@ -129,37 +136,38 @@ mod tests { #[test] fn content_type_string_test() { - assert_eq!( - ContentType::from_str("application/cbor").unwrap(), - ContentType::Cbor - ); - assert_eq!( - ContentType::from_str("application/cddl").unwrap(), - ContentType::Cddl - ); - assert_eq!( - ContentType::from_str("application/json").unwrap(), - ContentType::Json - ); - assert_eq!( - ContentType::from_str("application/json+schema").unwrap(), - ContentType::JsonSchema - ); - assert_eq!( - "application/cbor".parse::().unwrap(), - ContentType::Cbor - ); - assert_eq!( - "application/cddl".parse::().unwrap(), - ContentType::Cddl - ); - assert_eq!( - "application/json".parse::().unwrap(), - ContentType::Json - ); - assert_eq!( - "application/json+schema".parse::().unwrap(), - ContentType::JsonSchema - ); + let entries = [ + ("application/cbor", ContentType::Cbor), + ("application/cddl", ContentType::Cddl), + ("application/json", ContentType::Json), + ("application/json+schema", ContentType::JsonSchema), + ("text/css; charset=utf-8", ContentType::Css), + ( + "text/css; charset=utf-8; template=handlebars", + ContentType::CssHandlebars, + ), + ("text/html; charset=utf-8", ContentType::Html), + ( + "text/html; charset=utf-8; template=handlebars", + ContentType::HtmlHandlebars, + ), + ("text/markdown; charset=utf-8", ContentType::Markdown), + ( + "text/markdown; charset=utf-8; template=handlebars", + ContentType::MarkdownHandlebars, + ), + ("text/plain; charset=utf-8", ContentType::Plain), + ( + "text/plain; charset=utf-8; template=handlebars", + ContentType::PlainHandlebars, + ), + ]; + + for (raw_text, variant) in entries { + assert_eq!(ContentType::from_str(raw_text).unwrap(), variant); + } + for (raw_text, variant) in entries { + assert_eq!(raw_text.parse::().unwrap(), variant); + } } } From 60638ff147a99ca37136f11cf7d8844cd25b0ba2 Mon Sep 17 00:00:00 2001 From: Apisit Ritruengroj Date: Mon, 11 Aug 2025 20:40:15 +0700 Subject: [PATCH 3/9] feat: media types defining --- rust/signed_doc/src/metadata/content_type.rs | 21 +++++------ .../src/validator/rules/content_type.rs | 36 +++++++++++++++++-- .../src/validator/rules/template.rs | 12 ++++++- 3 files changed, 56 insertions(+), 13 deletions(-) diff --git a/rust/signed_doc/src/metadata/content_type.rs b/rust/signed_doc/src/metadata/content_type.rs index 65490479296..0ab6b6500ac 100644 --- a/rust/signed_doc/src/metadata/content_type.rs +++ b/rust/signed_doc/src/metadata/content_type.rs @@ -53,6 +53,7 @@ impl FromStr for ContentType { "application/cbor" => Ok(Self::Cbor), "application/cddl" => Ok(Self::Cddl), "application/json" => Ok(Self::Json), + "application/json+schema" => Ok(Self::JsonSchema), "text/css; charset=utf-8" => Ok(Self::Css), "text/css; charset=utf-8; template=handlebars" => Ok(Self::CssHandlebars), "text/html; charset=utf-8" => Ok(Self::Html), @@ -76,9 +77,7 @@ impl FromStr for ContentType { impl<'de> serde::Deserialize<'de> for ContentType { fn deserialize(deserializer: D) -> Result - where - D: serde::Deserializer<'de>, - { + where D: serde::Deserializer<'de> { let s = String::deserialize(deserializer)?; FromStr::from_str(&s).map_err(serde::de::Error::custom) } @@ -119,9 +118,11 @@ impl minicbor::Decode<'_, ()> for ContentType { Ok(val) if val == minicbor::data::Int::from(50_u8) => Ok(Self::Json), // CoAP Content Format CBOR Ok(val) if val == minicbor::data::Int::from(60_u8) => Ok(Self::Cbor), - Ok(val) => Err(minicbor::decode::Error::message(format!( - "unsupported CoAP Content Formats value: {val}" - ))), + Ok(val) => { + Err(minicbor::decode::Error::message(format!( + "unsupported CoAP Content Formats value: {val}" + ))) + }, Err(_) => { d.set_position(p); d.str()?.parse().map_err(minicbor::decode::Error::message) @@ -163,11 +164,11 @@ mod tests { ), ]; - for (raw_text, variant) in entries { - assert_eq!(ContentType::from_str(raw_text).unwrap(), variant); + for (raw_str, variant) in entries { + assert_eq!(ContentType::from_str(raw_str).unwrap(), variant); } - for (raw_text, variant) in entries { - assert_eq!(raw_text.parse::().unwrap(), variant); + for (raw_str, variant) in entries { + assert_eq!(raw_str.parse::().unwrap(), variant); } } } diff --git a/rust/signed_doc/src/validator/rules/content_type.rs b/rust/signed_doc/src/validator/rules/content_type.rs index 765593adba2..5a3bac61374 100644 --- a/rust/signed_doc/src/validator/rules/content_type.rs +++ b/rust/signed_doc/src/validator/rules/content_type.rs @@ -65,7 +65,7 @@ impl ContentTypeRule { }, ContentType::Cddl => { // TODO: not implemented yet - anyhow::bail!("`application/cddl` is valid but unavailable yet") + anyhow::bail!("`{}` is valid but unavailable yet", self.exp) }, ContentType::Cbor => { let mut decoder = minicbor::Decoder::new(content); @@ -78,7 +78,39 @@ impl ContentTypeRule { }, ContentType::JsonSchema => { // TODO: not implemented yet - anyhow::bail!("`application/json+schema` is valid but unavailable yet") + anyhow::bail!("`{}` is valid but unavailable yet", self.exp) + }, + ContentType::Css => { + // TODO: not implemented yet + anyhow::bail!("`{}` is valid but unavailable yet", self.exp) + }, + ContentType::CssHandlebars => { + // TODO: not implemented yet + anyhow::bail!("`{}` is valid but unavailable yet", self.exp) + }, + ContentType::Html => { + // TODO: not implemented yet + anyhow::bail!("`{}` is valid but unavailable yet", self.exp) + }, + ContentType::HtmlHandlebars => { + // TODO: not implemented yet + anyhow::bail!("`{}` is valid but unavailable yet", self.exp) + }, + ContentType::Markdown => { + // TODO: not implemented yet + anyhow::bail!("`{}` is valid but unavailable yet", self.exp) + }, + ContentType::MarkdownHandlebars => { + // TODO: not implemented yet + anyhow::bail!("`{}` is valid but unavailable yet", self.exp) + }, + ContentType::Plain => { + // TODO: not implemented yet + anyhow::bail!("`{}` is valid but unavailable yet", self.exp) + }, + ContentType::PlainHandlebars => { + // TODO: not implemented yet + anyhow::bail!("`{}` is valid but unavailable yet", self.exp) }, } Ok(()) diff --git a/rust/signed_doc/src/validator/rules/template.rs b/rust/signed_doc/src/validator/rules/template.rs index 06c14a256d1..7f792b5c4eb 100644 --- a/rust/signed_doc/src/validator/rules/template.rs +++ b/rust/signed_doc/src/validator/rules/template.rs @@ -65,7 +65,17 @@ impl ContentRule { }; match template_content_type { ContentType::Json => templated_json_schema_check(doc, &template_doc), - ContentType::Cddl | ContentType::Cbor | ContentType::JsonSchema => { + ContentType::Cddl + | ContentType::Cbor + | ContentType::JsonSchema + | ContentType::Css + | ContentType::CssHandlebars + | ContentType::Html + | ContentType::HtmlHandlebars + | ContentType::Markdown + | ContentType::MarkdownHandlebars + | ContentType::Plain + | ContentType::PlainHandlebars => { // TODO: not implemented yet true }, From 8f93b602f8e701e3e0be5d3c72fdfb95650bc8d4 Mon Sep 17 00:00:00 2001 From: Apisit Ritruengroj Date: Tue, 12 Aug 2025 19:00:59 +0700 Subject: [PATCH 4/9] feat: cbor decoding --- rust/signed_doc/src/metadata/content_type.rs | 32 +++++++++++++++----- 1 file changed, 24 insertions(+), 8 deletions(-) diff --git a/rust/signed_doc/src/metadata/content_type.rs b/rust/signed_doc/src/metadata/content_type.rs index 0ab6b6500ac..574d4fc4215 100644 --- a/rust/signed_doc/src/metadata/content_type.rs +++ b/rust/signed_doc/src/metadata/content_type.rs @@ -75,9 +75,30 @@ impl FromStr for ContentType { } } +impl TryFrom for ContentType { + type Error = anyhow::Error; + + fn try_from(value: u64) -> Result { + // https://www.iana.org/assignments/core-parameters/core-parameters.xhtml#content-formats + match value { + 0 => Ok(Self::Plain), + 50 => Ok(Self::Json), + 60 => Ok(Self::Cbor), + 20000 => Ok(Self::Css), + _ => { + anyhow::bail!( + "Unsupported CoAP Content-Format: {value}, Supported only: 0, 50, 60, 20000", + ) + }, + } + } +} + impl<'de> serde::Deserialize<'de> for ContentType { fn deserialize(deserializer: D) -> Result - where D: serde::Deserializer<'de> { + where + D: serde::Deserializer<'de>, + { let s = String::deserialize(deserializer)?; FromStr::from_str(&s).map_err(serde::de::Error::custom) } @@ -114,14 +135,9 @@ impl minicbor::Decode<'_, ()> for ContentType { ) -> Result { let p = d.position(); match d.int() { - // CoAP Content Format JSON - Ok(val) if val == minicbor::data::Int::from(50_u8) => Ok(Self::Json), - // CoAP Content Format CBOR - Ok(val) if val == minicbor::data::Int::from(60_u8) => Ok(Self::Cbor), Ok(val) => { - Err(minicbor::decode::Error::message(format!( - "unsupported CoAP Content Formats value: {val}" - ))) + let val: u64 = val.try_into().map_err(minicbor::decode::Error::custom)?; + Self::try_from(val).map_err(minicbor::decode::Error::message) }, Err(_) => { d.set_position(p); From a3711496eab790db8847ddd0653da34f204ace45 Mon Sep 17 00:00:00 2001 From: Apisit Ritruengroj Date: Tue, 12 Aug 2025 19:27:50 +0700 Subject: [PATCH 5/9] test: initial --- rust/signed_doc/src/metadata/content_type.rs | 38 ++++++++++++++++++-- 1 file changed, 35 insertions(+), 3 deletions(-) diff --git a/rust/signed_doc/src/metadata/content_type.rs b/rust/signed_doc/src/metadata/content_type.rs index 574d4fc4215..2dcc7810b01 100644 --- a/rust/signed_doc/src/metadata/content_type.rs +++ b/rust/signed_doc/src/metadata/content_type.rs @@ -96,9 +96,7 @@ impl TryFrom for ContentType { impl<'de> serde::Deserialize<'de> for ContentType { fn deserialize(deserializer: D) -> Result - where - D: serde::Deserializer<'de>, - { + where D: serde::Deserializer<'de> { let s = String::deserialize(deserializer)?; FromStr::from_str(&s).map_err(serde::de::Error::custom) } @@ -149,6 +147,8 @@ impl minicbor::Decode<'_, ()> for ContentType { #[cfg(test)] mod tests { + use minicbor::{Decode, Decoder, Encoder}; + use super::*; #[test] @@ -186,5 +186,37 @@ mod tests { for (raw_str, variant) in entries { assert_eq!(raw_str.parse::().unwrap(), variant); } + for (raw_str, variant) in entries { + let mut e = Encoder::new(vec![]); + e.str(raw_str).unwrap(); + let bytes = e.into_writer().clone(); + let mut decoder = Decoder::new(bytes.as_slice()); + + assert_eq!(ContentType::decode(&mut decoder, &mut ()).unwrap(), variant); + } + } + + #[test] + fn cbor_coap_decoding_test() { + let coap_valid_entries = [ + (vec![0x00], ContentType::Plain), + (vec![0x18, 0x32], ContentType::Json), + (vec![0x18, 0x3C], ContentType::Cbor), + (vec![0x19, 0x4E, 0x20], ContentType::Css), + ]; + + for (coap_code_bytes, variant) in coap_valid_entries { + let mut decoder = Decoder::new(coap_code_bytes.as_slice()); + assert_eq!(ContentType::decode(&mut decoder, &mut ()).unwrap(), variant); + } + + let coap_invalid_entries = [ + vec![0x13], // application/ace+cbor + ]; + + for coap_code_bytes in coap_invalid_entries { + let mut decoder = Decoder::new(coap_code_bytes.as_slice()); + assert!(ContentType::decode(&mut decoder, &mut ()).is_err()); + } } } From e4600c230c90d2632c26bc1a005abd54defd5c34 Mon Sep 17 00:00:00 2001 From: Apisit Ritruengroj Date: Tue, 12 Aug 2025 19:58:08 +0700 Subject: [PATCH 6/9] chore: lintfix --- .../src/validator/rules/content_type.rs | 47 ++++--------------- 1 file changed, 10 insertions(+), 37 deletions(-) diff --git a/rust/signed_doc/src/validator/rules/content_type.rs b/rust/signed_doc/src/validator/rules/content_type.rs index 5a3bac61374..313d220cebc 100644 --- a/rust/signed_doc/src/validator/rules/content_type.rs +++ b/rust/signed_doc/src/validator/rules/content_type.rs @@ -63,10 +63,6 @@ impl ContentTypeRule { anyhow::bail!("Invalid {} content: {e}", self.exp) } }, - ContentType::Cddl => { - // TODO: not implemented yet - anyhow::bail!("`{}` is valid but unavailable yet", self.exp) - }, ContentType::Cbor => { let mut decoder = minicbor::Decoder::new(content); @@ -76,39 +72,16 @@ impl ContentTypeRule { anyhow::bail!("Unused bytes remain in the input after decoding") } }, - ContentType::JsonSchema => { - // TODO: not implemented yet - anyhow::bail!("`{}` is valid but unavailable yet", self.exp) - }, - ContentType::Css => { - // TODO: not implemented yet - anyhow::bail!("`{}` is valid but unavailable yet", self.exp) - }, - ContentType::CssHandlebars => { - // TODO: not implemented yet - anyhow::bail!("`{}` is valid but unavailable yet", self.exp) - }, - ContentType::Html => { - // TODO: not implemented yet - anyhow::bail!("`{}` is valid but unavailable yet", self.exp) - }, - ContentType::HtmlHandlebars => { - // TODO: not implemented yet - anyhow::bail!("`{}` is valid but unavailable yet", self.exp) - }, - ContentType::Markdown => { - // TODO: not implemented yet - anyhow::bail!("`{}` is valid but unavailable yet", self.exp) - }, - ContentType::MarkdownHandlebars => { - // TODO: not implemented yet - anyhow::bail!("`{}` is valid but unavailable yet", self.exp) - }, - ContentType::Plain => { - // TODO: not implemented yet - anyhow::bail!("`{}` is valid but unavailable yet", self.exp) - }, - ContentType::PlainHandlebars => { + ContentType::Cddl + | ContentType::JsonSchema + | ContentType::Css + | ContentType::CssHandlebars + | ContentType::Html + | ContentType::HtmlHandlebars + | ContentType::Markdown + | ContentType::MarkdownHandlebars + | ContentType::Plain + | ContentType::PlainHandlebars => { // TODO: not implemented yet anyhow::bail!("`{}` is valid but unavailable yet", self.exp) }, From eb16ae5cea44136b405f4a87346782f0437671f7 Mon Sep 17 00:00:00 2001 From: Apisit Ritruengroj Date: Tue, 12 Aug 2025 20:34:03 +0700 Subject: [PATCH 7/9] chore: lintfix --- rust/signed_doc/src/metadata/content_type.rs | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) diff --git a/rust/signed_doc/src/metadata/content_type.rs b/rust/signed_doc/src/metadata/content_type.rs index 2dcc7810b01..a250a877130 100644 --- a/rust/signed_doc/src/metadata/content_type.rs +++ b/rust/signed_doc/src/metadata/content_type.rs @@ -132,15 +132,12 @@ impl minicbor::Decode<'_, ()> for ContentType { _ctx: &mut (), ) -> Result { let p = d.position(); - match d.int() { - Ok(val) => { - let val: u64 = val.try_into().map_err(minicbor::decode::Error::custom)?; - Self::try_from(val).map_err(minicbor::decode::Error::message) - }, - Err(_) => { - d.set_position(p); - d.str()?.parse().map_err(minicbor::decode::Error::message) - }, + if let Ok(val) = d.int() { + let val: u64 = val.try_into().map_err(minicbor::decode::Error::custom)?; + Self::try_from(val).map_err(minicbor::decode::Error::message) + } else { + d.set_position(p); + d.str()?.parse().map_err(minicbor::decode::Error::message) } } } From 0dd1035aaa747c5420c4105282c0717fe54a13fe Mon Sep 17 00:00:00 2001 From: Apisit Ritruengroj Date: Wed, 13 Aug 2025 12:34:39 +0700 Subject: [PATCH 8/9] test: restructure using test cases --- rust/signed_doc/src/metadata/content_type.rs | 154 +++++++++++-------- 1 file changed, 90 insertions(+), 64 deletions(-) diff --git a/rust/signed_doc/src/metadata/content_type.rs b/rust/signed_doc/src/metadata/content_type.rs index a250a877130..f6614eeccc3 100644 --- a/rust/signed_doc/src/metadata/content_type.rs +++ b/rust/signed_doc/src/metadata/content_type.rs @@ -145,75 +145,101 @@ impl minicbor::Decode<'_, ()> for ContentType { #[cfg(test)] mod tests { use minicbor::{Decode, Decoder, Encoder}; + use test_case::test_case; use super::*; - #[test] - fn content_type_string_test() { - let entries = [ - ("application/cbor", ContentType::Cbor), - ("application/cddl", ContentType::Cddl), - ("application/json", ContentType::Json), - ("application/json+schema", ContentType::JsonSchema), - ("text/css; charset=utf-8", ContentType::Css), - ( - "text/css; charset=utf-8; template=handlebars", - ContentType::CssHandlebars, - ), - ("text/html; charset=utf-8", ContentType::Html), - ( - "text/html; charset=utf-8; template=handlebars", - ContentType::HtmlHandlebars, - ), - ("text/markdown; charset=utf-8", ContentType::Markdown), - ( - "text/markdown; charset=utf-8; template=handlebars", - ContentType::MarkdownHandlebars, - ), - ("text/plain; charset=utf-8", ContentType::Plain), - ( - "text/plain; charset=utf-8; template=handlebars", - ContentType::PlainHandlebars, - ), - ]; - - for (raw_str, variant) in entries { - assert_eq!(ContentType::from_str(raw_str).unwrap(), variant); - } - for (raw_str, variant) in entries { - assert_eq!(raw_str.parse::().unwrap(), variant); - } - for (raw_str, variant) in entries { - let mut e = Encoder::new(vec![]); - e.str(raw_str).unwrap(); - let bytes = e.into_writer().clone(); - let mut decoder = Decoder::new(bytes.as_slice()); - - assert_eq!(ContentType::decode(&mut decoder, &mut ()).unwrap(), variant); - } + #[test_case( + ("application/cbor", ContentType::Cbor); + "application/cbor" + )] + #[test_case( + ("application/cddl", ContentType::Cddl); + "application/cddl" + )] + #[test_case( + ("application/json", ContentType::Json); + "application/json" + )] + #[test_case( + ("application/json+schema", ContentType::JsonSchema); + "application/json+schema" + )] + #[test_case( + ("text/css; charset=utf-8", ContentType::Css); + "text/css; charset=utf-8" + )] + #[test_case( + ("text/css; charset=utf-8; template=handlebars", ContentType::CssHandlebars); + "text/css; charset=utf-8; template=handlebars" + )] + #[test_case( + ("text/html; charset=utf-8", ContentType::Html); + "text/html; charset=utf-8" + )] + #[test_case( + ("text/html; charset=utf-8; template=handlebars", ContentType::HtmlHandlebars); + "text/html; charset=utf-8; template=handlebars" + )] + #[test_case( + ("text/markdown; charset=utf-8", ContentType::Markdown); + "text/markdown; charset=utf-8" + )] + #[test_case( + ("text/markdown; charset=utf-8; template=handlebars", ContentType::MarkdownHandlebars); + "text/markdown; charset=utf-8; template=handlebars" + )] + #[test_case( + ("text/plain; charset=utf-8", ContentType::Plain); + "text/plain; charset=utf-8" + )] + #[test_case( + ("text/plain; charset=utf-8; template=handlebars", ContentType::PlainHandlebars); + "text/plain; charset=utf-8; template=handlebars" + )] + fn content_type_string_test((raw_str, variant): (&str, ContentType)) { + // from str + assert_eq!(ContentType::from_str(raw_str).unwrap(), variant); + + // parsing + assert_eq!(raw_str.parse::().unwrap(), variant); + + // decoding from cbor + let mut e = Encoder::new(vec![]); + e.str(raw_str).unwrap(); + let bytes = e.into_writer().clone(); + let mut decoder = Decoder::new(bytes.as_slice()); + + assert_eq!(ContentType::decode(&mut decoder, &mut ()).unwrap(), variant); } - #[test] - fn cbor_coap_decoding_test() { - let coap_valid_entries = [ - (vec![0x00], ContentType::Plain), - (vec![0x18, 0x32], ContentType::Json), - (vec![0x18, 0x3C], ContentType::Cbor), - (vec![0x19, 0x4E, 0x20], ContentType::Css), - ]; - - for (coap_code_bytes, variant) in coap_valid_entries { - let mut decoder = Decoder::new(coap_code_bytes.as_slice()); - assert_eq!(ContentType::decode(&mut decoder, &mut ()).unwrap(), variant); - } - - let coap_invalid_entries = [ - vec![0x13], // application/ace+cbor - ]; + #[test_case( + (vec![0x00], ContentType::Plain); + "text/plain; charset=utf-8" + )] + #[test_case( + (vec![0x18, 0x32], ContentType::Json); + "application/json" + )] + #[test_case( + (vec![0x18, 0x3C], ContentType::Cbor); + "application/cbor" + )] + #[test_case( + (vec![0x19, 0x4E, 0x20], ContentType::Css); + "text/css; charset=utf-8" + )] + fn cbor_coap_decoding_test((coap_code_bytes, variant): (Vec, ContentType)) { + let mut decoder = Decoder::new(coap_code_bytes.as_slice()); + assert_eq!(ContentType::decode(&mut decoder, &mut ()).unwrap(), variant); + } - for coap_code_bytes in coap_invalid_entries { - let mut decoder = Decoder::new(coap_code_bytes.as_slice()); - assert!(ContentType::decode(&mut decoder, &mut ()).is_err()); - } + #[test_case( + vec![0x13]; + "application/ace+cbor" + )] + fn cbor_unsupported_coap_decoding_test(coap_code_bytes: Vec) { + let mut decoder = Decoder::new(coap_code_bytes.as_slice()); + assert!(ContentType::decode(&mut decoder, &mut ()).is_err()); } } From 5b97bf162a44ebe186a3d4867392fc6f7265a864 Mon Sep 17 00:00:00 2001 From: Apisit Ritruengroj Date: Wed, 13 Aug 2025 13:12:09 +0700 Subject: [PATCH 9/9] chore: lintfix --- rust/signed_doc/src/metadata/content_type.rs | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/rust/signed_doc/src/metadata/content_type.rs b/rust/signed_doc/src/metadata/content_type.rs index f6614eeccc3..40f10274c59 100644 --- a/rust/signed_doc/src/metadata/content_type.rs +++ b/rust/signed_doc/src/metadata/content_type.rs @@ -214,32 +214,32 @@ mod tests { } #[test_case( - (vec![0x00], ContentType::Plain); + (&[0x00], ContentType::Plain); "text/plain; charset=utf-8" )] #[test_case( - (vec![0x18, 0x32], ContentType::Json); + (&[0x18, 0x32], ContentType::Json); "application/json" )] #[test_case( - (vec![0x18, 0x3C], ContentType::Cbor); + (&[0x18, 0x3C], ContentType::Cbor); "application/cbor" )] #[test_case( - (vec![0x19, 0x4E, 0x20], ContentType::Css); + (&[0x19, 0x4E, 0x20], ContentType::Css); "text/css; charset=utf-8" )] - fn cbor_coap_decoding_test((coap_code_bytes, variant): (Vec, ContentType)) { - let mut decoder = Decoder::new(coap_code_bytes.as_slice()); + fn cbor_coap_decoding_test((coap_code_bytes, variant): (&[u8], ContentType)) { + let mut decoder = Decoder::new(coap_code_bytes); assert_eq!(ContentType::decode(&mut decoder, &mut ()).unwrap(), variant); } #[test_case( - vec![0x13]; + &[0x13]; "application/ace+cbor" )] - fn cbor_unsupported_coap_decoding_test(coap_code_bytes: Vec) { - let mut decoder = Decoder::new(coap_code_bytes.as_slice()); + fn cbor_unsupported_coap_decoding_test(coap_code_bytes: &[u8]) { + let mut decoder = Decoder::new(coap_code_bytes); assert!(ContentType::decode(&mut decoder, &mut ()).is_err()); } }