From 261f4d72ef4486e9216ab9a4dc87d1e756f1103c Mon Sep 17 00:00:00 2001 From: Anders429 Date: Tue, 2 Jul 2024 11:12:58 -0600 Subject: [PATCH 1/5] Roundtrip serde test. --- Cargo.toml | 4 ++++ src/lib.rs | 14 ++++++++++++++ 2 files changed, 18 insertions(+) diff --git a/Cargo.toml b/Cargo.toml index cd7c5e6..3850ac7 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -20,3 +20,7 @@ serde_support = ["serde"] [dependencies] serde = { optional = true, version = "1.0", features = ["derive"] } + +[dev-dependencies] +claims = "0.7.1" +serde_assert = "0.8.0" diff --git a/src/lib.rs b/src/lib.rs index 61fe358..5c43e35 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -809,6 +809,8 @@ fn is_ctext(s: &str) -> bool { #[cfg(test)] mod tests { use super::*; + use claims::{assert_ok, assert_ok_eq}; + use serde_assert::{Deserializer, Serializer, Token}; fn is_valid(address: &str, test_case: Option<&str>) { if let Some(test_case) = test_case { @@ -1109,4 +1111,16 @@ mod tests { is_send::(); is_sync::(); } + + #[cfg(feature = "serde_support")] + #[test] + fn test_serde_roundtrip() { + let email = assert_ok!(EmailAddress::from_str("simple@example.com")); + + let serializer = Serializer::builder().build(); + let mut deserializer = + Deserializer::builder(assert_ok!(email.serialize(&serializer))).build(); + + assert_ok_eq!(EmailAddress::deserialize(&mut deserializer), email); + } } From bf01d1acad65462cf90bf17453c4fd0042a740c2 Mon Sep 17 00:00:00 2001 From: Anders429 Date: Tue, 2 Jul 2024 11:15:11 -0600 Subject: [PATCH 2/5] Fix roundtrip serialization. --- src/lib.rs | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index 5c43e35..a364ed1 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -279,7 +279,7 @@ An informal description can be found on [Wikipedia](https://en.wikipedia.org/wik )] #[cfg(feature = "serde_support")] -use serde::{Deserialize, Serialize}; +use serde::{Deserialize, Serialize, Serializer}; use std::fmt; use std::fmt::{Debug, Display, Formatter}; use std::str::FromStr; @@ -326,7 +326,6 @@ pub enum Error { /// independently. /// #[derive(Debug, Clone, PartialEq, Eq, Hash)] -#[cfg_attr(feature = "serde_support", derive(Serialize))] pub struct EmailAddress(String); // ------------------------------------------------------------------------------------------------ @@ -426,6 +425,16 @@ impl AsRef for EmailAddress { } } +#[cfg(feature = "serde_support")] +impl Serialize for EmailAddress { + fn serialize(&self, serializer: S) -> Result + where + S: Serializer, + { + serializer.serialize_str(&self.0) + } +} + #[cfg(feature = "serde_support")] impl<'de> Deserialize<'de> for EmailAddress { fn deserialize(deserializer: D) -> Result From ef99e29f7779e3fd507ed9c1c4cd5dd6fc719bda Mon Sep 17 00:00:00 2001 From: Anders429 Date: Tue, 2 Jul 2024 11:35:18 -0600 Subject: [PATCH 3/5] Test all serialization and deserialization functionality. --- src/lib.rs | 57 ++++++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 55 insertions(+), 2 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index a364ed1..2296bfd 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -449,7 +449,7 @@ impl<'de> Deserialize<'de> for EmailAddress { type Value = EmailAddress; fn expecting(&self, fmt: &mut Formatter<'_>) -> fmt::Result { - fmt.write_str("data") + fmt.write_str("string containing a valid email address") } fn visit_str(self, s: &str) -> Result @@ -818,7 +818,8 @@ fn is_ctext(s: &str) -> bool { #[cfg(test)] mod tests { use super::*; - use claims::{assert_ok, assert_ok_eq}; + use claims::{assert_err_eq, assert_ok, assert_ok_eq}; + use serde::de::{Error as _, Unexpected}; use serde_assert::{Deserializer, Serializer, Token}; fn is_valid(address: &str, test_case: Option<&str>) { @@ -1121,6 +1122,58 @@ mod tests { is_sync::(); } + #[cfg(feature = "serde_support")] + #[test] + fn test_serialize() { + let email = assert_ok!(EmailAddress::from_str("simple@example.com")); + + let serializer = Serializer::builder().build(); + + assert_ok_eq!( + email.serialize(&serializer), + [Token::Str("simple@example.com".to_owned())] + ); + } + + #[cfg(feature = "serde_support")] + #[test] + fn test_deserialize() { + let mut deserializer = + Deserializer::builder([Token::Str("simple@example.com".to_owned())]).build(); + + let email = assert_ok!(EmailAddress::from_str("simple@example.com")); + assert_ok_eq!(EmailAddress::deserialize(&mut deserializer), email); + } + + #[cfg(feature = "serde_support")] + #[test] + fn test_deserialize_invalid_value() { + let mut deserializer = + Deserializer::builder([Token::Str("Abc.example.com".to_owned())]).build(); + + assert_err_eq!( + EmailAddress::deserialize(&mut deserializer), + serde_assert::de::Error::invalid_value( + Unexpected::Str("Abc.example.com"), + &"Missing separator character '@'." + ) + ); + } + + #[cfg(feature = "serde_support")] + #[test] + fn test_deserialize_invalid_type() { + let mut deserializer = Deserializer::builder([Token::U64(42)]).build(); + + assert_err_eq!( + EmailAddress::deserialize(&mut deserializer), + serde_assert::de::Error::invalid_type( + Unexpected::Unsigned(42), + &"string containing a valid email address" + ) + ); + } + #[cfg(feature = "serde_support")] #[test] fn test_serde_roundtrip() { From 71237e4f368fad09cd874f482983553f76a59f95 Mon Sep 17 00:00:00 2001 From: Anders429 Date: Tue, 2 Jul 2024 11:35:43 -0600 Subject: [PATCH 4/5] Remove serde derive feature. --- Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index 3850ac7..4d1c220 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -19,7 +19,7 @@ default = ["serde_support"] serde_support = ["serde"] [dependencies] -serde = { optional = true, version = "1.0", features = ["derive"] } +serde = { optional = true, version = "1.0" } [dev-dependencies] claims = "0.7.1" From bb4b881f4f1f669f4c7bda1b816e5a67929a7537 Mon Sep 17 00:00:00 2001 From: Anders429 Date: Thu, 4 Jul 2024 10:23:08 -0600 Subject: [PATCH 5/5] Add regression test comment. --- src/lib.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/lib.rs b/src/lib.rs index 2296bfd..9b6b382 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1174,6 +1174,7 @@ mod tests { ); } + // Regression test: GitHub issue #26 #[cfg(feature = "serde_support")] #[test] fn test_serde_roundtrip() {