Skip to content

Commit

Permalink
Added Serde, Store, PartialEq, Debug and Display for NonZero. (#4795)
Browse files Browse the repository at this point in the history
  • Loading branch information
orizi authored Jan 15, 2024
1 parent cb03d8f commit 1f29ddb
Show file tree
Hide file tree
Showing 6 changed files with 94 additions and 11 deletions.
14 changes: 14 additions & 0 deletions corelib/src/fmt.cairo
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,13 @@ impl DisplayInteger<
}
}

impl DisplayNonZero<T, +Display<T>, +Copy<T>, +Drop<T>> of Display<NonZero<T>> {
fn fmt(self: @NonZero<T>, ref f: Formatter) -> Result<(), Error> {
let value: T = (*self).into();
write!(f, "{value}")
}
}

impl DisplayBool of Display<bool> {
fn fmt(self: @bool, ref f: Formatter) -> Result<(), Error> {
if *self {
Expand Down Expand Up @@ -62,6 +69,13 @@ impl DebugInteger<
}
}

impl DebugNonZero<T, +Debug<T>, +Copy<T>, +Drop<T>> of Debug<NonZero<T>> {
fn fmt(self: @NonZero<T>, ref f: Formatter) -> Result<(), Error> {
let value: T = (*self).into();
write!(f, "{value:?}")
}
}

impl DebugBool of Debug<bool> {
fn fmt(self: @bool, ref f: Formatter) -> Result<(), Error> {
Display::fmt(self, ref f)
Expand Down
10 changes: 10 additions & 0 deletions corelib/src/starknet/storage_access.cairo
Original file line number Diff line number Diff line change
Expand Up @@ -268,6 +268,16 @@ impl StorePackingBytes31 of StorePacking<bytes31, felt252> {
}
}

impl StorePackingNonZero<T, +TryInto<T, NonZero<T>>> of StorePacking<NonZero<T>, T> {
fn pack(value: NonZero<T>) -> T {
value.into()
}
#[inline]
fn unpack(value: T) -> NonZero<T> {
value.try_into().expect('StoreNonZero - zero value')
}
}

impl StorePackingStorageAddress of StorePacking<StorageAddress, felt252> {
fn pack(value: StorageAddress) -> felt252 {
value.into()
Expand Down
2 changes: 2 additions & 0 deletions corelib/src/test/fmt_test.cairo
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@ fn test_format() {
assert(format!("{}{1}", 12_usize, 14_u32) == "1214", 'positional mix bad formatting');
assert(format!("{ba}_{}_{}_{1}", 12, 14_u32) == "hello_12_14_14", 'full mix bad formatting');
assert(format!("{{{{}}}}") == "{{}}", 'special cases bad formatting');
let nz_value: NonZero<felt252> = 1.try_into().unwrap();
assert(format!("{}", nz_value) == "1", 'non zero bad formatting');
}

#[derive(Debug, Drop)]
Expand Down
25 changes: 25 additions & 0 deletions corelib/src/zeroable.cairo
Original file line number Diff line number Diff line change
Expand Up @@ -57,3 +57,28 @@ impl IsZeroResultIntoBool<T, +Drop<T>> of Into<IsZeroResult<T>, bool> {
}
}
}

impl NonZeroPartialEq<T, +PartialEq<T>, +Copy<T>, +Drop<T>> of PartialEq<NonZero<T>> {
#[inline(always)]
fn eq(lhs: @NonZero<T>, rhs: @NonZero<T>) -> bool {
let lhs: T = (*lhs).into();
let rhs: T = (*rhs).into();
lhs == rhs
}
#[inline(always)]
fn ne(lhs: @NonZero<T>, rhs: @NonZero<T>) -> bool {
let lhs: T = (*lhs).into();
let rhs: T = (*rhs).into();
lhs != rhs
}
}

impl NonZeroSerde<T, +Serde<T>, +Copy<T>, +Drop<T>, +TryInto<T, NonZero<T>>> of Serde<NonZero<T>> {
fn serialize(self: @NonZero<T>, ref output: Array<felt252>) {
let value: T = (*self).into();
value.serialize(ref output);
}
fn deserialize(ref serialized: Span<felt252>) -> Option<NonZero<T>> {
Serde::<T>::deserialize(ref serialized)?.try_into()
}
}
50 changes: 39 additions & 11 deletions crates/cairo-lang-starknet/cairo_level_tests/storage_access.cairo
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ use starknet::{
storage_address_to_felt252, storage_address_try_from_felt252
};
use core::test::test_utils::assert_eq;
use super::utils::serialized;
use super::utils::{deserialized, serialized};
use core::integer::BoundedInt;
use core::zeroable::Zeroable;
use core::byte_array::ByteArrayTrait;
Expand All @@ -17,14 +17,14 @@ impl StorageAddressPartialEq of PartialEq<StorageAddress> {
}
}

#[derive(Drop, Serde, PartialEq, Copy, starknet::Store)]
#[derive(Copy, Drop, Debug, Serde, PartialEq, starknet::Store)]
struct Abc {
a: u8,
b: u16,
c: u32,
}

#[derive(Drop, Serde, PartialEq, Copy)]
#[derive(Copy, Drop, Debug, Serde, PartialEq)]
struct TupleStructure {
v1: u256,
v2: u256,
Expand All @@ -39,14 +39,14 @@ impl TupleStructureStorePacking of starknet::StorePacking<TupleStructure, (felt2
}
}

#[derive(Drop, Serde, PartialEq, Copy, starknet::Store)]
#[derive(Copy, Drop, Debug, Serde, PartialEq, starknet::Store)]
enum Efg {
E: (),
F: (),
G: u256
}

#[derive(Drop, Serde, PartialEq, Copy, starknet::Store)]
#[derive(Copy, Drop, Debug, Serde, PartialEq, starknet::Store)]
struct AbcEtc {
a: u8,
b: u16,
Expand All @@ -65,22 +65,30 @@ struct AbcEtc {
efg2: Efg,
}

#[derive(Drop, Serde, PartialEq, Clone, starknet::Store)]
#[derive(Clone, Drop, Debug, Serde, PartialEq, starknet::Store)]
struct ByteArrays {
empty: ByteArray,
single_word: ByteArray,
multi_word: ByteArray,
multi_chunk: ByteArray,
}

#[derive(Copy, Drop, Debug, Serde, PartialEq, starknet::Store)]
struct NonZeros {
value_u8: NonZero<u8>,
value_u256: NonZero<u256>,
value_felt252: NonZero<felt252>,
}

#[starknet::contract]
mod test_contract {
use super::{AbcEtc, ByteArrays};
use super::{AbcEtc, ByteArrays, NonZeros};

#[storage]
struct Storage {
data: AbcEtc,
byte_arrays: ByteArrays,
non_zeros: NonZeros,
}

#[external(v0)]
Expand All @@ -102,6 +110,16 @@ mod test_contract {
pub fn get_byte_arrays(self: @ContractState) -> ByteArrays {
self.byte_arrays.read()
}

#[external(v0)]
pub fn set_non_zeros(ref self: ContractState, value: NonZeros) {
self.non_zeros.write(value);
}

#[external(v0)]
pub fn get_non_zeros(self: @ContractState) -> NonZeros {
self.non_zeros.read()
}
}

#[test]
Expand All @@ -125,7 +143,7 @@ fn write_read_struct() {
};

assert!(test_contract::__external::set_data(serialized(x)).is_empty());
assert_eq(@test_contract::__external::get_data(serialized(())), @serialized(x), 'Wrong result');
assert_eq!(deserialized(test_contract::__external::get_data(serialized(()))), x);
}

#[test]
Expand All @@ -149,9 +167,7 @@ fn write_read_byte_arrays() {
};

assert!(test_contract::__external::set_byte_arrays(serialized(x.clone())).is_empty());
assert_eq(
@test_contract::__external::get_byte_arrays(serialized(())), @serialized(x), 'Wrong result'
);
assert_eq!(deserialized(test_contract::__external::get_byte_arrays(serialized(()))), x);
// Make sure the lengths were saved correctly.
let base_address = starknet::storage_base_address_from_felt252(selector!("byte_arrays"));
assert!(starknet::Store::read_at_offset(0, base_address, 0).unwrap() == 0_usize);
Expand All @@ -178,3 +194,15 @@ fn write_read_byte_arrays() {
'ef0123456789abcdef0123456789abc'_felt252
);
}

#[test]
fn test_read_write_non_zero() {
let x = NonZeros {
value_u8: 1_u8.try_into().unwrap(),
value_u256: 3_u256.try_into().unwrap(),
value_felt252: 5_felt252.try_into().unwrap(),
};

assert!(test_contract::__external::set_non_zeros(serialized(x.clone())).is_empty());
assert_eq!(deserialized(test_contract::__external::get_non_zeros(serialized(()))), x);
}
4 changes: 4 additions & 0 deletions crates/cairo-lang-starknet/cairo_level_tests/utils.cairo
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,7 @@ pub fn serialized<T, +Serde<T>, +Destruct<T>>(value: T) -> Span<felt252> {
value.serialize(ref arr);
arr.span()
}

pub fn deserialized<T, +Serde<T>, +Destruct<T>>(mut value: Span<felt252>) -> T {
Serde::deserialize(ref value).unwrap()
}

0 comments on commit 1f29ddb

Please sign in to comment.