Skip to main content

sp_metadata_ir/
types.rs

1// This file is part of Substrate.
2
3// Copyright (C) Parity Technologies (UK) Ltd.
4// SPDX-License-Identifier: Apache-2.0
5
6// Licensed under the Apache License, Version 2.0 (the "License");
7// you may not use this file except in compliance with the License.
8// You may obtain a copy of the License at
9//
10// 	http://www.apache.org/licenses/LICENSE-2.0
11//
12// Unless required by applicable law or agreed to in writing, software
13// distributed under the License is distributed on an "AS IS" BASIS,
14// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15// See the License for the specific language governing permissions and
16// limitations under the License.
17
18use codec::{Compact, Decode, Encode};
19use derive_where::derive_where;
20use scale_info::{
21	form::{Form, MetaForm, PortableForm},
22	prelude::{collections::BTreeMap, vec::Vec},
23	IntoPortable, Registry,
24};
25
26/// The intermediate representation for the runtime metadata.
27/// Contains the needed context that allows conversion to multiple metadata versions.
28///
29/// # Note
30///
31/// Further fields could be added or removed to ensure proper conversion.
32/// When the IR does not contain enough information to generate a specific version
33/// of the runtime metadata an appropriate default value is used (ie, empty vector).
34pub struct MetadataIR<T: Form = MetaForm> {
35	/// Pallet metadata.
36	pub pallets: Vec<PalletMetadataIR<T>>,
37	/// Metadata of the extrinsic.
38	pub extrinsic: ExtrinsicMetadataIR<T>,
39	/// The type of the `Runtime`.
40	pub ty: T::Type,
41	/// Metadata of the Runtime API.
42	pub apis: Vec<RuntimeApiMetadataIR<T>>,
43	/// The outer enums types as found in the runtime.
44	pub outer_enums: OuterEnumsIR<T>,
45}
46
47/// Metadata of a runtime trait.
48#[derive(Encode)]
49#[derive_where(Clone, PartialEq, Eq, Debug;)]
50pub struct RuntimeApiMetadataIR<T: Form = MetaForm> {
51	/// Trait name.
52	pub name: T::String,
53	/// Trait methods.
54	pub methods: Vec<RuntimeApiMethodMetadataIR<T>>,
55	/// Trait documentation.
56	pub docs: Vec<T::String>,
57	/// Deprecation info.
58	pub deprecation_info: ItemDeprecationInfoIR<T>,
59	/// Runtime API version.
60	pub version: Compact<u32>,
61}
62
63impl IntoPortable for RuntimeApiMetadataIR {
64	type Output = RuntimeApiMetadataIR<PortableForm>;
65
66	fn into_portable(self, registry: &mut Registry) -> Self::Output {
67		RuntimeApiMetadataIR {
68			name: self.name.into_portable(registry),
69			methods: registry.map_into_portable(self.methods),
70			docs: registry.map_into_portable(self.docs),
71			deprecation_info: self.deprecation_info.into_portable(registry),
72			version: self.version,
73		}
74	}
75}
76
77/// Metadata of a runtime method.
78#[derive(Encode)]
79#[derive_where(Clone, PartialEq, Eq, Debug;)]
80pub struct RuntimeApiMethodMetadataIR<T: Form = MetaForm> {
81	/// Method name.
82	pub name: T::String,
83	/// Method parameters.
84	pub inputs: Vec<RuntimeApiMethodParamMetadataIR<T>>,
85	/// Method output.
86	pub output: T::Type,
87	/// Method documentation.
88	pub docs: Vec<T::String>,
89	/// Deprecation info
90	pub deprecation_info: ItemDeprecationInfoIR<T>,
91}
92
93impl IntoPortable for RuntimeApiMethodMetadataIR {
94	type Output = RuntimeApiMethodMetadataIR<PortableForm>;
95
96	fn into_portable(self, registry: &mut Registry) -> Self::Output {
97		RuntimeApiMethodMetadataIR {
98			name: self.name.into_portable(registry),
99			inputs: registry.map_into_portable(self.inputs),
100			output: registry.register_type(&self.output),
101			docs: registry.map_into_portable(self.docs),
102			deprecation_info: self.deprecation_info.into_portable(registry),
103		}
104	}
105}
106
107/// Metadata of a runtime method parameter.
108#[derive(Encode)]
109#[derive_where(Clone, PartialEq, Eq, Debug;)]
110pub struct RuntimeApiMethodParamMetadataIR<T: Form = MetaForm> {
111	/// Parameter name.
112	pub name: T::String,
113	/// Parameter type.
114	pub ty: T::Type,
115}
116
117impl IntoPortable for RuntimeApiMethodParamMetadataIR {
118	type Output = RuntimeApiMethodParamMetadataIR<PortableForm>;
119
120	fn into_portable(self, registry: &mut Registry) -> Self::Output {
121		RuntimeApiMethodParamMetadataIR {
122			name: self.name.into_portable(registry),
123			ty: registry.register_type(&self.ty),
124		}
125	}
126}
127
128/// Metadata of a pallet view function method.
129#[derive(Encode, Decode)]
130#[derive_where(Clone, PartialEq, Eq, Debug;)]
131pub struct PalletViewFunctionMetadataIR<T: Form = MetaForm> {
132	/// Method name.
133	pub name: T::String,
134	/// Method id.
135	pub id: [u8; 32],
136	/// Method parameters.
137	pub inputs: Vec<PalletViewFunctionParamMetadataIR<T>>,
138	/// Method output.
139	pub output: T::Type,
140	/// Method documentation.
141	pub docs: Vec<T::String>,
142	/// Deprecation info
143	pub deprecation_info: ItemDeprecationInfoIR<T>,
144}
145
146impl IntoPortable for PalletViewFunctionMetadataIR {
147	type Output = PalletViewFunctionMetadataIR<PortableForm>;
148
149	fn into_portable(self, registry: &mut Registry) -> Self::Output {
150		PalletViewFunctionMetadataIR {
151			name: self.name.into_portable(registry),
152			id: self.id,
153			inputs: registry.map_into_portable(self.inputs),
154			output: registry.register_type(&self.output),
155			docs: registry.map_into_portable(self.docs),
156			deprecation_info: self.deprecation_info.into_portable(registry),
157		}
158	}
159}
160
161/// Metadata of a pallet view function method argument.
162#[derive(Encode, Decode)]
163#[derive_where(Clone, PartialEq, Eq, Debug;)]
164pub struct PalletViewFunctionParamMetadataIR<T: Form = MetaForm> {
165	/// Parameter name.
166	pub name: T::String,
167	/// Parameter type.
168	pub ty: T::Type,
169}
170
171impl IntoPortable for PalletViewFunctionParamMetadataIR {
172	type Output = PalletViewFunctionParamMetadataIR<PortableForm>;
173
174	fn into_portable(self, registry: &mut Registry) -> Self::Output {
175		PalletViewFunctionParamMetadataIR {
176			name: self.name.into_portable(registry),
177			ty: registry.register_type(&self.ty),
178		}
179	}
180}
181
182/// The intermediate representation for a pallet metadata.
183#[derive(Encode)]
184#[derive_where(Clone, PartialEq, Eq, Debug;)]
185pub struct PalletMetadataIR<T: Form = MetaForm> {
186	/// Pallet name.
187	pub name: T::String,
188	/// Pallet storage metadata.
189	pub storage: Option<PalletStorageMetadataIR<T>>,
190	/// Pallet calls metadata.
191	pub calls: Option<PalletCallMetadataIR<T>>,
192	/// Pallet view functions metadata.
193	pub view_functions: Vec<PalletViewFunctionMetadataIR<T>>,
194	/// Pallet event metadata.
195	pub event: Option<PalletEventMetadataIR<T>>,
196	/// Pallet constants metadata.
197	pub constants: Vec<PalletConstantMetadataIR<T>>,
198	/// Pallet error metadata.
199	pub error: Option<PalletErrorMetadataIR<T>>,
200	/// Config's trait associated types.
201	pub associated_types: Vec<PalletAssociatedTypeMetadataIR<T>>,
202	/// Define the index of the pallet, this index will be used for the encoding of pallet event,
203	/// call and origin variants.
204	pub index: u8,
205	/// Pallet documentation.
206	pub docs: Vec<T::String>,
207	/// Deprecation info
208	pub deprecation_info: ItemDeprecationInfoIR<T>,
209}
210
211impl IntoPortable for PalletMetadataIR {
212	type Output = PalletMetadataIR<PortableForm>;
213
214	fn into_portable(self, registry: &mut Registry) -> Self::Output {
215		PalletMetadataIR {
216			name: self.name.into_portable(registry),
217			storage: self.storage.map(|storage| storage.into_portable(registry)),
218			calls: self.calls.map(|calls| calls.into_portable(registry)),
219			view_functions: self
220				.view_functions
221				.into_iter()
222				.map(|view_functions| view_functions.into_portable(registry))
223				.collect(),
224			event: self.event.map(|event| event.into_portable(registry)),
225			constants: registry.map_into_portable(self.constants),
226			error: self.error.map(|error| error.into_portable(registry)),
227			associated_types: registry.map_into_portable(self.associated_types),
228			index: self.index,
229			docs: registry.map_into_portable(self.docs),
230			deprecation_info: self.deprecation_info.into_portable(registry),
231		}
232	}
233}
234
235/// Metadata of the extrinsic used by the runtime.
236#[derive(Encode)]
237#[derive_where(Clone, PartialEq, Eq, Debug;)]
238pub struct ExtrinsicMetadataIR<T: Form = MetaForm> {
239	/// The type of the extrinsic.
240	///
241	/// Note: Field used for metadata V14 only.
242	pub ty: T::Type,
243	/// Extrinsic versions.
244	pub versions: Vec<u8>,
245	/// The type of the address that signs the extrinsic
246	pub address_ty: T::Type,
247	/// The type of the outermost Call enum.
248	pub call_ty: T::Type,
249	/// The type of the extrinsic's signature.
250	pub signature_ty: T::Type,
251	/// The type of the outermost Extra/Extensions enum.
252	// TODO: metadata-v16: remove this, the `implicit` type can be found in `extensions::implicit`.
253	pub extra_ty: T::Type,
254	/// The transaction extensions for each version as a list of index in reference to items in
255	/// `extensions_in_versions` field.
256	pub extensions_by_version: BTreeMap<u8, Vec<u32>>,
257	/// The list of all transaction extensions used in `extensions_by_version`.
258	pub extensions_in_versions: Vec<TransactionExtensionMetadataIR<T>>,
259}
260
261impl<T: Form> ExtrinsicMetadataIR<T> {
262	/// The transaction extensions in the order they appear in the extrinsic for the version 0 if
263	/// defined.
264	pub fn extensions_v0(&self) -> Option<Vec<TransactionExtensionMetadataIR<T>>> {
265		self.extensions_by_version.get(&0).map(|indices| {
266			indices
267				.iter()
268				.map(|i| self.extensions_in_versions[*i as usize].clone())
269				.collect()
270		})
271	}
272}
273
274impl IntoPortable for ExtrinsicMetadataIR {
275	type Output = ExtrinsicMetadataIR<PortableForm>;
276
277	fn into_portable(self, registry: &mut Registry) -> Self::Output {
278		ExtrinsicMetadataIR {
279			ty: registry.register_type(&self.ty),
280			versions: self.versions,
281			address_ty: registry.register_type(&self.address_ty),
282			call_ty: registry.register_type(&self.call_ty),
283			signature_ty: registry.register_type(&self.signature_ty),
284			extra_ty: registry.register_type(&self.extra_ty),
285			extensions_by_version: self.extensions_by_version,
286			extensions_in_versions: registry.map_into_portable(self.extensions_in_versions),
287		}
288	}
289}
290
291/// Metadata of a pallet's associated type.
292#[derive(Encode)]
293#[derive_where(Clone, PartialEq, Eq, Debug;)]
294pub struct PalletAssociatedTypeMetadataIR<T: Form = MetaForm> {
295	/// The name of the associated type.
296	pub name: T::String,
297	/// The type of the associated type.
298	pub ty: T::Type,
299	/// The documentation of the associated type.
300	pub docs: Vec<T::String>,
301}
302
303impl IntoPortable for PalletAssociatedTypeMetadataIR {
304	type Output = PalletAssociatedTypeMetadataIR<PortableForm>;
305
306	fn into_portable(self, registry: &mut Registry) -> Self::Output {
307		PalletAssociatedTypeMetadataIR {
308			name: self.name.into_portable(registry),
309			ty: registry.register_type(&self.ty),
310			docs: registry.map_into_portable(self.docs),
311		}
312	}
313}
314
315/// Metadata of an extrinsic's signed extension.
316#[derive(Encode)]
317#[derive_where(Clone, PartialEq, Eq, Debug;)]
318pub struct TransactionExtensionMetadataIR<T: Form = MetaForm> {
319	/// The unique signed extension identifier, which may be different from the type name.
320	pub identifier: T::String,
321	/// The type of the signed extension, with the data to be included in the extrinsic.
322	pub ty: T::Type,
323	/// The type of the implicit data, with the data to be included in the signed payload.
324	pub implicit: T::Type,
325}
326
327impl IntoPortable for TransactionExtensionMetadataIR {
328	type Output = TransactionExtensionMetadataIR<PortableForm>;
329
330	fn into_portable(self, registry: &mut Registry) -> Self::Output {
331		TransactionExtensionMetadataIR {
332			identifier: self.identifier.into_portable(registry),
333			ty: registry.register_type(&self.ty),
334			implicit: registry.register_type(&self.implicit),
335		}
336	}
337}
338
339/// All metadata of the pallet's storage.
340///
341/// The common prefix used by all storage entries.
342#[derive(Encode)]
343#[derive_where(Clone, PartialEq, Eq, Debug;)]
344pub struct PalletStorageMetadataIR<T: Form = MetaForm> {
345	/// The common prefix used by all storage entries.
346	pub prefix: T::String,
347	/// Metadata for all storage entries.
348	pub entries: Vec<StorageEntryMetadataIR<T>>,
349}
350
351impl IntoPortable for PalletStorageMetadataIR {
352	type Output = PalletStorageMetadataIR<PortableForm>;
353
354	fn into_portable(self, registry: &mut Registry) -> Self::Output {
355		PalletStorageMetadataIR {
356			prefix: self.prefix.into_portable(registry),
357			entries: registry.map_into_portable(self.entries),
358		}
359	}
360}
361
362/// Metadata about one storage entry.
363#[derive(Encode)]
364#[derive_where(Clone, PartialEq, Eq, Debug;)]
365pub struct StorageEntryMetadataIR<T: Form = MetaForm> {
366	/// Variable name of the storage entry.
367	pub name: T::String,
368	/// An `Option` modifier of that storage entry.
369	pub modifier: StorageEntryModifierIR,
370	/// Type of the value stored in the entry.
371	pub ty: StorageEntryTypeIR<T>,
372	/// Default value (SCALE encoded).
373	pub default: Vec<u8>,
374	/// Storage entry documentation.
375	pub docs: Vec<T::String>,
376	/// Deprecation info
377	pub deprecation_info: ItemDeprecationInfoIR<T>,
378}
379
380impl IntoPortable for StorageEntryMetadataIR {
381	type Output = StorageEntryMetadataIR<PortableForm>;
382
383	fn into_portable(self, registry: &mut Registry) -> Self::Output {
384		StorageEntryMetadataIR {
385			name: self.name.into_portable(registry),
386			modifier: self.modifier,
387			ty: self.ty.into_portable(registry),
388			default: self.default,
389			docs: registry.map_into_portable(self.docs),
390			deprecation_info: self.deprecation_info.into_portable(registry),
391		}
392	}
393}
394
395/// A storage entry modifier indicates how a storage entry is returned when fetched and what the
396/// value will be if the key is not present. Specifically this refers to the "return type" when
397/// fetching a storage entry, and what the value will be if the key is not present.
398///
399/// `Optional` means you should expect an `Option<T>`, with `None` returned if the key is not
400/// present. `Default` means you should expect a `T` with the default value of default if the key is
401/// not present.
402#[derive(Clone, PartialEq, Eq, Encode, Debug)]
403pub enum StorageEntryModifierIR {
404	/// The storage entry returns an `Option<T>`, with `None` if the key is not present.
405	Optional,
406	/// The storage entry returns `T::Default` if the key is not present.
407	Default,
408}
409
410/// Hasher used by storage maps
411#[derive(Clone, PartialEq, Eq, Encode, Debug)]
412pub enum StorageHasherIR {
413	/// 128-bit Blake2 hash.
414	Blake2_128,
415	/// 256-bit Blake2 hash.
416	Blake2_256,
417	/// Multiple 128-bit Blake2 hashes concatenated.
418	Blake2_128Concat,
419	/// 128-bit XX hash.
420	Twox128,
421	/// 256-bit XX hash.
422	Twox256,
423	/// Multiple 64-bit XX hashes concatenated.
424	Twox64Concat,
425	/// Identity hashing (no hashing).
426	Identity,
427}
428
429/// A type of storage value.
430#[derive(Encode)]
431#[derive_where(Clone, PartialEq, Eq, Debug;)]
432pub enum StorageEntryTypeIR<T: Form = MetaForm> {
433	/// Plain storage entry (just the value).
434	Plain(T::Type),
435	/// A storage map.
436	Map {
437		/// One or more hashers, should be one hasher per key element.
438		hashers: Vec<StorageHasherIR>,
439		/// The type of the key, can be a tuple with elements for each of the hashers.
440		key: T::Type,
441		/// The type of the value.
442		value: T::Type,
443	},
444}
445
446impl IntoPortable for StorageEntryTypeIR {
447	type Output = StorageEntryTypeIR<PortableForm>;
448
449	fn into_portable(self, registry: &mut Registry) -> Self::Output {
450		match self {
451			Self::Plain(plain) => StorageEntryTypeIR::Plain(registry.register_type(&plain)),
452			Self::Map { hashers, key, value } => StorageEntryTypeIR::Map {
453				hashers,
454				key: registry.register_type(&key),
455				value: registry.register_type(&value),
456			},
457		}
458	}
459}
460
461/// Metadata for all calls in a pallet
462#[derive(Encode)]
463#[derive_where(Clone, PartialEq, Eq, Debug;)]
464pub struct PalletCallMetadataIR<T: Form = MetaForm> {
465	/// The corresponding enum type for the pallet call.
466	pub ty: T::Type,
467	/// Deprecation status of the pallet call
468	pub deprecation_info: EnumDeprecationInfoIR<T>,
469}
470
471impl IntoPortable for PalletCallMetadataIR {
472	type Output = PalletCallMetadataIR<PortableForm>;
473
474	fn into_portable(self, registry: &mut Registry) -> Self::Output {
475		PalletCallMetadataIR {
476			ty: registry.register_type(&self.ty),
477			deprecation_info: self.deprecation_info.into_portable(registry),
478		}
479	}
480}
481
482/// Metadata about the pallet Event type.
483#[derive(Encode)]
484#[derive_where(Clone, PartialEq, Eq, Debug;)]
485pub struct PalletEventMetadataIR<T: Form = MetaForm> {
486	/// The Event type.
487	pub ty: T::Type,
488	/// Deprecation info of the event
489	pub deprecation_info: EnumDeprecationInfoIR<T>,
490}
491
492impl IntoPortable for PalletEventMetadataIR {
493	type Output = PalletEventMetadataIR<PortableForm>;
494
495	fn into_portable(self, registry: &mut Registry) -> Self::Output {
496		PalletEventMetadataIR {
497			ty: registry.register_type(&self.ty),
498			deprecation_info: self.deprecation_info.into_portable(registry),
499		}
500	}
501}
502
503/// Metadata about one pallet constant.
504#[derive(Encode)]
505#[derive_where(Clone, PartialEq, Eq, Debug;)]
506pub struct PalletConstantMetadataIR<T: Form = MetaForm> {
507	/// Name of the pallet constant.
508	pub name: T::String,
509	/// Type of the pallet constant.
510	pub ty: T::Type,
511	/// Value stored in the constant (SCALE encoded).
512	pub value: Vec<u8>,
513	/// Documentation of the constant.
514	pub docs: Vec<T::String>,
515	/// Deprecation info
516	pub deprecation_info: ItemDeprecationInfoIR<T>,
517}
518
519impl IntoPortable for PalletConstantMetadataIR {
520	type Output = PalletConstantMetadataIR<PortableForm>;
521
522	fn into_portable(self, registry: &mut Registry) -> Self::Output {
523		PalletConstantMetadataIR {
524			name: self.name.into_portable(registry),
525			ty: registry.register_type(&self.ty),
526			value: self.value,
527			docs: registry.map_into_portable(self.docs),
528			deprecation_info: self.deprecation_info.into_portable(registry),
529		}
530	}
531}
532
533/// Metadata about a pallet error.
534#[derive(Encode)]
535#[derive_where(Clone, PartialEq, Eq, Debug;)]
536pub struct PalletErrorMetadataIR<T: Form = MetaForm> {
537	/// The error type information.
538	pub ty: T::Type,
539	/// Deprecation info
540	pub deprecation_info: EnumDeprecationInfoIR<T>,
541}
542
543impl IntoPortable for PalletErrorMetadataIR {
544	type Output = PalletErrorMetadataIR<PortableForm>;
545
546	fn into_portable(self, registry: &mut Registry) -> Self::Output {
547		PalletErrorMetadataIR {
548			ty: registry.register_type(&self.ty),
549			deprecation_info: self.deprecation_info.into_portable(registry),
550		}
551	}
552}
553
554/// The type of the outer enums.
555#[derive(Encode)]
556#[derive_where(Clone, PartialEq, Eq, Debug;)]
557pub struct OuterEnumsIR<T: Form = MetaForm> {
558	/// The type of the outer `RuntimeCall` enum.
559	pub call_enum_ty: T::Type,
560	/// The type of the outer `RuntimeEvent` enum.
561	pub event_enum_ty: T::Type,
562	/// The module error type of the
563	/// [`DispatchError::Module`](https://docs.rs/sp-runtime/24.0.0/sp_runtime/enum.DispatchError.html#variant.Module) variant.
564	///
565	/// The `Module` variant will be 5 scale encoded bytes which are normally decoded into
566	/// an `{ index: u8, error: [u8; 4] }` struct. This type ID points to an enum type which
567	/// instead interprets the first `index` byte as a pallet variant, and the remaining `error`
568	/// bytes as the appropriate `pallet::Error` type. It is an equally valid way to decode the
569	/// error bytes, and can be more informative.
570	///
571	/// # Note
572	///
573	/// - This type cannot be used directly to decode `sp_runtime::DispatchError` from the chain.
574	///   It provides just the information needed to decode `sp_runtime::DispatchError::Module`.
575	/// - Decoding the 5 error bytes into this type will not always lead to all of the bytes being
576	///   consumed; many error types do not require all of the bytes to represent them fully.
577	pub error_enum_ty: T::Type,
578}
579
580impl IntoPortable for OuterEnumsIR {
581	type Output = OuterEnumsIR<PortableForm>;
582
583	fn into_portable(self, registry: &mut Registry) -> Self::Output {
584		OuterEnumsIR {
585			call_enum_ty: registry.register_type(&self.call_enum_ty),
586			event_enum_ty: registry.register_type(&self.event_enum_ty),
587			error_enum_ty: registry.register_type(&self.error_enum_ty),
588		}
589	}
590}
591
592/// Deprecation information for generic items.
593#[derive(Encode)]
594#[derive_where(Clone, PartialEq, Eq, Debug;)]
595pub enum ItemDeprecationInfoIR<T: Form = MetaForm> {
596	/// Item is not deprecated.
597	NotDeprecated,
598	/// Item is fully deprecated without a note.
599	DeprecatedWithoutNote,
600	/// Item is fully deprecated with a note and an optional `since` field.
601	Deprecated {
602		/// Note explaining the deprecation
603		note: T::String,
604		/// Optional value for noting the version when the deprecation occurred.
605		since: Option<T::String>,
606	},
607}
608
609impl IntoPortable for ItemDeprecationInfoIR {
610	type Output = ItemDeprecationInfoIR<PortableForm>;
611
612	fn into_portable(self, registry: &mut Registry) -> Self::Output {
613		match self {
614			Self::NotDeprecated => ItemDeprecationInfoIR::NotDeprecated,
615			Self::DeprecatedWithoutNote => ItemDeprecationInfoIR::DeprecatedWithoutNote,
616			Self::Deprecated { note, since } => {
617				let note = note.into_portable(registry);
618				let since = since.map(|x| x.into_portable(registry));
619				ItemDeprecationInfoIR::Deprecated { note, since }
620			},
621		}
622	}
623}
624
625/// Deprecation information for enums in which specific variants can be deprecated.
626/// If the map is empty, then nothing is deprecated.
627#[derive(Encode)]
628#[derive_where(Clone, PartialEq, Eq, Debug;)]
629pub struct EnumDeprecationInfoIR<T: Form = MetaForm>(pub BTreeMap<u8, VariantDeprecationInfoIR<T>>);
630
631impl<T: Form> EnumDeprecationInfoIR<T> {
632	/// Construct an instance in which nothing is marked for deprecation.
633	pub fn nothing_deprecated() -> Self {
634		Self(BTreeMap::new())
635	}
636
637	/// Are any variants deprecated?
638	pub fn has_deprecated_variants(&self) -> bool {
639		!self.0.is_empty()
640	}
641
642	/// Is a specific variant deprecated?
643	pub fn is_variant_deprecated(&self, variant_index: u8) -> bool {
644		self.0.contains_key(&variant_index)
645	}
646}
647
648impl IntoPortable for EnumDeprecationInfoIR {
649	type Output = EnumDeprecationInfoIR<PortableForm>;
650
651	fn into_portable(self, registry: &mut Registry) -> Self::Output {
652		let entries = self.0.into_iter().map(|(k, entry)| (k, entry.into_portable(registry)));
653		EnumDeprecationInfoIR(entries.collect())
654	}
655}
656
657/// Deprecation information for an item or variant in the metadata.
658#[derive(Encode)]
659#[derive_where(Clone, PartialEq, Eq, Debug;)]
660pub enum VariantDeprecationInfoIR<T: Form = MetaForm> {
661	/// Variant is deprecated without a note.
662	DeprecatedWithoutNote,
663	/// Variant is deprecated with a note and an optional `since` field.
664	Deprecated {
665		/// Note explaining the deprecation
666		note: T::String,
667		/// Optional value for noting the version when the deprecation occurred.
668		since: Option<T::String>,
669	},
670}
671
672impl<T: Form> Into<ItemDeprecationInfoIR<T>> for VariantDeprecationInfoIR<T> {
673	fn into(self) -> ItemDeprecationInfoIR<T> {
674		match self {
675			Self::Deprecated { note, since } => ItemDeprecationInfoIR::Deprecated { note, since },
676			Self::DeprecatedWithoutNote => ItemDeprecationInfoIR::DeprecatedWithoutNote,
677		}
678	}
679}
680
681impl IntoPortable for VariantDeprecationInfoIR {
682	type Output = VariantDeprecationInfoIR<PortableForm>;
683
684	fn into_portable(self, registry: &mut Registry) -> Self::Output {
685		match self {
686			Self::Deprecated { note, since } => {
687				let note = note.into_portable(registry);
688				let since = since.map(|x| x.into_portable(registry));
689				VariantDeprecationInfoIR::Deprecated { note, since }
690			},
691			Self::DeprecatedWithoutNote => VariantDeprecationInfoIR::DeprecatedWithoutNote,
692		}
693	}
694}