oparl_types/
email_address.rs1use std::str::FromStr;
7
8use snafu::{ResultExt as _, Snafu};
9
10#[derive(
11 Debug,
12 Clone,
13 PartialEq,
14 Eq,
15 Hash,
16 derive_more::AsRef,
17 derive_more::Display,
18 derive_more::From,
19 derive_more::Into,
20 serde::Serialize,
21 serde::Deserialize,
22)]
23pub struct EmailAddress(email_address::EmailAddress);
24
25impl EmailAddress {
26 pub fn as_str(&self) -> &str {
27 self.0.as_str()
28 }
29}
30
31#[derive(Debug, Snafu)]
32pub enum TryFromEmailAddressError {
33 #[snafu(display("Failed to parse e-mail address: {source}"))]
34 Parse { source: email_address::Error },
35}
36
37impl FromStr for EmailAddress {
38 type Err = TryFromEmailAddressError;
39
40 fn from_str(s: &str) -> Result<Self, Self::Err> {
41 let email_address: email_address::EmailAddress = s.parse().context(ParseSnafu)?;
42 Ok(Self(email_address))
43 }
44}
45
46impl PartialOrd for EmailAddress {
47 fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
48 Some(self.cmp(other))
49 }
50}
51
52impl Ord for EmailAddress {
53 fn cmp(&self, other: &Self) -> std::cmp::Ordering {
54 self.as_str().cmp(other.as_str())
55 }
56}
57
58impl TryFrom<String> for EmailAddress {
59 type Error = TryFromEmailAddressError;
60
61 fn try_from(value: String) -> Result<Self, Self::Error> {
62 value.parse()
63 }
64}
65
66#[cfg(feature = "sea-orm")]
67mod sea_orm_impls {
68 use sea_orm::{
69 ActiveValue, ColumnType, DbErr, IntoActiveValue, TryGetError, TryGetable, Value,
70 sea_query::{ArrayType, Nullable, ValueType, ValueTypeErr},
71 };
72
73 use super::EmailAddress;
74
75 impl From<EmailAddress> for Value {
76 fn from(value: EmailAddress) -> Self {
77 value.as_str().into()
78 }
79 }
80
81 impl TryGetable for EmailAddress {
82 fn try_get_by<I: sea_orm::ColIdx>(
83 res: &sea_orm::QueryResult,
84 index: I,
85 ) -> Result<Self, TryGetError> {
86 let s = <String as TryGetable>::try_get_by(res, index)?;
87 s.try_into().map_err(|e| {
88 DbErr::TryIntoErr {
89 from: "String",
90 into: "EmailAddress",
91 source: Box::new(e),
92 }
93 .into()
94 })
95 }
96 }
97
98 impl ValueType for EmailAddress {
99 fn try_from(v: Value) -> Result<Self, ValueTypeErr> {
100 let s = <String as ValueType>::try_from(v)?;
101 s.try_into().map_err(|_| ValueTypeErr)
102 }
103
104 fn type_name() -> String {
105 stringify!(String).to_owned()
106 }
107
108 fn array_type() -> ArrayType {
109 <String as ValueType>::array_type()
110 }
111
112 fn column_type() -> ColumnType {
113 <String as ValueType>::column_type()
114 }
115 }
116
117 impl Nullable for EmailAddress {
118 fn null() -> Value {
119 Value::String(None)
120 }
121 }
122
123 impl IntoActiveValue<EmailAddress> for EmailAddress {
124 fn into_active_value(self) -> ActiveValue<EmailAddress> {
125 ActiveValue::Set(self)
126 }
127 }
128}
129
130#[cfg(test)]
131mod tests {
132 use pretty_assertions::assert_eq;
133
134 use super::EmailAddress;
135
136 #[test]
137 fn from_str() {
138 assert_eq!(
139 EmailAddress(
140 "hello@example.com"
141 .parse()
142 .expect("value must be a parseable EmailAddress")
143 ),
144 "hello@example.com"
145 .parse()
146 .expect("value must be a parseable EmailAddress")
147 );
148 }
149}
150
151#[cfg(test)]
152mod serde_tests {
153 use pretty_assertions::assert_eq;
154 use serde_json::json;
155
156 use super::EmailAddress;
157
158 #[test]
159 fn serialize() {
160 assert_eq!(
161 json!(EmailAddress(
162 "hello@example.com"
163 .parse()
164 .expect("value must be a parseable EmailAddress")
165 )),
166 json!("hello@example.com")
167 );
168 }
169
170 #[test]
171 fn deserialize_good() {
172 let deserialized: EmailAddress = serde_json::from_value(json!("hello@example.com"))
173 .expect("value must be deserializable as EmailAddress");
174 assert_eq!(
175 deserialized,
176 EmailAddress(
177 "hello@example.com"
178 .parse()
179 .expect("value must be a parseable EmailAddress")
180 )
181 );
182 }
183
184 #[test]
185 fn deserialize_bad() {
186 assert!(serde_json::from_value::<EmailAddress>(json!("xyzabcd")).is_err());
187 assert!(serde_json::from_value::<EmailAddress>(json!(true)).is_err());
188 assert!(serde_json::from_value::<EmailAddress>(json!(123)).is_err());
189 }
190}