1#[cfg(not(feature = "std"))]
2use alloc::collections::btree_map::BTreeMap;
3#[cfg(feature = "std")]
4use std::collections::BTreeMap;
5
6#[cfg(any(feature = "v13", feature = "v12",))]
7use frame_metadata::decode_different::{DecodeDifferent, DecodeDifferentArray};
8
9#[cfg(feature = "v14")]
10use scale_info::form::PortableForm;
11
12use codec::{Decode, Encode};
13
14#[cfg(not(feature = "std"))]
15use alloc::{
16 format,
17 string::{String, ToString},
18};
19use sp_std::prelude::*;
20
21mod storage;
22pub use storage::*;
23
24use crate::error::*;
25use crate::schema::*;
26use crate::type_def::*;
27use crate::*;
28
29#[cfg(any(feature = "v13", feature = "v12",))]
30pub(crate) fn decode_meta<B: Encode + 'static, O: Decode + Clone + 'static>(
31 encoded: &DecodeDifferent<B, O>,
32) -> Result<O> {
33 match encoded {
34 DecodeDifferent::Decoded(val) => Ok(val.clone()),
35 DecodeDifferent::Encode(val) => {
36 let encoded = val.encode();
37 O::decode(&mut &encoded[..])
38 .map_err(|_| Error::MetadataParseFailed(format!("Failed to decode value.")))
39 }
40 }
41}
42
43#[derive(Clone)]
44pub struct Metadata {
45 modules: BTreeMap<String, ModuleMetadata>,
46 idx_map: BTreeMap<u8, String>,
47}
48
49impl Metadata {
50 #[cfg(feature = "v12")]
51 pub fn from_v12_metadata(
52 md: frame_metadata::v12::RuntimeMetadataV12,
53 lookup: &mut Types,
54 ) -> Result<Self> {
55 let mut api_md = Self {
56 modules: BTreeMap::new(),
57 idx_map: BTreeMap::new(),
58 };
59
60 let mut mod_events = TypeDefVariant::new();
62 let mut mod_errors = TypeDefVariant::new();
63 let mut mod_calls = TypeDefVariant::new();
64
65 decode_meta(&md.modules)?
67 .iter()
68 .try_for_each(|m| -> Result<()> {
69 let m = ModuleMetadata::from_v12_meta(m, lookup)?;
70 let name = m.name.clone();
71 mod_events.insert(m.index, &name, m.event_ref.clone());
72 mod_errors.insert(m.index, &name, m.error_ref.clone());
73 mod_calls.insert(m.index, &name, m.call_ref.clone());
74 api_md.idx_map.insert(m.index, name.clone());
75 api_md.modules.insert(name, m);
76 Ok(())
77 })?;
78
79 let raw_event_ref = lookup.insert_type("RawEvent", TypeDef::Variant(mod_events));
80 lookup.insert_new_type("Event", raw_event_ref);
81 let raw_error_ref = lookup.insert_type("RawError", TypeDef::Variant(mod_errors));
82 lookup.insert_new_type("DispatchErrorModule", raw_error_ref);
83 lookup.insert_type("RuntimeCall", TypeDef::Variant(mod_calls));
85
86 Ok(api_md)
87 }
88
89 #[cfg(feature = "v13")]
90 pub fn from_v13_metadata(
91 md: frame_metadata::v13::RuntimeMetadataV13,
92 lookup: &mut Types,
93 ) -> Result<Self> {
94 let mut api_md = Self {
95 modules: BTreeMap::new(),
96 idx_map: BTreeMap::new(),
97 };
98
99 let mut mod_events = TypeDefVariant::new();
101 let mut mod_errors = TypeDefVariant::new();
102 let mut mod_calls = TypeDefVariant::new();
103
104 decode_meta(&md.modules)?
106 .iter()
107 .try_for_each(|m| -> Result<()> {
108 let m = ModuleMetadata::from_v13_meta(m, lookup)?;
109 let name = m.name.clone();
110 mod_events.insert(m.index, &name, m.event_ref.clone());
111 mod_errors.insert(m.index, &name, m.error_ref.clone());
112 mod_calls.insert(m.index, &name, m.call_ref.clone());
113 api_md.idx_map.insert(m.index, name.clone());
114 api_md.modules.insert(name, m);
115 Ok(())
116 })?;
117
118 let raw_event_ref = lookup.insert_type("RawEvent", TypeDef::Variant(mod_events));
119 lookup.insert_new_type("Event", raw_event_ref);
120 let raw_error_ref = lookup.insert_type("RawError", TypeDef::Variant(mod_errors));
121 lookup.insert_new_type("DispatchErrorModule", raw_error_ref);
122 lookup.insert_type("RuntimeCall", TypeDef::Variant(mod_calls));
124
125 Ok(api_md)
126 }
127
128 #[cfg(feature = "v14")]
129 pub fn from_v14_metadata(
130 md: frame_metadata::v14::RuntimeMetadataV14,
131 lookup: &mut Types,
132 ) -> Result<Self> {
133 let mut api_md = Self {
134 modules: BTreeMap::new(),
135 idx_map: BTreeMap::new(),
136 };
137
138 let types = PortableRegistry::from(&md.types);
139
140 lookup.import_v14_types(&types)?;
142
143 let mut mod_events = TypeDefVariant::new();
145 let mut mod_errors = TypeDefVariant::new();
146 let mut mod_calls = TypeDefVariant::new();
147
148 md.pallets.iter().try_for_each(|m| -> Result<()> {
150 let m = ModuleMetadata::from_v14_meta(m, &types)?;
151 let name = m.name.clone();
152 mod_events.insert(m.index, &name, m.event_ref.clone());
153 mod_errors.insert(m.index, &name, m.error_ref.clone());
154 mod_calls.insert(m.index, &name, m.call_ref.clone());
155 api_md.idx_map.insert(m.index, name.clone());
156 api_md.modules.insert(name, m);
157 Ok(())
158 })?;
159
160 let event_ty = lookup.insert_type("RuntimeEvent", TypeDef::Variant(mod_events));
161 lookup.insert_type("RuntimeError", TypeDef::Variant(mod_errors));
162 lookup.insert_type("RuntimeCall", TypeDef::Variant(mod_calls));
163
164 lookup.parse_named_type("H256", "[u8; 32]")?;
166 let phase_ty = lookup.resolve("frame_system::Phase").id;
167 let topics_ty = lookup.parse_type("Vec<H256>")?;
168
169 lookup.insert_type(
170 "EventRecord",
171 TypeDefComposite::new(vec![
172 Field::new_named("phase", phase_ty, None),
173 Field::new_named("event", event_ty, None),
174 Field::new_named("topics", topics_ty, None),
175 ])
176 .into(),
177 );
178 lookup.parse_named_type("EventRecords", "Vec<EventRecord>")?;
179
180 Ok(api_md)
181 }
182
183 pub fn get_module(&self, name: &str) -> Option<&ModuleMetadata> {
184 self.modules.get(name)
185 }
186
187 pub fn modules(&self) -> impl Iterator<Item = &ModuleMetadata> {
188 self.modules.values()
189 }
190}
191
192#[derive(Clone)]
193pub struct ModuleMetadata {
194 pub name: String,
195 pub index: u8,
196 pub funcs: BTreeMap<String, FuncMetadata>,
197 pub events: BTreeMap<String, EventMetadata>,
198 pub errors: BTreeMap<String, ErrorMetadata>,
199 pub err_idx_map: BTreeMap<u8, String>,
200 pub event_ref: Option<TypeId>,
201 pub error_ref: Option<TypeId>,
202 pub call_ref: Option<TypeId>,
203 pub storage: Option<StorageMetadata>,
204}
205
206impl ModuleMetadata {
207 #[cfg(feature = "v12")]
208 fn from_v12_meta(md: &frame_metadata::v12::ModuleMetadata, lookup: &mut Types) -> Result<Self> {
209 let mod_idx = md.index;
210 let mod_name = decode_meta(&md.name)?;
211 let mut module = Self {
212 name: mod_name.clone(),
213 index: mod_idx,
214 funcs: BTreeMap::new(),
215 events: BTreeMap::new(),
216 errors: BTreeMap::new(),
217 err_idx_map: BTreeMap::new(),
218 event_ref: None,
219 error_ref: None,
220 call_ref: None,
221 storage: None,
222 };
223
224 if let Some(calls) = &md.calls {
226 let mut raw_calls = TypeDefVariant::new();
228
229 decode_meta(calls)?
230 .iter()
231 .enumerate()
232 .try_for_each(|(func_idx, md)| -> Result<()> {
233 let (func, ty_ref) =
234 FuncMetadata::from_v12_meta(&mod_name, mod_idx, func_idx as u8, md, lookup)?;
235 let name = func.name.clone();
236 raw_calls.insert(func.func_idx, &name, ty_ref);
237 module.funcs.insert(name, func);
238 Ok(())
239 })?;
240 module.call_ref = Some(lookup.insert_type(
241 &format!("{}::RawCall", mod_name),
242 TypeDef::Variant(raw_calls),
243 ));
244 }
245
246 if let Some(events) = &md.event {
248 let mut raw_events = TypeDefVariant::new();
250
251 decode_meta(events)?
252 .iter()
253 .enumerate()
254 .try_for_each(|(event_idx, md)| -> Result<()> {
255 let (event, ty_ref) =
256 EventMetadata::from_v12_meta(&mod_name, mod_idx, event_idx as u8, md, lookup)?;
257 let name = event.name.clone();
258 raw_events.insert(event.event_idx, &name, ty_ref);
259 module.events.insert(name, event);
260 Ok(())
261 })?;
262 module.event_ref = Some(lookup.insert_type(
263 &format!("{}::RawEvent", mod_name),
264 TypeDef::Variant(raw_events),
265 ));
266 }
267
268 let mut raw_errors = TypeDefVariant::new();
271
272 decode_meta(&md.errors)?
273 .iter()
274 .enumerate()
275 .try_for_each(|(error_idx, md)| -> Result<()> {
276 let error = ErrorMetadata::from_v12_meta(&mod_name, mod_idx, error_idx as u8, md)?;
277 let name = error.name.clone();
278 raw_errors.insert(error.error_idx, &name, None);
279 module.err_idx_map.insert(error.error_idx, name.clone());
280 module.errors.insert(name, error);
281 Ok(())
282 })?;
283 module.error_ref = Some(lookup.insert_type(
284 &format!("{}::RawError", mod_name),
285 TypeDef::Variant(raw_errors),
286 ));
287
288 if let Some(storage) = &md.storage {
290 let storage = decode_meta(storage)?;
291 module.storage = Some(StorageMetadata::from_v12_meta(storage, lookup)?);
292 }
293
294 Ok(module)
295 }
296
297 #[cfg(feature = "v13")]
298 fn from_v13_meta(md: &frame_metadata::v13::ModuleMetadata, lookup: &mut Types) -> Result<Self> {
299 let mod_idx = md.index;
300 let mod_name = decode_meta(&md.name)?;
301 let mut module = Self {
302 name: mod_name.clone(),
303 index: mod_idx,
304 funcs: BTreeMap::new(),
305 events: BTreeMap::new(),
306 errors: BTreeMap::new(),
307 err_idx_map: BTreeMap::new(),
308 event_ref: None,
309 error_ref: None,
310 call_ref: None,
311 storage: None,
312 };
313
314 if let Some(calls) = &md.calls {
316 let mut raw_calls = TypeDefVariant::new();
318
319 decode_meta(calls)?
320 .iter()
321 .enumerate()
322 .try_for_each(|(func_idx, md)| -> Result<()> {
323 let (func, ty_ref) =
324 FuncMetadata::from_v13_meta(&mod_name, mod_idx, func_idx as u8, md, lookup)?;
325 let name = func.name.clone();
326 raw_calls.insert(func.func_idx, &name, ty_ref);
327 module.funcs.insert(name, func);
328 Ok(())
329 })?;
330 module.call_ref = Some(lookup.insert_type(
331 &format!("{}::RawCall", mod_name),
332 TypeDef::Variant(raw_calls),
333 ));
334 }
335
336 if let Some(events) = &md.event {
338 let mut raw_events = TypeDefVariant::new();
340
341 decode_meta(events)?
342 .iter()
343 .enumerate()
344 .try_for_each(|(event_idx, md)| -> Result<()> {
345 let (event, ty_ref) =
346 EventMetadata::from_v13_meta(&mod_name, mod_idx, event_idx as u8, md, lookup)?;
347 let name = event.name.clone();
348 raw_events.insert(event.event_idx, &name, ty_ref);
349 module.events.insert(name, event);
350 Ok(())
351 })?;
352 module.event_ref = Some(lookup.insert_type(
353 &format!("{}::RawEvent", mod_name),
354 TypeDef::Variant(raw_events),
355 ));
356 }
357
358 let mut raw_errors = TypeDefVariant::new();
361
362 decode_meta(&md.errors)?
363 .iter()
364 .enumerate()
365 .try_for_each(|(error_idx, md)| -> Result<()> {
366 let error = ErrorMetadata::from_v13_meta(&mod_name, mod_idx, error_idx as u8, md)?;
367 let name = error.name.clone();
368 raw_errors.insert(error.error_idx, &name, None);
369 module.err_idx_map.insert(error.error_idx, name.clone());
370 module.errors.insert(name, error);
371 Ok(())
372 })?;
373 module.error_ref = Some(lookup.insert_type(
374 &format!("{}::RawError", mod_name),
375 TypeDef::Variant(raw_errors),
376 ));
377
378 if let Some(storage) = &md.storage {
380 let storage = decode_meta(storage)?;
381 module.storage = Some(StorageMetadata::from_v13_meta(storage, lookup)?);
382 }
383
384 Ok(module)
385 }
386
387 #[cfg(feature = "v14")]
388 fn from_v14_meta(
389 md: &frame_metadata::v14::PalletMetadata<PortableForm>,
390 types: &PortableRegistry,
391 ) -> Result<Self> {
392 let mod_idx = md.index;
393 let mod_name = &md.name;
394 let mut module = Self {
395 name: mod_name.clone(),
396 index: mod_idx,
397 funcs: BTreeMap::new(),
398 events: BTreeMap::new(),
399 errors: BTreeMap::new(),
400 err_idx_map: BTreeMap::new(),
401 event_ref: None,
402 error_ref: None,
403 call_ref: None,
404 storage: None,
405 };
406
407 if let Some(calls) = &md.calls {
409 let id = calls.ty.id;
410 module.call_ref = Some(id.into());
411
412 let call_ty = types.resolve(id).expect("Missing Pallet call type");
413 match call_ty.type_def() {
414 TypeDef::Variant(v) => {
415 v.variants.iter().try_for_each(|md| -> Result<()> {
416 let func = FuncMetadata::from_v14_meta(&mod_name, mod_idx, md, types)?;
417 let name = func.name.clone();
418 module.funcs.insert(name, func);
419 Ok(())
420 })?;
421 }
422 _ => {
423 unimplemented!("Only Variant type supported for Pallet Call type.");
424 }
425 }
426 }
427
428 if let Some(events) = &md.event {
430 let id = events.ty.id;
431 module.event_ref = Some(id.into());
432
433 let event_ty = types.resolve(id).expect("Missing Pallet event type");
434 match event_ty.type_def() {
435 TypeDef::Variant(v) => {
436 v.variants.iter().try_for_each(|md| -> Result<()> {
437 let event = EventMetadata::from_v14_meta(&mod_name, mod_idx, md, types)?;
438 let name = event.name.clone();
439 module.events.insert(name, event);
440 Ok(())
441 })?;
442 }
443 _ => {
444 unimplemented!("Only Variant type supported for Pallet Event type.");
445 }
446 }
447 }
448
449 if let Some(error) = &md.error {
451 let id = error.ty.id;
452 module.error_ref = Some(id.into());
453
454 let error_ty = types.resolve(id).expect("Missing Pallet error type");
455 match error_ty.type_def() {
456 TypeDef::Variant(v) => {
457 v.variants.iter().try_for_each(|md| -> Result<()> {
458 let error = ErrorMetadata::from_v14_meta(&mod_name, mod_idx, md)?;
459 let name = error.name.clone();
460 module.err_idx_map.insert(error.error_idx, name.clone());
461 module.errors.insert(name, error);
462 Ok(())
463 })?;
464 }
465 _ => {
466 unimplemented!("Only Variant type supported for Pallet Error type.");
467 }
468 }
469 }
470
471 if let Some(storage) = &md.storage {
473 module.storage = Some(StorageMetadata::from_v14_meta(storage, types)?);
474 }
475
476 Ok(module)
477 }
478}
479
480#[derive(Debug, Clone)]
481pub struct NamedType {
482 pub name: String,
483 pub ty_id: TypeId,
484}
485
486impl NamedType {
487 pub fn new(name: &str, lookup: &mut Types) -> Result<Self> {
488 let ty_id = lookup.parse_type(name)?;
489 let named = Self {
490 name: name.into(),
491 ty_id,
492 };
493
494 Ok(named)
495 }
496
497 #[cfg(feature = "v14")]
498 pub fn new_field_type(md: &Field, types: &PortableRegistry) -> Result<Self> {
499 let ty = types
500 .resolve(md.ty)
501 .ok_or_else(|| Error::MetadataParseFailed(format!("Failed to resolve type.")))?;
502 let name = md
503 .type_name
504 .as_ref()
505 .map(|ty_name| {
506 let name = if ty_name.starts_with("/*«*/") {
508 let end = ty_name.len() - 6;
509 &ty_name[6..end]
510 } else {
511 &ty_name[..]
512 }
513 .trim();
514 if is_type_compact(ty) {
515 format!("Compact<{}>", name)
516 } else {
517 name.to_string()
518 }
519 })
520 .unwrap_or_else(|| get_type_name(ty, types, false));
521 let named = Self {
522 name: name.into(),
523 ty_id: md.ty,
524 };
525
526 Ok(named)
527 }
528}
529
530#[derive(Clone)]
531pub struct EventMetadata {
532 pub mod_name: String,
533 pub name: String,
534 pub event_idx: u8,
535 pub args: Vec<NamedType>,
536 pub docs: Docs,
537}
538
539impl EventMetadata {
540 #[cfg(feature = "v12")]
541 fn from_v12_meta(
542 mod_name: &str,
543 _mod_idx: u8,
544 event_idx: u8,
545 md: &frame_metadata::v12::EventMetadata,
546 lookup: &mut Types,
547 ) -> Result<(Self, Option<TypeId>)> {
548 let mut event = Self {
549 mod_name: mod_name.into(),
550 name: decode_meta(&md.name)?.clone(),
551 event_idx,
552 args: Vec::new(),
553 docs: Docs::from_v12_meta(&md.documentation)?,
554 };
555
556 let mut event_tuple = Vec::new();
557
558 decode_meta(&md.arguments)?
560 .iter()
561 .try_for_each(|name| -> Result<()> {
562 let arg = NamedType::new(name, lookup)?;
563 event_tuple.push(arg.ty_id.clone());
564 event.args.push(arg);
565 Ok(())
566 })?;
567
568 let event_ref = if event_tuple.len() > 0 {
569 let type_name = format!("{}::RawEvent::{}", mod_name, event.name);
570 Some(lookup.insert_type(&type_name, TypeDef::new_tuple(event_tuple)))
571 } else {
572 None
573 };
574
575 Ok((event, event_ref))
576 }
577
578 #[cfg(feature = "v13")]
579 fn from_v13_meta(
580 mod_name: &str,
581 _mod_idx: u8,
582 event_idx: u8,
583 md: &frame_metadata::v13::EventMetadata,
584 lookup: &mut Types,
585 ) -> Result<(Self, Option<TypeId>)> {
586 let mut event = Self {
587 mod_name: mod_name.into(),
588 name: decode_meta(&md.name)?.clone(),
589 event_idx,
590 args: Vec::new(),
591 docs: Docs::from_v13_meta(&md.documentation)?,
592 };
593
594 let mut event_tuple = Vec::new();
595
596 decode_meta(&md.arguments)?
598 .iter()
599 .try_for_each(|name| -> Result<()> {
600 let arg = NamedType::new(name, lookup)?;
601 event_tuple.push(arg.ty_id.clone());
602 event.args.push(arg);
603 Ok(())
604 })?;
605
606 let event_ref = if event_tuple.len() > 0 {
607 let type_name = format!("{}::RawEvent::{}", mod_name, event.name);
608 Some(lookup.insert_type(&type_name, TypeDef::new_tuple(event_tuple)))
609 } else {
610 None
611 };
612
613 Ok((event, event_ref))
614 }
615
616 #[cfg(feature = "v14")]
617 fn from_v14_meta(
618 mod_name: &str,
619 _mod_idx: u8,
620 md: &Variant,
621 types: &PortableRegistry,
622 ) -> Result<Self> {
623 let mut event = Self {
624 mod_name: mod_name.into(),
625 name: md.name.clone(),
626 event_idx: md.index,
627 args: Vec::new(),
628 docs: Docs::from_v14_meta(&md.docs),
629 };
630
631 md.fields.iter().try_for_each(|md| -> Result<()> {
633 let arg = NamedType::new_field_type(md, types)?;
634 log::trace!("-- Event: {mod_name}.{}: field: {md:?}", event.name);
635 event.args.push(arg);
636 Ok(())
637 })?;
638
639 Ok(event)
640 }
641}
642
643#[derive(Clone)]
644pub struct ErrorMetadata {
645 pub mod_name: String,
646 pub name: String,
647 pub error_idx: u8,
648 pub docs: Docs,
649}
650
651impl ErrorMetadata {
652 #[cfg(feature = "v12")]
653 fn from_v12_meta(
654 mod_name: &str,
655 _mod_idx: u8,
656 error_idx: u8,
657 md: &frame_metadata::v12::ErrorMetadata,
658 ) -> Result<Self> {
659 Ok(Self {
660 mod_name: mod_name.into(),
661 name: decode_meta(&md.name)?.clone(),
662 error_idx,
663 docs: Docs::from_v12_meta(&md.documentation)?,
664 })
665 }
666
667 #[cfg(feature = "v13")]
668 fn from_v13_meta(
669 mod_name: &str,
670 _mod_idx: u8,
671 error_idx: u8,
672 md: &frame_metadata::v13::ErrorMetadata,
673 ) -> Result<Self> {
674 Ok(Self {
675 mod_name: mod_name.into(),
676 name: decode_meta(&md.name)?.clone(),
677 error_idx,
678 docs: Docs::from_v13_meta(&md.documentation)?,
679 })
680 }
681
682 #[cfg(feature = "v14")]
683 fn from_v14_meta(mod_name: &str, _mod_idx: u8, md: &Variant) -> Result<Self> {
684 Ok(Self {
685 mod_name: mod_name.into(),
686 name: md.name.clone(),
687 error_idx: md.index,
688 docs: Docs::from_v14_meta(&md.docs),
689 })
690 }
691}
692
693#[derive(Clone)]
694pub struct FuncMetadata {
695 pub mod_name: String,
696 pub name: String,
697 pub mod_idx: u8,
698 pub func_idx: u8,
699 pub args: Vec<FuncArg>,
700 pub docs: Docs,
701}
702
703impl FuncMetadata {
704 #[cfg(feature = "v12")]
705 fn from_v12_meta(
706 mod_name: &str,
707 mod_idx: u8,
708 func_idx: u8,
709 md: &frame_metadata::v12::FunctionMetadata,
710 lookup: &mut Types,
711 ) -> Result<(Self, Option<TypeId>)> {
712 let mut func = Self {
713 mod_name: mod_name.into(),
714 name: decode_meta(&md.name)?.clone(),
715 mod_idx,
716 func_idx,
717 args: Vec::new(),
718 docs: Docs::from_v12_meta(&md.documentation)?,
719 };
720
721 let mut func_tuple = Vec::new();
722
723 decode_meta(&md.arguments)?
725 .iter()
726 .try_for_each(|md| -> Result<()> {
727 let arg = FuncArg::from_v12_meta(md, lookup)?;
728 func_tuple.push(arg.ty.ty_id.clone());
729 func.args.push(arg);
730 Ok(())
731 })?;
732
733 let func_ref = if func_tuple.len() > 0 {
734 let type_name = format!("{}::RawFunc::{}", mod_name, func.name);
735 Some(lookup.insert_type(&type_name, TypeDef::new_tuple(func_tuple)))
736 } else {
737 None
738 };
739
740 Ok((func, func_ref))
741 }
742
743 #[cfg(feature = "v13")]
744 fn from_v13_meta(
745 mod_name: &str,
746 mod_idx: u8,
747 func_idx: u8,
748 md: &frame_metadata::v13::FunctionMetadata,
749 lookup: &mut Types,
750 ) -> Result<(Self, Option<TypeId>)> {
751 let mut func = Self {
752 mod_name: mod_name.into(),
753 name: decode_meta(&md.name)?.clone(),
754 mod_idx,
755 func_idx,
756 args: Vec::new(),
757 docs: Docs::from_v13_meta(&md.documentation)?,
758 };
759
760 let mut func_tuple = Vec::new();
761
762 decode_meta(&md.arguments)?
764 .iter()
765 .try_for_each(|md| -> Result<()> {
766 let arg = FuncArg::from_v13_meta(md, lookup)?;
767 func_tuple.push(arg.ty.ty_id.clone());
768 func.args.push(arg);
769 Ok(())
770 })?;
771
772 let func_ref = if func_tuple.len() > 0 {
773 let type_name = format!("{}::RawFunc::{}", mod_name, func.name);
774 Some(lookup.insert_type(&type_name, TypeDef::new_tuple(func_tuple)))
775 } else {
776 None
777 };
778
779 Ok((func, func_ref))
780 }
781
782 #[cfg(feature = "v14")]
783 fn from_v14_meta(
784 mod_name: &str,
785 mod_idx: u8,
786 md: &Variant,
787 types: &PortableRegistry,
788 ) -> Result<Self> {
789 let mut func = Self {
790 mod_name: mod_name.into(),
791 name: md.name.clone(),
792 mod_idx,
793 func_idx: md.index,
794 args: Vec::new(),
795 docs: Docs::from_v14_meta(&md.docs),
796 };
797
798 md.fields.iter().try_for_each(|md| -> Result<()> {
800 let arg = FuncArg::from_v14_meta(md, types)?;
801 func.args.push(arg);
802 Ok(())
803 })?;
804
805 Ok(func)
806 }
807}
808
809#[derive(Clone)]
810pub struct FuncArg {
811 pub name: String,
812 pub ty: NamedType,
813}
814
815impl FuncArg {
816 #[cfg(feature = "v12")]
817 fn from_v12_meta(
818 md: &frame_metadata::v12::FunctionArgumentMetadata,
819 lookup: &mut Types,
820 ) -> Result<Self> {
821 let ty = decode_meta(&md.ty)?;
822 let arg = Self {
823 name: decode_meta(&md.name)?.clone(),
824 ty: NamedType::new(&ty, lookup)?,
825 };
826
827 Ok(arg)
828 }
829
830 #[cfg(feature = "v13")]
831 fn from_v13_meta(
832 md: &frame_metadata::v13::FunctionArgumentMetadata,
833 lookup: &mut Types,
834 ) -> Result<Self> {
835 let ty = decode_meta(&md.ty)?;
836 let arg = Self {
837 name: decode_meta(&md.name)?.clone(),
838 ty: NamedType::new(&ty, lookup)?,
839 };
840
841 Ok(arg)
842 }
843
844 #[cfg(feature = "v14")]
845 fn from_v14_meta(md: &Field, types: &PortableRegistry) -> Result<Self> {
846 let arg = Self {
847 name: md.name.clone().unwrap_or_default(),
848 ty: NamedType::new_field_type(md, types)?,
849 };
850
851 Ok(arg)
852 }
853}
854
855#[derive(Clone)]
856pub struct Docs {
857 pub lines: Vec<String>,
858}
859
860impl Docs {
861 #[cfg(feature = "v12")]
862 fn from_v12_meta(md: &DecodeDifferentArray<&'static str, String>) -> Result<Self> {
863 Ok(Self {
864 lines: decode_meta(md)?.clone(),
865 })
866 }
867
868 #[cfg(feature = "v13")]
869 fn from_v13_meta(md: &DecodeDifferentArray<&'static str, String>) -> Result<Self> {
870 Ok(Self {
871 lines: decode_meta(md)?.clone(),
872 })
873 }
874
875 #[cfg(feature = "v14")]
876 fn from_v14_meta(docs: &[String]) -> Self {
877 Self {
878 lines: docs.to_vec(),
879 }
880 }
881}