Skip to content

Commit

Permalink
Support for fixed sized arrays in models dojoengine#2785: Debugging
Browse files Browse the repository at this point in the history
  • Loading branch information
bengineer42 committed Dec 31, 2024
1 parent b0a88b0 commit 64765f1
Show file tree
Hide file tree
Showing 7 changed files with 183 additions and 145 deletions.
10 changes: 5 additions & 5 deletions crates/dojo/core-cairo-test/src/tests/meta/introspect.cairo
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,11 @@ struct WithArray {
arr: Array<u8>
}

// #[derive(Drop, Introspect)]
// struct WithFixedArray {
// value: u32,
// arr: [u8; 3]
// }
#[derive(Drop, Introspect)]
struct WithFixedArray {
value: u32,
arr: [u8; 3]
}

#[derive(Drop, Introspect)]
struct WithByteArray {
Expand Down
31 changes: 16 additions & 15 deletions crates/dojo/core/src/meta/introspect.cairo
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ pub enum Ty {
// And `Box` is not serializable. So using a Span, even if it's to have
// one element, does the trick.
Array: Span<Ty>,
// FixedArray: Span<(Ty, u32)>,
FixedArray: Span<(Ty, u32)>,
ByteArray,
}

Expand Down Expand Up @@ -91,20 +91,21 @@ pub impl Introspect_bool of Introspect<bool> {
}
}

// pub impl Introspect_FixedArray<T, const N: usize, +Introspect<T>> of Introspect<[T; N]> {
// fn size() -> Option<usize> {
// match Introspect::<T>::size() {
// Option::Some(size) => Option::Some(size * N),
// Option::None => Option::None
// }
// }
// fn layout() -> Layout {
// Layout::FixedArray([(Introspect::<T>::layout(), N)].span())
// }
// fn ty() -> Ty {
// Ty::FixedArray([(Introspect::<T>::ty(), N)].span())
// }
// }
pub impl Introspect_FixedArray<T, const N: usize, +Introspect<T>> of Introspect<[T; N]> {
fn size() -> Option<usize> {
match Introspect::<T>::size() {
Option::Some(size) => Option::Some(size * N),
Option::None => Option::None
}
}
fn layout() -> Layout {
Layout::FixedArray([(Introspect::<T>::layout(), N)].span())
}
fn ty() -> Ty {
Ty::FixedArray([(Introspect::<T>::ty(), N)].span())
}
}


pub impl Introspect_u8 of Introspect<u8> {
fn size() -> Option<usize> {
Expand Down
4 changes: 2 additions & 2 deletions crates/dojo/core/src/meta/layout.cairo
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ pub enum Layout {
// And `Box` is not serializable. So using a Span, even if it's to have
// one element, does the trick.
Array: Span<Layout>,
// FixedArray: Span<(Layout, u32)>,
FixedArray: Span<(Layout, u32)>,
ByteArray,
// there is one layout per variant.
// the `selector` field identifies the variant
Expand All @@ -31,7 +31,7 @@ pub impl LayoutCompareImpl of LayoutCompareTrait {
(Layout::Struct(_), Layout::Struct(_)) => true,
(Layout::Tuple(_), Layout::Tuple(_)) => true,
(Layout::Array(_), Layout::Array(_)) => true,
// (Layout::FixedArray(_), Layout::FixedArray(_)) => true,
(Layout::FixedArray(_), Layout::FixedArray(_)) => true,
(Layout::ByteArray, Layout::ByteArray) => true,
(Layout::Enum(_), Layout::Enum(_)) => true,
_ => false
Expand Down
98 changes: 49 additions & 49 deletions crates/dojo/core/src/storage/layout.cairo
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,9 @@ pub fn write_layout(
Layout::Fixed(layout) => { write_fixed_layout(model, key, values, ref offset, layout); },
Layout::Struct(layout) => { write_struct_layout(model, key, values, ref offset, layout); },
Layout::Array(layout) => { write_array_layout(model, key, values, ref offset, layout); },
// Layout::FixedArray(layout) => {
// write_fixed_array_layout(model, key, values, ref offset, layout);
// },
Layout::FixedArray(layout) => {
write_fixed_array_layout(model, key, values, ref offset, layout);
},
Layout::Tuple(layout) => { write_tuple_layout(model, key, values, ref offset, layout); },
Layout::ByteArray => { write_byte_array_layout(model, key, values, ref offset); },
Layout::Enum(layout) => { write_enum_layout(model, key, values, ref offset, layout); }
Expand Down Expand Up @@ -92,29 +92,29 @@ pub fn write_array_layout(
/// * `values` - the model record values.
/// * `offset` - the start of model record values in the `values` parameter.
/// * `item_layout` - the model record layout (temporary a Span because of type recursion issue).
// pub fn write_fixed_array_layout(
// model: felt252,
// key: felt252,
// values: Span<felt252>,
// ref offset: u32,
// mut item_layout: Span<(Layout, u32)>
// ) {
// let (item_layout, array_len): (Layout, u32) = *item_layout.pop_front().unwrap();
// assert((values.len() - offset) >= array_len, 'Invalid values length');

// // first, read array size which is the first felt252 from values
// assert(array_len.into() <= database::MAX_ARRAY_LENGTH, 'invalid array length');

// // then, write the array size
// database::set(model, key, values, offset, [packing::PACKING_MAX_BITS].span());
// offset += 1;

// // and then, write array items
// for i in 0
// ..array_len {
// write_layout(model, combine_key(key, i.into()), values, ref offset, item_layout);
// };
// }
pub fn write_fixed_array_layout(
model: felt252,
key: felt252,
values: Span<felt252>,
ref offset: u32,
mut item_layout: Span<(Layout, u32)>
) {
let (item_layout, array_len): (Layout, u32) = *item_layout.pop_front().unwrap();
assert((values.len() - offset) >= array_len, 'Invalid values length');

// first, read array size which is the first felt252 from values
assert(array_len.into() <= database::MAX_ARRAY_LENGTH, 'invalid array length');

// then, write the array size
database::set(model, key, values, offset, [packing::PACKING_MAX_BITS].span());
offset += 1;

// and then, write array items
for i in 0
..array_len {
write_layout(model, combine_key(key, i.into()), values, ref offset, item_layout);
};
}

///
pub fn write_byte_array_layout(
Expand Down Expand Up @@ -247,13 +247,13 @@ pub fn delete_array_layout(model: felt252, key: felt252) {
database::delete(model, key, [packing::PACKING_MAX_BITS].span());
}

// pub fn delete_fixed_array_layout(model: felt252, key: felt252, mut layout: Span<(Layout, u32)>) {
// let (item_layout, array_len): (Layout, u32) = *layout.pop_front().unwrap();
// database::delete(model, key, [packing::PACKING_MAX_BITS].span());
// for i in 0..array_len {
// delete_layout(model, combine_key(key, i.into()), item_layout);
// }
// }
pub fn delete_fixed_array_layout(model: felt252, key: felt252, mut layout: Span<(Layout, u32)>) {
let (item_layout, array_len): (Layout, u32) = *layout.pop_front().unwrap();
database::delete(model, key, [packing::PACKING_MAX_BITS].span());
for i in 0..array_len {
delete_layout(model, combine_key(key, i.into()), item_layout);
}
}

///
pub fn delete_byte_array_layout(model: felt252, key: felt252) {
Expand Down Expand Up @@ -284,7 +284,7 @@ pub fn delete_layout(model: felt252, key: felt252, layout: Layout) {
Layout::Fixed(layout) => { delete_fixed_layout(model, key, layout); },
Layout::Struct(layout) => { delete_struct_layout(model, key, layout); },
Layout::Array(_) => { delete_array_layout(model, key); },
// Layout::FixedArray(layout) => { delete_fixed_array_layout(model, key, layout); },
Layout::FixedArray(layout) => { delete_fixed_array_layout(model, key, layout); },
Layout::Tuple(layout) => { delete_tuple_layout(model, key, layout); },
Layout::ByteArray => { delete_byte_array_layout(model, key); },
Layout::Enum(layout) => { delete_enum_layout(model, key, layout); }
Expand Down Expand Up @@ -367,7 +367,7 @@ pub fn read_layout(model: felt252, key: felt252, ref read_data: Array<felt252>,
Layout::Fixed(layout) => read_fixed_layout(model, key, ref read_data, layout),
Layout::Struct(layout) => read_struct_layout(model, key, ref read_data, layout),
Layout::Array(layout) => read_array_layout(model, key, ref read_data, layout),
// Layout::FixedArray(layout) => read_fixed_array_layout(model, key, ref read_data, layout),
Layout::FixedArray(layout) => read_fixed_array_layout(model, key, ref read_data, layout),
Layout::Tuple(layout) => read_tuple_layout(model, key, ref read_data, layout),
Layout::ByteArray => read_byte_array_layout(model, key, ref read_data),
Layout::Enum(layout) => read_enum_layout(model, key, ref read_data, layout),
Expand Down Expand Up @@ -423,23 +423,23 @@ pub fn read_array_layout(
};
}

// pub fn read_fixed_array_layout(
// model: felt252, key: felt252, ref read_data: Array<felt252>, mut layout: Span<(Layout, u32)>
// ) {
// // read number of array items
// let (item_layout, array_len): (Layout, u32) = *layout.pop_front().unwrap();
// let res = database::get(model, key, [packing::PACKING_MAX_BITS].span());
// assert(res.len() == 1, 'internal database error');
pub fn read_fixed_array_layout(
model: felt252, key: felt252, ref read_data: Array<felt252>, mut layout: Span<(Layout, u32)>
) {
// read number of array items
let (item_layout, array_len): (Layout, u32) = *layout.pop_front().unwrap();
let res = database::get(model, key, [packing::PACKING_MAX_BITS].span());
assert(res.len() == 1, 'internal database error');

// assert(array_len.into() <= database::MAX_ARRAY_LENGTH, 'invalid array length');
assert(array_len.into() <= database::MAX_ARRAY_LENGTH, 'invalid array length');

// read_data.append(array_len.into());
read_data.append(array_len.into());

// for i in 0
// ..array_len {
// read_layout(model, combine_key(key, i.into()), ref read_data, item_layout);
// };
// }
for i in 0
..array_len {
read_layout(model, combine_key(key, i.into()), ref read_data, item_layout);
};
}

///
pub fn read_byte_array_layout(model: felt252, key: felt252, ref read_data: Array<felt252>) {
Expand Down
136 changes: 85 additions & 51 deletions crates/dojo/lang/src/derive_macros/introspect/layout.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,9 @@ use cairo_lang_syntax::node::{ids, Terminal, TypedSyntaxNode};
use starknet::core::utils::get_selector_from_name;

use super::utils::{
get_array_item_type, get_tuple_item_types, is_array, is_byte_array, is_tuple,
is_unsupported_option_type, primitive_type_introspection,
get_array_item_type, get_fixed_array_type_and_size, get_tuple_item_types, is_array,
is_byte_array, is_fixed_array, is_tuple, is_unsupported_option_type,
primitive_type_introspection,
};

pub enum Wrapper {
Expand Down Expand Up @@ -95,14 +96,14 @@ pub fn get_layout_from_type_clause(
let tuple_type = expr.as_syntax_node().get_text(db);
build_tuple_layout_from_type(diagnostics, type_clause.stable_ptr().0, &tuple_type)
}
// Expr::FixedSizeArray(fixed_size_array) => {
// let fixed_array_type = fixed_size_array.as_syntax_node().get_text(db);
// build_fixed_array_layout_from_type(
// diagnostics,
// type_clause.stable_ptr().0,
// &fixed_array_type,
// )
// }
Expr::FixedSizeArray(fixed_size_array) => {
let fixed_array_type = fixed_size_array.as_syntax_node().get_text(db);
build_fixed_array_layout_from_type(
diagnostics,
type_clause.stable_ptr().0,
&fixed_array_type,
)
}
_ => {
diagnostics.push(PluginDiagnostic {
stable_ptr: type_clause.stable_ptr().0,
Expand All @@ -121,6 +122,31 @@ pub fn build_array_layout_from_type(
diagnostic_item: ids::SyntaxStablePtrId,
item_type: &str,
) -> String {
// let array_item_type = get_array_item_type(item_type);

// if is_tuple(&array_item_type) {
// format!(
// "dojo::meta::Layout::Array(
// array![
// {}
// ].span()
// )",
// build_item_layout_from_type(diagnostics, diagnostic_item, &array_item_type)
// )
// } else if is_array(&array_item_type) {
// format!(
// "dojo::meta::Layout::Array(
// array![
// {}
// ].span()
// )",
// build_array_layout_from_type(diagnostics, diagnostic_item, &array_item_type)
// )
// } else {
// format!("dojo::meta::introspect::Introspect::<{}>::layout()", item_type)
// }
// }

let array_item_type = get_array_item_type(item_type);

match build_member_layout_from_type(diagnostics, diagnostic_item, &array_item_type) {
Expand All @@ -140,47 +166,47 @@ pub fn build_array_layout_from_type(
}
}

// pub fn build_member_layout_from_type(
// diagnostics: &mut Vec<PluginDiagnostic>,
// diagnostic_item: ids::SyntaxStablePtrId,
// item_type: &str,
// ) -> Wrapper {
// if is_array(item_type) {
// Wrapper::Array(build_array_layout_from_type(diagnostics, diagnostic_item, item_type))
// // } else if is_fixed_array(item_type) {
// // Wrapper::Array(build_fixed_array_layout_from_type(diagnostics, diagnostic_item, item_type))
// } else if is_tuple(item_type) {
// Wrapper::Array(build_tuple_layout_from_type(diagnostics, diagnostic_item, item_type))
// } else {
// Wrapper::Introspect
// }
// }

// pub fn build_fixed_array_layout_from_type(
// diagnostics: &mut Vec<PluginDiagnostic>,
// diagnostic_item: ids::SyntaxStablePtrId,
// item_type: &str,
// ) -> String {
// let (array_item_type, array_size) = get_fixed_array_type_and_size(item_type);
// match build_member_layout_from_type(diagnostics, diagnostic_item, &array_item_type) {
// Wrapper::Introspect => {
// format!(
// "dojo::meta::introspect::Introspect::<({}, {})>::layout()",
// array_item_type, array_size
// )
// }
// Wrapper::Array(layout) => {
// format!(
// "dojo::meta::Layout::FixedArray(
// array![
// ({}, {})
// ].span(),
// )",
// layout, array_size
// )
// }
// }
// }
pub fn build_member_layout_from_type(
diagnostics: &mut Vec<PluginDiagnostic>,
diagnostic_item: ids::SyntaxStablePtrId,
item_type: &str,
) -> Wrapper {
if is_array(item_type) {
Wrapper::Array(build_array_layout_from_type(diagnostics, diagnostic_item, item_type))
} else if is_fixed_array(item_type) {
Wrapper::Array(build_fixed_array_layout_from_type(diagnostics, diagnostic_item, item_type))
} else if is_tuple(item_type) {
Wrapper::Array(build_tuple_layout_from_type(diagnostics, diagnostic_item, item_type))
} else {
Wrapper::Introspect
}
}

pub fn build_fixed_array_layout_from_type(
diagnostics: &mut Vec<PluginDiagnostic>,
diagnostic_item: ids::SyntaxStablePtrId,
item_type: &str,
) -> String {
let (array_item_type, array_size) = get_fixed_array_type_and_size(item_type);
match build_member_layout_from_type(diagnostics, diagnostic_item, &array_item_type) {
Wrapper::Introspect => {
format!(
"dojo::meta::introspect::Introspect::<[{}; {}]>::layout()",
array_item_type, array_size
)
}
Wrapper::Array(layout) => {
format!(
"dojo::meta::Layout::FixedArray(
array![
({}, {})
].span(),
)",
layout, array_size
)
}
}
}

/// Build the tuple layout describing the provided tuple type.
/// item_type could be something like (u8, u32, u128) for example.
Expand Down Expand Up @@ -368,6 +394,14 @@ pub fn get_packed_field_layout_from_type_clause(
let tuple_type = expr.as_syntax_node().get_text(db);
get_packed_tuple_layout_from_type(diagnostics, type_clause.stable_ptr().0, &tuple_type)
}
// Expr::FixedSizeArray(fixed_size_array) => {
// let fixed_array_type = fixed_size_array.as_syntax_node().get_text(db);
// get_packed_item_layout_from_type(
// diagnostics,
// type_clause.stable_ptr().0,
// fixed_array_type.trim(),
// )
// }
_ => {
diagnostics.push(PluginDiagnostic {
stable_ptr: type_clause.stable_ptr().0,
Expand Down
Loading

0 comments on commit 64765f1

Please sign in to comment.