reliakit_validate/
valid.rs1use crate::Validate;
2use core::ops::Deref;
3
4#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
32pub struct Valid<T>(T);
33
34impl<T: Validate> Valid<T> {
35 pub fn new(value: T) -> Result<Self, T::Error> {
37 value.validate()?;
38 Ok(Self(value))
39 }
40
41 pub fn get(&self) -> &T {
43 &self.0
44 }
45
46 pub fn into_inner(self) -> T {
48 self.0
49 }
50}
51
52impl<T: Validate> Deref for Valid<T> {
53 type Target = T;
54
55 fn deref(&self) -> &Self::Target {
56 &self.0
57 }
58}
59
60impl<T: Validate + core::fmt::Display> core::fmt::Display for Valid<T> {
61 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
62 core::fmt::Display::fmt(&self.0, f)
63 }
64}
65
66#[cfg(all(test, feature = "alloc"))]
67mod tests {
68 use super::Valid;
69 use crate::{Validate, ValidationError};
70
71 struct MinAge(u8);
72
73 impl Validate for MinAge {
74 type Error = ValidationError;
75 fn validate(&self) -> Result<(), Self::Error> {
76 if self.0 < 18 {
77 return Err(ValidationError::new("must be at least 18"));
78 }
79 Ok(())
80 }
81 }
82
83 #[test]
84 fn valid_new_accepts_valid_value() {
85 let v = Valid::new(MinAge(18)).unwrap();
86 assert_eq!(v.get().0, 18);
87 }
88
89 #[test]
90 fn valid_new_rejects_invalid_value() {
91 assert!(Valid::new(MinAge(17)).is_err());
92 }
93
94 #[test]
95 fn valid_into_inner() {
96 let v = Valid::new(MinAge(25)).unwrap();
97 assert_eq!(v.into_inner().0, 25);
98 }
99
100 #[test]
101 fn valid_deref() {
102 let v = Valid::new(MinAge(30)).unwrap();
103 assert_eq!((*v).0, 30);
104 }
105
106 #[test]
107 fn valid_get() {
108 let v = Valid::new(MinAge(21)).unwrap();
109 assert_eq!(v.get().0, 21);
110 }
111
112 struct NamedAge(u8);
113
114 impl Validate for NamedAge {
115 type Error = ValidationError;
116 fn validate(&self) -> Result<(), Self::Error> {
117 if self.0 < 18 {
118 return Err(ValidationError::new("must be at least 18"));
119 }
120 Ok(())
121 }
122 }
123
124 impl core::fmt::Display for NamedAge {
125 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
126 write!(f, "age:{}", self.0)
127 }
128 }
129
130 #[test]
131 fn valid_display_delegates_to_inner() {
132 use alloc::string::ToString;
133 let v = Valid::new(NamedAge(25)).unwrap();
134 assert_eq!(v.to_string(), "age:25");
135 }
136}