garde/rules/length/
simple.rs

1//! Implemented by types which have a known length.
2//!
3//! The meaning of "length" depends on the type.
4//! For example, the length of a `String` is defined as the number of _bytes_ it stores.
5
6use crate::error::Error;
7
8pub fn apply<T: Simple>(v: &T, (min, max): (usize, usize)) -> Result<(), Error> {
9    v.validate_length(min, max)
10}
11
12pub trait Simple {
13    fn validate_length(&self, min: usize, max: usize) -> Result<(), Error>;
14}
15
16impl<T: HasSimpleLength> Simple for T {
17    fn validate_length(&self, min: usize, max: usize) -> Result<(), Error> {
18        super::check_len(self.length(), min, max)
19    }
20}
21
22impl<T: Simple> Simple for Option<T> {
23    fn validate_length(&self, min: usize, max: usize) -> Result<(), Error> {
24        match self {
25            Some(v) => v.validate_length(min, max),
26            None => Ok(()),
27        }
28    }
29}
30
31pub trait HasSimpleLength {
32    fn length(&self) -> usize;
33}
34
35macro_rules! impl_via_bytes {
36    ($(in<$lifetime:lifetime>)? $T:ty) => {
37        impl<$($lifetime)?> HasSimpleLength for $T {
38            fn length(&self) -> usize {
39                use super::bytes::HasBytes as _;
40                self.num_bytes()
41            }
42        }
43    };
44}
45
46impl_via_bytes!(std::string::String);
47impl_via_bytes!(in<'a> &'a std::string::String);
48impl_via_bytes!(in<'a> &'a str);
49impl_via_bytes!(in<'a> std::borrow::Cow<'a, str>);
50impl_via_bytes!(std::rc::Rc<str>);
51impl_via_bytes!(std::sync::Arc<str>);
52impl_via_bytes!(std::boxed::Box<str>);
53
54macro_rules! impl_via_len {
55    (in<$lifetime:lifetime, $($generic:ident),*> $T:ty) => {
56        impl<$lifetime, $($generic),*> HasSimpleLength for $T {
57            fn length(&self) -> usize {
58                self.len()
59            }
60        }
61    };
62    (in<$($generic:ident),*> $T:ty) => {
63        impl<$($generic),*> HasSimpleLength for $T {
64            fn length(&self) -> usize {
65                self.len()
66            }
67        }
68    };
69    (in<$lifetime:lifetime> $T:ty) => {
70        impl<$lifetime> HasSimpleLength for $T {
71            fn length(&self) -> usize {
72                self.len()
73            }
74        }
75    };
76    ($T:ty) => {
77        impl HasSimpleLength for $T {
78            fn length(&self) -> usize {
79                self.len()
80            }
81        }
82    };
83}
84
85impl_via_len!(in<T> Vec<T>);
86impl_via_len!(in<'a, T> &'a Vec<T>);
87impl_via_len!(in<'a, T> &'a [T]);
88
89impl<const N: usize, T> Simple for [T; N] {
90    fn validate_length(&self, min: usize, max: usize) -> Result<(), Error> {
91        super::check_len(self.len(), min, max)
92    }
93}
94
95impl<const N: usize, T> Simple for &[T; N] {
96    fn validate_length(&self, min: usize, max: usize) -> Result<(), Error> {
97        super::check_len(self.len(), min, max)
98    }
99}
100
101impl_via_len!(in<K, V, S> std::collections::HashMap<K, V, S>);
102impl_via_len!(in<T, S> std::collections::HashSet<T, S>);
103impl_via_len!(in<K, V> std::collections::BTreeMap<K, V>);
104impl_via_len!(in<T> std::collections::BTreeSet<T>);
105impl_via_len!(in<T> std::collections::VecDeque<T>);
106impl_via_len!(in<T> std::collections::BinaryHeap<T>);
107impl_via_len!(in<T> std::collections::LinkedList<T>);
108impl_via_len!(in<'a, K, V, S> &'a std::collections::HashMap<K, V, S>);
109impl_via_len!(in<'a, T, S> &'a std::collections::HashSet<T, S>);
110impl_via_len!(in<'a, K, V> &'a std::collections::BTreeMap<K, V>);
111impl_via_len!(in<'a, T> &'a std::collections::BTreeSet<T>);
112impl_via_len!(in<'a, T> &'a std::collections::VecDeque<T>);
113impl_via_len!(in<'a, T> &'a std::collections::BinaryHeap<T>);
114impl_via_len!(in<'a, T> &'a std::collections::LinkedList<T>);