1use crate::{
19 counter_prefix,
20 pallet::{
21 parse::{
22 helper::two128_str,
23 storage::{Metadata, QueryKind, StorageDef, StorageGenerics},
24 },
25 Def,
26 },
27};
28use quote::ToTokens;
29use std::{collections::HashMap, ops::IndexMut};
30use syn::spanned::Spanned;
31
32fn prefix_ident(storage: &StorageDef) -> syn::Ident {
35 let storage_ident = &storage.ident;
36 syn::Ident::new(&format!("_GeneratedPrefixForStorage{}", storage_ident), storage_ident.span())
37}
38
39fn counter_prefix_ident(storage_ident: &syn::Ident) -> syn::Ident {
42 syn::Ident::new(
43 &format!("_GeneratedCounterPrefixForStorage{}", storage_ident),
44 storage_ident.span(),
45 )
46}
47
48fn check_prefix_duplicates(
52 storage_def: &StorageDef,
53 used_prefixes: &mut HashMap<String, syn::Error>,
55) -> syn::Result<()> {
56 let prefix = storage_def.prefix();
57 let dup_err = syn::Error::new(
58 storage_def.prefix_span(),
59 format!("Duplicate storage prefixes found for `{}`", prefix),
60 );
61
62 if let Some(other_dup_err) = used_prefixes.insert(prefix.clone(), dup_err.clone()) {
63 let mut err = dup_err;
64 err.combine(other_dup_err);
65 return Err(err);
66 }
67
68 if let Metadata::CountedMap { .. } = storage_def.metadata {
69 let counter_prefix = counter_prefix(&prefix);
70 let counter_dup_err = syn::Error::new(
71 storage_def.prefix_span(),
72 format!(
73 "Duplicate storage prefixes found for `{}`, used for counter associated to \
74 counted storage map",
75 counter_prefix,
76 ),
77 );
78
79 if let Some(other_dup_err) = used_prefixes.insert(counter_prefix, counter_dup_err.clone()) {
80 let mut err = counter_dup_err;
81 err.combine(other_dup_err);
82 return Err(err);
83 }
84 }
85
86 Ok(())
87}
88
89pub struct ResultOnEmptyStructMetadata {
90 pub name: syn::Ident,
92 pub error_path: syn::Path,
94 pub visibility: syn::Visibility,
96 pub value_ty: syn::Type,
98 pub variant_name: syn::Ident,
100 pub span: proc_macro2::Span,
102}
103
104pub fn process_generics(def: &mut Def) -> syn::Result<Vec<ResultOnEmptyStructMetadata>> {
109 let frame_support = &def.frame_support;
110 let mut on_empty_struct_metadata = Vec::new();
111
112 for storage_def in def.storages.iter_mut() {
113 let item = &mut def.item.content.as_mut().expect("Checked by def").1[storage_def.index];
114
115 let typ_item = match item {
116 syn::Item::Type(t) => t,
117 _ => unreachable!("Checked by def"),
118 };
119
120 typ_item.attrs.push(syn::parse_quote!(#[allow(type_alias_bounds)]));
121
122 let typ_path = match &mut *typ_item.ty {
123 syn::Type::Path(p) => p,
124 _ => unreachable!("Checked by def"),
125 };
126
127 let args = match &mut typ_path.path.segments[0].arguments {
128 syn::PathArguments::AngleBracketed(args) => args,
129 _ => unreachable!("Checked by def"),
130 };
131
132 let prefix_ident = prefix_ident(storage_def);
133 let type_use_gen = if def.config.has_instance {
134 quote::quote_spanned!(storage_def.attr_span => T, I)
135 } else {
136 quote::quote_spanned!(storage_def.attr_span => T)
137 };
138
139 let default_query_kind: syn::Type =
140 syn::parse_quote!(#frame_support::storage::types::OptionQuery);
141 let mut default_on_empty = |value_ty: syn::Type| -> syn::Type {
142 if let Some(QueryKind::ResultQuery(error_path, variant_name)) =
143 storage_def.query_kind.as_ref()
144 {
145 let on_empty_ident =
146 quote::format_ident!("__Frame_Internal_Get{}Result", storage_def.ident);
147 on_empty_struct_metadata.push(ResultOnEmptyStructMetadata {
148 name: on_empty_ident.clone(),
149 visibility: storage_def.vis.clone(),
150 value_ty,
151 error_path: error_path.clone(),
152 variant_name: variant_name.clone(),
153 span: storage_def.attr_span,
154 });
155 return syn::parse_quote!(#on_empty_ident);
156 }
157 syn::parse_quote!(#frame_support::traits::GetDefault)
158 };
159 let default_max_values: syn::Type = syn::parse_quote!(#frame_support::traits::GetDefault);
160
161 let set_result_query_type_parameter = |query_type: &mut syn::Type| -> syn::Result<()> {
162 if let Some(QueryKind::ResultQuery(error_path, _)) = storage_def.query_kind.as_ref() {
163 if let syn::Type::Path(syn::TypePath { path: syn::Path { segments, .. }, .. }) =
164 query_type
165 {
166 if let Some(seg) = segments.last_mut() {
167 if let syn::PathArguments::AngleBracketed(
168 syn::AngleBracketedGenericArguments { args, .. },
169 ) = &mut seg.arguments
170 {
171 args.clear();
172 args.push(syn::GenericArgument::Type(syn::parse_quote!(#error_path)));
173 }
174 }
175 } else {
176 let msg = format!(
177 "Invalid pallet::storage, unexpected type for query, expected ResultQuery \
178 with 1 type parameter, found `{}`",
179 query_type.to_token_stream().to_string()
180 );
181 return Err(syn::Error::new(query_type.span(), msg));
182 }
183 }
184 Ok(())
185 };
186
187 if let Some(named_generics) = storage_def.named_generics.clone() {
188 args.args.clear();
189 args.args.push(syn::parse_quote!( #prefix_ident<#type_use_gen> ));
190 match named_generics {
191 StorageGenerics::Value { value, query_kind, on_empty } => {
192 args.args.push(syn::GenericArgument::Type(value.clone()));
193 let mut query_kind = query_kind.unwrap_or_else(|| default_query_kind.clone());
194 set_result_query_type_parameter(&mut query_kind)?;
195 args.args.push(syn::GenericArgument::Type(query_kind));
196 let on_empty = on_empty.unwrap_or_else(|| default_on_empty(value));
197 args.args.push(syn::GenericArgument::Type(on_empty));
198 },
199 StorageGenerics::Map { hasher, key, value, query_kind, on_empty, max_values } |
200 StorageGenerics::CountedMap {
201 hasher,
202 key,
203 value,
204 query_kind,
205 on_empty,
206 max_values,
207 } => {
208 args.args.push(syn::GenericArgument::Type(hasher));
209 args.args.push(syn::GenericArgument::Type(key));
210 args.args.push(syn::GenericArgument::Type(value.clone()));
211 let mut query_kind = query_kind.unwrap_or_else(|| default_query_kind.clone());
212 set_result_query_type_parameter(&mut query_kind)?;
213 args.args.push(syn::GenericArgument::Type(query_kind));
214 let on_empty = on_empty.unwrap_or_else(|| default_on_empty(value));
215 args.args.push(syn::GenericArgument::Type(on_empty));
216 let max_values = max_values.unwrap_or_else(|| default_max_values.clone());
217 args.args.push(syn::GenericArgument::Type(max_values));
218 },
219 StorageGenerics::DoubleMap {
220 hasher1,
221 key1,
222 hasher2,
223 key2,
224 value,
225 query_kind,
226 on_empty,
227 max_values,
228 } => {
229 args.args.push(syn::GenericArgument::Type(hasher1));
230 args.args.push(syn::GenericArgument::Type(key1));
231 args.args.push(syn::GenericArgument::Type(hasher2));
232 args.args.push(syn::GenericArgument::Type(key2));
233 args.args.push(syn::GenericArgument::Type(value.clone()));
234 let mut query_kind = query_kind.unwrap_or_else(|| default_query_kind.clone());
235 set_result_query_type_parameter(&mut query_kind)?;
236 args.args.push(syn::GenericArgument::Type(query_kind));
237 let on_empty = on_empty.unwrap_or_else(|| default_on_empty(value));
238 args.args.push(syn::GenericArgument::Type(on_empty));
239 let max_values = max_values.unwrap_or_else(|| default_max_values.clone());
240 args.args.push(syn::GenericArgument::Type(max_values));
241 },
242 StorageGenerics::NMap { keygen, value, query_kind, on_empty, max_values } |
243 StorageGenerics::CountedNMap {
244 keygen,
245 value,
246 query_kind,
247 on_empty,
248 max_values,
249 } => {
250 args.args.push(syn::GenericArgument::Type(keygen));
251 args.args.push(syn::GenericArgument::Type(value.clone()));
252 let mut query_kind = query_kind.unwrap_or_else(|| default_query_kind.clone());
253 set_result_query_type_parameter(&mut query_kind)?;
254 args.args.push(syn::GenericArgument::Type(query_kind));
255 let on_empty = on_empty.unwrap_or_else(|| default_on_empty(value));
256 args.args.push(syn::GenericArgument::Type(on_empty));
257 let max_values = max_values.unwrap_or_else(|| default_max_values.clone());
258 args.args.push(syn::GenericArgument::Type(max_values));
259 },
260 }
261 } else {
262 args.args[0] = syn::parse_quote!( #prefix_ident<#type_use_gen> );
263
264 let (value_idx, query_idx, on_empty_idx) = match storage_def.metadata {
265 Metadata::Value { .. } => (1, 2, 3),
266 Metadata::NMap { .. } | Metadata::CountedNMap { .. } => (2, 3, 4),
267 Metadata::Map { .. } | Metadata::CountedMap { .. } => (3, 4, 5),
268 Metadata::DoubleMap { .. } => (5, 6, 7),
269 };
270
271 if storage_def.use_default_hasher {
272 let hasher_indices: Vec<usize> = match storage_def.metadata {
273 Metadata::Map { .. } | Metadata::CountedMap { .. } => vec![1],
274 Metadata::DoubleMap { .. } => vec![1, 3],
275 _ => vec![],
276 };
277 for hasher_idx in hasher_indices {
278 args.args[hasher_idx] = syn::GenericArgument::Type(
279 syn::parse_quote!(#frame_support::Blake2_128Concat),
280 );
281 }
282 }
283
284 if query_idx < args.args.len() {
285 if let syn::GenericArgument::Type(query_kind) = args.args.index_mut(query_idx) {
286 set_result_query_type_parameter(query_kind)?;
287 }
288 } else if let Some(QueryKind::ResultQuery(error_path, _)) =
289 storage_def.query_kind.as_ref()
290 {
291 args.args.push(syn::GenericArgument::Type(syn::parse_quote!(#error_path)))
292 }
293
294 if on_empty_idx >= args.args.len() &&
297 matches!(storage_def.query_kind.as_ref(), Some(QueryKind::ResultQuery(_, _)))
298 {
299 let value_ty = match args.args[value_idx].clone() {
300 syn::GenericArgument::Type(ty) => ty,
301 _ => unreachable!(),
302 };
303 let on_empty = default_on_empty(value_ty);
304 args.args.push(syn::GenericArgument::Type(on_empty));
305 }
306 }
307 }
308
309 Ok(on_empty_struct_metadata)
310}
311
312fn augment_final_docs(def: &mut Def) {
313 let mut push_string_literal = |doc_line: &str, storage: &mut StorageDef| {
316 let item = &mut def.item.content.as_mut().expect("Checked by def").1[storage.index];
317 let typ_item = match item {
318 syn::Item::Type(t) => t,
319 _ => unreachable!("Checked by def"),
320 };
321 typ_item.attrs.push(syn::parse_quote!(#[doc = ""]));
322 typ_item.attrs.push(syn::parse_quote!(#[doc = #doc_line]));
323 };
324 def.storages.iter_mut().for_each(|storage| match &storage.metadata {
325 Metadata::Value { value } => {
326 let doc_line = format!(
327 "Storage type is [`StorageValue`] with value type `{}`.",
328 value.to_token_stream()
329 );
330 push_string_literal(&doc_line, storage);
331 },
332 Metadata::Map { key, value } => {
333 let doc_line = format!(
334 "Storage type is [`StorageMap`] with key type `{}` and value type `{}`.",
335 key.to_token_stream(),
336 value.to_token_stream()
337 );
338 push_string_literal(&doc_line, storage);
339 },
340 Metadata::DoubleMap { key1, key2, value } => {
341 let doc_line = format!(
342 "Storage type is [`StorageDoubleMap`] with key1 type {}, key2 type {} and value type {}.",
343 key1.to_token_stream(),
344 key2.to_token_stream(),
345 value.to_token_stream()
346 );
347 push_string_literal(&doc_line, storage);
348 },
349 Metadata::NMap { keys, value, .. } => {
350 let doc_line = format!(
351 "Storage type is [`StorageNMap`] with keys type ({}) and value type {}.",
352 keys.iter()
353 .map(|k| k.to_token_stream().to_string())
354 .collect::<Vec<_>>()
355 .join(", "),
356 value.to_token_stream()
357 );
358 push_string_literal(&doc_line, storage);
359 },
360 Metadata::CountedNMap { keys, value, .. } => {
361 let doc_line = format!(
362 "Storage type is [`CountedStorageNMap`] with keys type ({}) and value type {}.",
363 keys.iter()
364 .map(|k| k.to_token_stream().to_string())
365 .collect::<Vec<_>>()
366 .join(", "),
367 value.to_token_stream()
368 );
369 push_string_literal(&doc_line, storage);
370 },
371 Metadata::CountedMap { key, value } => {
372 let doc_line = format!(
373 "Storage type is [`CountedStorageMap`] with key type {} and value type {}.",
374 key.to_token_stream(),
375 value.to_token_stream()
376 );
377 push_string_literal(&doc_line, storage);
378 },
379 });
380}
381
382pub fn expand_storages(def: &mut Def) -> proc_macro2::TokenStream {
390 let on_empty_struct_metadata = match process_generics(def) {
391 Ok(idents) => idents,
392 Err(e) => return e.into_compile_error(),
393 };
394
395 augment_final_docs(def);
396
397 let mut prefix_set = HashMap::new();
399 let mut errors = def
400 .storages
401 .iter()
402 .filter_map(|storage_def| check_prefix_duplicates(storage_def, &mut prefix_set).err());
403 if let Some(mut final_error) = errors.next() {
404 errors.for_each(|error| final_error.combine(error));
405 return final_error.into_compile_error();
406 }
407
408 let frame_support = &def.frame_support;
409 let frame_system = &def.frame_system;
410 let pallet_ident = &def.pallet_struct.pallet;
411 let mut entries_builder = vec![];
412 for storage in def.storages.iter() {
413 let no_docs = vec![];
414 let docs = if cfg!(feature = "no-metadata-docs") { &no_docs } else { &storage.docs };
415
416 let ident = &storage.ident;
417 let gen = &def.type_use_generics(storage.attr_span);
418 let full_ident = quote::quote_spanned!(storage.attr_span => #ident<#gen> );
419
420 let cfg_attrs = &storage.cfg_attrs;
421 let deprecation = match crate::deprecation::get_deprecation(
422 "e::quote! { #frame_support },
423 &storage.attrs,
424 ) {
425 Ok(deprecation) => deprecation,
426 Err(e) => return e.into_compile_error(),
427 };
428 entries_builder.push(quote::quote_spanned!(storage.attr_span =>
429 #(#cfg_attrs)*
430 {
431 <#full_ident as #frame_support::storage::StorageEntryMetadataBuilder>::build_metadata(
432 #deprecation,
433 #frame_support::__private::vec![
434 #( #docs, )*
435 ],
436 &mut entries,
437 );
438 }
439 ))
440 }
441
442 let getters = def.storages.iter().map(|storage| {
443 if let Some(getter) = &storage.getter {
444 let completed_where_clause =
445 super::merge_where_clauses(&[&storage.where_clause, &def.config.where_clause]);
446
447 let ident = &storage.ident;
448 let gen = &def.type_use_generics(storage.attr_span);
449 let type_impl_gen = &def.type_impl_generics(storage.attr_span);
450 let type_use_gen = &def.type_use_generics(storage.attr_span);
451 let full_ident = quote::quote_spanned!(storage.attr_span => #ident<#gen> );
452
453 let cfg_attrs = &storage.cfg_attrs;
454
455 let getter_doc_line = if matches!(storage.vis, syn::Visibility::Public(_)) {
460 format!("An auto-generated getter for [`{}`].", storage.ident)
461 } else {
462 format!("An auto-generated getter for `{}`.", storage.ident)
463 };
464
465 match &storage.metadata {
466 Metadata::Value { value } => {
467 let query = match storage.query_kind.as_ref().expect("Checked by def") {
468 QueryKind::OptionQuery => quote::quote_spanned!(storage.attr_span =>
469 Option<#value>
470 ),
471 QueryKind::ResultQuery(error_path, _) => {
472 quote::quote_spanned!(storage.attr_span =>
473 Result<#value, #error_path>
474 )
475 },
476 QueryKind::ValueQuery => quote::quote!(#value),
477 };
478 quote::quote_spanned!(storage.attr_span =>
479 #(#cfg_attrs)*
480 impl<#type_impl_gen> #pallet_ident<#type_use_gen> #completed_where_clause {
481 #[doc = #getter_doc_line]
482 pub fn #getter() -> #query {
483 <
484 #full_ident as #frame_support::storage::StorageValue<#value>
485 >::get()
486 }
487 }
488 )
489 },
490 Metadata::Map { key, value } => {
491 let query = match storage.query_kind.as_ref().expect("Checked by def") {
492 QueryKind::OptionQuery => quote::quote_spanned!(storage.attr_span =>
493 Option<#value>
494 ),
495 QueryKind::ResultQuery(error_path, _) => {
496 quote::quote_spanned!(storage.attr_span =>
497 Result<#value, #error_path>
498 )
499 },
500 QueryKind::ValueQuery => quote::quote!(#value),
501 };
502 quote::quote_spanned!(storage.attr_span =>
503 #(#cfg_attrs)*
504 impl<#type_impl_gen> #pallet_ident<#type_use_gen> #completed_where_clause {
505 #[doc = #getter_doc_line]
506 pub fn #getter<KArg>(k: KArg) -> #query where
507 KArg: #frame_support::__private::codec::EncodeLike<#key>,
508 {
509 <
510 #full_ident as #frame_support::storage::StorageMap<#key, #value>
511 >::get(k)
512 }
513 }
514 )
515 },
516 Metadata::CountedMap { key, value } => {
517 let query = match storage.query_kind.as_ref().expect("Checked by def") {
518 QueryKind::OptionQuery => quote::quote_spanned!(storage.attr_span =>
519 Option<#value>
520 ),
521 QueryKind::ResultQuery(error_path, _) => {
522 quote::quote_spanned!(storage.attr_span =>
523 Result<#value, #error_path>
524 )
525 },
526 QueryKind::ValueQuery => quote::quote!(#value),
527 };
528 quote::quote_spanned!(storage.attr_span =>
529 #(#cfg_attrs)*
530 impl<#type_impl_gen> #pallet_ident<#type_use_gen> #completed_where_clause {
531 #[doc = #getter_doc_line]
532 pub fn #getter<KArg>(k: KArg) -> #query where
533 KArg: #frame_support::__private::codec::EncodeLike<#key>,
534 {
535 <#full_ident>::get(k)
538 }
539 }
540 )
541 },
542 Metadata::DoubleMap { key1, key2, value } => {
543 let query = match storage.query_kind.as_ref().expect("Checked by def") {
544 QueryKind::OptionQuery => quote::quote_spanned!(storage.attr_span =>
545 Option<#value>
546 ),
547 QueryKind::ResultQuery(error_path, _) => {
548 quote::quote_spanned!(storage.attr_span =>
549 Result<#value, #error_path>
550 )
551 },
552 QueryKind::ValueQuery => quote::quote!(#value),
553 };
554 quote::quote_spanned!(storage.attr_span =>
555 #(#cfg_attrs)*
556 impl<#type_impl_gen> #pallet_ident<#type_use_gen> #completed_where_clause {
557 #[doc = #getter_doc_line]
558 pub fn #getter<KArg1, KArg2>(k1: KArg1, k2: KArg2) -> #query where
559 KArg1: #frame_support::__private::codec::EncodeLike<#key1>,
560 KArg2: #frame_support::__private::codec::EncodeLike<#key2>,
561 {
562 <
563 #full_ident as
564 #frame_support::storage::StorageDoubleMap<#key1, #key2, #value>
565 >::get(k1, k2)
566 }
567 }
568 )
569 },
570 Metadata::NMap { keygen, value, .. } => {
571 let query = match storage.query_kind.as_ref().expect("Checked by def") {
572 QueryKind::OptionQuery => quote::quote_spanned!(storage.attr_span =>
573 Option<#value>
574 ),
575 QueryKind::ResultQuery(error_path, _) => {
576 quote::quote_spanned!(storage.attr_span =>
577 Result<#value, #error_path>
578 )
579 },
580 QueryKind::ValueQuery => quote::quote!(#value),
581 };
582 quote::quote_spanned!(storage.attr_span =>
583 #(#cfg_attrs)*
584 impl<#type_impl_gen> #pallet_ident<#type_use_gen> #completed_where_clause {
585 #[doc = #getter_doc_line]
586 pub fn #getter<KArg>(key: KArg) -> #query
587 where
588 KArg: #frame_support::storage::types::EncodeLikeTuple<
589 <#keygen as #frame_support::storage::types::KeyGenerator>::KArg
590 >
591 + #frame_support::storage::types::TupleToEncodedIter,
592 {
593 <
594 #full_ident as
595 #frame_support::storage::StorageNMap<#keygen, #value>
596 >::get(key)
597 }
598 }
599 )
600 },
601 Metadata::CountedNMap { keygen, value, .. } => {
602 let query = match storage.query_kind.as_ref().expect("Checked by def") {
603 QueryKind::OptionQuery => quote::quote_spanned!(storage.attr_span =>
604 Option<#value>
605 ),
606 QueryKind::ResultQuery(error_path, _) => {
607 quote::quote_spanned!(storage.attr_span =>
608 Result<#value, #error_path>
609 )
610 },
611 QueryKind::ValueQuery => quote::quote!(#value),
612 };
613 quote::quote_spanned!(storage.attr_span =>
614 #(#cfg_attrs)*
615 impl<#type_impl_gen> #pallet_ident<#type_use_gen> #completed_where_clause {
616 #[doc = #getter_doc_line]
617 pub fn #getter<KArg>(key: KArg) -> #query
618 where
619 KArg: #frame_support::storage::types::EncodeLikeTuple<
620 <#keygen as #frame_support::storage::types::KeyGenerator>::KArg
621 >
622 + #frame_support::storage::types::TupleToEncodedIter,
623 {
624 <#full_ident>::get(key)
627 }
628 }
629 )
630 },
631 }
632 } else {
633 Default::default()
634 }
635 });
636
637 let prefix_structs = def.storages.iter().map(|storage_def| {
638 let type_impl_gen = &def.type_impl_generics(storage_def.attr_span);
639 let type_use_gen = &def.type_use_generics(storage_def.attr_span);
640 let prefix_struct_ident = prefix_ident(storage_def);
641 let prefix_struct_vis = &storage_def.vis;
642 let prefix_struct_const = storage_def.prefix();
643 let config_where_clause = &def.config.where_clause;
644
645 let cfg_attrs = &storage_def.cfg_attrs;
646
647 let maybe_counter = match storage_def.metadata {
648 Metadata::CountedMap { .. } => {
649 let counter_prefix_struct_ident = counter_prefix_ident(&storage_def.ident);
650 let counter_prefix_struct_const = counter_prefix(&prefix_struct_const);
651 let storage_prefix_hash = two128_str(&counter_prefix_struct_const);
652 quote::quote_spanned!(storage_def.attr_span =>
653 #(#cfg_attrs)*
654 #[doc(hidden)]
655 #prefix_struct_vis struct #counter_prefix_struct_ident<#type_use_gen>(
656 core::marker::PhantomData<(#type_use_gen,)>
657 );
658 #(#cfg_attrs)*
659 impl<#type_impl_gen> #frame_support::traits::StorageInstance
660 for #counter_prefix_struct_ident<#type_use_gen>
661 #config_where_clause
662 {
663 fn pallet_prefix() -> &'static str {
664 <
665 <T as #frame_system::Config>::PalletInfo
666 as #frame_support::traits::PalletInfo
667 >::name::<Pallet<#type_use_gen>>()
668 .expect("No name found for the pallet in the runtime! This usually means that the pallet wasn't added to `construct_runtime!`.")
669 }
670
671 fn pallet_prefix_hash() -> [u8; 16] {
672 <
673 <T as #frame_system::Config>::PalletInfo
674 as #frame_support::traits::PalletInfo
675 >::name_hash::<Pallet<#type_use_gen>>()
676 .expect("No name_hash found for the pallet in the runtime! This usually means that the pallet wasn't added to `construct_runtime!`.")
677 }
678
679 const STORAGE_PREFIX: &'static str = #counter_prefix_struct_const;
680 fn storage_prefix_hash() -> [u8; 16] {
681 #storage_prefix_hash
682 }
683 }
684 #(#cfg_attrs)*
685 impl<#type_impl_gen> #frame_support::storage::types::CountedStorageMapInstance
686 for #prefix_struct_ident<#type_use_gen>
687 #config_where_clause
688 {
689 type CounterPrefix = #counter_prefix_struct_ident<#type_use_gen>;
690 }
691 )
692 },
693 Metadata::CountedNMap { .. } => {
694 let counter_prefix_struct_ident = counter_prefix_ident(&storage_def.ident);
695 let counter_prefix_struct_const = counter_prefix(&prefix_struct_const);
696 let storage_prefix_hash = two128_str(&counter_prefix_struct_const);
697 quote::quote_spanned!(storage_def.attr_span =>
698 #(#cfg_attrs)*
699 #[doc(hidden)]
700 #prefix_struct_vis struct #counter_prefix_struct_ident<#type_use_gen>(
701 core::marker::PhantomData<(#type_use_gen,)>
702 );
703 #(#cfg_attrs)*
704 impl<#type_impl_gen> #frame_support::traits::StorageInstance
705 for #counter_prefix_struct_ident<#type_use_gen>
706 #config_where_clause
707 {
708 fn pallet_prefix() -> &'static str {
709 <
710 <T as #frame_system::Config>::PalletInfo
711 as #frame_support::traits::PalletInfo
712 >::name::<Pallet<#type_use_gen>>()
713 .expect("No name found for the pallet in the runtime! This usually means that the pallet wasn't added to `construct_runtime!`.")
714 }
715 fn pallet_prefix_hash() -> [u8; 16] {
716 <
717 <T as #frame_system::Config>::PalletInfo
718 as #frame_support::traits::PalletInfo
719 >::name_hash::<Pallet<#type_use_gen>>()
720 .expect("No name_hash found for the pallet in the runtime! This usually means that the pallet wasn't added to `construct_runtime!`.")
721 }
722 const STORAGE_PREFIX: &'static str = #counter_prefix_struct_const;
723 fn storage_prefix_hash() -> [u8; 16] {
724 #storage_prefix_hash
725 }
726 }
727 #(#cfg_attrs)*
728 impl<#type_impl_gen> #frame_support::storage::types::CountedStorageNMapInstance
729 for #prefix_struct_ident<#type_use_gen>
730 #config_where_clause
731 {
732 type CounterPrefix = #counter_prefix_struct_ident<#type_use_gen>;
733 }
734 )
735 },
736 _ => proc_macro2::TokenStream::default(),
737 };
738
739 let storage_prefix_hash = two128_str(&prefix_struct_const);
740 quote::quote_spanned!(storage_def.attr_span =>
741 #maybe_counter
742
743 #(#cfg_attrs)*
744 #[doc(hidden)]
745 #prefix_struct_vis struct #prefix_struct_ident<#type_use_gen>(
746 core::marker::PhantomData<(#type_use_gen,)>
747 );
748 #(#cfg_attrs)*
749 impl<#type_impl_gen> #frame_support::traits::StorageInstance
750 for #prefix_struct_ident<#type_use_gen>
751 #config_where_clause
752 {
753 fn pallet_prefix() -> &'static str {
754 <
755 <T as #frame_system::Config>::PalletInfo
756 as #frame_support::traits::PalletInfo
757 >::name::<Pallet<#type_use_gen>>()
758 .expect("No name found for the pallet in the runtime! This usually means that the pallet wasn't added to `construct_runtime!`.")
759 }
760
761 fn pallet_prefix_hash() -> [u8; 16] {
762 <
763 <T as #frame_system::Config>::PalletInfo
764 as #frame_support::traits::PalletInfo
765 >::name_hash::<Pallet<#type_use_gen>>()
766 .expect("No name_hash found for the pallet in the runtime! This usually means that the pallet wasn't added to `construct_runtime!`.")
767 }
768
769 const STORAGE_PREFIX: &'static str = #prefix_struct_const;
770 fn storage_prefix_hash() -> [u8; 16] {
771 #storage_prefix_hash
772 }
773 }
774 )
775 });
776
777 let on_empty_structs = on_empty_struct_metadata.into_iter().map(|metadata| {
778 use crate::pallet::parse::GenericKind;
779 use syn::{GenericArgument, Path, PathArguments, PathSegment, Type, TypePath};
780
781 let ResultOnEmptyStructMetadata {
782 name,
783 visibility,
784 value_ty,
785 error_path,
786 variant_name,
787 span,
788 } = metadata;
789
790 let generic_kind = match error_path.segments.last() {
791 Some(PathSegment { arguments: PathArguments::AngleBracketed(args), .. }) => {
792 let (has_config, has_instance) =
793 args.args.iter().fold((false, false), |(has_config, has_instance), arg| {
794 match arg {
795 GenericArgument::Type(Type::Path(TypePath {
796 path: Path { segments, .. },
797 ..
798 })) => {
799 let maybe_config =
800 segments.first().map_or(false, |seg| seg.ident == "T");
801 let maybe_instance =
802 segments.first().map_or(false, |seg| seg.ident == "I");
803
804 (has_config || maybe_config, has_instance || maybe_instance)
805 },
806 _ => (has_config, has_instance),
807 }
808 });
809 GenericKind::from_gens(has_config, has_instance).unwrap_or(GenericKind::None)
810 },
811 _ => GenericKind::None,
812 };
813 let type_impl_gen = generic_kind.type_impl_gen(proc_macro2::Span::call_site());
814 let config_where_clause = &def.config.where_clause;
815
816 quote::quote_spanned!(span =>
817 #[doc(hidden)]
818 #[allow(non_camel_case_types)]
819 #visibility struct #name;
820
821 impl<#type_impl_gen> #frame_support::traits::Get<Result<#value_ty, #error_path>>
822 for #name
823 #config_where_clause
824 {
825 fn get() -> Result<#value_ty, #error_path> {
826 Err(<#error_path>::#variant_name)
827 }
828 }
829 )
830 });
831
832 let mut where_clauses = vec![&def.config.where_clause];
834 where_clauses.extend(def.storages.iter().map(|storage| &storage.where_clause));
835 let completed_where_clause = super::merge_where_clauses(&where_clauses);
836 let type_impl_gen = &def.type_impl_generics(proc_macro2::Span::call_site());
837 let type_use_gen = &def.type_use_generics(proc_macro2::Span::call_site());
838
839 let try_decode_entire_state = {
840 let mut storage_names = def
841 .storages
842 .iter()
843 .filter_map(|storage| {
844 if storage.try_decode && storage.cfg_attrs.is_empty() {
848 let ident = &storage.ident;
849 let gen = &def.type_use_generics(storage.attr_span);
850 Some(quote::quote_spanned!(storage.attr_span => #ident<#gen> ))
851 } else {
852 None
853 }
854 })
855 .collect::<Vec<_>>();
856 storage_names.sort_by_cached_key(|ident| ident.to_string());
857
858 quote::quote!(
859 #frame_support::try_runtime_enabled! {
860 impl<#type_impl_gen> #frame_support::traits::TryDecodeEntireStorage
861 for #pallet_ident<#type_use_gen> #completed_where_clause
862 {
863 fn try_decode_entire_state() -> Result<usize, #frame_support::__private::Vec<#frame_support::traits::TryDecodeEntireStorageError>> {
864 let pallet_name = <<T as #frame_system::Config>::PalletInfo as #frame_support::traits::PalletInfo>
865 ::name::<#pallet_ident<#type_use_gen>>()
866 .expect("Every active pallet has a name in the runtime; qed");
867
868 #frame_support::__private::log::debug!(target: "runtime::try-decode-state", "trying to decode pallet: {pallet_name}");
869
870 let mut errors = #frame_support::__private::Vec::new();
872 let mut decoded = 0usize;
873
874 #(
875 #frame_support::__private::log::debug!(target: "runtime::try-decode-state", "trying to decode storage: \
876 {pallet_name}::{}", stringify!(#storage_names));
877
878 match <#storage_names as #frame_support::traits::TryDecodeEntireStorage>::try_decode_entire_state() {
879 Ok(count) => {
880 decoded += count;
881 },
882 Err(err) => {
883 errors.extend(err);
884 },
885 }
886 )*
887
888 if errors.is_empty() {
889 Ok(decoded)
890 } else {
891 Err(errors)
892 }
893 }
894 }
895 }
896 )
897 };
898
899 quote::quote!(
900 impl<#type_impl_gen> #pallet_ident<#type_use_gen>
901 #completed_where_clause
902 {
903 #[doc(hidden)]
904 pub fn storage_metadata() -> #frame_support::__private::metadata_ir::PalletStorageMetadataIR {
905 #frame_support::__private::metadata_ir::PalletStorageMetadataIR {
906 prefix: <
907 <T as #frame_system::Config>::PalletInfo as
908 #frame_support::traits::PalletInfo
909 >::name::<#pallet_ident<#type_use_gen>>()
910 .expect("No name found for the pallet in the runtime! This usually means that the pallet wasn't added to `construct_runtime!`."),
911 entries: {
912 #[allow(unused_mut)]
913 let mut entries = #frame_support::__private::vec![];
914 #( #entries_builder )*
915 entries
916 },
917 }
918 }
919 }
920
921 #( #getters )*
922 #( #prefix_structs )*
923 #( #on_empty_structs )*
924
925 #try_decode_entire_state
926 )
927}