Skip to content

Commit

Permalink
[move][stdlib] Add vector::split_off and vector::remove library methods
Browse files Browse the repository at this point in the history
  • Loading branch information
igor-aptos committed Sep 25, 2024
1 parent 1d949f1 commit 6e1add6
Show file tree
Hide file tree
Showing 2 changed files with 62 additions and 0 deletions.
27 changes: 27 additions & 0 deletions aptos-move/framework/move-stdlib/sources/vector.move
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,22 @@ module std::vector {
pragma intrinsic = true;
}

/// Splits the collection into two at the given index.
/// Returns a newly allocated vector containing the elements in the range [at, len).
/// After the call, the original vector will be left containing the elements [0, at)
/// with its previous capacity unchanged.
public fun split_off<Element>(self: &mut vector<Element>, at: u64): vector<Element> {
let len = length(self);
assert!(at <= len, EINDEX_OUT_OF_BOUNDS);
let other = empty();
while (len > at) {
push_back(&mut other, pop_back(self));
len = len - 1;
};
reverse(&mut other);
other
}

/// Trim a vector to a smaller size, returning the evicted elements in order
public fun trim<Element>(self: &mut vector<Element>, new_len: u64): vector<Element> {
let res = trim_reverse(self, new_len);
Expand Down Expand Up @@ -266,6 +282,17 @@ module std::vector {
pragma intrinsic = true;
}

/// Replace the `i`th element of the vector `self` with the given value, and return
/// to the caller the value that was there before.
/// Aborts if `i` is out of bounds.
public fun replace<Element>(self: &mut vector<Element>, i: u64, val: Element): Element {
let last_idx = length(self);
assert!(i < last_idx, EINDEX_OUT_OF_BOUNDS);
push_back(self, val);
swap(self, i, last_idx);
pop_back(self)
}

/// Apply the function to each element in the vector, consuming it.
public inline fun for_each<Element>(self: vector<Element>, f: |Element|) {
reverse(&mut self); // We need to reverse the vector to consume it efficiently
Expand Down
35 changes: 35 additions & 0 deletions aptos-move/framework/move-stdlib/tests/vector_tests.move
Original file line number Diff line number Diff line change
Expand Up @@ -954,4 +954,39 @@ module std::vector_tests {
let v = vector[MoveOnly {}];
vector::destroy(v, |m| { let MoveOnly {} = m; })
}

#[test]
#[expected_failure(abort_code = V::EINDEX_OUT_OF_BOUNDS)]
fun test_replace_empty_abort() {
let v = vector[];
let MoveOnly {} = vector::replace(&mut v, 0, MoveOnly {});
vector::destroy_empty(v);
}

#[test]
fun test_replace() {
let v = vector[1, 2, 3, 4];
vector::replace(&mut v, 1, 17);
assert!(v == vector[1, 17, 3, 4], 0);
}

#[test]
fun test_split_off() {
let v = vector[1, 2, 3, 4, 5, 6];
let other = vector::split_off(&mut v, 4);
assert!(v == vector[1, 2, 3, 4], 0);
assert!(other == vector[5, 6], 1);

let other_empty = vector::split_off(&mut v, 4);
assert!(v == vector[1, 2, 3, 4], 2);
assert!(other_empty == vector[], 3);

}

#[test]
#[expected_failure(abort_code = V::EINDEX_OUT_OF_BOUNDS)]
fun test_split_off_abort() {
let v = vector[1, 2, 3];
vector::split_off(&mut v, 4);
}
}

0 comments on commit 6e1add6

Please sign in to comment.