From ab4b2db4569e48745a4562d3a54b7e100691e327 Mon Sep 17 00:00:00 2001 From: Andrei Avram <6795248+andreiavrammsd@users.noreply.github.com> Date: Tue, 27 May 2025 09:49:05 +0300 Subject: [PATCH 1/5] Accept expr for capacity and length --- src/macros.rs | 39 +++++++++++++++++++++++++++++++++------ 1 file changed, 33 insertions(+), 6 deletions(-) diff --git a/src/macros.rs b/src/macros.rs index 6b2af3b..1185858 100644 --- a/src/macros.rs +++ b/src/macros.rs @@ -33,7 +33,7 @@ /// let vec = vec![u16; 8; 5]; // Vector with capacity 8, length set to 5, initialized with zeros /// ``` macro_rules! vec { - ($type:ty; $capacity:literal) => { + ($type:ty; $capacity:expr) => { $crate::Vec::<$type, $capacity>::new() }; @@ -45,7 +45,7 @@ macro_rules! vec { } }; - ($capacity:literal; $($value:expr),+ $(,)?) => { + ($capacity:expr; $($value:expr),+ $(,)?) => { { let mut vec = $crate::Vec::<_, $capacity>::new(); vec.extend_from_slice(&[$($value),+]).expect("length is less than or equal to capacity"); @@ -53,7 +53,7 @@ macro_rules! vec { } }; - ($type:ty; $capacity:literal; $length:literal) => { + ($type:ty; $capacity:expr; $length:expr) => { { let mut vec = $crate::Vec::<$type, $capacity>::new(); vec.set_len($length).expect("length is less than or equal to capacity"); @@ -65,12 +65,20 @@ macro_rules! vec { #[cfg(test)] mod tests { #[test] - fn vec_with_type_and_capacity() { + fn vec_with_type_and_capacity_literal() { let vec = vec![i32; 10]; assert_eq!(vec.capacity(), 10); assert!(vec.is_empty()); } + #[test] + fn vec_with_type_and_capacity_constant() { + const CAPACITY: usize = 10; + let vec = vec![i32; CAPACITY]; + assert_eq!(vec.capacity(), 10); + assert!(vec.is_empty()); + } + #[test] #[should_panic(expected = "CAPACITY must be greater than 0")] fn vec_with_type_and_capacity_zero() { @@ -94,13 +102,22 @@ mod tests { } #[test] - fn vec_with_capacity_and_elements() { + fn vec_with_capacity_literal_and_elements() { let vec = vec![10; 1, 2, 3]; assert_eq!(vec.capacity(), 10); assert_eq!(vec.len(), 3); assert_eq!(vec.as_slice(), &[1, 2, 3]); } + #[test] + fn vec_with_capacity_constants_and_elements() { + const CAPACITY: usize = 10; + let vec = vec![CAPACITY; 1, 2, 3]; + assert_eq!(vec.capacity(), 10); + assert_eq!(vec.len(), 3); + assert_eq!(vec.as_slice(), &[1, 2, 3]); + } + #[test] #[should_panic(expected = "length is less than or equal to capacity: CapacityError")] fn vec_with_more_elements_than_capacity() { @@ -108,13 +125,23 @@ mod tests { } #[test] - fn vec_with_capacity_and_length() { + fn vec_with_capacity_and_length_literals() { let vec = vec![i32; 10; 3]; assert_eq!(vec.capacity(), 10); assert_eq!(vec.len(), 3); assert_eq!(vec.as_slice(), &[0, 0, 0]); } + #[test] + fn vec_with_capacity_and_length_constants() { + const CAPACITY: usize = 10; + const LENGTH: usize = 3; + let vec = vec![i32; CAPACITY; LENGTH]; + assert_eq!(vec.capacity(), 10); + assert_eq!(vec.len(), 3); + assert_eq!(vec.as_slice(), &[0, 0, 0]); + } + #[test] fn vec_with_capacity_and_length_zero() { let vec = vec![i32; 10; 0]; From 2a58a718591edb8b00edc911d3a0c623308f4595 Mon Sep 17 00:00:00 2001 From: Andrei Avram <6795248+andreiavrammsd@users.noreply.github.com> Date: Tue, 27 May 2025 10:52:36 +0300 Subject: [PATCH 2/5] Add history example --- Makefile | 9 +++++-- examples/history.rs | 66 +++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 73 insertions(+), 2 deletions(-) create mode 100644 examples/history.rs diff --git a/Makefile b/Makefile index af734c8..f6fc594 100644 --- a/Makefile +++ b/Makefile @@ -1,8 +1,8 @@ .SILENT: -.PHONY: fuzz +.PHONY: fuzz examples # VS Code: Ctrl+Shift+B -all: test fmt lint build-doc +all: test fmt lint build-doc examples test: cargo test @@ -37,6 +37,11 @@ build-doc: fuzz: cargo +nightly fuzz run static_vector +examples: + for ex in $$(cargo metadata --format-version=1 --no-deps | jq -r '.packages[].targets[] | select(.kind[] == "example") | .name'); do \ + cargo run --example $$ex; \ + done + dev: echo Installing pre-commit hook... curl -1sLf 'https://dl.cloudsmith.io/public/evilmartians/lefthook/setup.deb.sh' | sudo -E bash diff --git a/examples/history.rs b/examples/history.rs new file mode 100644 index 0000000..b1f96e1 --- /dev/null +++ b/examples/history.rs @@ -0,0 +1,66 @@ +use static_vector::{Vec, vec}; + +#[derive(Debug, PartialEq, Clone, Copy)] +enum Event { + Start, + Load, + Run, + Pause, + Resume, + Stop, + Exit, +} + +struct EventHistory { + events: Vec, +} + +impl EventHistory { + const fn new() -> Self { + Self { events: vec![Event; N] } + } + + fn insert(&mut self, event: Event) { + if self.events.is_full() { + // Remove the oldest event (FIFO) + self.events.as_mut_slice().copy_within(1..N, 0); + + // Can ignore the error here since we are guaranteed to have at least one element + // because the vector is full. + let _ = self.events.pop(); + } + + // Can ignore the error here since we are guaranteed to have space after popping + // if the vector was full. + let _ = self.events.push(event); + } + + const fn get_events(&self) -> &[Event] { + self.events.as_slice() + } +} + +// Example of using static_vector to maintain a history of events +fn main() { + const HISTORY_SIZE: usize = 5; + let mut history = EventHistory::::new(); + + let events = [ + Event::Start, + Event::Load, + Event::Run, + Event::Pause, + Event::Resume, + Event::Stop, + Event::Exit, + ]; + for &event in &events { + history.insert(event); + } + + assert_eq!( + history.get_events(), + &[Event::Run, Event::Pause, Event::Resume, Event::Stop, Event::Exit], + "Expected history to contain the last 5 events" + ); +} From 386cbae873aeab47d721c22aea9cdfc4666b0385 Mon Sep 17 00:00:00 2001 From: Andrei Avram <6795248+andreiavrammsd@users.noreply.github.com> Date: Tue, 27 May 2025 10:54:54 +0300 Subject: [PATCH 3/5] Run examples in CI --- .github/workflows/ci.yml | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 530777e..444bc11 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -91,3 +91,20 @@ jobs: with: token: ${{ secrets.CODECOV_TOKEN }} files: lcov.info + + examples: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + + - uses: actions/cache@v4 + with: + path: | + ~/.cargo/registry + ~/.cargo/git + target + key: ${{ runner.os }}-cargo-${{ hashFiles('**/Cargo.toml') }} + + - uses: dtolnay/rust-toolchain@stable + + - run: make examples From 4da04fbb4d14b87c4260e457e3f2053e8aa7c961 Mon Sep 17 00:00:00 2001 From: Andrei Avram <6795248+andreiavrammsd@users.noreply.github.com> Date: Tue, 27 May 2025 11:00:16 +0300 Subject: [PATCH 4/5] Add jq to dev setup --- Makefile | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Makefile b/Makefile index f6fc594..e54e706 100644 --- a/Makefile +++ b/Makefile @@ -56,6 +56,9 @@ dev: echo Installing cargo-fuzz... cargo install cargo-fuzz + echo Installing jq... + sudo apt install jq -y + deny-commit-on-master: ifeq ($(shell git symbolic-ref --short HEAD),master) $(error Direct commits to 'master' are not allowed.) From a40f685f845b4f2af01040bbfb9417b47c5962e3 Mon Sep 17 00:00:00 2001 From: Andrei Avram <6795248+andreiavrammsd@users.noreply.github.com> Date: Tue, 27 May 2025 11:03:57 +0300 Subject: [PATCH 5/5] Use len instead of capacity --- examples/history.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/examples/history.rs b/examples/history.rs index b1f96e1..72324fd 100644 --- a/examples/history.rs +++ b/examples/history.rs @@ -23,7 +23,8 @@ impl EventHistory { fn insert(&mut self, event: Event) { if self.events.is_full() { // Remove the oldest event (FIFO) - self.events.as_mut_slice().copy_within(1..N, 0); + let len = self.events.len(); + self.events.as_mut_slice().copy_within(1..len, 0); // Can ignore the error here since we are guaranteed to have at least one element // because the vector is full.