use crate::error::StorageKeyError;
use alloc::sync::Arc;
use core::marker::PhantomData;
use frame_decode::storage::{IntoDecodableValues, StorageInfo, StorageKey as StorageKeyPartInfo};
use scale_info::PortableRegistry;
pub use frame_decode::storage::StorageHasher;
pub struct StorageKey<'info, KeyParts> {
info: Arc<StorageKeyPartInfo<u32>>,
types: &'info PortableRegistry,
bytes: Arc<[u8]>,
marker: PhantomData<KeyParts>,
}
impl<'info, KeyParts: IntoDecodableValues> StorageKey<'info, KeyParts> {
pub(crate) fn new(
info: &StorageInfo<'info, u32>,
types: &'info PortableRegistry,
bytes: Arc<[u8]>,
) -> Result<Self, StorageKeyError> {
let cursor = &mut &*bytes;
let storage_key_info = frame_decode::storage::decode_storage_key_with_info(
cursor, info, types,
)
.map_err(|e| StorageKeyError::StorageKeyDecodeError { bytes: bytes.to_vec(), error: e })?;
if !cursor.is_empty() {
return Err(StorageKeyError::LeftoverBytes { bytes: cursor.to_vec() });
}
Ok(StorageKey { info: Arc::new(storage_key_info), types, bytes, marker: PhantomData })
}
pub fn decode(&self) -> Result<KeyParts, StorageKeyError> {
let values =
frame_decode::storage::decode_storage_key_values(&self.bytes, &self.info, self.types)
.map_err(StorageKeyError::CannotDecodeValuesInKey)?;
Ok(values)
}
pub fn parts(&self) -> impl ExactSizeIterator<Item = StorageKeyPart<'info>> + '_ {
let parts_len = self.info.parts().len();
(0..parts_len).map(move |index| StorageKeyPart {
index,
info: self.info.clone(),
types: self.types,
bytes: self.bytes.clone(),
})
}
pub fn part(&self, index: usize) -> Option<StorageKeyPart<'info>> {
if index < self.parts().len() {
Some(StorageKeyPart {
index,
info: self.info.clone(),
types: self.types,
bytes: self.bytes.clone(),
})
} else {
None
}
}
}
pub struct StorageKeyPart<'info> {
index: usize,
info: Arc<StorageKeyPartInfo<u32>>,
types: &'info PortableRegistry,
bytes: Arc<[u8]>,
}
impl<'info> StorageKeyPart<'info> {
pub fn bytes(&self) -> &[u8] {
let part = &self.info[self.index];
let hash_range = part.hash_range();
let value_range = part
.value()
.map(|v| v.range())
.unwrap_or(core::ops::Range { start: hash_range.end, end: hash_range.end });
let combined_range = core::ops::Range { start: hash_range.start, end: value_range.end };
&self.bytes[combined_range]
}
pub fn hasher(&self) -> StorageHasher {
self.info[self.index].hasher()
}
pub fn decode_as<T: scale_decode::DecodeAsType>(&self) -> Result<Option<T>, StorageKeyError> {
let part_info = &self.info[self.index];
let Some(value_info) = part_info.value() else {
return Ok(None);
};
let value_bytes = &self.bytes[value_info.range()];
let value_ty = *value_info.ty();
let decoded_key_part = T::decode_as_type(&mut &*value_bytes, value_ty, self.types)
.map_err(|e| StorageKeyError::CannotDecodeValueInKey { index: self.index, error: e })?;
Ok(Some(decoded_key_part))
}
}