From 2fad73e3247126c13224b44da4febbf7722ca945 Mon Sep 17 00:00:00 2001 From: ekuinox Date: Wed, 18 Dec 2024 23:49:15 +0900 Subject: [PATCH 1/2] Deserializing `BDAddr` from non-borrowed string without clone (70ee65cc) --- Cargo.toml | 1 + src/api/bdaddr.rs | 65 ++++++++++++++++++++++++++++++++++++++--------- 2 files changed, 54 insertions(+), 12 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index c9cd7854..137d82d9 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -81,3 +81,4 @@ rand = "0.8.5" pretty_env_logger = "0.5.0" tokio = { version = "1.40.0", features = ["macros", "rt", "rt-multi-thread"] } serde_json = "1.0.128" +toml = "0.8.19" diff --git a/src/api/bdaddr.rs b/src/api/bdaddr.rs index 042318fc..25ccea8e 100644 --- a/src/api/bdaddr.rs +++ b/src/api/bdaddr.rs @@ -266,12 +266,11 @@ pub mod serde { where D: Deserializer<'de>, { - let buf = d.deserialize_str(ColonDelimVisitor)?; - BDAddr::from_str_delim(&buf).map_err(D::Error::custom) + d.deserialize_str(ColonDelimVisitor) } impl<'de> Visitor<'de> for ColonDelimVisitor { - type Value = Cow<'de, str>; + type Value = BDAddr; fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { write!( @@ -284,21 +283,21 @@ pub mod serde { where E: DeError, { - Ok(v.to_string().into()) + BDAddr::from_str_delim(v).map_err(E::custom) } fn visit_borrowed_str(self, v: &'de str) -> Result where E: DeError, { - Ok(v.into()) + BDAddr::from_str_delim(v).map_err(E::custom) } fn visit_string(self, v: String) -> Result where E: DeError, { - Ok(v.into()) + BDAddr::from_str_delim(&v).map_err(E::custom) } } } @@ -343,12 +342,11 @@ pub mod serde { where D: Deserializer<'de>, { - let buf = d.deserialize_str(NoDelimVisitor)?; - BDAddr::from_str_no_delim(&buf).map_err(D::Error::custom) + d.deserialize_str(NoDelimVisitor) } impl<'de> Visitor<'de> for NoDelimVisitor { - type Value = Cow<'de, str>; + type Value = BDAddr; fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { write!( @@ -361,21 +359,21 @@ pub mod serde { where E: DeError, { - Ok(v.to_string().into()) + BDAddr::from_str_no_delim(v).map_err(E::custom) } fn visit_borrowed_str(self, v: &'de str) -> Result where E: DeError, { - Ok(v.into()) + BDAddr::from_str_no_delim(v).map_err(E::custom) } fn visit_string(self, v: String) -> Result where E: DeError, { - Ok(v.into()) + BDAddr::from_str_no_delim(&v).map_err(E::custom) } } } @@ -481,4 +479,47 @@ mod tests { let addr_back: BDAddr = addr_as_hex.try_into().unwrap(); assert_eq!(ADDR, addr_back); } + + #[cfg(feature = "serde")] + #[test] + fn deserialize_toml_delim_bdaddr_with_struct() { + use serde_cr::Deserialize; + + #[derive(Deserialize, PartialEq, Copy, Clone, Debug)] + #[serde(crate = "serde_cr")] + struct Data { + addr: BDAddr, + } + + let data = Data { + addr: BDAddr::from([0xff, 0x00, 0xff, 0x00, 0xff, 0x00]), + }; + + assert_eq!(toml::from_str(r#"addr = "ff:00:ff:00:ff:00""#), Ok(data)); + assert!( + matches!(toml::from_str::(r"addr = 0"), Err(e) if e.message().contains("A colon seperated Bluetooth address, like `00:11:22:33:44:55`")) + ); + } + + #[cfg(feature = "serde")] + #[test] + fn deserialize_toml_nodelim_bdaddr_with_struct() { + use serde_cr::Deserialize; + + #[derive(Deserialize, PartialEq, Copy, Clone, Debug)] + #[serde(crate = "serde_cr")] + struct Data { + #[serde(with = "crate::serde::bdaddr::no_delim")] + addr: BDAddr, + } + + let data = Data { + addr: BDAddr::from([0xff, 0x00, 0xff, 0x00, 0xff, 0x00]), + }; + + assert_eq!(toml::from_str(r#"addr = "ff00ff00ff00""#), Ok(data)); + assert!( + matches!(toml::from_str::(r"addr = 0"), Err(e) if e.message().contains("A Bluetooth address without any delimiters, like `001122334455`")), + ); + } } From 5fa6f6df8d08dac9603f1c18ec0e679969e0862d Mon Sep 17 00:00:00 2001 From: ekuinox Date: Thu, 19 Dec 2024 20:32:20 +0900 Subject: [PATCH 2/2] remove import `Cow` --- src/api/bdaddr.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/src/api/bdaddr.rs b/src/api/bdaddr.rs index 25ccea8e..9d4b587a 100644 --- a/src/api/bdaddr.rs +++ b/src/api/bdaddr.rs @@ -197,7 +197,6 @@ impl BDAddr { /// Different de-/serialization formats for [`BDAddr`]. #[cfg(feature = "serde")] pub mod serde { - use std::borrow::Cow; use std::fmt::{self, Write as _}; use serde::{