Skip to content

Commit

Permalink
feat: implement Eq trait on BoundedVec (#4830)
Browse files Browse the repository at this point in the history
# Description

## Problem\*

Resolves #4827 

## Summary\*

We're currently not implementing the `Eq` trait on `BoundedVec`, which
is added in this PR.

I've opted for ignoring differences in the storage array past `len` as
while it's not possible to have non-zeroed entries past this index if
you use the proper interface, it's possible to construct `BoundedVec`s
for which this is not the case. Once we allow proper encapsulation of
the internal state then we could simply check that the underlying
storage is equal.

## 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: jfecher <jake@aztecprotocol.com>
  • Loading branch information
TomAFrench and jfecher committed Apr 17, 2024
1 parent 5f02129 commit 6cefe16
Showing 1 changed file with 61 additions and 0 deletions.
61 changes: 61 additions & 0 deletions noir_stdlib/src/collections/bounded_vec.nr
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
use crate::cmp::Eq;

struct BoundedVec<T, MaxLen> {
storage: [T; MaxLen],
len: u64,
Expand Down Expand Up @@ -93,3 +95,62 @@ impl<T, MaxLen> BoundedVec<T, MaxLen> {
ret
}
}

impl<T, MaxLen> Eq for BoundedVec<T, MaxLen> where T: Eq {
fn eq(self, other: BoundedVec<T, MaxLen>) -> bool {
let mut ret = self.len == other.len;
let mut exceeded_len = false;
for i in 0..MaxLen {
exceeded_len |= i == self.len;
if !exceeded_len {
ret &= self.storage[i] == other.storage[i];
}
}
ret
}
}

mod bounded_vec_tests {
// TODO: Allow imports from "super"
use crate::collections::bounded_vec::BoundedVec;

#[test]
fn empty_equality() {
let mut bounded_vec1: BoundedVec<Field, 3> = BoundedVec::new();
let mut bounded_vec2: BoundedVec<Field, 3> = BoundedVec::new();

assert_eq(bounded_vec1, bounded_vec2);
}

#[test]
fn inequality() {
let mut bounded_vec1: BoundedVec<Field, 3> = BoundedVec::new();
let mut bounded_vec2: BoundedVec<Field, 3> = BoundedVec::new();
bounded_vec1.push(1);
bounded_vec2.push(2);

assert(bounded_vec1 != bounded_vec2);
}

#[test]
fn equality_respects_specified_length() {
let mut bounded_vec1: BoundedVec<Field, 3> = BoundedVec::new();
bounded_vec1.push(1);

// This BoundedVec has an extra value past the end of its specified length,
// this should be ignored when checking equality so they are considered equal.
let mut bounded_vec2: BoundedVec<Field, 3> = BoundedVec { storage: [1, 2, 0], len: 1 };

assert_eq(bounded_vec1, bounded_vec2);

// Pushing another entry onto `bounded_vec1` to make the underlying arrays equal should
// result in the `BoundedVec`s being unequal as their lengths are different.
bounded_vec1.push(2);

assert(bounded_vec1 != bounded_vec2);

bounded_vec2.push(2);

assert_eq(bounded_vec1, bounded_vec2);
}
}

0 comments on commit 6cefe16

Please sign in to comment.