diff --git a/crates/storage/src/collections.rs b/crates/storage/src/collections.rs index 952b20ae5..1686eaf26 100644 --- a/crates/storage/src/collections.rs +++ b/crates/storage/src/collections.rs @@ -20,15 +20,12 @@ pub mod error; pub use error::StoreError; // fixme! macro expects `calimero_storage` to be in deps -use crate as calimero_storage; use crate::address::{Id, Path}; use crate::entities::{Data, Element}; use crate::interface::{Interface, StorageError}; -use crate::{AtomicUnit, Collection}; +use crate::{self as calimero_storage, AtomicUnit, Collection}; #[derive(AtomicUnit, BorshSerialize, BorshDeserialize, Clone, Debug)] -#[type_id(255)] -#[root] struct Collection { /// The entries in the collection. #[collection] @@ -82,7 +79,6 @@ struct Entries { /// An entry in a map. #[derive(AtomicUnit, BorshSerialize, BorshDeserialize, Clone, Debug)] -#[type_id(254)] struct Entry { /// The item in the entry. item: T, @@ -107,14 +103,24 @@ type StoreResult = std::result::Result; impl Collection { /// Creates a new collection. - fn new() -> Self { + fn new(id: Option) -> Self { + let id = id.unwrap_or_else(|| Id::random()); + let mut this = Self { entries: Entries::default(), children_ids: RefCell::new(None), - storage: Element::new(&Path::new("::unused").expect("valid path"), None), + storage: Element::new(&Path::new("::unused").expect("valid path"), Some(id)), }; - let _ = Interface::save(&mut this).expect("save collection"); + if id.is_root() { + let _ignored = Interface::save(&mut this).expect("save"); + } else { + let root = root::ROOT + .with(|root| root.borrow().clone()) + .expect("no root??"); + + let _ = Interface::add_child_to(root.id, &root, &mut this).expect("add child"); + } this } diff --git a/crates/storage/src/collections/root.rs b/crates/storage/src/collections/root.rs index 5a2280e61..2d5d8823c 100644 --- a/crates/storage/src/collections/root.rs +++ b/crates/storage/src/collections/root.rs @@ -1,13 +1,45 @@ //! A root collection that stores a single value. use std::cell::RefCell; +use std::marker::PhantomData; use std::ptr; use borsh::{BorshDeserialize, BorshSerialize}; -use calimero_sdk::env; -use super::Collection; +use super::{Collection, Entry}; use crate::address::Id; +use crate::entities::Data; +use crate::env; + +/// Thing. +#[derive(Copy, Clone, Debug, Eq, PartialEq)] +pub struct RootHandle { + /// The ID of the root collection. + pub id: Id, + _priv: PhantomData, +} + +impl RootHandle { + fn new(id: Id) -> Self { + Self { + id, + _priv: PhantomData, + } + } +} + +impl crate::entities::Collection for RootHandle { + type Child = T; + + fn name(&self) -> &str { + "RootHandle" + } +} + +thread_local! { + /// The root collection handle. + pub static ROOT: RefCell>>> = RefCell::new(None); +} /// A set collection that stores unqiue values once. #[derive(Clone, Debug, BorshSerialize, BorshDeserialize)] @@ -25,7 +57,13 @@ where pub fn new(value: T) -> Self { let id = Id::new(env::context_id()); - let mut inner = Collection::new(); + let old = ROOT.with(|root| root.borrow_mut().replace(RootHandle::new(id))); + + if old.is_some() { + panic!("root collection already defined"); + } + + let mut inner = Collection::new(Some(id)); let value = inner.insert(Some(id), value).unwrap(); diff --git a/crates/storage/src/collections/unordered_map.rs b/crates/storage/src/collections/unordered_map.rs index 017261514..d122baf3c 100644 --- a/crates/storage/src/collections/unordered_map.rs +++ b/crates/storage/src/collections/unordered_map.rs @@ -26,7 +26,7 @@ where /// pub fn new() -> Self { Self { - inner: Collection::new(), + inner: Collection::new(None), } } @@ -198,9 +198,12 @@ where #[cfg(test)] mod tests { use crate::collections::unordered_map::UnorderedMap; + use crate::collections::Root; #[test] fn test_unordered_map_basic_operations() { + let _root = Root::new(()); + let mut map = UnorderedMap::::new(); assert!(map @@ -250,6 +253,8 @@ mod tests { #[test] fn test_unordered_map_insert_and_get() { + let _root = Root::new(()); + let mut map = UnorderedMap::::new(); assert!(map @@ -273,6 +278,8 @@ mod tests { #[test] fn test_unordered_map_update_value() { + let _root = Root::new(()); + let mut map = UnorderedMap::::new(); assert!(map @@ -292,6 +299,8 @@ mod tests { #[test] fn test_remove() { + let _root = Root::new(()); + let mut map = UnorderedMap::::new(); assert!(map @@ -308,6 +317,8 @@ mod tests { #[test] fn test_clear() { + let _root = Root::new(()); + let mut map = UnorderedMap::::new(); assert!(map @@ -327,6 +338,8 @@ mod tests { #[test] fn test_unordered_map_len() { + let _root = Root::new(()); + let mut map = UnorderedMap::::new(); assert_eq!(map.len().expect("len failed"), 0); @@ -356,6 +369,8 @@ mod tests { #[test] fn test_unordered_map_contains() { + let _root = Root::new(()); + let mut map = UnorderedMap::::new(); assert!(map @@ -369,6 +384,8 @@ mod tests { #[test] fn test_unordered_map_entries() { + let _root = Root::new(()); + let mut map = UnorderedMap::::new(); assert!(map diff --git a/crates/storage/src/collections/unordered_set.rs b/crates/storage/src/collections/unordered_set.rs index 4781ba5f0..cb36a2599 100644 --- a/crates/storage/src/collections/unordered_set.rs +++ b/crates/storage/src/collections/unordered_set.rs @@ -24,7 +24,7 @@ where /// pub fn new() -> Self { Self { - inner: Collection::new(), + inner: Collection::new(None), } } @@ -171,10 +171,12 @@ where #[cfg(test)] mod tests { - use crate::collections::UnorderedSet; + use crate::collections::{Root, UnorderedSet}; #[test] fn test_unordered_set_operations() { + let _root = Root::new(()); + let mut set = UnorderedSet::::new(); assert!(set.insert("value1".to_string()).expect("insert failed")); @@ -203,6 +205,8 @@ mod tests { #[test] fn test_unordered_set_len() { + let _root = Root::new(()); + let mut set = UnorderedSet::::new(); assert!(set.insert("value1".to_string()).expect("insert failed")); @@ -218,6 +222,8 @@ mod tests { #[test] fn test_unordered_set_clear() { + let _root = Root::new(()); + let mut set = UnorderedSet::::new(); assert!(set.insert("value1".to_string()).expect("insert failed")); @@ -234,6 +240,8 @@ mod tests { #[test] fn test_unordered_set_entries() { + let _root = Root::new(()); + let mut set = UnorderedSet::::new(); assert!(set.insert("value1".to_string()).expect("insert failed")); diff --git a/crates/storage/src/collections/vector.rs b/crates/storage/src/collections/vector.rs index b797e69fd..c3310e095 100644 --- a/crates/storage/src/collections/vector.rs +++ b/crates/storage/src/collections/vector.rs @@ -22,7 +22,7 @@ where /// pub fn new() -> Self { Self { - inner: Collection::new(), + inner: Collection::new(None), } } @@ -159,9 +159,12 @@ where #[cfg(test)] mod tests { use crate::collections::vector::Vector; + use crate::collections::Root; #[test] fn test_vector_push() { + let _root = Root::new(()); + let mut vector: Vector = Vector::new(); let value = "test_data".to_string(); let result = vector.push(value.clone()); @@ -171,6 +174,8 @@ mod tests { #[test] fn test_vector_get() { + let _root = Root::new(()); + let mut vector: Vector = Vector::new(); let value = "test_data".to_string(); let _ = vector.push(value.clone()).unwrap(); @@ -180,6 +185,8 @@ mod tests { #[test] fn test_vector_update() { + let _root = Root::new(()); + let mut vector: Vector = Vector::new(); let value1 = "test_data1".to_string(); let value2 = "test_data2".to_string(); @@ -192,6 +199,8 @@ mod tests { #[test] fn test_vector_get_non_existent() { + let _root = Root::new(()); + let vector: Vector = Vector::new(); match vector.get(0) { Ok(retrieved_value) => assert_eq!(retrieved_value, None), @@ -201,6 +210,8 @@ mod tests { #[test] fn test_vector_pop() { + let _root = Root::new(()); + let mut vector: Vector = Vector::new(); let value = "test_data".to_string(); let _ = vector.push(value.clone()).unwrap(); @@ -211,6 +222,8 @@ mod tests { #[test] fn test_vector_entries() { + let _root = Root::new(()); + let mut vector: Vector = Vector::new(); let value1 = "test_data1".to_string(); let value2 = "test_data2".to_string(); @@ -222,6 +235,8 @@ mod tests { #[test] fn test_vector_contains() { + let _root = Root::new(()); + let mut vector: Vector = Vector::new(); let value = "test_data".to_string(); let _ = vector.push(value.clone()).unwrap(); @@ -232,6 +247,8 @@ mod tests { #[test] fn test_vector_clear() { + let _root = Root::new(()); + let mut vector: Vector = Vector::new(); let value = "test_data".to_string(); let _ = vector.push(value.clone()).unwrap(); diff --git a/crates/storage/src/entities.rs b/crates/storage/src/entities.rs index 01f5b3af5..211ba676e 100644 --- a/crates/storage/src/entities.rs +++ b/crates/storage/src/entities.rs @@ -788,6 +788,7 @@ pub struct Metadata { pub(crate) updated_at: UpdatedAt, } +/// The timestamp when the [`Element`] was last updated. #[derive( BorshDeserialize, BorshSerialize, Copy, Clone, Debug, Default, Eq, Hash, Ord, PartialOrd, )]