Skip to content

Commit

Permalink
stdlib Vec (FuelLabs#1118)
Browse files Browse the repository at this point in the history
* Add partial implementation.

* Fix offset calculation.

* memcopy when growing

* Add more methods.

* Fix copy bytes calculation.

* Update sway-lib-std/src/vec.sw

Co-authored-by: mitchmindtree <[email protected]>

* Add empty test.

* Add push functionality.

* Add get operation.

* Add test.

* Fix path to stdlib.

* Fix revert name.

* Minor fixes to vec + new test

* fmt

* Remove all asm blocks

* Additional clean up

* * Format the test and add JSON oracle
* Use size_of from the intrinsics library instead of __size_of

* remove unnecessary import

* remove unnecessary file

* Update sway-lib-std/src/vec.sw

Co-authored-by: Braqzen <[email protected]>

* Update sway-lib-std/src/vec.sw

Co-authored-by: Braqzen <[email protected]>

* first wave of comments

* Update test/src/e2e_vm_tests/test_programs/should_pass/stdlib/vec/src/main.sw

Co-authored-by: Braqzen <[email protected]>

* Update test/src/e2e_vm_tests/test_programs/should_pass/stdlib/vec/src/main.sw

Co-authored-by: Braqzen <[email protected]>

* wave 2 of comments

* revert the alphbeization of ptr and cap

* Address more comments

Co-authored-by: mitchmindtree <[email protected]>
Co-authored-by: Alex Hansen <[email protected]>
Co-authored-by: Mohammad Fawaz <[email protected]>
Co-authored-by: Braqzen <[email protected]>
Co-authored-by: Emily Herbert <[email protected]>
  • Loading branch information
6 people authored Jun 17, 2022
1 parent 3a2e719 commit 422c9ca
Show file tree
Hide file tree
Showing 7 changed files with 889 additions and 0 deletions.
1 change: 1 addition & 0 deletions sway-lib-std/src/lib.sw
Original file line number Diff line number Diff line change
Expand Up @@ -26,5 +26,6 @@ dep reentrancy;
dep vm/mod;
dep flags;
dep u128;
dep vec;

use core::*;
142 changes: 142 additions & 0 deletions sway-lib-std/src/vec.sw
Original file line number Diff line number Diff line change
@@ -0,0 +1,142 @@
library vec;

use ::alloc::{alloc, realloc};
use ::intrinsics::size_of;
use ::mem::{read, write};
use ::option::Option;

struct RawVec<T> {
ptr: u64,
cap: u64,
}

impl<T> RawVec<T> {
/// Create a new `RawVec` with zero capacity.
fn new() -> Self {
RawVec {
ptr: alloc(0),
cap: 0,
}
}

/// Creates a `RawVec` (on the heap) with exactly the capacity for a
/// `[T; capacity]`. This is equivalent to calling `RawVec::new` when
/// `capacity` is `0`.
fn with_capacity(capacity: u64) -> Self {
RawVec {
ptr: alloc(capacity * size_of::<T>()),
cap: capacity,
}
}

/// Gets the pointer of the allocation.
fn ptr(self) -> u64 {
self.ptr
}

/// Gets the capacity of the allocation.
fn capacity(self) -> u64 {
self.cap
}

/// Grow the capacity of the vector by doubling its current capacity. The
/// `realloc` function / allocates memory on the heap and copies the data
/// from the old allocation to the new allocation
fn grow(mut self) {
let new_cap = match self.cap {
0 => 1, _ => 2 * self.cap,
};

self.ptr = realloc(self.ptr, self.cap * size_of::<T>(), new_cap * size_of::<T>());
self.cap = new_cap;
}
}

/// A contiguous growable array type, written as `Vec<T>`, short for 'vector'.
pub struct Vec<T> {
buf: RawVec<T>,
len: u64,
}

impl<T> Vec<T> {
/// Constructs a new, empty `Vec<T>`.
///
/// The vector will not allocate until elements are pushed onto it.
pub fn new() -> Self {
Vec {
buf: ~RawVec::new(),
len: 0,
}
}

/// Constructs a new, empty `Vec<T>` with the specified capacity.
///
/// The vector will be able to hold exactly `capacity` elements without
/// reallocating. If `capacity` is 0, the vector will not allocate.
///
/// It is important to note that although the returned vector has the
/// *capacity* specified, the vector will have a zero *length*.
pub fn with_capacity(capacity: u64) -> Self {
Vec {
buf: ~RawVec::with_capacity(capacity),
len: 0,
}
}

/// Appends an element to the back of a collection.
pub fn push(mut self, value: T) {
// If there is insufficient capacity, grow the buffer.
if self.len == self.buf.capacity() {
self.buf.grow();
};

// Get a pointer to the end of the buffer, where the new element will
// be inserted.
let end = self.buf.ptr() + self.len * size_of::<T>();

// Write `value` at pointer `end`
write(end, value);

// Increment length.
self.len = self.len + 1;
}

/// Gets the capacity of the allocation.
pub fn capacity(self) -> u64 {
self.buf.cap
}

/// Clears the vector, removing all values.
///
/// Note that this method has no effect on the allocated capacity
/// of the vector.
pub fn clear(mut self) {
self.len = 0;
}

/// Returns a vector element at `index`, or None if `index` is out of
/// bounds.
pub fn get(self, index: u64) -> Option<T> {
// First check that index is within bounds.
if self.len <= index {
return Option::None::<T>();
};

// Get a pointer to the desired element using `index`
let ptr = self.buf.ptr() + index * size_of::<T>();

// Read from `ptr`
Option::Some(read(ptr))
}

/// Returns the number of elements in the vector, also referred to
/// as its 'length'.
pub fn len(self) -> u64 {
self.len
}

/// Returns `true` if the vector contains no elements.
pub fn is_empty(self) -> bool {
self.len == 0
}
}
1 change: 1 addition & 0 deletions test/src/e2e_vm_tests/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -222,6 +222,7 @@ pub fn run(locked: bool, filter_regex: Option<regex::Regex>) {
),
("should_pass/stdlib/b512_test", ProgramState::Return(1)), // true
("should_pass/stdlib/block_height", ProgramState::Return(1)), // true
("should_pass/stdlib/vec", ProgramState::Return(1)), // true
(
"should_pass/language/trait_override_bug",
ProgramState::Return(7),
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
[[package]]
name = 'core'
source = 'path+from-root-E8B33641BFB485A7'
dependencies = []

[[package]]
name = 'std'
source = 'path+from-root-E8B33641BFB485A7'
dependencies = ['core']

[[package]]
name = 'vec'
source = 'root'
dependencies = ['std']
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
[project]
authors = ["Fuel Labs <[email protected]>"]
entry = "main.sw"
license = "Apache-2.0"
name = "vec"

[dependencies]
std = { path = "../../../../../../../sway-lib-std" }
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
[
{
"inputs": [],
"name": "main",
"outputs": [
{
"components": null,
"name": "",
"type": "bool"
}
],
"type": "function"
}
]
Loading

0 comments on commit 422c9ca

Please sign in to comment.