Skip to content

Commit

Permalink
added member access back into the world store
Browse files Browse the repository at this point in the history
  • Loading branch information
bengineer42 committed Nov 1, 2024
1 parent 218cac9 commit 0a70242
Show file tree
Hide file tree
Showing 3 changed files with 68 additions and 9 deletions.
12 changes: 10 additions & 2 deletions crates/dojo/core/src/model/model.cairo
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
use dojo::{meta::{Layout, introspect::Ty, layout::compute_packed_size}, utils::entity_id_from_keys};
use dojo::{
meta::{Layout, introspect::Ty, layout::compute_packed_size},
utils::{entity_id_from_keys, find_model_field_layout}
};

use super::{ModelDefinition, ModelDef};

/// Trait `KeyParser` defines a trait for parsing keys from a given model.
pub trait KeyParser<M, K> {
/// Parses the key from the given model.
Expand Down Expand Up @@ -39,6 +41,8 @@ pub trait Model<M> {
fn schema() -> Ty;
/// Returns the memory layout of the model.
fn layout() -> Layout;
/// Returns the layout of a field in the model.
fn field_layout(field_selector: felt252) -> Option<Layout>;
/// Returns the unpacked size of the model. Only applicable for fixed size models.
fn unpacked_size() -> Option<usize>;
/// Returns the packed size of the model. Only applicable for fixed size models.
Expand Down Expand Up @@ -92,6 +96,10 @@ pub impl ModelImpl<M, +ModelParser<M>, +ModelDefinition<M>, +Serde<M>> of Model<
ModelDefinition::<M>::layout()
}

fn field_layout(field_selector: felt252) -> Option<Layout> {
find_model_field_layout(Self::layout(), field_selector)
}

fn schema() -> Ty {
ModelDefinition::<M>::schema()
}
Expand Down
28 changes: 23 additions & 5 deletions crates/dojo/core/src/model/storage.cairo
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use dojo::model::model_value::ModelValueKey;
use dojo::{model::model_value::ModelValueKey, utils::entity_id_from_keys};

// TODO: define the right interface for member accesses.

Expand All @@ -12,24 +12,42 @@ pub enum ModelPtr<M> {
Keys: Span<felt252>,
}


pub trait ModelPtrTrait<M> {
/// Returns the entity id of the model.
fn entity_id(self: @ModelPtr<M>) -> felt252;
}

pub impl ModelPtrImpl<M> of ModelPtrTrait<M> {
/// Returns the entity id of the model.
fn entity_id(self: @ModelPtr<M>) -> felt252 {
match self {
ModelPtr::Id(id) => *id,
ModelPtr::Keys(keys) => entity_id_from_keys(*keys),
}
}
}

/// A `ModelStorage` trait that abstracts where the storage is.
///
/// Currently it's only world storage, but this will be useful when we have other
/// storage solutions (micro worlds).
pub trait ModelStorage<S, M> {
/// Sets a model of type `M`.
fn write_model(ref self: S, model: @M);

/// Retrieves a model of type `M` using the provided key of type `K`.
fn read_model<K, +Drop<K>, +Serde<K>>(self: @S, key: K) -> M;

/// Deletes a model of type `M`.
fn erase_model(ref self: S, model: @M);

/// Deletes a model of type `M` using the provided entity id.
/// The ptr is mostly used for type inferrence.
fn erase_model_ptr(ref self: S, ptr: ModelPtr<M>);

/// Retrieves a model of type `M` using the provided entity idref .
fn read_member<T, +Serde<T>>(self: @S, ptr: ModelPtr<M>, field_selector: felt252) -> T;
/// Retrieves a model of type `M` using the provided entity id.
fn write_member<T, +Serde<T>, +Drop<T>>(
ref self: S, ptr: ModelPtr<M>, field_selector: felt252, value: T
);
/// Returns the current namespace hash.
fn namespace_hash(self: @S) -> felt252;
}
Expand Down
37 changes: 35 additions & 2 deletions crates/dojo/core/src/world/storage.cairo
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,14 @@

use core::panic_with_felt252;
use dojo::world::{IWorldDispatcher, IWorldDispatcherTrait, Resource};
use dojo::model::{Model, ModelIndex, ModelValueKey, ModelValue, ModelStorage, ModelPtr};
use dojo::model::{
Model, ModelIndex, ModelValueKey, ModelValue, ModelStorage, ModelPtr, storage::ModelPtrTrait
};
use dojo::event::{Event, EventStorage};
use dojo::meta::Layout;
use dojo::utils::{
entity_id_from_key, entity_id_from_keys, serialize_inline, find_model_field_layout
entity_id_from_key, entity_id_from_keys, serialize_inline, find_model_field_layout,
deserialize_unwrap
};
use starknet::{ContractAddress, ClassHash};

Expand All @@ -16,6 +19,13 @@ pub struct WorldStorage {
pub namespace_hash: felt252,
}

fn field_layout_unwrap<M, +Model<M>>(field_selector: felt252) -> Layout {
match Model::<M>::field_layout(field_selector) {
Option::Some(layout) => layout,
Option::None => panic_with_felt252('bad member id')
}
}

#[generate_trait]
pub impl WorldStorageInternalImpl of WorldStorageTrait {
fn new(world: IWorldDispatcher, namespace: @ByteArray) -> WorldStorage {
Expand Down Expand Up @@ -108,6 +118,29 @@ pub impl ModelStorageWorldStorageImpl<M, +Model<M>, +Drop<M>> of ModelStorage<Wo
Model::<M>::layout()
);
}
fn read_member<T, +Serde<T>>(
self: @WorldStorage, ptr: ModelPtr<M>, field_selector: felt252
) -> T {
deserialize_unwrap(
IWorldDispatcherTrait::entity(
*self.dispatcher,
Model::<M>::selector(*self.namespace_hash),
ModelIndex::MemberId((ptr.entity_id(), field_selector)),
field_layout_unwrap::<M>(field_selector)
)
)
}
fn write_member<T, +Serde<T>, +Drop<T>>(
ref self: WorldStorage, ptr: ModelPtr<M>, field_selector: felt252, value: T
) {
IWorldDispatcherTrait::set_entity(
self.dispatcher,
Model::<M>::selector(self.namespace_hash),
ModelIndex::MemberId((ptr.entity_id(), field_selector)),
serialize_inline(@value),
field_layout_unwrap::<M>(field_selector)
);
}

fn namespace_hash(self: @WorldStorage) -> felt252 {
*self.namespace_hash
Expand Down

0 comments on commit 0a70242

Please sign in to comment.