From 90d2ff41b26eed58ec6d6e490ce258ee5de61c99 Mon Sep 17 00:00:00 2001 From: Dean Carmel Date: Tue, 21 Jan 2025 12:53:34 +0200 Subject: [PATCH] implemented push and pop --- corelib/src/starknet/storage/vec.cairo | 80 +++++++++++++++++++ .../cairo_level_tests/collections_test.cairo | 25 ++++++ 2 files changed, 105 insertions(+) diff --git a/corelib/src/starknet/storage/vec.cairo b/corelib/src/starknet/storage/vec.cairo index 2a4a3bc8b0d..5645d664491 100644 --- a/corelib/src/starknet/storage/vec.cairo +++ b/corelib/src/starknet/storage/vec.cairo @@ -321,6 +321,55 @@ pub trait MutableVecTrait { /// } /// ``` fn append(self: T) -> StoragePath>; + + /// Pushes a new value onto the vector. + /// + /// This operation: + /// 1. Increments the vector's length. + /// 2. Writes the provided value to the new storage location at the end of the vector. + /// + /// # Examples + /// + /// ``` + /// use core::starknet::storage::{Vec, MutableVecTrait, StoragePointerWriteAccess}; + /// + /// #[storage] + /// struct Storage { + /// numbers: Vec, + /// } + /// + /// fn push_number(ref self: ContractState, number: u256) { + /// self.numbers.push(number); + /// } + /// ``` + fn push<+Drop, +starknet::Store>( + self: T, value: Self::ElementType, + ); + + /// Pops the last value off the vector. + /// + /// This operation: + /// 1. Retrieves the value stored at the last position in the vector. + /// 2. Decrements the vector's length. + /// 3. Returns the retrieved value or `None` if the vector is empty. + /// + /// # Examples + /// + /// ``` + /// use core::starknet::storage::{Vec, MutableVecTrait, StoragePointerWriteAccess}; + /// + /// #[storage] + /// struct Storage { + /// numbers: Vec, + /// } + /// + /// fn pop_number(ref self: ContractState) -> Option { + /// self.numbers.pop() + /// } + /// ``` + fn pop<+Drop, +starknet::Store>( + self: T, + ) -> Option; } /// Implement `MutableVecTrait` for `StoragePath>`. @@ -350,6 +399,25 @@ impl MutableVecImpl of MutableVecTrait>>> { self.as_ptr().write(vec_len + 1); self.update(vec_len) } + + fn push<+Drop, +starknet::Store>( + self: StoragePath>>, value: Self::ElementType, + ) { + let storage_path = self.append(); + storage_path.write(value); + } + + fn pop<+Drop, +starknet::Store>( + self: StoragePath>>, + ) -> Option { + let vec_len: u64 = self.len(); + if vec_len == 0 { + return Option::None; + } + let last_element = self.at(vec_len - 1).read(); + self.as_ptr().write(vec_len - 1); + Option::Some(last_element) + } } /// Implement `MutableVecTrait` for any type that implements StorageAsPath into a storage @@ -377,6 +445,18 @@ impl PathableMutableVecImpl< fn append(self: T) -> StoragePath> { self.as_path().append() } + + fn push<+Drop, +starknet::Store>( + self: T, value: Self::ElementType, + ) { + self.as_path().push(value) + } + + fn pop<+Drop, +starknet::Store>( + self: T, + ) -> Option { + self.as_path().pop() + } } pub impl VecIndexView< diff --git a/crates/cairo-lang-starknet/cairo_level_tests/collections_test.cairo b/crates/cairo-lang-starknet/cairo_level_tests/collections_test.cairo index e5f492a7b49..df34b88ff27 100644 --- a/crates/cairo-lang-starknet/cairo_level_tests/collections_test.cairo +++ b/crates/cairo-lang-starknet/cairo_level_tests/collections_test.cairo @@ -101,3 +101,28 @@ fn test_nested_member_write_to_vec() { vec_contract_state.nested.append().append().write(1); assert_eq!(map_contract_state.nested.entry(0).entry(0).read(), 1); } + +#[test] +fn test_simple_member_push_to_vec() { + let mut vec_contract_state = contract_with_vec::contract_state_for_testing(); + vec_contract_state.simple.push(10); + vec_contract_state.simple.push(20); + vec_contract_state.simple.push(30); + assert_eq!(vec_contract_state.simple.len(), 3); + assert_eq!(vec_contract_state.simple.at(0).read(), 10); + assert_eq!(vec_contract_state.simple.at(1).read(), 20); + assert_eq!(vec_contract_state.simple.at(2).read(), 30); +} + +#[test] +fn test_simple_member_pop_from_vec() { + let mut vec_contract_state = contract_with_vec::contract_state_for_testing(); + vec_contract_state.simple.append().write(10); + vec_contract_state.simple.append().write(20); + vec_contract_state.simple.append().write(30); + assert_eq!(vec_contract_state.simple.pop(), Some(30)); + assert_eq!(vec_contract_state.simple.pop(), Some(20)); + assert_eq!(vec_contract_state.simple.pop(), Some(10)); + assert_eq!(vec_contract_state.simple.len(), 0); + assert_eq!(vec_contract_state.simple.pop(), None); +}