-
Notifications
You must be signed in to change notification settings - Fork 189
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
24 changed files
with
377 additions
and
356 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,94 @@ | ||
use array::{ArrayTrait, SpanTrait}; | ||
use traits::{Into, TryInto}; | ||
use serde::Serde; | ||
use hash::LegacyHash; | ||
use poseidon::poseidon_hash_span; | ||
|
||
mod index; | ||
mod query; | ||
mod storage; | ||
mod utils; | ||
|
||
use dojo_core::database::{query::{Query, QueryTrait}}; | ||
use dojo_core::interfaces::{IComponentLibraryDispatcher, IComponentDispatcherTrait}; | ||
use dojo_core::serde::SpanSerde; | ||
|
||
fn get( | ||
class_hash: starknet::ClassHash, table: felt252, query: Query, offset: u8, length: usize | ||
) -> Option<Span<felt252>> { | ||
let mut length = length; | ||
if length == 0 { | ||
length = IComponentLibraryDispatcher { class_hash: class_hash }.len(); | ||
} | ||
|
||
let id = query.hash(); | ||
let mut keys = ArrayTrait::new(); | ||
keys.append('dojo_storage'); | ||
keys.append(table); | ||
keys.append(id); | ||
match index::exists(0, table, id) { | ||
bool::False(()) => Option::None(()), | ||
bool::True(()) => Option::Some(storage::get_many(0, keys.span(), offset, length)), | ||
} | ||
} | ||
|
||
fn set( | ||
class_hash: starknet::ClassHash, table: felt252, query: Query, offset: u8, value: Span<felt252> | ||
) { | ||
let keys = query.keys(); | ||
let id = query.hash(); | ||
|
||
let length = IComponentLibraryDispatcher { class_hash: class_hash }.len(); | ||
assert(value.len() <= length, 'Value too long'); | ||
|
||
index::create(0, table, id); | ||
|
||
let mut keys = ArrayTrait::new(); | ||
keys.append('dojo_storage'); | ||
keys.append(table); | ||
keys.append(id); | ||
storage::set_many(0, keys.span(), offset, value); | ||
} | ||
|
||
fn del(class_hash: starknet::ClassHash, table: felt252, query: Query) { | ||
index::delete(0, table, query.hash()); | ||
} | ||
|
||
// returns a tuple of spans, first contains the entity IDs, | ||
// second the deserialized entities themselves | ||
fn all( | ||
class_hash: starknet::ClassHash, component: felt252, partition: felt252 | ||
) -> (Span<felt252>, Span<Span<felt252>>) { | ||
let table = { | ||
if partition == 0.into() { | ||
component | ||
} else { | ||
let mut serialized = ArrayTrait::new(); | ||
component.serialize(ref serialized); | ||
partition.serialize(ref serialized); | ||
let hash = poseidon_hash_span(serialized.span()); | ||
hash.into() | ||
} | ||
}; | ||
|
||
let all_ids = index::get(0, table); | ||
let length = IComponentLibraryDispatcher { class_hash: class_hash }.len(); | ||
|
||
let mut ids = all_ids.span(); | ||
let mut entities: Array<Span<felt252>> = ArrayTrait::new(); | ||
loop { | ||
match ids.pop_front() { | ||
Option::Some(id) => { | ||
let mut keys = ArrayTrait::new(); | ||
keys.append('dojo_storage'); | ||
keys.append(table); | ||
keys.append(*id); | ||
let value: Span<felt252> = storage::get_many(0, keys.span(), 0_u8, length); | ||
entities.append(value); | ||
}, | ||
Option::None(_) => { | ||
break (all_ids.span(), entities.span()); | ||
} | ||
}; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,92 @@ | ||
use array::{ArrayTrait, SpanTrait}; | ||
use traits::Into; | ||
use option::OptionTrait; | ||
use poseidon::poseidon_hash_span; | ||
use serde::Serde; | ||
|
||
use dojo_core::database::storage; | ||
use dojo_core::serde::SpanSerde; | ||
|
||
fn create(address_domain: u32, index: felt252, id: felt252) { | ||
if exists(address_domain, index, id) { | ||
return (); | ||
} | ||
|
||
let index_len_key = build_index_len_key(index); | ||
let index_len = storage::get(address_domain, index_len_key); | ||
storage::set(address_domain, build_index_item_key(index, id), index_len + 1); | ||
storage::set(address_domain, index_len_key, index_len + 1); | ||
storage::set(address_domain, build_index_key(index, index_len), id); | ||
} | ||
|
||
fn delete(address_domain: u32, index: felt252, id: felt252) { | ||
if !exists(address_domain, index, id) { | ||
return (); | ||
} | ||
|
||
let index_len_key = build_index_len_key(index); | ||
let replace_item_idx = storage::get(address_domain, index_len_key) - 1; | ||
|
||
let index_item_key = build_index_item_key(index, id); | ||
let delete_item_idx = storage::get(address_domain, index_item_key) - 1; | ||
|
||
storage::set(address_domain, index_item_key, 0); | ||
storage::set(address_domain, index_len_key, replace_item_idx); | ||
|
||
// Replace the deleted element with the last element. | ||
// NOTE: We leave the last element set as to not produce an unncessary state diff. | ||
let replace_item_value = storage::get(address_domain, build_index_key(index, replace_item_idx)); | ||
storage::set(address_domain, build_index_key(index, delete_item_idx), replace_item_value); | ||
} | ||
|
||
fn exists(address_domain: u32, index: felt252, id: felt252) -> bool { | ||
storage::get(address_domain, build_index_item_key(index, id)) != 0 | ||
} | ||
|
||
fn get(address_domain: u32, index: felt252) -> Array<felt252> { | ||
let mut res = ArrayTrait::new(); | ||
|
||
let index_len_key = build_index_len_key(index); | ||
let index_len = storage::get(address_domain, index_len_key); | ||
let mut idx = 0; | ||
|
||
loop { | ||
if idx == index_len { | ||
break (); | ||
} | ||
|
||
res.append(storage::get(address_domain, build_index_key(index, idx))); | ||
idx += 1; | ||
}; | ||
|
||
res | ||
} | ||
|
||
fn index_key_prefix() -> Array<felt252> { | ||
let mut prefix = ArrayTrait::new(); | ||
prefix.append('dojo_index'); | ||
prefix | ||
} | ||
|
||
fn build_index_len_key(index: felt252) -> Span<felt252> { | ||
let mut index_len_key = index_key_prefix(); | ||
index_len_key.append('index_lens'); | ||
index_len_key.append(index); | ||
index_len_key.span() | ||
} | ||
|
||
fn build_index_key(index: felt252, idx: felt252) -> Span<felt252> { | ||
let mut key = index_key_prefix(); | ||
key.append('indexes'); | ||
key.append(index); | ||
key.append(idx); | ||
key.span() | ||
} | ||
|
||
fn build_index_item_key(index: felt252, id: felt252) -> Span<felt252> { | ||
let mut index_len_key = index_key_prefix(); | ||
index_len_key.append('index_ids'); | ||
index_len_key.append(index); | ||
index_len_key.append(id); | ||
index_len_key.span() | ||
} |
File renamed without changes.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,63 @@ | ||
use array::{ArrayTrait, SpanTrait}; | ||
use option::OptionTrait; | ||
use starknet::SyscallResultTrait; | ||
use traits::Into; | ||
use poseidon::poseidon_hash_span; | ||
use serde::Serde; | ||
use dojo_core::serde::SpanSerde; | ||
|
||
fn get(address_domain: u32, keys: Span<felt252>) -> felt252 { | ||
let base = starknet::storage_base_address_from_felt252(poseidon_hash_span(keys)); | ||
starknet::storage_read_syscall( | ||
address_domain, starknet::storage_address_from_base(base) | ||
).unwrap_syscall() | ||
} | ||
|
||
fn get_many(address_domain: u32, keys: Span<felt252>, offset: u8, length: usize) -> Span<felt252> { | ||
let base = starknet::storage_base_address_from_felt252(poseidon_hash_span(keys)); | ||
let mut value = ArrayTrait::new(); | ||
|
||
let mut offset = offset; | ||
loop { | ||
if length == offset.into() { | ||
break (); | ||
} | ||
|
||
value | ||
.append( | ||
starknet::storage_read_syscall( | ||
address_domain, starknet::storage_address_from_base_and_offset(base, offset) | ||
).unwrap_syscall() | ||
); | ||
|
||
offset += 1; | ||
}; | ||
|
||
value.span() | ||
} | ||
|
||
fn set(address_domain: u32, keys: Span<felt252>, value: felt252) { | ||
let base = starknet::storage_base_address_from_felt252(poseidon_hash_span(keys)); | ||
starknet::storage_write_syscall( | ||
address_domain, starknet::storage_address_from_base(base), value | ||
); | ||
} | ||
|
||
fn set_many(address_domain: u32, keys: Span<felt252>, offset: u8, mut value: Span<felt252>) { | ||
let base = starknet::storage_base_address_from_felt252(poseidon_hash_span(keys)); | ||
|
||
let mut offset = offset; | ||
loop { | ||
match value.pop_front() { | ||
Option::Some(v) => { | ||
starknet::storage_write_syscall( | ||
address_domain, starknet::storage_address_from_base_and_offset(base, offset), *v | ||
); | ||
offset += 1 | ||
}, | ||
Option::None(_) => { | ||
break (); | ||
}, | ||
}; | ||
}; | ||
} |
File renamed without changes.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file was deleted.
Oops, something went wrong.
This file was deleted.
Oops, something went wrong.
Oops, something went wrong.