Skip to content

Commit

Permalink
feat: add BoundedVec::map (#5250)
Browse files Browse the repository at this point in the history
# Description

This adds a `map` function to `BoundedMap`, which I've found to be a
relatively common need, and quite annoying to implement outside of the
stdlib as it requires raw access to the internals of the data structure.

## Documentation

Check one:
- [ ] No documentation needed.
- [x] Documentation included in this 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.
  • Loading branch information
nventuro authored Jun 14, 2024
1 parent c6b42ed commit da1549c
Show file tree
Hide file tree
Showing 2 changed files with 57 additions and 0 deletions.
12 changes: 12 additions & 0 deletions docs/docs/noir/standard_library/containers/boundedvec.md
Original file line number Diff line number Diff line change
Expand Up @@ -246,6 +246,18 @@ Example:
let bounded_vec: BoundedVec<Field, 10> = BoundedVec::from_array([1, 2, 3])
```

### map

```rust
pub fn map<U, Env>(self, f: fn[Env](T) -> U) -> BoundedVec<U, MaxLen>
```

Creates a new vector of equal size by calling a closure on each element in this vector.

Example:

#include_code bounded-vec-map-example noir_stdlib/src/collections/bounded_vec.nr rust

### any

```rust
Expand Down
45 changes: 45 additions & 0 deletions noir_stdlib/src/collections/bounded_vec.nr
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,17 @@ impl<T, MaxLen> BoundedVec<T, MaxLen> {
}
ret
}

pub fn map<U, Env>(self, f: fn[Env](T) -> U) -> BoundedVec<U, MaxLen> {
let mut ret = BoundedVec::new();
ret.len = self.len();
for i in 0..MaxLen {
if i < self.len() {
ret.storage[i] = f(self.get_unchecked(i));
}
}
ret
}
}

impl<T, MaxLen> Eq for BoundedVec<T, MaxLen> where T: Eq {
Expand Down Expand Up @@ -195,6 +206,40 @@ mod bounded_vec_tests {
}
}

mod map {
use crate::collections::bounded_vec::BoundedVec;

#[test]
fn applies_function_correctly() {
// docs:start:bounded-vec-map-example
let vec: BoundedVec<u32, 4> = BoundedVec::from_array([1, 2, 3, 4]);
let result = vec.map(|value| value * 2);
// docs:end:bounded-vec-map-example
let expected = BoundedVec::from_array([2, 4, 6, 8]);

assert_eq(result, expected);
}

#[test]
fn applies_function_that_changes_return_type() {
let vec: BoundedVec<u32, 4> = BoundedVec::from_array([1, 2, 3, 4]);
let result = vec.map(|value| (value * 2) as Field);
let expected: BoundedVec<Field, 4> = BoundedVec::from_array([2, 4, 6, 8]);

assert_eq(result, expected);
}

#[test]
fn does_not_apply_function_past_len() {
let vec: BoundedVec<u32, 3> = BoundedVec::from_array([0, 1]);
let result = vec.map(|value| if value == 0 { 5 } else { value });
let expected = BoundedVec::from_array([5, 1]);

assert_eq(result, expected);
assert_eq(result.storage()[2], 0);
}
}

mod from_array {
use crate::collections::bounded_vec::BoundedVec;

Expand Down

0 comments on commit da1549c

Please sign in to comment.