diff --git a/src/storage/src/list.cairo b/src/storage/src/list.cairo index db161a1f..d8cbf765 100644 --- a/src/storage/src/list.cairo +++ b/src/storage/src/list.cairo @@ -28,6 +28,8 @@ trait ListTrait { fn clean(ref self: List); fn pop_front(ref self: List) -> Option; fn array(self: @List) -> Array; + fn from_array(ref self: List, array: @Array); + fn from_span(ref self: List, span: Span); } impl ListImpl, impl TDrop: Drop, impl TStore: Store> of ListTrait { @@ -104,6 +106,30 @@ impl ListImpl, impl TDrop: Drop, impl TStore: Store }; array } + + fn from_array(ref self: List, array: @Array) { + self.from_span(array.span()); + } + + fn from_span(ref self: List, mut span: Span) { + let mut index = 0; + self.len = span.len(); + loop { + match span.pop_front() { + Option::Some(v) => { + let (base, offset) = calculate_base_and_offset_for_index( + self.base, index, self.storage_size + ); + Store::write_at_offset(self.address_domain, base, offset, *v).unwrap_syscall(); + index += 1; + }, + Option::None => { + break; + } + }; + }; + Store::write(self.address_domain, self.base, self.len); + } } impl AListIndexViewImpl< diff --git a/src/storage/src/tests/list_test.cairo b/src/storage/src/tests/list_test.cairo index abf0d6d1..21830f81 100644 --- a/src/storage/src/tests/list_test.cairo +++ b/src/storage/src/tests/list_test.cairo @@ -16,6 +16,9 @@ trait IAListHolder { fn do_clean(ref self: TContractState); fn do_pop_front(ref self: TContractState) -> (Option, Option); fn do_array(self: @TContractState) -> (Array, Array); + fn do_from_array( + ref self: TContractState, addrs_array: Array, numbers_array: Array + ); } #[starknet::contract] @@ -86,6 +89,15 @@ mod AListHolder { let mut n = self.numbers.read(); (a.array(), n.array()) } + + fn do_from_array( + ref self: ContractState, addrs_array: Array, numbers_array: Array + ) { + let mut a = self.addrs.read(); + let mut n = self.numbers.read(); + a.from_array(@addrs_array); + n.from_array(@numbers_array); + } } } @@ -415,4 +427,45 @@ mod tests { assert(addr.is_none(), 'addr is none'); assert(number.is_none(), 'number is none'); } + + #[test] + #[available_gas(100000000)] + fn test_from_array() { + let contract = deploy_mock(); + let mock_addr = mock_addr(); + + let addrs_array = array![mock_addr, mock_addr, mock_addr]; + let numbers_array = array![200, 300, 100]; + contract.do_from_array(addrs_array, numbers_array); + assert(contract.do_get_len() == (3, 3), 'len should be 3'); + assert(contract.do_get_index(0) == (mock_addr, 200), 'idx 0'); + assert(contract.do_get_index(1) == (mock_addr, 300), 'idx 1'); + assert(contract.do_get_index(2) == (mock_addr, 100), 'idx 2'); + } + + #[test] + #[available_gas(100000000)] + fn test_from_array_empty() { + let contract = deploy_mock(); + + contract.do_from_array(array![], array![]); + assert(contract.do_is_empty() == (true, true), 'should be empty'); + } + + #[test] + #[available_gas(100000000)] + fn test_from_array_remove_elements() { + let contract = deploy_mock(); + let mock_addr = mock_addr(); + + assert(contract.do_append(mock_addr, 10) == (0, 0), '1st append idx'); + assert(contract.do_append(mock_addr, 20) == (1, 1), '2nd append idx'); + assert(contract.do_get_len() == (2, 2), 'len'); + assert(contract.do_get_index(0) == (mock_addr, 10), 'idx 0'); + assert(contract.do_get_index(1) == (mock_addr, 20), 'idx 1'); + + contract.do_from_array(array![], array![]); + let (a, b) = contract.do_get_len(); + assert(contract.do_is_empty() == (true, true), 'should be empty'); + } }