self<
+
+
+
+
+## Function `split_off`
+
+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>
+
+
+
+
+
+Implementation
+
+
+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
+}
+
+
+
+
@@ -800,6 +838,37 @@ Aborts if i
is out of bounds.
+
+
+
+
+## Function `replace`
+
+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
+
+
+
+
+
+Implementation
+
+
+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)
+}
+
+
+
+
diff --git a/aptos-move/framework/move-stdlib/sources/vector.move b/aptos-move/framework/move-stdlib/sources/vector.move
index 1f7754a2a4cb81..ba58f20ab10ae0 100644
--- a/aptos-move/framework/move-stdlib/sources/vector.move
+++ b/aptos-move/framework/move-stdlib/sources/vector.move
@@ -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(self: &mut vector, at: u64): vector {
+ 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(self: &mut vector, new_len: u64): vector {
let res = trim_reverse(self, new_len);
@@ -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(self: &mut vector, 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(self: vector, f: |Element|) {
reverse(&mut self); // We need to reverse the vector to consume it efficiently
diff --git a/aptos-move/framework/move-stdlib/tests/vector_tests.move b/aptos-move/framework/move-stdlib/tests/vector_tests.move
index b8c9e19a4dd84e..4a95517f7960eb 100644
--- a/aptos-move/framework/move-stdlib/tests/vector_tests.move
+++ b/aptos-move/framework/move-stdlib/tests/vector_tests.move
@@ -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);
+ }
}