rusdantic_types/
string.rs1use serde::{Deserialize, Serialize};
4use std::fmt;
5use std::ops::Deref;
6
7#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
19pub struct NonEmptyString(String);
20
21impl NonEmptyString {
22 pub fn new(value: impl Into<String>) -> Result<Self, String> {
24 let s = value.into();
25 if s.is_empty() {
26 Err("string must not be empty".to_string())
27 } else {
28 Ok(Self(s))
29 }
30 }
31
32 pub fn into_inner(self) -> String {
34 self.0
35 }
36
37 pub fn as_str(&self) -> &str {
39 &self.0
40 }
41}
42
43impl Deref for NonEmptyString {
44 type Target = str;
45 fn deref(&self) -> &str {
46 &self.0
47 }
48}
49
50impl fmt::Debug for NonEmptyString {
51 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
52 write!(f, "NonEmptyString({:?})", self.0)
53 }
54}
55
56impl fmt::Display for NonEmptyString {
57 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
58 write!(f, "{}", self.0)
59 }
60}
61
62impl Serialize for NonEmptyString {
63 fn serialize<S: serde::Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
64 self.0.serialize(serializer)
65 }
66}
67
68impl<'de> Deserialize<'de> for NonEmptyString {
69 fn deserialize<D: serde::Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
70 let s = String::deserialize(deserializer)?;
71 Self::new(s).map_err(serde::de::Error::custom)
72 }
73}
74
75#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
87pub struct EmailStr(String);
88
89fn get_email_regex() -> &'static regex::Regex {
91 rusdantic_core::rules::email::get_email_regex()
92}
93
94impl EmailStr {
95 pub fn new(value: impl Into<String>) -> Result<Self, String> {
97 let s = value.into();
98 if s.is_empty() || !s.contains('@') || s.len() > 254 {
99 return Err("invalid email format".to_string());
100 }
101 if !get_email_regex().is_match(&s) {
102 return Err("invalid email format".to_string());
103 }
104 Ok(Self(s))
105 }
106
107 pub fn into_inner(self) -> String {
109 self.0
110 }
111
112 pub fn as_str(&self) -> &str {
114 &self.0
115 }
116}
117
118impl Deref for EmailStr {
119 type Target = str;
120 fn deref(&self) -> &str {
121 &self.0
122 }
123}
124
125impl fmt::Debug for EmailStr {
126 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
127 write!(f, "EmailStr({:?})", self.0)
128 }
129}
130
131impl fmt::Display for EmailStr {
132 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
133 write!(f, "{}", self.0)
134 }
135}
136
137impl Serialize for EmailStr {
138 fn serialize<S: serde::Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
139 self.0.serialize(serializer)
140 }
141}
142
143impl<'de> Deserialize<'de> for EmailStr {
144 fn deserialize<D: serde::Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
145 let s = String::deserialize(deserializer)?;
146 Self::new(s).map_err(serde::de::Error::custom)
147 }
148}
149
150#[cfg(test)]
151mod tests {
152 use super::*;
153
154 #[test]
155 fn test_non_empty_string_valid() {
156 assert!(NonEmptyString::new("hello").is_ok());
157 assert!(NonEmptyString::new("a").is_ok());
158 }
159
160 #[test]
161 fn test_non_empty_string_invalid() {
162 assert!(NonEmptyString::new("").is_err());
163 }
164
165 #[test]
166 fn test_non_empty_string_deref() {
167 let s = NonEmptyString::new("hello").unwrap();
168 assert_eq!(&*s, "hello");
169 assert_eq!(s.len(), 5);
170 }
171
172 #[test]
173 fn test_non_empty_string_serialize() {
174 let s = NonEmptyString::new("test").unwrap();
175 let json = serde_json::to_value(&s).unwrap();
176 assert_eq!(json, "test");
177 }
178
179 #[test]
180 fn test_non_empty_string_deserialize() {
181 let s: NonEmptyString = serde_json::from_value(serde_json::json!("hello")).unwrap();
182 assert_eq!(s.as_str(), "hello");
183 }
184
185 #[test]
186 fn test_non_empty_string_deserialize_empty() {
187 let result: Result<NonEmptyString, _> = serde_json::from_value(serde_json::json!(""));
188 assert!(result.is_err());
189 }
190
191 #[test]
192 fn test_email_str_valid() {
193 assert!(EmailStr::new("user@example.com").is_ok());
194 assert!(EmailStr::new("first.last@sub.domain.com").is_ok());
195 }
196
197 #[test]
198 fn test_email_str_invalid() {
199 assert!(EmailStr::new("").is_err());
200 assert!(EmailStr::new("not-email").is_err());
201 assert!(EmailStr::new("@example.com").is_err());
202 }
203
204 #[test]
205 fn test_email_str_serialize() {
206 let e = EmailStr::new("user@example.com").unwrap();
207 let json = serde_json::to_value(&e).unwrap();
208 assert_eq!(json, "user@example.com");
209 }
210
211 #[test]
212 fn test_email_str_deserialize() {
213 let e: EmailStr = serde_json::from_value(serde_json::json!("user@example.com")).unwrap();
214 assert_eq!(e.as_str(), "user@example.com");
215 }
216}