use crate::utils::{Maybe, YesMaybe};
use frame_decode::storage::{IntoDecodableValues, IntoEncodableValues};
use scale_decode::DecodeAsType;
use std::borrow::Cow;
pub trait Address {
type KeyParts: IntoEncodableValues + IntoDecodableValues;
type Value: DecodeAsType;
type IsPlain: YesMaybe;
fn pallet_name(&self) -> &str;
fn entry_name(&self) -> &str;
fn validation_hash(&self) -> Option<[u8; 32]>;
}
impl<A: Address + ?Sized> Address for &'_ A {
type KeyParts = A::KeyParts;
type Value = A::Value;
type IsPlain = A::IsPlain;
fn pallet_name(&self) -> &str {
A::pallet_name(*self)
}
fn entry_name(&self) -> &str {
A::entry_name(*self)
}
fn validation_hash(&self) -> Option<[u8; 32]> {
A::validation_hash(*self)
}
}
pub struct StaticAddress<KeyParts, Value, IsPlain> {
pallet_name: Cow<'static, str>,
entry_name: Cow<'static, str>,
validation_hash: Option<[u8; 32]>,
marker: core::marker::PhantomData<(KeyParts, Value, IsPlain)>,
}
impl<KeyParts, Value, IsPlain> Clone for StaticAddress<KeyParts, Value, IsPlain> {
fn clone(&self) -> Self {
Self {
pallet_name: self.pallet_name.clone(),
entry_name: self.entry_name.clone(),
validation_hash: self.validation_hash,
marker: self.marker,
}
}
}
impl<KeyParts, Value, IsPlain> core::fmt::Debug for StaticAddress<KeyParts, Value, IsPlain> {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
f.debug_struct("StaticAddress")
.field("pallet_name", &self.pallet_name)
.field("entry_name", &self.entry_name)
.field("validation_hash", &self.validation_hash)
.finish()
}
}
impl<KeyParts, Value, IsPlain> StaticAddress<KeyParts, Value, IsPlain> {
#[doc(hidden)]
pub fn new_static(pallet_name: &'static str, entry_name: &'static str, hash: [u8; 32]) -> Self {
Self {
pallet_name: Cow::Borrowed(pallet_name),
entry_name: Cow::Borrowed(entry_name),
validation_hash: Some(hash),
marker: core::marker::PhantomData,
}
}
pub fn new(pallet_name: impl Into<String>, entry_name: impl Into<String>) -> Self {
Self {
pallet_name: pallet_name.into().into(),
entry_name: entry_name.into().into(),
validation_hash: None,
marker: core::marker::PhantomData,
}
}
pub fn unvalidated(mut self) -> Self {
self.validation_hash = None;
self
}
}
impl<KeyParts, Value, IsPlain> Address for StaticAddress<KeyParts, Value, IsPlain>
where
KeyParts: IntoEncodableValues + IntoDecodableValues,
Value: DecodeAsType,
IsPlain: YesMaybe,
{
type KeyParts = KeyParts;
type Value = Value;
type IsPlain = IsPlain;
fn pallet_name(&self) -> &str {
&self.pallet_name
}
fn entry_name(&self) -> &str {
&self.entry_name
}
fn validation_hash(&self) -> Option<[u8; 32]> {
self.validation_hash
}
}
impl<A: AsRef<str>, B: AsRef<str>> Address for (A, B) {
type KeyParts = Vec<scale_value::Value>;
type Value = scale_value::Value;
type IsPlain = Maybe;
fn pallet_name(&self) -> &str {
self.0.as_ref()
}
fn entry_name(&self) -> &str {
self.1.as_ref()
}
fn validation_hash(&self) -> Option<[u8; 32]> {
None
}
}
pub type DynamicAddress<KeyParts = Vec<scale_value::Value>, Value = scale_value::Value> =
StaticAddress<KeyParts, Value, Maybe>;
pub fn dynamic<KeyParts: IntoEncodableValues, Value: DecodeAsType>(
pallet_name: impl Into<String>,
entry_name: impl Into<String>,
) -> DynamicAddress<KeyParts, Value> {
DynamicAddress::<KeyParts, Value>::new(pallet_name.into(), entry_name.into())
}