use crate::codec::Codec32;
use crate::env;
use crate::error::Result;
use crate::hashing;
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
pub struct Slot(pub [u8; 32]);
impl Slot {
pub const fn new(slot: [u8; 32]) -> Self {
Self(slot)
}
pub fn from_label(label: &str) -> Self {
Self(hashing::derive_slot(b"trth:sdk:slot", &[label.as_bytes()]))
}
pub fn derived(namespace: &[u8; 32], parts: &[&[u8]]) -> Self {
Self(hashing::derive_slot(namespace, parts))
}
pub fn read(self) -> Result<[u8; 32]> {
env::storage_read_32(&self.0)
}
pub fn write(self, value: &[u8; 32]) -> Result<()> {
env::storage_write_32(&self.0, value)
}
pub fn write_typed<T: Codec32>(self, value: &T) -> Result<()> {
let encoded = value.encode_32();
self.write(&encoded)
}
pub fn read_typed<T: Codec32>(self) -> Result<T> {
let raw = self.read()?;
T::decode_32(&raw)
}
pub fn write_u64(self, value: u64) -> Result<()> {
let mut bytes = [0u8; 32];
bytes[..8].copy_from_slice(&value.to_le_bytes());
self.write(&bytes)
}
pub fn read_u64(self) -> Result<u64> {
let bytes = self.read()?;
let mut out = [0u8; 8];
out.copy_from_slice(&bytes[..8]);
Ok(u64::from_le_bytes(out))
}
pub fn write_u128(self, value: u128) -> Result<()> {
let mut bytes = [0u8; 32];
bytes[..16].copy_from_slice(&value.to_le_bytes());
self.write(&bytes)
}
pub fn read_u128(self) -> Result<u128> {
let bytes = self.read()?;
let mut out = [0u8; 16];
out.copy_from_slice(&bytes[..16]);
Ok(u128::from_le_bytes(out))
}
}
pub fn namespace(label: &str) -> [u8; 32] {
hashing::hash32(label.as_bytes())
}
pub fn slot_for(namespace: &[u8; 32], key: &[u8]) -> Slot {
Slot::derived(namespace, &[key])
}
pub fn slot_for_parts(namespace: &[u8; 32], parts: &[&[u8]]) -> Slot {
Slot::derived(namespace, parts)
}
#[macro_export]
macro_rules! slot {
($bytes:expr) => {{
$crate::storage::Slot::new($bytes)
}};
}