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