1use crate::result::Error;
2use crate::rule::Rule;
3use serde::{Deserialize, Deserializer, Serialize, Serializer};
4use std::collections::{HashMap, HashSet, VecDeque};
5use std::fmt::{Debug, Display, Formatter};
6
7#[derive(Debug, Eq, PartialEq, Ord, PartialOrd)]
20pub struct Refined<RULE>
21where
22 RULE: Rule,
23{
24 value: RULE::Item,
25}
26
27impl<RULE, T> Serialize for Refined<RULE>
28where
29 RULE: Rule<Item = T>,
30 T: Serialize,
31{
32 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
33 where
34 S: Serializer,
35 {
36 self.value.serialize(serializer)
37 }
38}
39
40impl<'de, RULE, T> Deserialize<'de> for Refined<RULE>
41where
42 RULE: Rule<Item = T>,
43 T: Deserialize<'de>,
44{
45 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
46 where
47 D: Deserializer<'de>,
48 {
49 use serde::de::Error;
50 let item: T = Deserialize::deserialize(deserializer)?;
51 let refined = Refined::new(item).map_err(|e| Error::custom(e.to_string()))?;
52 Ok(refined)
53 }
54}
55
56impl<RULE, T> Refined<RULE>
57where
58 RULE: Rule<Item = T>,
59{
60 pub fn new(value: T) -> Result<Self, Error<T>> {
83 let value = RULE::validate(value).map_err(|e| {
84 let message = e.to_string();
85 Error::new(e.into_value(), message)
86 })?;
87 Ok(Self { value })
88 }
89
90 pub fn unsafe_new(value: T) -> Self
113 where
114 T: Debug,
115 {
116 let value = RULE::validate(value).expect("initialization by `unsafe_new` failed");
117 Self { value }
118 }
119
120 pub(crate) fn new_unchecked(value: T) -> Self {
121 Self { value }
122 }
123
124 pub fn mutate<F>(self, f: F) -> Result<Self, Error<T>>
159 where
160 F: FnOnce(T) -> T,
161 {
162 Refined::new(f(self.into_value()))
163 }
164
165 pub fn value(&self) -> &RULE::Item {
181 &self.value
182 }
183
184 pub fn into_value(self) -> RULE::Item {
200 self.value
201 }
202}
203
204macro_rules! impl_try_from {
205 ($t: ty) => {
206 impl<RULE: Rule<Item = $t>> TryFrom<$t> for Refined<RULE> {
207 type Error = Error<$t>;
208
209 fn try_from(value: $t) -> Result<Self, Self::Error> {
210 Refined::new(value)
211 }
212 }
213 };
214 ($($ts: ty), +) => {
215 $(impl_try_from!($ts);)+
216 };
217}
218
219impl_try_from![u8, u16, u32, u64, u128, usize, i8, i16, i32, i64, i128, isize, f32, f64];
220impl_try_from![String, char];
221
222impl<'a, RULE: Rule<Item = String>> TryFrom<&'a str> for Refined<RULE> {
223 type Error = Error<String>;
224
225 fn try_from(value: &'a str) -> Result<Self, Self::Error> {
226 Refined::new(value.into())
227 }
228}
229
230impl<T, RULE: Rule<Item = Vec<T>>> TryFrom<Vec<T>> for Refined<RULE> {
231 type Error = Error<Vec<T>>;
232
233 fn try_from(value: Vec<T>) -> Result<Self, Self::Error> {
234 Refined::new(value)
235 }
236}
237
238impl<T, RULE: Rule<Item = VecDeque<T>>> TryFrom<VecDeque<T>> for Refined<RULE> {
239 type Error = Error<VecDeque<T>>;
240
241 fn try_from(value: VecDeque<T>) -> Result<Self, Self::Error> {
242 Refined::new(value)
243 }
244}
245
246impl<T, RULE: Rule<Item = HashSet<T>>> TryFrom<HashSet<T>> for Refined<RULE> {
247 type Error = Error<HashSet<T>>;
248
249 fn try_from(value: HashSet<T>) -> Result<Self, Self::Error> {
250 Refined::new(value)
251 }
252}
253
254impl<K, V, RULE: Rule<Item = HashMap<K, V>>> TryFrom<HashMap<K, V>> for Refined<RULE> {
255 type Error = Error<HashMap<K, V>>;
256
257 fn try_from(value: HashMap<K, V>) -> Result<Self, Self::Error> {
258 Refined::new(value)
259 }
260}
261
262impl<RULE, T> Display for Refined<RULE>
263where
264 RULE: Rule<Item = T>,
265 T: Display,
266{
267 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
268 write!(f, "{}", self.value)
269 }
270}
271
272#[cfg(test)]
273mod test {
274 use serde::{Deserialize, Serialize};
275 use serde_json::json;
276 use std::collections::{HashMap, HashSet, VecDeque};
277
278 use crate::refined::Refined;
279 use crate::result::Error;
280 use crate::rule::{
281 EqualI128, EqualI16, EqualI32, EqualI64, EqualI8, EqualIsize, EqualU128, EqualU16,
282 EqualU32, EqualU64, EqualU8, EqualUsize, NonEmptyHashMap, NonEmptyHashSet, NonEmptyString,
283 NonEmptyStringRule, NonEmptyVec, NonEmptyVecDeque,
284 };
285
286 #[test]
287 fn test_unsafe_new_success() {
288 let non_empty_string = Refined::<NonEmptyStringRule>::unsafe_new("Hello".to_string());
289 assert_eq!(non_empty_string.value, "Hello");
290 }
291
292 #[test]
293 #[should_panic(expected = "initialization by `unsafe_new` failed")]
294 fn test_unsafe_new_panic() {
295 let non_empty_string = Refined::<NonEmptyStringRule>::unsafe_new("".to_string());
296 assert_eq!(non_empty_string.value, ""); }
298
299 #[test]
300 fn test_refined_non_empty_string_ok() -> Result<(), Error<String>> {
301 let non_empty_string = Refined::<NonEmptyStringRule>::new("Hello".to_string())?;
302 assert_eq!(non_empty_string.value, "Hello");
303 Ok(())
304 }
305
306 #[test]
307 fn test_refined_non_empty_string_err() -> Result<(), String> {
308 let non_empty_string = Refined::<NonEmptyStringRule>::new("".to_string());
309 assert!(non_empty_string.is_err());
310 Ok(())
311 }
312
313 #[test]
314 fn test_refined_display() -> Result<(), Error<String>> {
315 let non_empty_string = Refined::<NonEmptyStringRule>::new("Hello".to_string())?;
316 assert_eq!(format!("{}", non_empty_string), "Hello");
317 Ok(())
318 }
319
320 #[test]
321 fn test_refined_serialize_json_string() -> Result<(), Error<String>> {
322 let non_empty_string = Refined::<NonEmptyStringRule>::new("hello".to_string())?;
323
324 let actual = json!(non_empty_string);
325 let expected = json!("hello");
326 assert_eq!(actual, expected);
327 Ok(())
328 }
329
330 #[test]
331 fn test_refined_serialize_json_struct() -> Result<(), Error<String>> {
332 type NonEmptyString = Refined<NonEmptyStringRule>;
333 #[derive(Serialize)]
334 struct Human {
335 name: NonEmptyString,
336 age: u8,
337 }
338
339 let john = Human {
340 name: NonEmptyString::new("john".to_string())?,
341 age: 8,
342 };
343
344 let actual = json!(john);
345 let expected = json! {{
346 "name": "john",
347 "age": 8
348 }};
349 assert_eq!(actual, expected);
350 Ok(())
351 }
352
353 #[test]
354 fn test_refined_deserialize_json_ok_string() -> anyhow::Result<()> {
355 let json = json!("hello").to_string();
356 let non_empty_string: Refined<NonEmptyStringRule> = serde_json::from_str(&json)?;
357
358 let actual = non_empty_string.into_value();
359 let expected = "hello";
360 assert_eq!(actual, expected);
361 Ok(())
362 }
363
364 #[test]
365 fn test_refined_deserialize_json_ok_1() -> anyhow::Result<()> {
366 #[derive(Debug, Eq, PartialEq, Deserialize)]
367 struct Human {
368 name: NonEmptyString,
369 friends: NonEmptyVec<String>,
370 age: u8,
371 }
372 let json = json! {{
373 "name": "john",
374 "friends": ["tom", "taro"],
375 "age": 8
376 }}
377 .to_string();
378
379 let actual = serde_json::from_str::<Human>(&json)?;
380
381 let expected = Human {
382 name: NonEmptyString::unsafe_new("john".to_string()),
383 friends: NonEmptyVec::unsafe_new(vec!["tom".to_string(), "taro".to_string()]),
384 age: 8,
385 };
386 assert_eq!(actual, expected);
387 Ok(())
388 }
389
390 #[test]
391 fn test_refined_deserialize_json_err_1() -> anyhow::Result<()> {
392 #[derive(Debug, Eq, PartialEq, Deserialize)]
393 struct Human {
394 name: NonEmptyString,
395 friends: NonEmptyVec<String>,
396 age: u8,
397 }
398 let json = json! {{
399 "name": "john",
400 "friends": [],
401 "age": 8
402 }}
403 .to_string();
404
405 assert!(serde_json::from_str::<Human>(&json).is_err());
407 Ok(())
408 }
409
410 #[test]
411 fn test_refined_deserialize_json_err_2() -> anyhow::Result<()> {
412 #[derive(Debug, Eq, PartialEq, Deserialize)]
413 struct Human {
414 name: NonEmptyString,
415 friends: NonEmptyVec<String>,
416 age: u8,
417 }
418 let json = json! {{
419 "name": "",
420 "friends": ["tom", "taro"],
421 "age": 8
422 }}
423 .to_string();
424
425 assert!(serde_json::from_str::<Human>(&json).is_err());
427 Ok(())
428 }
429
430 #[test]
431 fn test_refined_deserialize_json_err_3() -> anyhow::Result<()> {
432 let json = json!("").to_string();
433 let result = serde_json::from_str::<Refined<NonEmptyStringRule>>(&json);
434 assert!(result.is_err());
435 Ok(())
436 }
437
438 #[test]
439 fn test_try_from() -> anyhow::Result<()> {
440 let value = NonEmptyString::try_from("hello")?;
441 assert_eq!(value.into_value(), "hello");
442
443 let value = NonEmptyString::try_from("hello".to_string())?;
444 assert_eq!(value.into_value(), "hello");
445
446 let value = EqualU8::<8>::try_from(8)?;
447 assert_eq!(value.into_value(), 8);
448
449 let value = EqualU16::<16>::try_from(16)?;
450 assert_eq!(value.into_value(), 16);
451
452 let value = EqualU32::<32>::try_from(32)?;
453 assert_eq!(value.into_value(), 32);
454
455 let value = EqualU64::<64>::try_from(64)?;
456 assert_eq!(value.into_value(), 64);
457
458 let value = EqualU128::<128>::try_from(128)?;
459 assert_eq!(value.into_value(), 128);
460
461 let value = EqualUsize::<1>::try_from(1)?;
462 assert_eq!(value.into_value(), 1);
463
464 let value = EqualI8::<8>::try_from(8)?;
465 assert_eq!(value.into_value(), 8);
466
467 let value = EqualI16::<16>::try_from(16)?;
468 assert_eq!(value.into_value(), 16);
469
470 let value = EqualI32::<32>::try_from(32)?;
471 assert_eq!(value.into_value(), 32);
472
473 let value = EqualI64::<64>::try_from(64)?;
474 assert_eq!(value.into_value(), 64);
475
476 let value = EqualI128::<128>::try_from(128)?;
477 assert_eq!(value.into_value(), 128);
478
479 let value = EqualIsize::<1>::try_from(1)?;
480 assert_eq!(value.into_value(), 1);
481
482 let value = NonEmptyVec::try_from(vec!["hello".to_string()])?;
483 assert_eq!(value.into_value(), vec!["hello".to_string()]);
484
485 let value = NonEmptyVecDeque::try_from(
486 vec!["hello".to_string()]
487 .into_iter()
488 .collect::<VecDeque<_>>(),
489 )?;
490 assert_eq!(value.into_value(), vec!["hello".to_string()]);
491
492 let value = NonEmptyHashSet::try_from(
493 vec!["hello".to_string()]
494 .into_iter()
495 .collect::<HashSet<_>>(),
496 )?;
497 assert_eq!(
498 value.into_value(),
499 vec!["hello".to_string()].into_iter().collect()
500 );
501
502 let value = NonEmptyHashMap::try_from(
503 vec![("hello".to_string(), "world".to_string())]
504 .into_iter()
505 .collect::<HashMap<_, _>>(),
506 )?;
507 assert_eq!(
508 value.into_value(),
509 vec![("hello".to_string(), "world".to_string())]
510 .into_iter()
511 .collect()
512 );
513
514 let value: NonEmptyVec<NonEmptyString> =
515 NonEmptyVec::try_from(vec!["hello".to_string().try_into()?])?;
516 assert_eq!(value.into_value(), vec!["hello".to_string().try_into()?]);
517 Ok(())
518 }
519
520 #[test]
521 fn test_mutate() -> anyhow::Result<()> {
522 let value = NonEmptyString::try_from("h")?
523 .mutate(|n| n + "e")?
524 .mutate(|n| n + "l")?
525 .mutate(|n| n + "l")?
526 .mutate(|n| n + "o")?;
527 assert_eq!(value.into_value(), "hello");
528 Ok(())
529 }
530}