From bf491dce9595d0e37057ae6d6721eb7a83cec0e2 Mon Sep 17 00:00:00 2001 From: Leonid Logvinov Date: Mon, 6 May 2024 17:52:51 +0200 Subject: [PATCH] feat: implement `From` array trait for `BoundedVec` (#4927) # Description ## Problem\* Implementing a concise, single-line method for converting arrays to BoundedVec would enhance usability. ## Summary\* This pull request implements the `From` trait to enable array-to-BoundedVec conversions, allowing for the following usage ```rust let vec = BoundedVec::from([1, 2, 3]); ``` instead of: ```rust let vec: BoundedVec = BoundedVec::new(); vec.extend_from_array([1, 2, 3]); ``` ## Additional Context ## Documentation\* Check one: - [x] No documentation needed. - [ ] Documentation included in this PR. - [ ] **[For Experimental Features]** Documentation to be submitted in a separate PR. # PR Checklist\* - [x] I have tested the changes locally. - [x] I have formatted the changes with [Prettier](https://prettier.io/) and/or `cargo fmt` on default settings. --------- Co-authored-by: Arkadiusz Konior --- .../standard_library/containers/boundedvec.md | 14 ++++ noir_stdlib/src/collections/bounded_vec.nr | 71 ++++++++++++++++++- 2 files changed, 84 insertions(+), 1 deletion(-) diff --git a/docs/docs/noir/standard_library/containers/boundedvec.md b/docs/docs/noir/standard_library/containers/boundedvec.md index cd0f725f870..ccce62562f8 100644 --- a/docs/docs/noir/standard_library/containers/boundedvec.md +++ b/docs/docs/noir/standard_library/containers/boundedvec.md @@ -196,6 +196,20 @@ Example: #include_code bounded-vec-extend-from-bounded-vec-example test_programs/noir_test_success/bounded_vec/src/main.nr rust +### from_array + +```rust +pub fn from_array(array: [T; Len]) -> Self +``` + +Creates a new vector, populating it with values derived from an array input. +The maximum length of the vector is determined based on the type signature. + +Example: +```rust +let bounded_vec: BoundedVec = BoundedVec::from_array([1, 2, 3]) +``` + ### any ```rust diff --git a/noir_stdlib/src/collections/bounded_vec.nr b/noir_stdlib/src/collections/bounded_vec.nr index c6a3365a979..65f3716dd34 100644 --- a/noir_stdlib/src/collections/bounded_vec.nr +++ b/noir_stdlib/src/collections/bounded_vec.nr @@ -1,4 +1,4 @@ -use crate::cmp::Eq; +use crate::{cmp::Eq, convert::From}; struct BoundedVec { storage: [T; MaxLen], @@ -74,6 +74,13 @@ impl BoundedVec { self.len = new_len; } + pub fn from_array(array: [T; Len]) -> Self { + assert(Len <= MaxLen, "from array out of bounds"); + let mut vec: BoundedVec = BoundedVec::new(); + vec.extend_from_array(array); + vec + } + pub fn pop(&mut self) -> T { assert(self.len > 0); self.len -= 1; @@ -107,6 +114,12 @@ impl Eq for BoundedVec where T: Eq { } } +impl From<[T; Len]> for BoundedVec { + fn from(array: [T; Len]) -> BoundedVec { + BoundedVec::from_array(array) + } +} + mod bounded_vec_tests { // TODO: Allow imports from "super" use crate::collections::bounded_vec::BoundedVec; @@ -128,4 +141,60 @@ mod bounded_vec_tests { assert(bounded_vec1 != bounded_vec2); } + + mod from_array { + use crate::collections::bounded_vec::BoundedVec; + + #[test] + fn empty() { + let empty_array: [Field; 0] = []; + let bounded_vec = BoundedVec::from_array([]); + + assert_eq(bounded_vec.max_len(), 0); + assert_eq(bounded_vec.len(), 0); + assert_eq(bounded_vec.storage(), empty_array); + } + + #[test] + fn equal_len() { + let array = [1, 2, 3]; + let bounded_vec = BoundedVec::from_array(array); + + assert_eq(bounded_vec.max_len(), 3); + assert_eq(bounded_vec.len(), 3); + assert_eq(bounded_vec.storage(), array); + } + + #[test] + fn max_len_greater_then_array_len() { + let array = [1, 2, 3]; + let bounded_vec: BoundedVec = BoundedVec::from_array(array); + + assert_eq(bounded_vec.max_len(), 10); + assert_eq(bounded_vec.len(), 3); + assert_eq(bounded_vec.storage()[0], 1); + assert_eq(bounded_vec.storage()[1], 2); + assert_eq(bounded_vec.storage()[2], 3); + } + + #[test(should_fail_with="from array out of bounds")] + fn max_len_lower_then_array_len() { + let _: BoundedVec = BoundedVec::from_array([0; 3]); + } + } + + mod trait_from { + use crate::collections::bounded_vec::BoundedVec; + + #[test] + fn simple() { + let array = [1, 2]; + let bounded_vec: BoundedVec = BoundedVec::from(array); + + assert_eq(bounded_vec.max_len(), 10); + assert_eq(bounded_vec.len(), 2); + assert_eq(bounded_vec.storage()[0], 1); + assert_eq(bounded_vec.storage()[1], 2); + } + } }