1use crate::{
8 dynamic::DecodedValueThunk,
9 error::{Error, MetadataError},
10 metadata::{DecodeWithMetadata, Metadata},
11 utils::Yes,
12};
13use derive_where::derive_where;
14
15use alloc::borrow::{Cow, ToOwned};
16use alloc::string::String;
17use alloc::vec::Vec;
18
19pub use super::storage_key::{StaticStorageKey, StorageHashers, StorageHashersIter, StorageKey};
21
22pub trait Address {
25 type Target: DecodeWithMetadata;
27 type Keys: StorageKey;
29 type IsFetchable;
32 type IsDefaultable;
35 type IsIterable;
38
39 fn pallet_name(&self) -> &str;
41
42 fn entry_name(&self) -> &str;
44
45 fn append_entry_bytes(&self, metadata: &Metadata, bytes: &mut Vec<u8>) -> Result<(), Error>;
48
49 fn validation_hash(&self) -> Option<[u8; 32]> {
53 None
54 }
55}
56
57#[derive_where(Clone, Debug, Eq, Ord, PartialEq, PartialOrd; Keys)]
60pub struct DefaultAddress<Keys: StorageKey, ReturnTy, Fetchable, Defaultable, Iterable> {
61 pallet_name: Cow<'static, str>,
62 entry_name: Cow<'static, str>,
63 keys: Keys,
64 validation_hash: Option<[u8; 32]>,
65 _marker: core::marker::PhantomData<(ReturnTy, Fetchable, Defaultable, Iterable)>,
66}
67
68pub type StaticAddress<Keys, ReturnTy, Fetchable, Defaultable, Iterable> =
70 DefaultAddress<Keys, ReturnTy, Fetchable, Defaultable, Iterable>;
71pub type DynamicAddress<Keys> = DefaultAddress<Keys, DecodedValueThunk, Yes, Yes, Yes>;
74
75impl<Keys: StorageKey> DynamicAddress<Keys> {
76 pub fn new(pallet_name: impl Into<String>, entry_name: impl Into<String>, keys: Keys) -> Self {
78 Self {
79 pallet_name: Cow::Owned(pallet_name.into()),
80 entry_name: Cow::Owned(entry_name.into()),
81 keys,
82 validation_hash: None,
83 _marker: core::marker::PhantomData,
84 }
85 }
86}
87
88impl<Keys, ReturnTy, Fetchable, Defaultable, Iterable>
89 DefaultAddress<Keys, ReturnTy, Fetchable, Defaultable, Iterable>
90where
91 Keys: StorageKey,
92 ReturnTy: DecodeWithMetadata,
93{
94 #[doc(hidden)]
97 pub fn new_static(
98 pallet_name: &'static str,
99 entry_name: &'static str,
100 keys: Keys,
101 hash: [u8; 32],
102 ) -> Self {
103 Self {
104 pallet_name: Cow::Borrowed(pallet_name),
105 entry_name: Cow::Borrowed(entry_name),
106 keys,
107 validation_hash: Some(hash),
108 _marker: core::marker::PhantomData,
109 }
110 }
111}
112
113impl<Keys, ReturnTy, Fetchable, Defaultable, Iterable>
114 DefaultAddress<Keys, ReturnTy, Fetchable, Defaultable, Iterable>
115where
116 Keys: StorageKey,
117 ReturnTy: DecodeWithMetadata,
118{
119 pub fn unvalidated(self) -> Self {
121 Self {
122 validation_hash: None,
123 ..self
124 }
125 }
126
127 pub fn to_root_bytes(&self) -> Vec<u8> {
129 super::get_address_root_bytes(self)
130 }
131}
132
133impl<Keys, ReturnTy, Fetchable, Defaultable, Iterable> Address
134 for DefaultAddress<Keys, ReturnTy, Fetchable, Defaultable, Iterable>
135where
136 Keys: StorageKey,
137 ReturnTy: DecodeWithMetadata,
138{
139 type Target = ReturnTy;
140 type Keys = Keys;
141 type IsFetchable = Fetchable;
142 type IsDefaultable = Defaultable;
143 type IsIterable = Iterable;
144
145 fn pallet_name(&self) -> &str {
146 &self.pallet_name
147 }
148
149 fn entry_name(&self) -> &str {
150 &self.entry_name
151 }
152
153 fn append_entry_bytes(&self, metadata: &Metadata, bytes: &mut Vec<u8>) -> Result<(), Error> {
154 let pallet = metadata.pallet_by_name_err(self.pallet_name())?;
155 let storage = pallet
156 .storage()
157 .ok_or_else(|| MetadataError::StorageNotFoundInPallet(self.pallet_name().to_owned()))?;
158 let entry = storage
159 .entry_by_name(self.entry_name())
160 .ok_or_else(|| MetadataError::StorageEntryNotFound(self.entry_name().to_owned()))?;
161
162 let hashers = StorageHashers::new(entry.entry_type(), metadata.types())?;
163 self.keys
164 .encode_storage_key(bytes, &mut hashers.iter(), metadata.types())?;
165 Ok(())
166 }
167
168 fn validation_hash(&self) -> Option<[u8; 32]> {
169 self.validation_hash
170 }
171}
172
173pub fn dynamic<Keys: StorageKey>(
175 pallet_name: impl Into<String>,
176 entry_name: impl Into<String>,
177 storage_entry_keys: Keys,
178) -> DynamicAddress<Keys> {
179 DynamicAddress::new(pallet_name, entry_name, storage_entry_keys)
180}