From 1e9eb3cd2fb1d2edc05dae51a1dbdd1d9eba29c3 Mon Sep 17 00:00:00 2001 From: Andrei Avram <6795248+andreiavrammsd@users.noreply.github.com> Date: Sun, 18 May 2025 00:34:14 +0300 Subject: [PATCH] Test iterators --- README.md | 6 +++--- codecov.yml | 8 ++++++++ src/lib.rs | 59 +++++++++++++++++++++++++++++++++++++---------------- 3 files changed, 52 insertions(+), 21 deletions(-) create mode 100644 codecov.yml diff --git a/README.md b/README.md index 4cc24d9..759c854 100644 --- a/README.md +++ b/README.md @@ -6,7 +6,7 @@ A no-std, stack-allocated vector with fixed capacity and dynamic length. -`StaticVector` stores elements on the stack using a fixed-size array without heap allocations. +`StaticVector` stores elements on the stack using a fixed-size array without heap allocations. Aims to be suitable for low-level projects and to have an API as safe and explicit as possible. The goal is to allocate only when needed. When first constructed, the vector will not allocate. @@ -17,12 +17,12 @@ The goal is to allocate only when needed. When first constructed, the vector wil - No heap allocation (`#![no_std]` compatible) - Constant-time indexed access -- Supports iteration, mutable access, clearing, and appending +- Supports iteration, mutable access, clearing, resizing - Compile-time enforced capacity ## Requirements -- `T: Clone` for insertion (e.g., `push`, `append`) +- `T: Clone` for insertion: `push` - `T: Default` only if `set_len` is used - `CAPACITY > 0` diff --git a/codecov.yml b/codecov.yml new file mode 100644 index 0000000..36bbd8a --- /dev/null +++ b/codecov.yml @@ -0,0 +1,8 @@ +coverage: + status: + patch: + default: + threshold: 100 + project: + default: + threshold: 100 diff --git a/src/lib.rs b/src/lib.rs index 8094781..2ec4c7d 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,6 +1,6 @@ //! A no-std, stack-allocated vector with fixed capacity and dynamic length. //! -//! `StaticVector` stores elements on the stack using a fixed-size array without heap allocations. +//! [`StaticVector`] stores elements on the stack using a fixed-size array without heap allocations. //! //! Aims to be suitable for low-level projects and to have an API as safe and explicit as possible. //! The goal is to allocate only when needed. When first constructed, the vector will not allocate. @@ -10,12 +10,12 @@ //! # Features //! - No heap allocation (`#![no_std]` compatible) //! - Constant-time indexed access -//! - Supports iteration, mutable access, clearing, and appending +//! - Supports iteration, mutable access, clearing, resizing //! - Compile-time enforced capacity //! //! # Requirements -//! - `T: Clone` for insertion (e.g., `push`, `append`) -//! - `T: Default` only if `set_len` is used +//! - `T: Clone` for insertion: [`StaticVector::push()`] +//! - `T: Default` only if [`StaticVector::set_len()`] is used //! - `CAPACITY > 0` //! //! # Example @@ -29,10 +29,11 @@ //! ``` #![no_std] +#![deny(missing_docs)] -use core::{array, borrow::Borrow, mem::MaybeUninit}; +use core::{array, mem::MaybeUninit}; -/// Error type returned by `StaticVector`. +/// Error type returned by [`StaticVector`]. #[derive(Debug)] pub struct Error(pub &'static str); @@ -45,7 +46,7 @@ pub struct StaticVector { } impl Default for StaticVector { - /// Creates an empty `StaticVector`. Equivalent to `StaticVector::new()`. + /// Creates an empty [`StaticVector`]. Equivalent to [`StaticVector::new()`]. fn default() -> Self { Self::new() } @@ -54,7 +55,7 @@ impl Default for StaticVector { impl StaticVector { const ASSERT_CAPACITY: () = assert!(CAPACITY > 0); - /// Creates a new empty `StaticVector` with maximum `CAPACITY` elements of type `T`. + /// Creates a new empty [`StaticVector`] with maximum `CAPACITY` elements of type `T`. #[inline] pub fn new() -> Self { let () = Self::ASSERT_CAPACITY; @@ -84,7 +85,7 @@ impl StaticVector { /// /// # Errors /// - /// Returns [`Error`](`crate::Error`) if the vector is already at full capacity. + /// Returns [`Error`] if the vector is already at full capacity. pub fn push(&mut self, value: &T) -> Result<(), Error> { if self.length == CAPACITY { return Err(Error("capacity")); @@ -96,14 +97,6 @@ impl StaticVector { Ok(()) } - pub fn append(&mut self, iter: I) -> Result<(), Error> - where - I: IntoIterator, - I::Item: Borrow, - { - iter.into_iter().try_for_each(|value| self.push(value.borrow())) - } - /// Removes all elements. Size will be zero. pub fn clear(&mut self) { self.drop(0, self.length); @@ -119,7 +112,7 @@ impl StaticVector { /// /// # Errors /// - /// Returns [`Error`](`crate::Error`) if `new_length` exceeds the vector's fixed capacity. + /// Returns [`Error`] if `new_length` exceeds the vector's fixed capacity. pub fn set_len(&mut self, new_length: usize) -> Result<(), Error> where T: Default, @@ -170,11 +163,13 @@ impl StaticVector { } } + /// Returns an iterator over immutable references to the elements in the vector. #[inline(always)] pub fn iter(&self) -> StaticVectorIterator { StaticVectorIterator { data: &self.data, size: self.length, index: 0 } } + /// Returns an iterator over mutable references to the elements in the vector. #[inline(always)] pub fn iter_mut(&mut self) -> StaticVectorMutableIterator { StaticVectorMutableIterator { data: &mut self.data, size: self.length, index: 0 } @@ -195,6 +190,9 @@ impl Drop for StaticVector { } } +/// Immutable iterator over a [`StaticVector`]. +/// +/// Created by calling [`StaticVector::iter()`]. #[must_use = "must consume iterator"] pub struct StaticVectorIterator<'a, T> { data: &'a [MaybeUninit], @@ -216,6 +214,9 @@ impl<'a, T> Iterator for StaticVectorIterator<'a, T> { } } +/// Mutable iterator over a [`StaticVector`]. +/// +/// Created by calling [`StaticVector::iter_mut()`]. #[must_use = "must consume iterator"] pub struct StaticVectorMutableIterator<'a, T> { data: &'a mut [MaybeUninit], @@ -324,4 +325,26 @@ mod tests { assert_eq!(vec.get_mut(0).unwrap(), &5); assert!(vec.get_mut(3).is_none()); } + + #[test] + fn iter() { + let mut vec = StaticVector::::new(); + for i in 1..8 { + vec.push(&i).unwrap() + } + + let even_sum = vec.iter().filter(|v| *v % 2 == 0).sum::(); + assert_eq!(even_sum, 12); + } + + #[test] + fn iter_mut() { + let mut vec = StaticVector::::new(); + for i in 1..8 { + vec.push(&i).unwrap() + } + + let even_sum = vec.iter_mut().filter(|v| **v % 2 == 0).map(|v| *v).sum::(); + assert_eq!(even_sum, 12); + } }