Skip to content

Commit

Permalink
changed macros to funs
Browse files Browse the repository at this point in the history
  • Loading branch information
damirka committed Jul 26, 2024
1 parent ec17d52 commit 1f6f169
Show file tree
Hide file tree
Showing 2 changed files with 100 additions and 108 deletions.
89 changes: 41 additions & 48 deletions crates/sui-framework/packages/move-stdlib/sources/vector.move
Original file line number Diff line number Diff line change
Expand Up @@ -158,6 +158,40 @@ module std::vector {
v.pop_back()
}

/// Take all elements of the vector `v` except the first `n` elements. Aborts if `n` is greater
/// than the length of `v`. Modifies the original vector.
public fun skip_mut<T>(v: &mut vector<T>, n: u64): vector<T> {
assert!(n <= v.length());
let mut r = vector[];
let i = v.length() - n;
i.do!(|_| r.push_back(v.pop_back()));
r.reverse();
r
}

/// Return a new vector containing the elements of `v` in the range `[start, end)`.
/// Take all elements of the vector `v` except the first `n` elements and drop the vector.
public fun skip<T: drop>(mut v: vector<T>, n: u64): vector<T> {
v.skip_mut(n)
}

/// Take the first `n` elements of the vector `v`. Aborts if `n` is greater than the length of `v`.
/// Modifies the original vector.
public fun take_mut<T>(v: &mut vector<T>, n: u64): vector<T> {
assert!(n <= v.length());
v.reverse();
let mut r = vector[];
n.do!(|_| r.push_back(v.pop_back()));
v.reverse();
r
}

/// Take the first `n` elements of the vector `v` and drop the rest. Aborts if `n` is greater
/// than the length of `v`. Destroys the original vector after taking the elements.
public fun take<T: drop>(mut v: vector<T>, n: u64): vector<T> {
v.take_mut(n)
}

// === Macros ===

/// Create a vector of length `n` by calling the function `f` on each index.
Expand Down Expand Up @@ -372,22 +406,9 @@ module std::vector {
r
}

/// Take the first `n` elements of the vector `v`. Aborts if `n` is greater than the length of `v`.
/// Modifies the original vector.
public macro fun take<$T>($v: &mut vector<$T>, $n: u64): vector<$T> {
let n = $n;
let v = $v;
assert!(n <= v.length());
v.reverse();
let mut r = vector[];
n.do!(|_| r.push_back(v.pop_back()));
v.reverse();
r
}

/// Takes the first `n` elements of the vector `v` that satisfy the predicate `p`.
/// Modifies the original vector.
public macro fun take_while<$T>($v: &mut vector<$T>, $p: |&$T| -> bool): vector<$T> {
public macro fun take_mut_while<$T>($v: &mut vector<$T>, $p: |&$T| -> bool): vector<$T> {
let v = $v;
let mut r = vector[];
v.reverse();
Expand All @@ -398,53 +419,25 @@ module std::vector {
r
}

/// Take the first `n` elements of the vector `v` and drop the rest. Aborts if `n` is greater
/// than the length of `v`. Destroys the original vector after taking the elements.
public macro fun take_and_drop<$T: drop>($v: vector<$T>, $n: u64): vector<$T> {
let mut v = $v;
take!(&mut v, $n)
}

/// Takes the first `n` elements of the vector `v` that satisfy the predicate `p` and drops the rest.
/// Destroys the original vector after taking the elements.
public macro fun take_while_and_drop<$T: drop>($v: vector<$T>, $p: |&$T| -> bool): vector<$T> {
public macro fun take_while<$T: drop>($v: vector<$T>, $p: |&$T| -> bool): vector<$T> {
let mut v = $v;
take_while!(&mut v, $p)
}

/// Take all elements of the vector `v` except the first `n` elements. Aborts if `n` is greater
/// than the length of `v`. Modifies the original vector.
///
/// TODO: do we want assert here?
public macro fun skip<$T>($v: &mut vector<$T>, $n: u64): vector<$T> {
let n = $n;
let v = $v;
assert!(n <= v.length());
let mut r = vector[];
let i = v.length() - n;
i.do!(|_| r.push_back(v.pop_back()));
r.reverse();
r
take_mut_while!(&mut v, $p)
}

/// Take all elements of the vector `v` except the first `n` elements that satisfy the predicate `p`.
/// Modifies the original vector.
public macro fun skip_while<$T>($v: &mut vector<$T>, $p: |&$T| -> bool): vector<$T> {
public macro fun skip_mut_while<$T>($v: &mut vector<$T>, $p: |&$T| -> bool): vector<$T> {
let v = $v;
// find first element that does not satisfy the predicate, then skip from there
v.find_index!(|e| !$p(e)).map!(|c| v.skip!(c)).destroy_or!(vector[])
}

/// Take all elements of the vector `v` except the first `n` elements and drop the vector.
public macro fun skip_and_drop<$T: drop>($v: vector<$T>, $n: u64): vector<$T> {
let mut v = $v;
skip!(&mut v, $n)
v.find_index!(|e| !$p(e)).map!(|c| v.skip_mut(c)).destroy_or!(vector[])
}

/// Take all elements of the vector `v` except the first `n` elements that satisfy the predicate `p`
/// and drop the vector.
public macro fun skip_while_and_drop<$T: drop>($v: vector<$T>, $p: |&$T| -> bool): vector<$T> {
public macro fun skip_while<$T: drop>($v: vector<$T>, $p: |&$T| -> bool): vector<$T> {
let mut v = $v;
skip_while!(&mut v, $p)
skip_mut_while!(&mut v, $p)
}
}
119 changes: 59 additions & 60 deletions crates/sui-framework/packages/move-stdlib/tests/vector_tests.move
Original file line number Diff line number Diff line change
Expand Up @@ -581,6 +581,49 @@ module std::vector_tests {
assert!(b"hello_world".try_to_ascii_string().is_some());
}

#[test, expected_failure]
fun take_mut_fail() {
let mut v = vector[1u64, 2, 3, 4, 5];
v.take_mut(6);
}

#[test]
fun take_mut() {
let mut v = vector[1u64, 2, 3, 4, 5];
assert!(v.take_mut(0) == vector[]);
assert!(v.take_mut(3) == vector[1, 2, 3]); // vec length is now 2
assert!(v == vector[4, 5]);
assert!(v.take_mut(1) == vector[4]);
assert!(v == vector[5]);
assert!(v.take_mut(1) == vector[5]);
assert!(v.length() == 0);
}

#[test]
fun take() {
assert!(vector[1, 2, 3, 4, 5].take(2) == vector[1, 2]);
assert!(vector[1, 2, 3, 4, 5].take(0) == vector[]);
}

#[test]
fun skip_mut() {
let mut v = vector[1u64, 2, 3, 4, 5];
assert!(v.skip_mut(4) == vector[5]);
assert!(v == vector[1, 2, 3, 4]);
assert!(v.skip_mut(2) == vector[3, 4]);
assert!(v == vector[1, 2]);
assert!(v.skip_mut(2) == vector[]);
assert!(v == vector[1, 2]);
assert!(v.skip_mut(0) == vector[1, 2]);
}

#[test]
fun skip() {
assert!(vector[1, 2, 3, 4, 5].skip(2) == vector[3, 4, 5]);
assert!(vector[1, 2, 3, 4, 5].skip(0) == vector[1, 2, 3, 4, 5]);
assert!(vector[1, 2, 3, 4, 5].skip(5) == vector[]);
}

// === Macros ===

#[test]
Expand Down Expand Up @@ -795,80 +838,36 @@ module std::vector_tests {
assert!(v.find_indices!(|e| *e == 1) == vector[0, 4]);
}

#[test, expected_failure]
fun take_macro_fail() {
let mut v = vector[1u64, 2, 3, 4, 5];
v.take!(6);
}

#[test]
fun take_macro() {
let mut v = vector[1u64, 2, 3, 4, 5];
assert!(v.take!(0) == vector[]);
assert!(v.take!(3) == vector[1, 2, 3]); // vec length is now 2
assert!(v == vector[4, 5]);
assert!(v.take!(1) == vector[4]);
assert!(v == vector[5]);
assert!(v.take!(1) == vector[5]);
assert!(v.length() == 0);
}

#[test]
fun take_while_macro() {
fun take_mut_while_macro() {
let mut v = vector[1, 1, 1, 2, 2, 2, 3, 3, 3];
assert!(v.take_while!(|e| *e == 1) == vector[1, 1, 1]);
assert!(v.take_mut_while!(|e| *e == 1) == vector[1, 1, 1]);
assert!(v == vector[2, 2, 2, 3, 3, 3]);
assert!(v.take_while!(|e| *e == 2) == vector[2, 2, 2]);
assert!(v.take_mut_while!(|e| *e == 2) == vector[2, 2, 2]);
assert!(v == vector[3, 3, 3]);
assert!(v.take_while!(|e| *e == 3) == vector[3, 3, 3]);
assert!(v.take_mut_while!(|e| *e == 3) == vector[3, 3, 3]);
assert!(v.length() == 0);
}

#[test]
fun take_and_drop() {
assert!(vector[1, 2, 3, 4, 5].take_and_drop!(2) == vector[1, 2]);
assert!(vector[1, 2, 3, 4, 5].take_and_drop!(0) == vector[]);
}

#[test]
fun take_while_and_drop() {
assert!(vector[1, 1, 1, 2, 2, 2, 3, 3, 3].take_while_and_drop!(|e| *e == 1) == vector[1, 1, 1]);
assert!(vector[1, 1, 1, 2, 2, 2, 3, 3, 3].take_while_and_drop!(|e| *e == 2) == vector[2, 2, 2]);
assert!(vector[1, 1, 1, 2, 2, 2, 3, 3, 3].take_while_and_drop!(|e| *e == 3) == vector[3, 3, 3]);
}

#[test]
fun skip_macro() {
let mut v = vector[1u64, 2, 3, 4, 5];
assert!(v.skip!(4) == vector[5]);
assert!(v == vector[1, 2, 3, 4]);
assert!(v.skip!(2) == vector[3, 4]);
assert!(v == vector[1, 2]);
assert!(v.skip!(2) == vector[]);
assert!(v == vector[1, 2]);
assert!(v.skip!(0) == vector[1, 2]);

fun take_while_macro() {
assert!(vector[1, 1, 1, 2, 2, 2, 3, 3, 3].take_while!(|e| *e == 1) == vector[1, 1, 1]);
assert!(vector[1, 1, 1, 2, 2, 2, 3, 3, 3].take_while!(|e| *e == 2) == vector[]);
assert!(vector[1, 1, 1, 2, 2, 2, 3, 3, 3].take_while!(|e| *e == 3) == vector[]);
}

#[test]
fun skip_while_macro() {
fun skip_mut_while_macro() {
let mut v = vector[1, 1, 1, 2, 2, 2, 3, 3, 3];
assert!(v.skip_while!(|e| *e == 1) == vector[2, 2, 2, 3, 3, 3]);
assert!(v.skip_while!(|e| *e == 2) == vector[3, 3, 3]);
assert!(v.skip_while!(|e| *e == 3) == vector[]);
}

#[test]
fun skip_and_drop() {
assert!(vector[1, 2, 3, 4, 5].skip_and_drop!(2) == vector[3, 4, 5]);
assert!(vector[1, 2, 3, 4, 5].skip_and_drop!(0) == vector[1, 2, 3, 4, 5]);
assert!(vector[1, 2, 3, 4, 5].skip_and_drop!(5) == vector[]);
assert!(v.skip_mut_while!(|e| *e == 1) == vector[2, 2, 2, 3, 3, 3]);
assert!(v.skip_mut_while!(|e| *e == 2) == vector[1, 1, 1]);
assert!(v.skip_mut_while!(|e| *e == 3) == vector[]); // v = vector[]
}

#[test]
fun skip_while_and_drop() {
assert!(vector[1, 1, 1, 2, 2, 2, 3, 3, 3].skip_while_and_drop!(|e| *e == 1) == vector[2, 2, 2, 3, 3, 3]);
assert!(vector[1, 1, 1, 2, 2, 2, 3, 3, 3].skip_while_and_drop!(|e| *e == 2) == vector[3, 3, 3]);
assert!(vector[1, 1, 1, 2, 2, 2, 3, 3, 3].skip_while_and_drop!(|e| *e == 3) == vector[]);
fun skip_while_macro() {
assert!(vector[1, 1, 1, 2, 2, 2, 3, 3, 3].skip_while!(|e| *e == 1) == vector[2, 2, 2, 3, 3, 3]);
assert!(vector[1, 1, 1, 2, 2, 2, 3, 3, 3].skip_while!(|e| *e == 2) == vector[1, 1, 1, 2, 2, 2, 3, 3, 3]);
assert!(vector[1, 1, 1, 2, 2, 2, 3, 3, 3].skip_while!(|e| *e == 3) == vector[1, 1, 1, 2, 2, 2, 3, 3, 3]);
}
}

0 comments on commit 1f6f169

Please sign in to comment.