1use core::fmt::{Debug, Display, Formatter};
9
10pub struct Bounds<T> {
13 upper_left: T,
15 upper_right: T,
17 lower_left: T,
19 lower_right: T,
21}
22
23impl<T> Bounds<T> {
24 pub const fn new(upper_left: T, upper_right: T, lower_left: T, lower_right: T) -> Bounds<T> {
27 Bounds {
28 upper_left,
29 upper_right,
30 lower_left,
31 lower_right,
32 }
33 }
34
35 pub fn upper_left_corner(&self) -> &T {
36 &self.upper_left
37 }
38
39 pub fn lower_left_corner(&self) -> &T {
40 &self.lower_left
41 }
42
43 pub fn upper_right_corner(&self) -> &T {
44 &self.upper_right
45 }
46
47 pub fn lower_right_corner(&self) -> &T {
48 &self.lower_right
49 }
50}
51
52pub trait Range<T>
55where
56 T: Debug + Display + Clone + PartialOrd,
57{
58 type Error;
59
60 fn value_is_valid(&self, value: &T) -> bool;
63
64 fn check_value_is_valid(&self, value: &T) -> Result<(), Self::Error>;
68}
69
70#[derive(Debug, Clone)]
73pub struct LessThanValue<T>
74where
75 T: Debug + Display + Clone + PartialOrd,
76{
77 pub(crate) value: T,
78}
79impl<T: Debug + Display + Clone + PartialOrd> LessThanValue<T> {
80 #[must_use]
81 pub const fn new(value: T) -> Self {
82 Self { value }
83 }
84
85 pub fn value(&self) -> &T {
87 &self.value
88 }
89}
90impl<T: Debug + Display + Clone + PartialOrd> Range<T> for LessThanValue<T> {
91 type Error = GreaterThanEqualToValueError<T>;
92 fn value_is_valid(&self, value: &T) -> bool {
93 value.lt(&self.value)
94 }
95
96 fn check_value_is_valid(&self, value: &T) -> Result<(), Self::Error> {
97 if self.value_is_valid(value) {
98 return Ok(());
99 }
100 Err(GreaterThanEqualToValueError {
101 value: value.clone(),
102 valid_range: self.clone(),
103 })
104 }
105}
106
107#[derive(Debug, Clone)]
110pub struct LessThanEqualToValueError<T>
111where
112 T: Debug + Display + Clone + PartialOrd,
113{
114 pub(crate) value: T,
115 pub(crate) valid_range: GreaterThanValue<T>,
116}
117
118impl<T: Debug + Display + Clone + PartialOrd> Display for LessThanEqualToValueError<T> {
119 fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result {
120 f.write_fmt(format_args!(
121 "value {} is less than or equal to {}",
122 self.value, self.valid_range.value
123 ))
124 }
125}
126
127impl<T: Debug + Display + Clone + PartialOrd> LessThanEqualToValueError<T> {
128 pub fn value(&self) -> &T {
130 &self.value
131 }
132
133 pub fn valid_range(&self) -> &GreaterThanValue<T> {
135 &self.valid_range
136 }
137}
138#[cfg(feature = "std")]
139impl<T: Debug + Display + Clone + PartialOrd> std::error::Error for LessThanEqualToValueError<T> {}
140
141#[derive(Debug, Clone)]
144pub struct GreaterThanValue<T>
145where
146 T: Debug + Display + Clone + PartialOrd,
147{
148 pub(crate) value: T,
149}
150
151impl<T: Debug + Display + Clone + PartialOrd> GreaterThanValue<T> {
152 #[must_use]
153 pub const fn new(value: T) -> Self {
154 Self { value }
155 }
156
157 pub fn value(&self) -> &T {
160 &self.value
161 }
162}
163
164impl<T: Debug + Display + Clone + PartialOrd> Range<T> for GreaterThanValue<T> {
165 type Error = LessThanEqualToValueError<T>;
166
167 fn value_is_valid(&self, value: &T) -> bool {
168 value.gt(&self.value)
169 }
170
171 fn check_value_is_valid(&self, value: &T) -> Result<(), Self::Error> {
172 if self.value_is_valid(value) {
173 return Ok(());
174 }
175 Err(LessThanEqualToValueError {
176 valid_range: self.clone(),
177 value: value.clone(),
178 })
179 }
180}
181
182#[derive(Debug, Clone)]
186pub struct GreaterThanEqualToValueError<T>
187where
188 T: Debug + Display + Clone + PartialOrd,
189{
190 pub(crate) value: T,
191 pub(crate) valid_range: LessThanValue<T>,
192}
193impl<T: Debug + Display + Clone + PartialOrd> Display for GreaterThanEqualToValueError<T> {
194 fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result {
195 f.write_fmt(format_args!(
196 "the value {} is greater than or equal to {}",
197 self.value, self.valid_range.value
198 ))
199 }
200}
201#[cfg(feature = "std")]
202impl<T: Debug + Display + Clone + PartialOrd> std::error::Error
203 for GreaterThanEqualToValueError<T>
204{
205}
206
207impl<T: Debug + Display + Clone + PartialOrd> GreaterThanEqualToValueError<T> {
208 #[must_use]
209 pub fn new(value: T, valid_range: LessThanValue<T>) -> Self {
210 Self { value, valid_range }
211 }
212
213 pub fn err<O>(value: T, valid_range: LessThanValue<T>) -> Result<O, Self> {
214 Err(Self::new(value, valid_range))
215 }
216
217 pub fn value(&self) -> &T {
219 &self.value
220 }
221
222 pub fn valid_range(&self) -> &LessThanValue<T> {
224 &self.valid_range
225 }
226}
227macro_rules! upconvert_error_type {
228 ($lower:tt,$upper:tt,$error:tt) => {
229 impl From<$error<$lower>> for $error<$upper> {
230 fn from(value: $error<$lower>) -> Self {
231 $error {
232 value: value.value as $upper,
233 valid_range: LessThanValue {
234 value: value.valid_range.value as $upper,
235 },
236 }
237 }
238 }
239 };
240}
241upconvert_error_type!(u8, u16, GreaterThanEqualToValueError);
242upconvert_error_type!(u8, u32, GreaterThanEqualToValueError);
243upconvert_error_type!(u8, u64, GreaterThanEqualToValueError);
244upconvert_error_type!(u8, u128, GreaterThanEqualToValueError);
245upconvert_error_type!(u8, f32, GreaterThanEqualToValueError);
246upconvert_error_type!(u8, f64, GreaterThanEqualToValueError);
247upconvert_error_type!(u16, u32, GreaterThanEqualToValueError);
248upconvert_error_type!(u16, u64, GreaterThanEqualToValueError);
249upconvert_error_type!(u16, u128, GreaterThanEqualToValueError);
250upconvert_error_type!(u16, f32, GreaterThanEqualToValueError);
251upconvert_error_type!(u16, f64, GreaterThanEqualToValueError);
252upconvert_error_type!(u32, u64, GreaterThanEqualToValueError);
253upconvert_error_type!(u32, u128, GreaterThanEqualToValueError);
254upconvert_error_type!(u32, f32, GreaterThanEqualToValueError);
255upconvert_error_type!(u32, f64, GreaterThanEqualToValueError);
256
257#[derive(Debug, Clone)]
260pub struct WithinRange<T>
261where
262 T: Debug + Display + Clone + PartialOrd,
263{
264 pub(crate) lower_bound: GreaterThanValue<T>,
265 pub(crate) upper_bound: LessThanValue<T>,
266}
267impl<T: Debug + Display + Clone + PartialOrd> WithinRange<T> {
268 #[must_use]
274 pub const fn new(lower_bound: T, upper_bound: T) -> Self {
275 Self {
276 lower_bound: GreaterThanValue::new(lower_bound),
277 upper_bound: LessThanValue::new(upper_bound),
278 }
279 }
280
281 #[must_use]
283 pub fn lower_bound(&self) -> &GreaterThanValue<T> {
284 &self.lower_bound
285 }
286 #[must_use]
288 pub fn upper_bound(&self) -> &LessThanValue<T> {
289 &self.upper_bound
290 }
291}
292impl<T: Debug + Display + Clone + PartialOrd> Range<T> for WithinRange<T> {
293 type Error = OutsideRangeError<T>;
294
295 fn value_is_valid(&self, value: &T) -> bool {
296 self.lower_bound.value_is_valid(value) && self.upper_bound.value_is_valid(value)
297 }
298
299 fn check_value_is_valid(&self, value: &T) -> Result<(), Self::Error> {
300 if self.value_is_valid(value) {
301 return Ok(());
302 }
303 Err(OutsideRangeError {
304 value: value.clone(),
305 valid_range: self.clone(),
306 })
307 }
308}
309
310#[derive(Debug, Clone)]
313pub struct OutsideRange<T>
314where
315 T: Debug + Display + Clone + PartialOrd,
316{
317 pub(crate) lower_bound: LessThanValue<T>,
318 pub(crate) upper_bound: GreaterThanValue<T>,
319}
320
321impl<T: Debug + Display + Clone + PartialOrd> OutsideRange<T> {
322 #[must_use]
325 pub fn new(lower_bound: T, upper_bound: T) -> Self {
326 Self {
327 lower_bound: LessThanValue::new(lower_bound),
328 upper_bound: GreaterThanValue::new(upper_bound),
329 }
330 }
331
332 pub fn lower_bound(&self) -> &LessThanValue<T> {
334 &self.lower_bound
335 }
336
337 pub fn upper_bound(&self) -> &GreaterThanValue<T> {
339 &self.upper_bound
340 }
341}
342
343impl<T: Debug + Display + Clone + PartialOrd> Range<T> for OutsideRange<T> {
344 type Error = InsideRangeError<T>;
345
346 fn value_is_valid(&self, value: &T) -> bool {
347 self.lower_bound.value_is_valid(value) || self.upper_bound.value_is_valid(value)
348 }
349
350 fn check_value_is_valid(&self, value: &T) -> Result<(), Self::Error> {
351 if !self.lower_bound.value_is_valid(value) && !self.upper_bound.value_is_valid(value) {
352 return InsideRangeError::err(value.clone(), self.clone());
353 }
354 Ok(())
355 }
356}
357
358#[derive(Debug, Clone)]
362pub struct OutsideRangeError<T>
363where
364 T: Debug + Display + Clone + PartialOrd,
365{
366 pub(crate) value: T,
367 pub(crate) valid_range: WithinRange<T>,
368}
369
370impl<T: Debug + Display + Clone + PartialOrd> OutsideRangeError<T> {
371 pub fn new(value: T, valid_range: WithinRange<T>) -> Self {
372 Self { value, valid_range }
373 }
374
375 pub fn err<O>(value: T, valid_range: WithinRange<T>) -> Result<O, Self> {
376 Err(Self::new(value, valid_range))
377 }
378}
379
380impl<T: Debug + Display + Clone + PartialOrd> Display for OutsideRangeError<T> {
381 fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result {
382 f.write_fmt(format_args!(
383 "Value {} is outside valid range {} -> {}",
384 self.value, self.valid_range.lower_bound.value, self.valid_range.upper_bound.value
385 ))
386 }
387}
388#[cfg(feature = "std")]
389impl<T: Debug + Display + Clone + PartialOrd> std::error::Error for OutsideRangeError<T> {}
390
391#[derive(Debug, Clone)]
394pub struct InsideRangeError<T>
395where
396 T: Debug + Display + Clone + PartialOrd,
397{
398 pub(crate) value: T,
399 pub(crate) valid_range: OutsideRange<T>,
400}
401impl<T: Debug + Display + Clone + PartialOrd> InsideRangeError<T> {
402 pub fn new(value: T, valid_range: OutsideRange<T>) -> Self {
403 Self { value, valid_range }
404 }
405
406 pub fn err<O>(value: T, valid_range: OutsideRange<T>) -> Result<O, Self> {
407 Err(Self::new(value, valid_range))
408 }
409}
410
411impl<T: Debug + Display + Clone + PartialOrd> Display for InsideRangeError<T> {
412 fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result {
413 f.write_fmt(format_args!(
414 "Value {} is inside invalid range {} -> {}",
415 self.value, self.valid_range.lower_bound.value, self.valid_range.upper_bound.value
416 ))
417 }
418}
419impl<T: Debug + Display + Clone + PartialOrd> core::error::Error for InsideRangeError<T> {}