1use super::helper;
19use frame_support_procedural_tools::get_doc_literals;
20use quote::ToTokens;
21use std::collections::HashMap;
22use syn::spanned::Spanned;
23
24mod keyword {
26 syn::custom_keyword!(Error);
27 syn::custom_keyword!(pallet);
28 syn::custom_keyword!(getter);
29 syn::custom_keyword!(storage_prefix);
30 syn::custom_keyword!(unbounded);
31 syn::custom_keyword!(whitelist_storage);
32 syn::custom_keyword!(disable_try_decode_storage);
33 syn::custom_keyword!(OptionQuery);
34 syn::custom_keyword!(ResultQuery);
35 syn::custom_keyword!(ValueQuery);
36}
37
38pub enum PalletStorageAttr {
45 Getter(syn::Ident, proc_macro2::Span),
46 StorageName(syn::LitStr, proc_macro2::Span),
47 Unbounded(proc_macro2::Span),
48 WhitelistStorage(proc_macro2::Span),
49 DisableTryDecodeStorage(proc_macro2::Span),
50}
51
52impl PalletStorageAttr {
53 fn attr_span(&self) -> proc_macro2::Span {
54 match self {
55 Self::Getter(_, span) |
56 Self::StorageName(_, span) |
57 Self::Unbounded(span) |
58 Self::WhitelistStorage(span) => *span,
59 Self::DisableTryDecodeStorage(span) => *span,
60 }
61 }
62}
63
64impl syn::parse::Parse for PalletStorageAttr {
65 fn parse(input: syn::parse::ParseStream) -> syn::Result<Self> {
66 input.parse::<syn::Token![#]>()?;
67 let attr_span = input.span();
68 let content;
69 syn::bracketed!(content in input);
70 content.parse::<keyword::pallet>()?;
71 content.parse::<syn::Token![::]>()?;
72
73 let lookahead = content.lookahead1();
74 if lookahead.peek(keyword::getter) {
75 content.parse::<keyword::getter>()?;
76
77 let generate_content;
78 syn::parenthesized!(generate_content in content);
79 generate_content.parse::<syn::Token![fn]>()?;
80 Ok(Self::Getter(generate_content.parse::<syn::Ident>()?, attr_span))
81 } else if lookahead.peek(keyword::storage_prefix) {
82 content.parse::<keyword::storage_prefix>()?;
83 content.parse::<syn::Token![=]>()?;
84
85 let renamed_prefix = content.parse::<syn::LitStr>()?;
86 syn::parse_str::<syn::Ident>(&renamed_prefix.value()).map_err(|_| {
88 let msg = format!("`{}` is not a valid identifier", renamed_prefix.value());
89 syn::Error::new(renamed_prefix.span(), msg)
90 })?;
91
92 Ok(Self::StorageName(renamed_prefix, attr_span))
93 } else if lookahead.peek(keyword::unbounded) {
94 content.parse::<keyword::unbounded>()?;
95
96 Ok(Self::Unbounded(attr_span))
97 } else if lookahead.peek(keyword::whitelist_storage) {
98 content.parse::<keyword::whitelist_storage>()?;
99 Ok(Self::WhitelistStorage(attr_span))
100 } else if lookahead.peek(keyword::disable_try_decode_storage) {
101 content.parse::<keyword::disable_try_decode_storage>()?;
102 Ok(Self::DisableTryDecodeStorage(attr_span))
103 } else {
104 Err(lookahead.error())
105 }
106 }
107}
108
109struct PalletStorageAttrInfo {
110 getter: Option<syn::Ident>,
111 rename_as: Option<syn::LitStr>,
112 unbounded: bool,
113 whitelisted: bool,
114 try_decode: bool,
115}
116
117impl PalletStorageAttrInfo {
118 fn from_attrs(attrs: Vec<PalletStorageAttr>) -> syn::Result<Self> {
119 let mut getter = None;
120 let mut rename_as = None;
121 let mut unbounded = false;
122 let mut whitelisted = false;
123 let mut disable_try_decode_storage = false;
124 for attr in attrs {
125 match attr {
126 PalletStorageAttr::Getter(ident, ..) if getter.is_none() => getter = Some(ident),
127 PalletStorageAttr::StorageName(name, ..) if rename_as.is_none() =>
128 rename_as = Some(name),
129 PalletStorageAttr::Unbounded(..) if !unbounded => unbounded = true,
130 PalletStorageAttr::WhitelistStorage(..) if !whitelisted => whitelisted = true,
131 PalletStorageAttr::DisableTryDecodeStorage(..) if !disable_try_decode_storage =>
132 disable_try_decode_storage = true,
133 attr =>
134 return Err(syn::Error::new(
135 attr.attr_span(),
136 "Invalid attribute: Duplicate attribute",
137 )),
138 }
139 }
140
141 Ok(PalletStorageAttrInfo {
142 getter,
143 rename_as,
144 unbounded,
145 whitelisted,
146 try_decode: !disable_try_decode_storage,
147 })
148 }
149}
150
151pub enum Metadata {
153 Value { value: syn::Type },
154 Map { value: syn::Type, key: syn::Type },
155 CountedMap { value: syn::Type, key: syn::Type },
156 DoubleMap { value: syn::Type, key1: syn::Type, key2: syn::Type },
157 NMap { keys: Vec<syn::Type>, keygen: syn::Type, value: syn::Type },
158 CountedNMap { keys: Vec<syn::Type>, keygen: syn::Type, value: syn::Type },
159}
160
161pub enum QueryKind {
162 OptionQuery,
163 ResultQuery(syn::Path, syn::Ident),
164 ValueQuery,
165}
166
167pub struct StorageDef {
171 pub index: usize,
173 pub vis: syn::Visibility,
175 pub ident: syn::Ident,
177 pub metadata: Metadata,
179 pub docs: Vec<syn::Expr>,
181 pub instances: Vec<helper::InstanceUsage>,
183 pub getter: Option<syn::Ident>,
185 pub rename_as: Option<syn::LitStr>,
188 pub query_kind: Option<QueryKind>,
192 pub where_clause: Option<syn::WhereClause>,
194 pub attr_span: proc_macro2::Span,
196 pub cfg_attrs: Vec<syn::Attribute>,
198 pub named_generics: Option<StorageGenerics>,
202 pub unbounded: bool,
204 pub whitelisted: bool,
206 pub try_decode: bool,
208 pub use_default_hasher: bool,
210 pub attrs: Vec<syn::Attribute>,
212}
213
214#[derive(Clone)]
216pub enum StorageGenerics {
217 DoubleMap {
218 hasher1: syn::Type,
219 key1: syn::Type,
220 hasher2: syn::Type,
221 key2: syn::Type,
222 value: syn::Type,
223 query_kind: Option<syn::Type>,
224 on_empty: Option<syn::Type>,
225 max_values: Option<syn::Type>,
226 },
227 Map {
228 hasher: syn::Type,
229 key: syn::Type,
230 value: syn::Type,
231 query_kind: Option<syn::Type>,
232 on_empty: Option<syn::Type>,
233 max_values: Option<syn::Type>,
234 },
235 CountedMap {
236 hasher: syn::Type,
237 key: syn::Type,
238 value: syn::Type,
239 query_kind: Option<syn::Type>,
240 on_empty: Option<syn::Type>,
241 max_values: Option<syn::Type>,
242 },
243 Value {
244 value: syn::Type,
245 query_kind: Option<syn::Type>,
246 on_empty: Option<syn::Type>,
247 },
248 NMap {
249 keygen: syn::Type,
250 value: syn::Type,
251 query_kind: Option<syn::Type>,
252 on_empty: Option<syn::Type>,
253 max_values: Option<syn::Type>,
254 },
255 CountedNMap {
256 keygen: syn::Type,
257 value: syn::Type,
258 query_kind: Option<syn::Type>,
259 on_empty: Option<syn::Type>,
260 max_values: Option<syn::Type>,
261 },
262}
263
264impl StorageGenerics {
265 fn metadata(&self) -> syn::Result<Metadata> {
267 let res = match self.clone() {
268 Self::DoubleMap { value, key1, key2, .. } => Metadata::DoubleMap { value, key1, key2 },
269 Self::Map { value, key, .. } => Metadata::Map { value, key },
270 Self::CountedMap { value, key, .. } => Metadata::CountedMap { value, key },
271 Self::Value { value, .. } => Metadata::Value { value },
272 Self::NMap { keygen, value, .. } =>
273 Metadata::NMap { keys: collect_keys(&keygen)?, keygen, value },
274 Self::CountedNMap { keygen, value, .. } =>
275 Metadata::CountedNMap { keys: collect_keys(&keygen)?, keygen, value },
276 };
277
278 Ok(res)
279 }
280
281 fn query_kind(&self) -> Option<syn::Type> {
283 match &self {
284 Self::DoubleMap { query_kind, .. } |
285 Self::Map { query_kind, .. } |
286 Self::CountedMap { query_kind, .. } |
287 Self::Value { query_kind, .. } |
288 Self::NMap { query_kind, .. } |
289 Self::CountedNMap { query_kind, .. } => query_kind.clone(),
290 }
291 }
292}
293
294enum StorageKind {
295 Value,
296 Map,
297 CountedMap,
298 DoubleMap,
299 NMap,
300 CountedNMap,
301}
302
303fn check_generics(
306 map: &HashMap<String, syn::AssocType>,
307 mandatory_generics: &[&str],
308 optional_generics: &[&str],
309 storage_type_name: &str,
310 args_span: proc_macro2::Span,
311) -> syn::Result<()> {
312 let mut errors = vec![];
313
314 let expectation = {
315 let mut e = format!(
316 "`{}` expect generics {}and optional generics {}",
317 storage_type_name,
318 mandatory_generics
319 .iter()
320 .map(|name| format!("`{}`, ", name))
321 .collect::<String>(),
322 &optional_generics.iter().map(|name| format!("`{}`, ", name)).collect::<String>(),
323 );
324 e.pop();
325 e.pop();
326 e.push('.');
327 e
328 };
329
330 for (gen_name, gen_binding) in map {
331 if !mandatory_generics.contains(&gen_name.as_str()) &&
332 !optional_generics.contains(&gen_name.as_str())
333 {
334 let msg = format!(
335 "Invalid pallet::storage, Unexpected generic `{}` for `{}`. {}",
336 gen_name, storage_type_name, expectation,
337 );
338 errors.push(syn::Error::new(gen_binding.span(), msg));
339 }
340 }
341
342 for mandatory_generic in mandatory_generics {
343 if !map.contains_key(&mandatory_generic.to_string()) {
344 let msg = format!(
345 "Invalid pallet::storage, cannot find `{}` generic, required for `{}`.",
346 mandatory_generic, storage_type_name
347 );
348 errors.push(syn::Error::new(args_span, msg));
349 }
350 }
351
352 let mut errors = errors.drain(..);
353 if let Some(mut error) = errors.next() {
354 for other_error in errors {
355 error.combine(other_error);
356 }
357 Err(error)
358 } else {
359 Ok(())
360 }
361}
362
363fn process_named_generics(
365 storage: &StorageKind,
366 args_span: proc_macro2::Span,
367 args: &[syn::AssocType],
368 dev_mode: bool,
369) -> syn::Result<(Option<StorageGenerics>, Metadata, Option<syn::Type>, bool)> {
370 let mut parsed = HashMap::<String, syn::AssocType>::new();
371
372 for arg in args {
374 if let Some(other) = parsed.get(&arg.ident.to_string()) {
375 let msg = "Invalid pallet::storage, Duplicated named generic";
376 let mut err = syn::Error::new(arg.ident.span(), msg);
377 err.combine(syn::Error::new(other.ident.span(), msg));
378 return Err(err);
379 }
380 parsed.insert(arg.ident.to_string(), arg.clone());
381 }
382
383 let mut map_mandatory_generics = vec!["Key", "Value"];
384 let mut map_optional_generics = vec!["QueryKind", "OnEmpty", "MaxValues"];
385 if dev_mode {
386 map_optional_generics.push("Hasher");
387 } else {
388 map_mandatory_generics.push("Hasher");
389 }
390
391 let generics = match storage {
392 StorageKind::Value => {
393 check_generics(
394 &parsed,
395 &["Value"],
396 &["QueryKind", "OnEmpty"],
397 "StorageValue",
398 args_span,
399 )?;
400
401 StorageGenerics::Value {
402 value: parsed
403 .remove("Value")
404 .map(|binding| binding.ty)
405 .expect("checked above as mandatory generic"),
406 query_kind: parsed.remove("QueryKind").map(|binding| binding.ty),
407 on_empty: parsed.remove("OnEmpty").map(|binding| binding.ty),
408 }
409 },
410 StorageKind::Map => {
411 check_generics(
412 &parsed,
413 &map_mandatory_generics,
414 &map_optional_generics,
415 "StorageMap",
416 args_span,
417 )?;
418
419 StorageGenerics::Map {
420 hasher: parsed
421 .remove("Hasher")
422 .map(|binding| binding.ty)
423 .unwrap_or(syn::parse_quote!(Blake2_128Concat)),
424 key: parsed
425 .remove("Key")
426 .map(|binding| binding.ty)
427 .expect("checked above as mandatory generic"),
428 value: parsed
429 .remove("Value")
430 .map(|binding| binding.ty)
431 .expect("checked above as mandatory generic"),
432 query_kind: parsed.remove("QueryKind").map(|binding| binding.ty),
433 on_empty: parsed.remove("OnEmpty").map(|binding| binding.ty),
434 max_values: parsed.remove("MaxValues").map(|binding| binding.ty),
435 }
436 },
437 StorageKind::CountedMap => {
438 check_generics(
439 &parsed,
440 &map_mandatory_generics,
441 &map_optional_generics,
442 "CountedStorageMap",
443 args_span,
444 )?;
445
446 StorageGenerics::CountedMap {
447 hasher: parsed
448 .remove("Hasher")
449 .map(|binding| binding.ty)
450 .unwrap_or(syn::Type::Verbatim(quote::quote! { Blake2_128Concat })),
451 key: parsed
452 .remove("Key")
453 .map(|binding| binding.ty)
454 .expect("checked above as mandatory generic"),
455 value: parsed
456 .remove("Value")
457 .map(|binding| binding.ty)
458 .expect("checked above as mandatory generic"),
459 query_kind: parsed.remove("QueryKind").map(|binding| binding.ty),
460 on_empty: parsed.remove("OnEmpty").map(|binding| binding.ty),
461 max_values: parsed.remove("MaxValues").map(|binding| binding.ty),
462 }
463 },
464 StorageKind::DoubleMap => {
465 let mut double_map_mandatory_generics = vec!["Key1", "Key2", "Value"];
466 if dev_mode {
467 map_optional_generics.extend(["Hasher1", "Hasher2"]);
468 } else {
469 double_map_mandatory_generics.extend(["Hasher1", "Hasher2"]);
470 }
471
472 check_generics(
473 &parsed,
474 &double_map_mandatory_generics,
475 &map_optional_generics,
476 "StorageDoubleMap",
477 args_span,
478 )?;
479
480 StorageGenerics::DoubleMap {
481 hasher1: parsed
482 .remove("Hasher1")
483 .map(|binding| binding.ty)
484 .unwrap_or(syn::parse_quote!(Blake2_128Concat)),
485 key1: parsed
486 .remove("Key1")
487 .map(|binding| binding.ty)
488 .expect("checked above as mandatory generic"),
489 hasher2: parsed
490 .remove("Hasher2")
491 .map(|binding| binding.ty)
492 .unwrap_or(syn::parse_quote!(Blake2_128Concat)),
493 key2: parsed
494 .remove("Key2")
495 .map(|binding| binding.ty)
496 .expect("checked above as mandatory generic"),
497 value: parsed
498 .remove("Value")
499 .map(|binding| binding.ty)
500 .expect("checked above as mandatory generic"),
501 query_kind: parsed.remove("QueryKind").map(|binding| binding.ty),
502 on_empty: parsed.remove("OnEmpty").map(|binding| binding.ty),
503 max_values: parsed.remove("MaxValues").map(|binding| binding.ty),
504 }
505 },
506 StorageKind::NMap => {
507 check_generics(
508 &parsed,
509 &["Key", "Value"],
510 &["QueryKind", "OnEmpty", "MaxValues"],
511 "StorageNMap",
512 args_span,
513 )?;
514
515 StorageGenerics::NMap {
516 keygen: parsed
517 .remove("Key")
518 .map(|binding| binding.ty)
519 .expect("checked above as mandatory generic"),
520 value: parsed
521 .remove("Value")
522 .map(|binding| binding.ty)
523 .expect("checked above as mandatory generic"),
524 query_kind: parsed.remove("QueryKind").map(|binding| binding.ty),
525 on_empty: parsed.remove("OnEmpty").map(|binding| binding.ty),
526 max_values: parsed.remove("MaxValues").map(|binding| binding.ty),
527 }
528 },
529 StorageKind::CountedNMap => {
530 check_generics(
531 &parsed,
532 &["Key", "Value"],
533 &["QueryKind", "OnEmpty", "MaxValues"],
534 "CountedStorageNMap",
535 args_span,
536 )?;
537
538 StorageGenerics::CountedNMap {
539 keygen: parsed
540 .remove("Key")
541 .map(|binding| binding.ty)
542 .expect("checked above as mandatory generic"),
543 value: parsed
544 .remove("Value")
545 .map(|binding| binding.ty)
546 .expect("checked above as mandatory generic"),
547 query_kind: parsed.remove("QueryKind").map(|binding| binding.ty),
548 on_empty: parsed.remove("OnEmpty").map(|binding| binding.ty),
549 max_values: parsed.remove("MaxValues").map(|binding| binding.ty),
550 }
551 },
552 };
553
554 let metadata = generics.metadata()?;
555 let query_kind = generics.query_kind();
556
557 Ok((Some(generics), metadata, query_kind, false))
558}
559
560fn process_unnamed_generics(
562 storage: &StorageKind,
563 args_span: proc_macro2::Span,
564 args: &[syn::Type],
565 dev_mode: bool,
566) -> syn::Result<(Option<StorageGenerics>, Metadata, Option<syn::Type>, bool)> {
567 let retrieve_arg = |arg_pos| {
568 args.get(arg_pos).cloned().ok_or_else(|| {
569 let msg = format!(
570 "Invalid pallet::storage, unexpected number of generic argument, \
571 expect at least {} args, found {}.",
572 arg_pos + 1,
573 args.len(),
574 );
575 syn::Error::new(args_span, msg)
576 })
577 };
578
579 let prefix_arg = retrieve_arg(0)?;
580 syn::parse2::<syn::Token![_]>(prefix_arg.to_token_stream()).map_err(|e| {
581 let msg = "Invalid pallet::storage, for unnamed generic arguments the type \
582 first generic argument must be `_`, the argument is then replaced by macro.";
583 let mut err = syn::Error::new(prefix_arg.span(), msg);
584 err.combine(e);
585 err
586 })?;
587
588 let use_default_hasher = |arg_pos| {
589 let arg = retrieve_arg(arg_pos)?;
590 if syn::parse2::<syn::Token![_]>(arg.to_token_stream()).is_ok() {
591 if dev_mode {
592 Ok(true)
593 } else {
594 let msg = "`_` can only be used in dev_mode. Please specify an appropriate hasher.";
595 Err(syn::Error::new(arg.span(), msg))
596 }
597 } else {
598 Ok(false)
599 }
600 };
601
602 let res = match storage {
603 StorageKind::Value =>
604 (None, Metadata::Value { value: retrieve_arg(1)? }, retrieve_arg(2).ok(), false),
605 StorageKind::Map => (
606 None,
607 Metadata::Map { key: retrieve_arg(2)?, value: retrieve_arg(3)? },
608 retrieve_arg(4).ok(),
609 use_default_hasher(1)?,
610 ),
611 StorageKind::CountedMap => (
612 None,
613 Metadata::CountedMap { key: retrieve_arg(2)?, value: retrieve_arg(3)? },
614 retrieve_arg(4).ok(),
615 use_default_hasher(1)?,
616 ),
617 StorageKind::DoubleMap => (
618 None,
619 Metadata::DoubleMap {
620 key1: retrieve_arg(2)?,
621 key2: retrieve_arg(4)?,
622 value: retrieve_arg(5)?,
623 },
624 retrieve_arg(6).ok(),
625 use_default_hasher(1)? && use_default_hasher(3)?,
626 ),
627 StorageKind::NMap => {
628 let keygen = retrieve_arg(1)?;
629 let keys = collect_keys(&keygen)?;
630 (
631 None,
632 Metadata::NMap { keys, keygen, value: retrieve_arg(2)? },
633 retrieve_arg(3).ok(),
634 false,
635 )
636 },
637 StorageKind::CountedNMap => {
638 let keygen = retrieve_arg(1)?;
639 let keys = collect_keys(&keygen)?;
640 (
641 None,
642 Metadata::CountedNMap { keys, keygen, value: retrieve_arg(2)? },
643 retrieve_arg(3).ok(),
644 false,
645 )
646 },
647 };
648
649 Ok(res)
650}
651
652fn process_generics(
654 segment: &syn::PathSegment,
655 dev_mode: bool,
656) -> syn::Result<(Option<StorageGenerics>, Metadata, Option<syn::Type>, bool)> {
657 let storage_kind = match &*segment.ident.to_string() {
658 "StorageValue" => StorageKind::Value,
659 "StorageMap" => StorageKind::Map,
660 "CountedStorageMap" => StorageKind::CountedMap,
661 "StorageDoubleMap" => StorageKind::DoubleMap,
662 "StorageNMap" => StorageKind::NMap,
663 "CountedStorageNMap" => StorageKind::CountedNMap,
664 found => {
665 let msg = format!(
666 "Invalid pallet::storage, expected ident: `StorageValue` or \
667 `StorageMap` or `CountedStorageMap` or `StorageDoubleMap` or `StorageNMap` or `CountedStorageNMap` \
668 in order to expand metadata, found `{}`.",
669 found,
670 );
671 return Err(syn::Error::new(segment.ident.span(), msg));
672 },
673 };
674
675 let args_span = segment.arguments.span();
676
677 let args = match &segment.arguments {
678 syn::PathArguments::AngleBracketed(args) if !args.args.is_empty() => args,
679 _ => {
680 let msg = "Invalid pallet::storage, invalid number of generic generic arguments, \
681 expect more that 0 generic arguments.";
682 return Err(syn::Error::new(segment.span(), msg));
683 },
684 };
685
686 if args.args.iter().all(|gen| matches!(gen, syn::GenericArgument::Type(_))) {
687 let args = args
688 .args
689 .iter()
690 .map(|gen| match gen {
691 syn::GenericArgument::Type(gen) => gen.clone(),
692 _ => unreachable!("It is asserted above that all generics are types"),
693 })
694 .collect::<Vec<_>>();
695 process_unnamed_generics(&storage_kind, args_span, &args, dev_mode)
696 } else if args.args.iter().all(|gen| matches!(gen, syn::GenericArgument::AssocType(_))) {
697 let args = args
698 .args
699 .iter()
700 .map(|gen| match gen {
701 syn::GenericArgument::AssocType(gen) => gen.clone(),
702 _ => unreachable!("It is asserted above that all generics are bindings"),
703 })
704 .collect::<Vec<_>>();
705 process_named_generics(&storage_kind, args_span, &args, dev_mode)
706 } else {
707 let msg = "Invalid pallet::storage, invalid generic declaration for storage. Expect only \
708 type generics or binding generics, e.g. `<Name1 = Gen1, Name2 = Gen2, ..>` or \
709 `<Gen1, Gen2, ..>`.";
710 Err(syn::Error::new(segment.span(), msg))
711 }
712}
713
714fn collect_keys(keygen: &syn::Type) -> syn::Result<Vec<syn::Type>> {
716 if let syn::Type::Tuple(tup) = keygen {
717 tup.elems.iter().map(extract_key).collect::<syn::Result<Vec<_>>>()
718 } else {
719 Ok(vec![extract_key(keygen)?])
720 }
721}
722
723fn extract_key(ty: &syn::Type) -> syn::Result<syn::Type> {
725 let typ = if let syn::Type::Path(typ) = ty {
726 typ
727 } else {
728 let msg = "Invalid pallet::storage, expected type path";
729 return Err(syn::Error::new(ty.span(), msg));
730 };
731
732 let key_struct = typ.path.segments.last().ok_or_else(|| {
733 let msg = "Invalid pallet::storage, expected type path with at least one segment";
734 syn::Error::new(typ.path.span(), msg)
735 })?;
736 if key_struct.ident != "Key" && key_struct.ident != "NMapKey" {
737 let msg = "Invalid pallet::storage, expected Key or NMapKey struct";
738 return Err(syn::Error::new(key_struct.ident.span(), msg));
739 }
740
741 let ty_params = if let syn::PathArguments::AngleBracketed(args) = &key_struct.arguments {
742 args
743 } else {
744 let msg = "Invalid pallet::storage, expected angle bracketed arguments";
745 return Err(syn::Error::new(key_struct.arguments.span(), msg));
746 };
747
748 if ty_params.args.len() != 2 {
749 let msg = format!(
750 "Invalid pallet::storage, unexpected number of generic arguments \
751 for Key struct, expected 2 args, found {}",
752 ty_params.args.len()
753 );
754 return Err(syn::Error::new(ty_params.span(), msg));
755 }
756
757 let key = match &ty_params.args[1] {
758 syn::GenericArgument::Type(key_ty) => key_ty.clone(),
759 _ => {
760 let msg = "Invalid pallet::storage, expected type";
761 return Err(syn::Error::new(ty_params.args[1].span(), msg));
762 },
763 };
764
765 Ok(key)
766}
767
768impl StorageDef {
769 pub fn prefix(&self) -> String {
771 self.rename_as
772 .as_ref()
773 .map(syn::LitStr::value)
774 .unwrap_or_else(|| self.ident.to_string())
775 }
776
777 pub fn prefix_span(&self) -> proc_macro2::Span {
780 self.rename_as
781 .as_ref()
782 .map(syn::LitStr::span)
783 .unwrap_or_else(|| self.ident.span())
784 }
785
786 pub fn try_from(
787 attr_span: proc_macro2::Span,
788 index: usize,
789 item: &mut syn::Item,
790 dev_mode: bool,
791 ) -> syn::Result<Self> {
792 let item = if let syn::Item::Type(item) = item {
793 item
794 } else {
795 return Err(syn::Error::new(item.span(), "Invalid pallet::storage, expect item type."));
796 };
797
798 let attrs: Vec<PalletStorageAttr> = helper::take_item_pallet_attrs(&mut item.attrs)?;
799 let PalletStorageAttrInfo { getter, rename_as, mut unbounded, whitelisted, try_decode } =
800 PalletStorageAttrInfo::from_attrs(attrs)?;
801
802 unbounded |= dev_mode;
804 let cfg_attrs = helper::get_item_cfg_attrs(&item.attrs);
805
806 let instances = vec![helper::check_type_def_gen(&item.generics, item.ident.span())?];
807
808 let where_clause = item.generics.where_clause.clone();
809 let docs = get_doc_literals(&item.attrs);
810
811 let typ = if let syn::Type::Path(typ) = &*item.ty {
812 typ
813 } else {
814 let msg = "Invalid pallet::storage, expected type path";
815 return Err(syn::Error::new(item.ty.span(), msg));
816 };
817
818 if typ.path.segments.len() != 1 {
819 let msg = "Invalid pallet::storage, expected type path with one segment";
820 return Err(syn::Error::new(item.ty.span(), msg));
821 }
822
823 let (named_generics, metadata, query_kind, use_default_hasher) =
824 process_generics(&typ.path.segments[0], dev_mode)?;
825
826 let query_kind = query_kind
827 .map(|query_kind| {
828 use syn::{
829 AngleBracketedGenericArguments, GenericArgument, Path, PathArguments, Type,
830 TypePath,
831 };
832
833 let result_query = match query_kind {
834 Type::Path(path)
835 if path
836 .path
837 .segments
838 .last()
839 .map_or(false, |s| s.ident == "OptionQuery") =>
840 return Ok(Some(QueryKind::OptionQuery)),
841 Type::Path(TypePath { path: Path { segments, .. }, .. })
842 if segments.last().map_or(false, |s| s.ident == "ResultQuery") =>
843 segments
844 .last()
845 .expect("segments is checked to have the last value; qed")
846 .clone(),
847 Type::Path(path)
848 if path.path.segments.last().map_or(false, |s| s.ident == "ValueQuery") =>
849 return Ok(Some(QueryKind::ValueQuery)),
850 _ => return Ok(None),
851 };
852
853 let error_type = match result_query.arguments {
854 PathArguments::AngleBracketed(AngleBracketedGenericArguments {
855 args, ..
856 }) => {
857 if args.len() != 1 {
858 let msg = format!(
859 "Invalid pallet::storage, unexpected number of generic arguments \
860 for ResultQuery, expected 1 type argument, found {}",
861 args.len(),
862 );
863 return Err(syn::Error::new(args.span(), msg));
864 }
865
866 args[0].clone()
867 },
868 args => {
869 let msg = format!(
870 "Invalid pallet::storage, unexpected generic args for ResultQuery, \
871 expected angle-bracketed arguments, found `{}`",
872 args.to_token_stream().to_string()
873 );
874 return Err(syn::Error::new(args.span(), msg));
875 },
876 };
877
878 match error_type {
879 GenericArgument::Type(Type::Path(TypePath {
880 path: Path { segments: err_variant, leading_colon },
881 ..
882 })) => {
883 if err_variant.len() < 2 {
884 let msg = format!(
885 "Invalid pallet::storage, unexpected number of path segments for \
886 the generics in ResultQuery, expected a path with at least 2 \
887 segments, found {}",
888 err_variant.len(),
889 );
890 return Err(syn::Error::new(err_variant.span(), msg));
891 }
892 let mut error = err_variant.clone();
893 let err_variant = error
894 .pop()
895 .expect("Checked to have at least 2; qed")
896 .into_value()
897 .ident;
898
899 let last =
901 error.pop().expect("Checked to have at least 2; qed").into_value();
902 error.push_value(last);
903
904 Ok(Some(QueryKind::ResultQuery(
905 syn::Path { leading_colon, segments: error },
906 err_variant,
907 )))
908 },
909 gen_arg => {
910 let msg = format!(
911 "Invalid pallet::storage, unexpected generic argument kind, expected a \
912 type path to a `PalletError` enum variant, found `{}`",
913 gen_arg.to_token_stream().to_string(),
914 );
915 Err(syn::Error::new(gen_arg.span(), msg))
916 },
917 }
918 })
919 .transpose()?
920 .unwrap_or(Some(QueryKind::OptionQuery));
921
922 if let (None, Some(getter)) = (query_kind.as_ref(), getter.as_ref()) {
923 let msg = "Invalid pallet::storage, cannot generate getter because QueryKind is not \
924 identifiable. QueryKind must be `OptionQuery`, `ResultQuery`, `ValueQuery`, or default \
925 one to be identifiable.";
926 return Err(syn::Error::new(getter.span(), msg));
927 }
928
929 Ok(StorageDef {
930 attr_span,
931 index,
932 vis: item.vis.clone(),
933 ident: item.ident.clone(),
934 instances,
935 metadata,
936 docs,
937 getter,
938 rename_as,
939 query_kind,
940 where_clause,
941 cfg_attrs,
942 named_generics,
943 unbounded,
944 whitelisted,
945 try_decode,
946 use_default_hasher,
947 attrs: item.attrs.clone(),
948 })
949 }
950}