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