radicle_protocol/
bounded.rs1use std::{
2 collections::BTreeSet,
3 ops::{self, RangeBounds},
4};
5
6#[derive(thiserror::Error, Debug)]
7pub enum Error {
8 #[error("invalid size: expected {expected}, got {actual}")]
9 InvalidSize { expected: usize, actual: usize },
10}
11
12#[derive(Default, Clone, PartialEq, Eq)]
14pub struct BoundedVec<T, const N: usize> {
15 v: Vec<T>,
16}
17
18impl<T, const N: usize> BoundedVec<T, N> {
19 pub fn new() -> Self {
21 BoundedVec {
22 v: Vec::with_capacity(N),
23 }
24 }
25
26 pub fn collect_from<I: IntoIterator<Item = T>>(iter: I) -> Self {
40 BoundedVec {
41 v: iter.into_iter().take(N).collect(),
42 }
43 }
44
45 pub fn truncate(mut v: Vec<T>) -> Self {
58 v.truncate(N);
59 BoundedVec { v }
60 }
61
62 #[inline]
80 pub fn with_capacity(capacity: usize) -> Result<Self, Error> {
81 if capacity > N {
82 return Err(Error::InvalidSize {
83 expected: N,
84 actual: capacity,
85 });
86 }
87 Ok(Self {
88 v: Vec::with_capacity(capacity),
89 })
90 }
91
92 #[inline]
103 pub fn max() -> usize {
104 N
105 }
106
107 #[inline]
109 pub fn as_slice(&self) -> &[T] {
110 self.v.as_slice()
111 }
112
113 pub fn capacity(&self) -> usize {
115 self.v.capacity()
116 }
117
118 #[inline]
134 pub fn push(&mut self, item: T) -> Result<(), Error> {
135 if self.len() >= N {
136 return Err(Error::InvalidSize {
137 expected: N,
138 actual: N + 1,
139 });
140 }
141 self.v.push(item);
142 Ok(())
143 }
144
145 pub fn unbound(self) -> Vec<T> {
159 self.v
160 }
161
162 pub fn drain<R: RangeBounds<usize>>(&mut self, range: R) -> std::vec::Drain<T> {
164 self.v.drain(range)
165 }
166}
167
168impl<T: Clone, const N: usize> BoundedVec<T, N> {
169 pub fn extend_from_slice(&mut self, slice: &[T]) -> Result<(), Error> {
171 if self.len() + slice.len() > N {
172 return Err(Error::InvalidSize {
173 expected: N,
174 actual: self.len() + slice.len(),
175 });
176 }
177 self.v.extend_from_slice(slice);
178
179 Ok(())
180 }
181}
182
183impl<T, const N: usize> ops::Deref for BoundedVec<T, N> {
184 type Target = [T];
185
186 fn deref(&self) -> &Self::Target {
187 self.v.as_slice()
188 }
189}
190
191impl<T, const N: usize> From<Option<T>> for BoundedVec<T, N> {
192 fn from(value: Option<T>) -> Self {
193 let v = match value {
194 None => vec![],
195 Some(v) => vec![v],
196 };
197 BoundedVec { v }
198 }
199}
200
201impl<T, const N: usize> TryFrom<Vec<T>> for BoundedVec<T, N> {
202 type Error = Error;
203
204 fn try_from(value: Vec<T>) -> Result<Self, Self::Error> {
205 if value.len() > N {
206 return Err(Error::InvalidSize {
207 expected: N,
208 actual: value.len(),
209 });
210 }
211 Ok(BoundedVec { v: value })
212 }
213}
214
215impl<T, const N: usize> TryFrom<BTreeSet<T>> for BoundedVec<T, N> {
216 type Error = Error;
217
218 fn try_from(value: BTreeSet<T>) -> Result<Self, Self::Error> {
219 if value.len() > N {
220 return Err(Error::InvalidSize {
221 expected: N,
222 actual: value.len(),
223 });
224 }
225 Ok(BoundedVec {
226 v: value.into_iter().collect(),
227 })
228 }
229}
230
231impl<T, const N: usize> From<BoundedVec<T, N>> for Vec<T> {
232 fn from(value: BoundedVec<T, N>) -> Self {
233 value.v
234 }
235}
236
237impl<T: std::fmt::Debug, const N: usize> std::fmt::Debug for BoundedVec<T, N> {
238 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
239 self.v.fmt(f)
240 }
241}
242
243unsafe impl<const N: usize> bytes::BufMut for BoundedVec<u8, N> {
244 fn remaining_mut(&self) -> usize {
245 N - self.v.len()
246 }
247
248 unsafe fn advance_mut(&mut self, cnt: usize) {
249 let len = {
250 let len = self.v.len();
251 let remaining = N - len;
252
253 if remaining >= cnt {
254 len + cnt
255 } else {
256 panic!("advance out of bounds: have {remaining} remaining, but advancing by {cnt}",);
257 }
258 };
259
260 debug_assert!(len <= N);
261
262 self.v.set_len(len);
264 }
265
266 fn chunk_mut(&mut self) -> &mut bytes::buf::UninitSlice {
267 let len = self.v.len();
268
269 if self.v.capacity() == len {
271 self.v.reserve(std::cmp::min(len, N - len));
272 }
273
274 let cap = self.v.capacity();
275
276 debug_assert!(cap <= N);
277 debug_assert!(len <= cap);
278
279 let ptr = self.v.as_mut_ptr();
280
281 unsafe { bytes::buf::UninitSlice::from_raw_parts_mut(ptr.add(len), cap - len) }
285 }
286}
287
288#[cfg(any(test, feature = "test"))]
289impl<T, const N: usize> qcheck::Arbitrary for BoundedVec<T, N>
290where
291 T: qcheck::Arbitrary + Eq,
292{
293 fn arbitrary(g: &mut qcheck::Gen) -> Self {
294 let mut v: Vec<T> = qcheck::Arbitrary::arbitrary(g);
295 v.truncate(N);
296 v.try_into().expect("size within bounds")
297 }
298}