copy_stack_vec/vec/array/
extend.rs

1// This file is part of copy-stack-vec.
2// SPDX-License-Identifier: MIT OR Apache-2.0
3
4// Crate imports
5use crate::{error::Error, vec::CopyStackVec};
6
7impl<T: Copy, const N: usize> Extend<T> for CopyStackVec<T, N> {
8    fn extend<I: IntoIterator<Item = T>>(&mut self, iter: I) {
9        let remaining = N - self.len;
10        if remaining == 0 {
11            return;
12        }
13
14        for item in iter.into_iter().take(remaining) {
15            self.buf[self.len] = item;
16            self.len += 1;
17        }
18    }
19}
20
21impl<T: Copy, const N: usize> CopyStackVec<T, N> {
22    /// Extends from `src` if it fits; otherwise no-op and returns [`Error::Full`].
23    #[inline]
24    pub fn extend_from_slice(&mut self, src: &[T]) -> Result<(), Error> {
25        let avail = N - self.len;
26        if src.len() > avail {
27            return Err(Error::Full);
28        }
29        let len = self.len;
30        self.buf[len..len + src.len()].copy_from_slice(src);
31        self.len = len + src.len();
32        Ok(())
33    }
34
35    /// Copies as many elements from `src` as will fit and returns the count copied.
36    #[inline]
37    #[must_use]
38    pub fn extend_from_slice_truncated(&mut self, src: &[T]) -> usize {
39        let len = self.len;
40        let avail = N - len;
41        let take = avail.min(src.len());
42        self.buf[len..len + take].copy_from_slice(&src[..take]);
43        self.len = len + take;
44        take
45    }
46}
47
48impl<T: Copy + Default, const N: usize> CopyStackVec<T, N> {
49    /// Tries to extend `self` from an iterator **without truncation**.
50    ///
51    /// Semantics:
52    /// - All-or-nothing:
53    ///   - If the iterator yields at most `spare_capacity()` items, they are
54    ///     appended in order and `Ok(())` is returned.
55    ///   - If it yields more than `spare_capacity()`, this returns `Err(Error::Full)`
56    ///     and `self` is left unchanged.
57    /// - The source iterator may be partially consumed on error; no elements
58    ///   are written into `self` unless the whole extend succeeds.
59    #[inline]
60    pub fn try_extend_from_iter<I: IntoIterator<Item = T>>(
61        &mut self,
62        iter: I,
63    ) -> Result<(), Error> {
64        let spare = N - self.len;
65
66        // Temporary buffer to ensure `self` is unchanged on error.
67        let mut tmp: CopyStackVec<T, N> = CopyStackVec::default();
68        for item in iter {
69            if tmp.len() == spare {
70                return Err(Error::Full);
71            }
72            // tmp.len() < spare <= N so this cannot overflow tmp; but if it ever
73            // did, we just propagate the error instead of panicking.
74            tmp.push(item)?;
75        }
76
77        // Now we know everything fits into `self`.
78        self.extend_from_slice(tmp.as_slice())
79    }
80}