Open ponderingdemocritus opened 1 year ago
Howdy and merry merries--
I experimented with whether it was possible to pass the struct constructor as an argument to a helper and had no luck. I wrote out the ways to move from struct<>arr as a test, which I'll go ahead and share the contents here so I can get feedback if my understanding is on target:
%lang starknet
from starkware.cairo.common.alloc import alloc
from contracts.utils.Utils import Utils
from starkware.cairo.common.registers import get_label_location
from starkware.cairo.common.cairo_builtins import HashBuiltin
struct MyStruct {
foo: felt,
bar: felt,
}
@external
func test_struct_to_arr_using_new{syscall_ptr: felt*, pedersen_ptr: HashBuiltin*, range_check_ptr}(
) {
// constructing a struct with 'new' gives test_struct the type 'MyStruct*'
// which can be casted to felt*
// note: cannot use let binding when using `new`
tempvar test_struct_as_arr: felt* = new MyStruct(1, 2);
// to use the MyStruct* as an array, we just need the size,
// which we obtain by the SIZE field in the constructor
assert [test_struct_as_arr + MyStruct.SIZE - 1] = 2;
// I do not believe it is possible to parameterize the struct constructor
// so it can be passed to a helper function
return ();
}
@external
func test_struct_to_arr{syscall_ptr: felt*, pedersen_ptr: HashBuiltin*, range_check_ptr}() {
alloc_locals;
// in the case of not using 'new'
local test_struct: MyStruct = MyStruct(3, 4);
let test_struct_as_arr: felt* = &test_struct;
assert [test_struct_as_arr + MyStruct.SIZE - 1] = 4;
return ();
}
@external
func test_arr_to_struct{syscall_ptr: felt*, pedersen_ptr: HashBuiltin*, range_check_ptr}() {
let (array_to_struct) = alloc();
assert [array_to_struct] = 1;
assert [array_to_struct + 1] = 2;
let castedStruct = cast(array_to_struct, MyStruct*);
assert castedStruct.foo = 1;
return ();
}
nice!
also @milancermak suggested:
struct Army {
troop1: felt,
troop2: felt,
troop3: felt,
}
@view
func army_to_array(a: Army) -> (a_len: felt, a: felt*) {
let (__fp__, _) = get_fp_and_pc();
return (Army.SIZE, &a);
}
@view
func array_to_army(a_len: felt, a: felt*) -> (a: Army) {
let p: Army* = cast(a, Army*);
return ([p]);
}
These two helpers could be at the bottom of every component and if we name the Struct that is imported the same then we get the correct result
To allow generalised parsing of data in the system, two util functions need to exist:
Can be found in
Utils.cairo
struct_to_array
converts any struct to an array and returns length and the arrayarray_to_struct
converts any array into a struct and returns the struct