0x1::Vector
A variable-sized container that can hold any type. Indexing is 0-based, and
vectors are growable. This module has many native functions.
Verification of modules that use this one uses model functions that are implemented
directly in Boogie. The specification language has built-in functions operations such
as vec
. There are some helper functions defined here for specifications in other
modules as well.
Note: We did not verify most of the Move functions here because many have loops, requiring loop invariants to prove, and the return on investment didn’t seem worth it for these simple functions.
empty
length
borrow
push_back
borrow_mut
pop_back
destroy_empty
swap
singleton
reverse
native_reverse
append
native_append
is_empty
contains
index_of
remove
native_remove
swap_remove
split
The index into the vector is out of bounds
const EINDEX_OUT_OF_BOUNDS: u64 = 0;
empty
Create an empty vector.
public fun empty<Element>(): vector<Element>
native public fun empty<Element>(): vector<Element>;
length
Return the length of the vector.
public fun length<Element>(v: &vector<Element>): u64
native public fun length<Element>(v: &vector<Element>): u64;
borrow
Acquire an immutable reference to the i
th element of the vector v
.
Aborts if i
is out of bounds.
public fun borrow<Element>(v: &vector<Element>, i: u64): &Element
native public fun borrow<Element>(v: &vector<Element>, i: u64): ∈
push_back
Add element e
to the end of the vector v
.
public fun push_back<Element>(v: &mut vector<Element>, e: Element)
native public fun push_back<Element>(v: &mut vector<Element>, e: Element);
borrow_mut
Return a mutable reference to the i
th element in the vector v
.
Aborts if i
is out of bounds.
public fun borrow_mut<Element>(v: &mut vector<Element>, i: u64): &mut Element
native public fun borrow_mut<Element>(v: &mut vector<Element>, i: u64): &mut Element;
pop_back
Pop an element from the end of vector v
.
Aborts if v
is empty.
public fun pop_back<Element>(v: &mut vector<Element>): Element
native public fun pop_back<Element>(v: &mut vector<Element>): Element;
destroy_empty
Destroy the vector v
.
Aborts if v
is not empty.
public fun destroy_empty<Element>(v: vector<Element>)
native public fun destroy_empty<Element>(v: vector<Element>);
swap
Swaps the elements at the i
th and j
th indices in the vector v
.
Aborts if i
or j
is out of bounds.
public fun swap<Element>(v: &mut vector<Element>, i: u64, j: u64)
native public fun swap<Element>(v: &mut vector<Element>, i: u64, j: u64);
singleton
Return an vector of size one containing element e
.
public fun singleton<Element>(e: Element): vector<Element>
public fun singleton<Element>(e: Element): vector<Element> {
let v = empty();
push_back(&mut v, e);
v
}
aborts_if false;
ensures result == vec(e);
fun spec_singleton<Element>(e: Element): vector<Element> {
vec(e)
}
reverse
Reverses the order of the elements in the vector v
in place.
public fun reverse<Element>(v: &mut vector<Element>)
public fun reverse<Element>(v: &mut vector<Element>) {
native_reverse(v)
}
pragma intrinsic = true;
native_reverse
fun native_reverse<Element>(this: &mut vector<Element>)
native fun native_reverse<Element>(this: &mut vector<Element>);
append
Pushes all of the elements of the other
vector into the lhs
vector.
public fun append<Element>(lhs: &mut vector<Element>, other: vector<Element>)
public fun append<Element>(lhs: &mut vector<Element>, other: vector<Element>) {
native_append(lhs, other);
}
pragma intrinsic = true;
native_append
fun native_append<Element>(lhs: &mut vector<Element>, other: vector<Element>)
native fun native_append<Element>(lhs: &mut vector<Element>, other: vector<Element>);
is_empty
Return true
if the vector v
has no elements and false
otherwise.
public fun is_empty<Element>(v: &vector<Element>): bool
pragma intrinsic = true;
contains
Return true if e
is in the vector v
.
public fun contains<Element>(v: &vector<Element>, e: &Element): bool
public fun contains<Element>(v: &vector<Element>, e: &Element): bool {
let i = 0;
let len = length(v);
while (i < len) {
if (borrow(v, i) == e) return true;
i = i + 1;
};
false
}
pragma intrinsic = true;
index_of
Return (true, i)
if e
is in the vector v
at index i
.
Otherwise, returns (false, 0)
.
public fun index_of<Element>(v: &vector<Element>, e: &Element): (bool, u64)
public fun index_of<Element>(v: &vector<Element>, e: &Element): (bool, u64) {
let i = 0;
let len = length(v);
while (i < len) {
if (borrow(v, i) == e) return (true, i);
i = i + 1;
};
(false, 0)
}
pragma intrinsic = true;
remove
Remove the i
th element of the vector v
, shifting all subsequent elements.
This is O(n) and preserves ordering of elements in the vector.
Aborts if i
is out of bounds.
public fun remove<Element>(v: &mut vector<Element>, i: u64): Element
public fun remove<Element>(v: &mut vector<Element>, i: u64): Element {
let len = length(v);
// i out of bounds; abort
if (i >= len) abort EINDEX_OUT_OF_BOUNDS;
native_remove(v, i)
}
pragma intrinsic = true;
native_remove
fun native_remove<Element>(this: &mut vector<Element>, i: u64): Element
native fun native_remove<Element>(this: &mut vector<Element>, i: u64): Element;
swap_remove
Swap the i
th element of the vector v
with the last element and then pop the vector.
This is O(1), but does not preserve ordering of elements in the vector.
Aborts if i
is out of bounds.
public fun swap_remove<Element>(v: &mut vector<Element>, i: u64): Element
public fun swap_remove<Element>(v: &mut vector<Element>, i: u64): Element {
let last_idx = length(v) - 1;
swap(v, i, last_idx);
pop_back(v)
}
pragma intrinsic = true;
split
Split a vector into sub-vectors of size sub_len,
public fun split<Element: copy, drop, store>(v: &vector<Element>, sub_len: u64): vector<vector<Element>>
public fun split<Element: copy + drop + store>(v: &vector<Element>, sub_len: u64): vector<vector<Element>> {
let result = empty<vector<Element>>();
let len = length(v) / sub_len;
let rem = 0;
if (len * sub_len < length(v)) {
rem = length(v) - len * sub_len;
};
let i = 0;
while (i < len) {
let sub = empty<Element>();
let j = 0;
while (j < sub_len) {
let index = sub_len * i + j;
push_back(&mut sub, *borrow(v, index));
j = j + 1;
};
push_back<vector<Element>>(&mut result, sub);
i = i + 1;
};
if (rem > 0) {
let sub = empty<Element>();
let index = length(v) - rem;
while (index < length(v)) {
push_back(&mut sub, *borrow(v, index));
index = index + 1;
};
push_back<vector<Element>>(&mut result, sub);
};
result
}
pragma verify = false;
aborts_if sub_len == 0;
Check whether a vector contains an element.
fun spec_contains<Element>(v: vector<Element>, e: Element): bool {
exists x in v: x == e
}
Check if v1
is equal to the result of adding e
at the end of v2
fun eq_push_back<Element>(v1: vector<Element>, v2: vector<Element>, e: Element): bool {
len(v1) == len(v2) + 1 &&
v1[len(v1)-1] == e &&
v1[0..len(v1)-1] == v2[0..len(v2)]
}
Check if v
is equal to the result of concatenating v1
and v2
fun eq_append<Element>(v: vector<Element>, v1: vector<Element>, v2: vector<Element>): bool {
len(v) == len(v1) + len(v2) &&
v[0..len(v1)] == v1 &&
v[len(v1)..len(v)] == v2
}
Check v1
is equal to the result of removing the first element of v2
fun eq_pop_front<Element>(v1: vector<Element>, v2: vector<Element>): bool {
len(v1) + 1 == len(v2) &&
v1 == v2[1..len(v2)]
}
Check that v1
is equal to the result of removing the element at index i
from v2
.
fun eq_remove_elem_at_index<Element>(i: u64, v1: vector<Element>, v2: vector<Element>): bool {
len(v1) + 1 == len(v2) &&
v1[0..i] == v2[0..i] &&
v1[i..len(v1)] == v2[i + 1..len(v2)]
}