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