Skip to content

Commit

Permalink
feat: implement From array trait for BoundedVec (#4927)
Browse files Browse the repository at this point in the history
# 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<Field, 3> = 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 <akonior@gmail.com>
  • Loading branch information
LogvinovLeon and akonior authored May 6, 2024
1 parent 2da2899 commit bf491dc
Show file tree
Hide file tree
Showing 2 changed files with 84 additions and 1 deletion.
14 changes: 14 additions & 0 deletions docs/docs/noir/standard_library/containers/boundedvec.md
Original file line number Diff line number Diff line change
Expand Up @@ -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<Len>(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<Field, 10> = BoundedVec::from_array([1, 2, 3])
```

### any

```rust
Expand Down
71 changes: 70 additions & 1 deletion noir_stdlib/src/collections/bounded_vec.nr
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use crate::cmp::Eq;
use crate::{cmp::Eq, convert::From};

struct BoundedVec<T, MaxLen> {
storage: [T; MaxLen],
Expand Down Expand Up @@ -74,6 +74,13 @@ impl<T, MaxLen> BoundedVec<T, MaxLen> {
self.len = new_len;
}

pub fn from_array<Len>(array: [T; Len]) -> Self {
assert(Len <= MaxLen, "from array out of bounds");
let mut vec: BoundedVec<T, MaxLen> = BoundedVec::new();
vec.extend_from_array(array);
vec
}

pub fn pop(&mut self) -> T {
assert(self.len > 0);
self.len -= 1;
Expand Down Expand Up @@ -107,6 +114,12 @@ impl<T, MaxLen> Eq for BoundedVec<T, MaxLen> where T: Eq {
}
}

impl<T, MaxLen, Len> From<[T; Len]> for BoundedVec<T, MaxLen> {
fn from(array: [T; Len]) -> BoundedVec<T, MaxLen> {
BoundedVec::from_array(array)
}
}

mod bounded_vec_tests {
// TODO: Allow imports from "super"
use crate::collections::bounded_vec::BoundedVec;
Expand All @@ -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<Field, 10> = 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<Field, 2> = 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<Field, 10> = 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);
}
}
}

0 comments on commit bf491dc

Please sign in to comment.