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