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> IntoIterator for BoundedVec<T, N> {
184 type Item = T;
185 type IntoIter = std::vec::IntoIter<T>;
186
187 fn into_iter(self) -> Self::IntoIter {
188 self.v.into_iter()
189 }
190}
191
192impl<T, const N: usize> ops::Deref for BoundedVec<T, N> {
193 type Target = [T];
194
195 fn deref(&self) -> &Self::Target {
196 self.v.as_slice()
197 }
198}
199
200impl<T, const N: usize> From<Option<T>> for BoundedVec<T, N> {
201 fn from(value: Option<T>) -> Self {
202 let v = match value {
203 None => vec![],
204 Some(v) => vec![v],
205 };
206 BoundedVec { v }
207 }
208}
209
210impl<T, const N: usize> TryFrom<Vec<T>> for BoundedVec<T, N> {
211 type Error = Error;
212
213 fn try_from(value: Vec<T>) -> Result<Self, Self::Error> {
214 if value.len() > N {
215 return Err(Error::InvalidSize {
216 expected: N,
217 actual: value.len(),
218 });
219 }
220 Ok(BoundedVec { v: value })
221 }
222}
223
224impl<T, const N: usize> TryFrom<BTreeSet<T>> for BoundedVec<T, N> {
225 type Error = Error;
226
227 fn try_from(value: BTreeSet<T>) -> Result<Self, Self::Error> {
228 if value.len() > N {
229 return Err(Error::InvalidSize {
230 expected: N,
231 actual: value.len(),
232 });
233 }
234 Ok(BoundedVec {
235 v: value.into_iter().collect(),
236 })
237 }
238}
239
240impl<T, const N: usize> From<BoundedVec<T, N>> for Vec<T> {
241 fn from(value: BoundedVec<T, N>) -> Self {
242 value.v
243 }
244}
245
246impl<T: std::fmt::Debug, const N: usize> std::fmt::Debug for BoundedVec<T, N> {
247 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
248 self.v.fmt(f)
249 }
250}
251
252unsafe impl<const N: usize> bytes::BufMut for BoundedVec<u8, N> {
253 fn remaining_mut(&self) -> usize {
254 N - self.v.len()
255 }
256
257 unsafe fn advance_mut(&mut self, cnt: usize) {
258 let len = {
259 let len = self.v.len();
260 let remaining = N - len;
261
262 if remaining >= cnt {
263 len + cnt
264 } else {
265 panic!("advance out of bounds: have {remaining} remaining, but advancing by {cnt}",);
266 }
267 };
268
269 debug_assert!(len <= N);
270
271 self.v.set_len(len);
273 }
274
275 fn chunk_mut(&mut self) -> &mut bytes::buf::UninitSlice {
276 let len = self.v.len();
277
278 if self.v.capacity() == len {
280 self.v.reserve(std::cmp::min(len, N - len));
281 }
282
283 let cap = self.v.capacity();
284
285 debug_assert!(cap <= N);
286 debug_assert!(len <= cap);
287
288 let ptr = self.v.as_mut_ptr();
289
290 unsafe { bytes::buf::UninitSlice::from_raw_parts_mut(ptr.add(len), cap - len) }
294 }
295}
296
297#[cfg(any(test, feature = "test"))]
298impl<T, const N: usize> qcheck::Arbitrary for BoundedVec<T, N>
299where
300 T: qcheck::Arbitrary + Eq,
301{
302 fn arbitrary(g: &mut qcheck::Gen) -> Self {
303 let mut v: Vec<T> = qcheck::Arbitrary::arbitrary(g);
304 v.truncate(N);
305 v.try_into().expect("size within bounds")
306 }
307}