use super::keypath::Keypath;
use super::sealed::Sealed;
use core::ops::{Deref, DerefMut};
#[allow(private_bounds)]
#[diagnostic::on_unimplemented(
message = "`{Self}` cannot be stored in a `Map` or `Vector`",
note = "element types must be storage handles: wrap plain data in `Value<{Self}>`; a nested `#[storage]` struct goes in `Node<_>`"
)]
pub trait StorageType: Sealed + From<Keypath> {}
#[doc(hidden)]
pub fn __field_from_keypath<T: From<Keypath>>(keypath: Keypath) -> T {
T::from(keypath)
}
#[derive(Debug)]
pub struct Node<T> {
fields: T,
}
impl<T: From<Keypath>> From<Keypath> for Node<T> {
fn from(keypath: Keypath) -> Self {
Self {
fields: T::from(keypath),
}
}
}
impl<T> Deref for Node<T> {
type Target = T;
fn deref(&self) -> &T {
&self.fields
}
}
impl<T> DerefMut for Node<T> {
fn deref_mut(&mut self) -> &mut T {
&mut self.fields
}
}
impl<T> Sealed for Node<T> {}
impl<T: From<Keypath>> StorageType for Node<T> {}
impl<T: super::deletable::Deletable> super::deletable::Deletable for Node<T> {
fn delete_internal(&mut self, exclusive: bool) {
self.fields.delete_internal(exclusive);
}
}
#[diagnostic::on_unimplemented(
message = "`{Self}` cannot be used as contract state",
note = "methods taking `&self`/`&mut self` require the state type to be a storage struct: add `#[storage]` to the definition of `{Self}`",
note = "contracts with only associated functions (no `self` methods) do not need `#[storage]`"
)]
pub trait ContractState: From<Keypath> {}
impl<T: From<Keypath>> ContractState for T {}
pub trait StorageDomain {
const DOMAIN: crate::storage::FramedDomain;
}
#[doc(hidden)]
#[inline(never)]
pub fn contract_state_root<T: ContractState + StorageDomain>() -> Node<T> {
Node::from(Keypath::root(T::DOMAIN))
}
#[cfg(test)]
mod tests {
use super::*;
#[derive(crate::Storage)]
struct UnitState;
crate::contract_test!(unit_struct_contract_state_root_constructs {
let _node: Node<UnitState> = contract_state_root::<UnitState>();
});
#[derive(crate::Storage)]
struct LeafState {
value: crate::storage::Value<u64>,
}
crate::contract_test!(contract_state_root_seeds_domain {
let node: Node<LeafState> = contract_state_root::<LeafState>();
let expected = Keypath::default().child("LeafState").child(&0u32);
assert_eq!(*node.value.key(), expected.generate_key());
});
}