hopr_primitive_types/
bounded.rs1use std::fmt::{Display, Formatter};
2
3use crate::prelude::GeneralError;
4
5#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Default, Hash, serde::Serialize, serde::Deserialize)]
8pub struct BoundedSize<const B: usize>(usize);
9
10impl<const B: usize> BoundedSize<B> {
11 pub const MAX: Self = Self(B);
13 pub const MIN: Self = Self(0);
15}
16
17impl<const B: usize> TryFrom<u8> for BoundedSize<B> {
18 type Error = GeneralError;
19
20 fn try_from(value: u8) -> Result<Self, Self::Error> {
21 (value as usize).try_into()
22 }
23}
24
25impl<const B: usize> TryFrom<u16> for BoundedSize<B> {
26 type Error = GeneralError;
27
28 fn try_from(value: u16) -> Result<Self, Self::Error> {
29 (value as usize).try_into()
30 }
31}
32
33impl<const B: usize> TryFrom<u32> for BoundedSize<B> {
34 type Error = GeneralError;
35
36 fn try_from(value: u32) -> Result<Self, Self::Error> {
37 (value as usize).try_into()
38 }
39}
40
41impl<const B: usize> TryFrom<u64> for BoundedSize<B> {
42 type Error = GeneralError;
43
44 fn try_from(value: u64) -> Result<Self, Self::Error> {
45 (value as usize).try_into()
46 }
47}
48
49impl<const B: usize> TryFrom<usize> for BoundedSize<B> {
50 type Error = GeneralError;
51
52 fn try_from(value: usize) -> Result<Self, Self::Error> {
53 if value <= B {
54 Ok(Self(value))
55 } else {
56 Err(GeneralError::InvalidInput)
57 }
58 }
59}
60
61impl<const B: usize> TryFrom<i8> for BoundedSize<B> {
62 type Error = GeneralError;
63
64 fn try_from(value: i8) -> Result<Self, Self::Error> {
65 Self::try_from(value as isize)
66 }
67}
68
69impl<const B: usize> TryFrom<i16> for BoundedSize<B> {
70 type Error = GeneralError;
71
72 fn try_from(value: i16) -> Result<Self, Self::Error> {
73 Self::try_from(value as isize)
74 }
75}
76
77impl<const B: usize> TryFrom<i32> for BoundedSize<B> {
78 type Error = GeneralError;
79
80 fn try_from(value: i32) -> Result<Self, Self::Error> {
81 Self::try_from(value as isize)
82 }
83}
84
85impl<const B: usize> TryFrom<i64> for BoundedSize<B> {
86 type Error = GeneralError;
87
88 fn try_from(value: i64) -> Result<Self, Self::Error> {
89 Self::try_from(value as isize)
90 }
91}
92
93impl<const B: usize> TryFrom<isize> for BoundedSize<B> {
94 type Error = GeneralError;
95
96 fn try_from(value: isize) -> Result<Self, Self::Error> {
97 if value >= 0 {
98 Self::try_from(value as usize)
99 } else {
100 Err(GeneralError::InvalidInput)
101 }
102 }
103}
104
105impl<const B: usize> Display for BoundedSize<B> {
106 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
107 write!(f, "{}", self.0)
108 }
109}
110
111impl<const B: usize> From<BoundedSize<B>> for u8 {
112 fn from(value: BoundedSize<B>) -> Self {
113 value.0 as u8
114 }
115}
116
117impl<const B: usize> From<BoundedSize<B>> for u16 {
118 fn from(value: BoundedSize<B>) -> Self {
119 value.0 as u16
120 }
121}
122
123impl<const B: usize> From<BoundedSize<B>> for u32 {
124 fn from(value: BoundedSize<B>) -> Self {
125 value.0 as u32
126 }
127}
128
129impl<const B: usize> From<BoundedSize<B>> for u64 {
130 fn from(value: BoundedSize<B>) -> Self {
131 value.0 as u64
132 }
133}
134
135impl<const B: usize> From<BoundedSize<B>> for usize {
136 fn from(value: BoundedSize<B>) -> Self {
137 value.0
138 }
139}
140
141#[derive(Debug, Clone, PartialEq, Eq, serde::Serialize, serde::Deserialize)]
144pub struct BoundedVec<T, const N: usize>(Vec<T>);
145
146impl<T, const N: usize> Default for BoundedVec<T, N> {
147 fn default() -> Self {
148 Self(vec![])
149 }
150}
151
152impl<T, const N: usize> TryFrom<Vec<T>> for BoundedVec<T, N> {
153 type Error = GeneralError;
154
155 fn try_from(value: Vec<T>) -> Result<Self, Self::Error> {
156 if value.len() <= N {
157 Ok(Self(value))
158 } else {
159 Err(GeneralError::InvalidInput)
160 }
161 }
162}
163
164impl<T, const N: usize> IntoIterator for BoundedVec<T, N> {
165 type IntoIter = std::vec::IntoIter<Self::Item>;
166 type Item = T;
167
168 fn into_iter(self) -> Self::IntoIter {
169 self.0.into_iter()
170 }
171}
172
173impl<T, const N: usize> FromIterator<T> for BoundedVec<T, N> {
174 fn from_iter<V: IntoIterator<Item = T>>(iter: V) -> Self {
175 Self(iter.into_iter().take(N).collect())
176 }
177}
178
179impl<T, const N: usize> From<[T; N]> for BoundedVec<T, N> {
180 fn from(value: [T; N]) -> Self {
181 Self(Vec::from(value))
182 }
183}
184
185impl<T, const N: usize> From<BoundedVec<T, N>> for Vec<T> {
186 fn from(value: BoundedVec<T, N>) -> Self {
187 value.0
188 }
189}
190
191impl<T, const N: usize> AsRef<[T]> for BoundedVec<T, N> {
192 fn as_ref(&self) -> &[T] {
193 &self.0
194 }
195}
196
197impl<T: Default + Copy, const N: usize> From<BoundedVec<T, N>> for [T; N] {
198 fn from(value: BoundedVec<T, N>) -> Self {
199 let mut out = [T::default(); N];
200 value.0.into_iter().enumerate().for_each(|(i, e)| out[i] = e);
201 out
202 }
203}
204
205#[cfg(test)]
206mod tests {
207 use crate::bounded::{BoundedSize, BoundedVec};
208
209 #[test]
210 fn bounded_size_should_not_allow_bigger_numbers() {
211 let min_bounded_size: usize = BoundedSize::<10>::MIN.into();
212 assert_eq!(0usize, min_bounded_size);
213 let max_bounded_size: usize = BoundedSize::<10>::MAX.into();
214 assert_eq!(10usize, max_bounded_size);
215
216 assert!(BoundedSize::<10>::try_from(5).is_ok_and(|b| u8::from(b) == 5));
217 assert!(BoundedSize::<10>::try_from(11).is_err());
218 }
219
220 #[test]
221 fn bounded_vec_should_not_fit_more_than_allowed() {
222 assert!(BoundedVec::<i32, 3>::try_from(vec![]).is_ok_and(|b| Vec::from(b).is_empty()));
223 assert!(BoundedVec::<i32, 3>::try_from(vec![1, 2]).is_ok_and(|b| Vec::from(b) == vec![1, 2]));
224 assert!(BoundedVec::<i32, 3>::try_from(vec![1, 2, 3]).is_ok_and(|b| Vec::from(b) == vec![1, 2, 3]));
225 assert!(BoundedVec::<i32, 3>::try_from(vec![1, 2, 3, 4]).is_err());
226
227 assert_eq!(
228 vec![1, 2, 3],
229 Vec::from(BoundedVec::<i32, 3>::from_iter(vec![1, 2, 3, 4]))
230 );
231 }
232}