use alloc::vec::Vec;
use codec::FullCodec;
use sp_metadata_ir::{StorageEntryMetadataIR, StorageEntryModifierIR};
mod counted_map;
mod counted_nmap;
mod double_map;
mod key;
mod map;
mod nmap;
mod value;
pub use counted_map::{CountedStorageMap, CountedStorageMapInstance, Counter};
pub use counted_nmap::{CountedStorageNMap, CountedStorageNMapInstance};
pub use double_map::StorageDoubleMap;
pub use key::{
EncodeLikeTuple, HasKeyPrefix, HasReversibleKeyPrefix, Key, KeyGenerator,
KeyGeneratorMaxEncodedLen, ReversibleKeyGenerator, TupleToEncodedIter,
};
pub use map::StorageMap;
pub use nmap::StorageNMap;
pub use value::StorageValue;
#[doc = docify::embed!("src/storage/types/mod.rs", value_query_examples)]
pub trait QueryKindTrait<Value, OnEmpty> {
const METADATA: StorageEntryModifierIR;
type Query: FullCodec + 'static;
fn from_optional_value_to_query(v: Option<Value>) -> Self::Query;
fn from_query_to_optional_value(v: Self::Query) -> Option<Value>;
}
pub struct OptionQuery;
impl<Value> QueryKindTrait<Value, crate::traits::GetDefault> for OptionQuery
where
Value: FullCodec + 'static,
{
const METADATA: StorageEntryModifierIR = StorageEntryModifierIR::Optional;
type Query = Option<Value>;
fn from_optional_value_to_query(v: Option<Value>) -> Self::Query {
v
}
fn from_query_to_optional_value(v: Self::Query) -> Option<Value> {
v
}
}
pub struct ResultQuery<Error>(core::marker::PhantomData<Error>);
impl<Value, Error, OnEmpty> QueryKindTrait<Value, OnEmpty> for ResultQuery<Error>
where
Value: FullCodec + 'static,
Error: FullCodec + 'static,
OnEmpty: crate::traits::Get<Result<Value, Error>>,
{
const METADATA: StorageEntryModifierIR = StorageEntryModifierIR::Optional;
type Query = Result<Value, Error>;
fn from_optional_value_to_query(v: Option<Value>) -> Self::Query {
match v {
Some(v) => Ok(v),
None => OnEmpty::get(),
}
}
fn from_query_to_optional_value(v: Self::Query) -> Option<Value> {
v.ok()
}
}
pub struct ValueQuery;
impl<Value, OnEmpty> QueryKindTrait<Value, OnEmpty> for ValueQuery
where
Value: FullCodec + 'static,
OnEmpty: crate::traits::Get<Value>,
{
const METADATA: StorageEntryModifierIR = StorageEntryModifierIR::Default;
type Query = Value;
fn from_optional_value_to_query(v: Option<Value>) -> Self::Query {
v.unwrap_or_else(|| OnEmpty::get())
}
fn from_query_to_optional_value(v: Self::Query) -> Option<Value> {
Some(v)
}
}
pub trait StorageEntryMetadataBuilder {
fn build_metadata(
deprecation_status: sp_metadata_ir::DeprecationStatusIR,
doc: Vec<&'static str>,
entries: &mut Vec<StorageEntryMetadataIR>,
);
}
#[cfg(test)]
mod test {
use super::*;
use crate::{
storage::types::ValueQuery,
traits::{Get, StorageInstance},
};
use sp_io::TestExternalities;
struct Prefix;
impl StorageInstance for Prefix {
fn pallet_prefix() -> &'static str {
"test"
}
const STORAGE_PREFIX: &'static str = "foo";
}
#[docify::export]
#[test]
pub fn value_query_examples() {
struct UniverseSecret;
impl Get<u32> for UniverseSecret {
fn get() -> u32 {
42
}
}
struct GetDefaultForResult;
impl Get<Result<u32, ()>> for GetDefaultForResult {
fn get() -> Result<u32, ()> {
Err(())
}
}
type A = StorageValue<Prefix, u32, ValueQuery>;
type B = StorageValue<Prefix, u32, OptionQuery>;
type C = StorageValue<Prefix, u32, ResultQuery<()>, GetDefaultForResult>;
type D = StorageValue<Prefix, u32, ValueQuery, UniverseSecret>;
TestExternalities::default().execute_with(|| {
assert_eq!(A::get(), 0);
assert_eq!(B::get(), None);
assert_eq!(C::get(), Err(()));
assert_eq!(D::get(), 42);
});
}
}