hickory_proto/serialize/binary/
restrict.rs1#[derive(Clone, Copy)]
5pub struct Restrict<T>(T);
6
7impl<T> Restrict<T> {
8 #[inline]
10 pub fn new(restricted: T) -> Self {
11 Self(restricted)
12 }
13
14 #[inline]
27 pub fn verify<'a, F: Fn(&'a T) -> bool>(&'a self, f: F) -> Verified<'a, T> {
28 if f(&self.0) {
29 Verified(VerifiedInner::Valid(&self.0))
30 } else {
31 Verified(VerifiedInner::Invalid(&self.0))
32 }
33 }
34
35 #[inline]
49 pub fn verify_unwrap<F: Fn(&T) -> bool>(self, f: F) -> Result<T, T> {
50 if f(&self.0) { Ok(self.0) } else { Err(self.0) }
51 }
52
53 #[inline]
55 pub fn unverified(self) -> T {
56 self.0
57 }
58
59 #[inline]
69 pub fn map<R, F: Fn(T) -> R>(self, f: F) -> Restrict<R> {
70 Restrict(f(self.0))
71 }
72}
73
74pub struct Verified<'a, T>(VerifiedInner<'a, T>);
76
77impl<T> Verified<'_, T> {
78 #[inline]
80 pub fn then<R, F: Fn(&T) -> R>(&self, f: F) -> Result<R, &T> {
81 match self.0 {
82 VerifiedInner::Valid(t) => Ok(f(t)),
83 VerifiedInner::Invalid(t) => Err(t),
84 }
85 }
86
87 #[inline]
89 pub fn is_valid(&self) -> bool {
90 match self.0 {
91 VerifiedInner::Valid(_) => true,
92 VerifiedInner::Invalid(_) => false,
93 }
94 }
95}
96
97enum VerifiedInner<'a, T> {
99 Valid(&'a T),
100 Invalid(&'a T),
101}
102
103pub trait RestrictedMath {
105 type Arg: 'static + Sized + Copy;
107 type Value: 'static + Sized + Copy;
109
110 fn checked_add(&self, arg: Self::Arg) -> Result<Restrict<Self::Value>, Self::Arg>;
112 fn checked_sub(&self, arg: Self::Arg) -> Result<Restrict<Self::Value>, Self::Arg>;
114 fn checked_mul(&self, arg: Self::Arg) -> Result<Restrict<Self::Value>, Self::Arg>;
116}
117
118impl RestrictedMath for Restrict<usize> {
119 type Arg = usize;
120 type Value = usize;
121
122 fn checked_add(&self, arg: Self::Arg) -> Result<Restrict<Self::Value>, Self::Arg> {
123 self.0.checked_add(arg).map(Restrict).ok_or(arg)
124 }
125 fn checked_sub(&self, arg: Self::Arg) -> Result<Restrict<Self::Value>, Self::Arg> {
126 self.0.checked_sub(arg).map(Restrict).ok_or(arg)
127 }
128 fn checked_mul(&self, arg: Self::Arg) -> Result<Restrict<Self::Value>, Self::Arg> {
129 self.0.checked_mul(arg).map(Restrict).ok_or(arg)
130 }
131}
132
133impl RestrictedMath for Restrict<u8> {
134 type Arg = u8;
135 type Value = u8;
136
137 fn checked_add(&self, arg: Self::Arg) -> Result<Restrict<Self::Value>, Self::Arg> {
138 self.0.checked_add(arg).map(Restrict).ok_or(arg)
139 }
140 fn checked_sub(&self, arg: Self::Arg) -> Result<Restrict<Self::Value>, Self::Arg> {
141 self.0.checked_sub(arg).map(Restrict).ok_or(arg)
142 }
143 fn checked_mul(&self, arg: Self::Arg) -> Result<Restrict<Self::Value>, Self::Arg> {
144 self.0.checked_mul(arg).map(Restrict).ok_or(arg)
145 }
146}
147
148impl RestrictedMath for Restrict<u16> {
149 type Arg = u16;
150 type Value = u16;
151
152 fn checked_add(&self, arg: Self::Arg) -> Result<Restrict<Self::Value>, Self::Arg> {
153 self.0.checked_add(arg).map(Restrict).ok_or(arg)
154 }
155 fn checked_sub(&self, arg: Self::Arg) -> Result<Restrict<Self::Value>, Self::Arg> {
156 self.0.checked_sub(arg).map(Restrict).ok_or(arg)
157 }
158 fn checked_mul(&self, arg: Self::Arg) -> Result<Restrict<Self::Value>, Self::Arg> {
159 self.0.checked_mul(arg).map(Restrict).ok_or(arg)
160 }
161}
162
163impl<R, A> RestrictedMath for Result<R, A>
164where
165 R: RestrictedMath,
166 A: 'static + Sized + Copy,
167{
168 type Arg = <R as RestrictedMath>::Arg;
169 type Value = <R as RestrictedMath>::Value;
170
171 fn checked_add(&self, arg: Self::Arg) -> Result<Restrict<Self::Value>, Self::Arg> {
172 match self {
173 Ok(r) => r.checked_add(arg),
174 Err(_) => Err(arg),
175 }
176 }
177
178 fn checked_sub(&self, arg: Self::Arg) -> Result<Restrict<Self::Value>, Self::Arg> {
179 match self {
180 Ok(r) => r.checked_sub(arg),
181 Err(_) => Err(arg),
182 }
183 }
184
185 fn checked_mul(&self, arg: Self::Arg) -> Result<Restrict<Self::Value>, Self::Arg> {
186 match self {
187 Ok(r) => r.checked_mul(arg),
188 Err(_) => Err(arg),
189 }
190 }
191}
192
193#[cfg(test)]
194mod tests {
195 use super::*;
196
197 #[test]
198 fn test_checked_add() {
199 assert_eq!(
200 Restrict(1_usize).checked_add(2_usize).unwrap().unverified(),
201 3_usize
202 );
203 assert_eq!(
204 Restrict(1_u16).checked_add(2_u16).unwrap().unverified(),
205 3_u16
206 );
207 assert_eq!(Restrict(1_u8).checked_add(2_u8).unwrap().unverified(), 3_u8);
208 }
209
210 #[test]
211 fn test_checked_sub() {
212 assert_eq!(
213 Restrict(2_usize).checked_sub(1_usize).unwrap().unverified(),
214 1_usize
215 );
216 assert_eq!(
217 Restrict(2_u16).checked_sub(1_u16).unwrap().unverified(),
218 1_u16
219 );
220 assert_eq!(Restrict(2_u8).checked_sub(1_u8).unwrap().unverified(), 1_u8);
221 }
222
223 #[test]
224 fn test_checked_mul() {
225 assert_eq!(
226 Restrict(1_usize).checked_mul(2_usize).unwrap().unverified(),
227 2_usize
228 );
229 assert_eq!(
230 Restrict(1_u16).checked_mul(2_u16).unwrap().unverified(),
231 2_u16
232 );
233 assert_eq!(Restrict(1_u8).checked_mul(2_u8).unwrap().unverified(), 2_u8);
234 }
235}