Skip to main content

getargs_derive/
collection.rs

1use crate::__private::{Input, text};
2use crate::Error;
3use core::fmt;
4use core::hash::{Hash, Hasher};
5use core::mem::MaybeUninit;
6use core::ops::{Deref, DerefMut};
7
8/// A vector of at most `N` values stored inline, without allocation.
9///
10/// It is the collection type available without any feature: a field of type `Values<T, N>`
11/// collects the repeated values of an argument, and parsing fails with
12/// [`Error::TooManyValues`] when more than `N` values are given.
13/// It dereferences to a slice, so every slice method is available.
14///
15/// ```
16/// use getargs_derive::Values;
17///
18/// let mut values: Values<u8, 2> = Values::new();
19/// assert_eq!(values.push(1), Ok(()));
20/// assert_eq!(values.push(2), Ok(()));
21/// assert_eq!(values.push(3), Err(3));
22/// assert_eq!(values, [1, 2]);
23/// assert_eq!(values.iter().sum::<u8>(), 3);
24/// ```
25pub struct Values<T, const N: usize> {
26    items: [MaybeUninit<T>; N],
27    len: usize,
28}
29
30impl<T, const N: usize> Values<T, N> {
31    /// Creates an empty vector.
32    pub const fn new() -> Self {
33        Values {
34            items: [const { MaybeUninit::uninit() }; N],
35            len: 0,
36        }
37    }
38
39    /// The maximum number of values, `N`.
40    pub const fn capacity(&self) -> usize {
41        N
42    }
43
44    /// Appends a value, or gives it back when the vector already holds `N` values.
45    pub fn push(&mut self, value: T) -> Result<(), T> {
46        if self.len == N {
47            return Err(value);
48        }
49        self.items[self.len].write(value);
50        self.len += 1;
51        Ok(())
52    }
53
54    /// The values, in insertion order.
55    pub fn as_slice(&self) -> &[T] {
56        unsafe { core::slice::from_raw_parts(self.items.as_ptr().cast::<T>(), self.len) }
57    }
58
59    /// The values, in insertion order, mutably.
60    pub fn as_mut_slice(&mut self) -> &mut [T] {
61        unsafe { core::slice::from_raw_parts_mut(self.items.as_mut_ptr().cast::<T>(), self.len) }
62    }
63}
64
65impl<T, const N: usize> Drop for Values<T, N> {
66    fn drop(&mut self) {
67        unsafe { core::ptr::drop_in_place(self.as_mut_slice()) }
68    }
69}
70
71impl<T, const N: usize> Default for Values<T, N> {
72    fn default() -> Self {
73        Self::new()
74    }
75}
76
77impl<T, const N: usize> Deref for Values<T, N> {
78    type Target = [T];
79
80    fn deref(&self) -> &[T] {
81        self.as_slice()
82    }
83}
84
85impl<T, const N: usize> DerefMut for Values<T, N> {
86    fn deref_mut(&mut self) -> &mut [T] {
87        self.as_mut_slice()
88    }
89}
90
91impl<T: Clone, const N: usize> Clone for Values<T, N> {
92    fn clone(&self) -> Self {
93        let mut clone = Self::new();
94        for value in self.iter() {
95            let _ = clone.push(value.clone());
96        }
97        clone
98    }
99}
100
101impl<T: fmt::Debug, const N: usize> fmt::Debug for Values<T, N> {
102    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
103        f.debug_list().entries(self.iter()).finish()
104    }
105}
106
107impl<T: PartialEq<U>, U, const N: usize, const M: usize> PartialEq<Values<U, M>> for Values<T, N> {
108    fn eq(&self, other: &Values<U, M>) -> bool {
109        self.as_slice() == other.as_slice()
110    }
111}
112
113impl<T: Eq, const N: usize> Eq for Values<T, N> {}
114
115impl<T: PartialEq<U>, U, const N: usize> PartialEq<[U]> for Values<T, N> {
116    fn eq(&self, other: &[U]) -> bool {
117        self.as_slice() == other
118    }
119}
120
121impl<T: PartialEq<U>, U, const N: usize> PartialEq<&[U]> for Values<T, N> {
122    fn eq(&self, other: &&[U]) -> bool {
123        self.as_slice() == *other
124    }
125}
126
127impl<T: PartialEq<U>, U, const N: usize, const M: usize> PartialEq<[U; M]> for Values<T, N> {
128    fn eq(&self, other: &[U; M]) -> bool {
129        self.as_slice() == other
130    }
131}
132
133impl<T: Hash, const N: usize> Hash for Values<T, N> {
134    fn hash<H: Hasher>(&self, state: &mut H) {
135        self.as_slice().hash(state);
136    }
137}
138
139impl<'v, T, const N: usize> IntoIterator for &'v Values<T, N> {
140    type Item = &'v T;
141    type IntoIter = core::slice::Iter<'v, T>;
142
143    fn into_iter(self) -> Self::IntoIter {
144        self.iter()
145    }
146}
147
148impl<'v, T, const N: usize> IntoIterator for &'v mut Values<T, N> {
149    type Item = &'v mut T;
150    type IntoIter = core::slice::IterMut<'v, T>;
151
152    fn into_iter(self) -> Self::IntoIter {
153        self.iter_mut()
154    }
155}
156
157#[doc(hidden)]
158#[diagnostic::on_unimplemented(
159    message = "`{Self}` cannot collect repeated argument values",
160    label = "unsupported collection type",
161    note = "use `getargs_derive::Values<T, N>`, `heapless::Vec<T, N>` with the `heapless` feature of `getargs-derive`, or `Vec<T>` with its `alloc` feature"
162)]
163pub trait Collection: Sized {
164    type Item;
165
166    fn empty() -> Self;
167
168    fn count(&self) -> usize;
169
170    fn limit(&self) -> usize;
171
172    fn append(&mut self, item: Self::Item);
173}
174
175#[diagnostic::do_not_recommend]
176impl<T, const N: usize> Collection for Values<T, N> {
177    type Item = T;
178
179    fn empty() -> Self {
180        Self::new()
181    }
182
183    fn count(&self) -> usize {
184        self.len
185    }
186
187    fn limit(&self) -> usize {
188        N
189    }
190
191    fn append(&mut self, item: T) {
192        let _ = self.push(item);
193    }
194}
195
196#[cfg(feature = "heapless")]
197#[diagnostic::do_not_recommend]
198impl<T, const N: usize, L: heapless::LenType> Collection for heapless::Vec<T, N, L> {
199    type Item = T;
200
201    fn empty() -> Self {
202        Self::new()
203    }
204
205    fn count(&self) -> usize {
206        self.len()
207    }
208
209    fn limit(&self) -> usize {
210        self.capacity()
211    }
212
213    fn append(&mut self, item: T) {
214        let _ = self.push(item);
215    }
216}
217
218#[cfg(feature = "alloc")]
219#[diagnostic::do_not_recommend]
220impl<T> Collection for alloc::vec::Vec<T> {
221    type Item = T;
222
223    fn empty() -> Self {
224        Self::new()
225    }
226
227    fn count(&self) -> usize {
228        self.len()
229    }
230
231    fn limit(&self) -> usize {
232        usize::MAX
233    }
234
235    fn append(&mut self, item: T) {
236        self.push(item);
237    }
238}
239
240fn append<'a, V: Input<'a>, C: Collection>(
241    collection: &mut C,
242    value: V,
243    name: &'static str,
244    max: usize,
245    convert: &mut impl FnMut(V) -> Result<C::Item, Error<'a>>,
246) -> Result<(), Error<'a>> {
247    if collection.count() >= max {
248        return Err(Error::TooManyValues {
249            name,
250            value: text(value, name)?,
251            max,
252        });
253    }
254    let item = convert(value)?;
255    collection.append(item);
256    Ok(())
257}
258
259#[doc(hidden)]
260pub fn push_values<'a, V: Input<'a>, C: Collection>(
261    slot: &mut Option<C>,
262    value: V,
263    delimiter: Option<char>,
264    name: &'static str,
265    max: usize,
266    mut convert: impl FnMut(V) -> Result<C::Item, Error<'a>>,
267) -> Result<(), Error<'a>> {
268    let collection = slot.get_or_insert_with(C::empty);
269    let max = max.min(collection.limit());
270    let Some(delimiter) = delimiter else {
271        return append(collection, value, name, max, &mut convert);
272    };
273    let mut rest = value;
274    while let Some((piece, tail)) = rest.split_once(delimiter) {
275        append(collection, piece, name, max, &mut convert)?;
276        rest = tail;
277    }
278    append(collection, rest, name, max, &mut convert)
279}
280
281#[doc(hidden)]
282pub fn values_len<C: Collection>(slot: &Option<C>) -> usize {
283    slot.as_ref().map_or(0, C::count)
284}
285
286#[doc(hidden)]
287pub fn finish_values<'a, C: Collection>(
288    slot: Option<C>,
289    name: &'static str,
290    min: usize,
291) -> Result<C, Error<'a>> {
292    let collection = slot.unwrap_or_else(C::empty);
293    let actual = collection.count();
294    if actual >= min {
295        Ok(collection)
296    } else if actual == 0 {
297        Err(Error::MissingArgument(name))
298    } else {
299        Err(Error::TooFewValues { name, min, actual })
300    }
301}