Skip to main content

eosio_scale_info/ty/
mod.rs

1// Copyright 2019-2022 Parity Technologies (UK) Ltd.
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7//     http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15use crate::prelude::{
16    vec,
17    vec::Vec,
18};
19
20use crate::{
21    build::TypeBuilder,
22    form::{
23        Form,
24        MetaForm,
25        PortableForm,
26    },
27    IntoPortable,
28    MetaType,
29    Registry,
30    TypeInfo,
31};
32use derive_more::From;
33use scale::Encode;
34#[cfg(feature = "serde")]
35use serde::{
36    de::DeserializeOwned,
37    Deserialize,
38    Serialize,
39};
40
41mod composite;
42mod fields;
43mod path;
44mod variant;
45
46pub use self::{
47    composite::*,
48    fields::*,
49    path::*,
50    variant::*,
51};
52
53/// A [`Type`] definition with optional metadata.
54#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
55#[cfg_attr(
56    feature = "serde",
57    serde(bound(
58        serialize = "T::Type: Serialize, T::String: Serialize",
59        deserialize = "T::Type: DeserializeOwned, T::String: DeserializeOwned",
60    ))
61)]
62#[cfg_attr(feature = "serde", serde(rename_all = "lowercase"))]
63#[cfg_attr(any(feature = "std", feature = "decode"), derive(scale::Decode))]
64#[derive(PartialEq, Eq, PartialOrd, Ord, Clone, From, Debug, Encode)]
65pub struct Type<T: Form = MetaForm> {
66    /// The unique path to the type. Can be empty for built-in types
67    #[cfg_attr(
68        feature = "serde",
69        serde(skip_serializing_if = "Path::is_empty", default)
70    )]
71    path: Path<T>,
72    /// The generic type parameters of the type in use. Empty for non generic types
73    #[cfg_attr(
74        feature = "serde",
75        serde(rename = "params", skip_serializing_if = "Vec::is_empty", default)
76    )]
77    type_params: Vec<TypeParameter<T>>,
78    /// The actual type definition
79    #[cfg_attr(feature = "serde", serde(rename = "def"))]
80    type_def: TypeDef<T>,
81    /// Documentation
82    #[cfg_attr(
83        feature = "serde",
84        serde(skip_serializing_if = "Vec::is_empty", default)
85    )]
86    docs: Vec<T::String>,
87}
88
89impl IntoPortable for Type {
90    type Output = Type<PortableForm>;
91
92    fn into_portable(self, registry: &mut Registry) -> Self::Output {
93        Type {
94            path: self.path.into_portable(registry),
95            type_params: registry.map_into_portable(self.type_params),
96            type_def: self.type_def.into_portable(registry),
97            docs: registry.map_into_portable(self.docs),
98        }
99    }
100}
101
102macro_rules! impl_from_type_def_for_type {
103    ( $( $t:ty  ), + $(,)?) => { $(
104        impl From<$t> for Type {
105            fn from(item: $t) -> Self {
106                Self::new(Path::voldemort(), Vec::new(), item, Vec::new())
107            }
108        }
109    )* }
110}
111
112impl_from_type_def_for_type!(
113    TypeDefPrimitive,
114    TypeDefArray,
115    TypeDefSequence,
116    TypeDefTuple,
117    TypeDefCompact,
118    TypeDefBitSequence,
119);
120
121impl Type {
122    /// Create a [`TypeBuilder`](`crate::build::TypeBuilder`) the public API for constructing a [`Type`]
123    pub fn builder() -> TypeBuilder {
124        TypeBuilder::default()
125    }
126
127    pub(crate) fn new<I, D>(
128        path: Path,
129        type_params: I,
130        type_def: D,
131        docs: Vec<&'static str>,
132    ) -> Self
133    where
134        I: IntoIterator<Item = TypeParameter>,
135        D: Into<TypeDef>,
136    {
137        Self {
138            path,
139            type_params: type_params.into_iter().collect(),
140            type_def: type_def.into(),
141            docs,
142        }
143    }
144}
145
146impl<T> Type<T>
147where
148    T: Form,
149{
150    /// Returns the path of the type
151    pub fn path(&self) -> &Path<T> {
152        &self.path
153    }
154
155    /// Returns the generic type parameters of the type
156    pub fn type_params(&self) -> &[TypeParameter<T>] {
157        &self.type_params
158    }
159
160    /// Returns the definition of the type
161    pub fn type_def(&self) -> &TypeDef<T> {
162        &self.type_def
163    }
164
165    /// Returns the documentation of the type
166    pub fn docs(&self) -> &[T::String] {
167        &self.docs
168    }
169}
170
171/// A generic type parameter.
172#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
173#[cfg_attr(
174    feature = "serde",
175    serde(bound(
176        serialize = "T::Type: Serialize, T::String: Serialize",
177        deserialize = "T::Type: DeserializeOwned, T::String: DeserializeOwned",
178    ))
179)]
180#[cfg_attr(any(feature = "std", feature = "decode"), derive(scale::Decode))]
181#[derive(PartialEq, Eq, PartialOrd, Ord, Clone, From, Debug, Encode)]
182pub struct TypeParameter<T: Form = MetaForm> {
183    /// The name of the generic type parameter e.g. "T".
184    name: T::String,
185    /// The concrete type for the type parameter.
186    ///
187    /// `None` if the type parameter is skipped.
188    #[cfg_attr(feature = "serde", serde(rename = "type"))]
189    ty: Option<T::Type>,
190}
191
192impl IntoPortable for TypeParameter {
193    type Output = TypeParameter<PortableForm>;
194
195    fn into_portable(self, registry: &mut Registry) -> Self::Output {
196        TypeParameter {
197            name: self.name.into_portable(registry),
198            ty: self.ty.map(|ty| registry.register_type(&ty)),
199        }
200    }
201}
202
203impl<T> TypeParameter<T>
204where
205    T: Form,
206{
207    /// Create a new [`TypeParameter`].
208    pub fn new(name: T::String, ty: Option<T::Type>) -> Self {
209        Self { name, ty }
210    }
211
212    /// Get the type of the parameter.
213    ///
214    /// `None` if the parameter is skipped.
215    pub fn ty(&self) -> Option<&T::Type> {
216        self.ty.as_ref()
217    }
218
219    /// Get the name of the parameter.
220    pub fn name(&self) -> &T::String {
221        &self.name
222    }
223}
224
225/// The possible types a SCALE encodable Rust value could have.
226///
227/// # Note
228///
229/// In order to preserve backwards compatibility, variant indices are explicitly specified instead
230/// of depending on the default implicit ordering.
231///
232/// When adding a new variant, it must be added at the end with an incremented index.
233///
234/// When removing an existing variant, the rest of variant indices remain the same, and the removed
235/// index should not be reused.
236#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
237#[cfg_attr(
238    feature = "serde",
239    serde(bound(
240        serialize = "T::Type: Serialize, T::String: Serialize",
241        deserialize = "T::Type: DeserializeOwned, T::String: DeserializeOwned",
242    ))
243)]
244#[cfg_attr(feature = "serde", serde(rename_all = "lowercase"))]
245#[cfg_attr(any(feature = "std", feature = "decode"), derive(scale::Decode))]
246#[derive(PartialEq, Eq, PartialOrd, Ord, Clone, From, Debug, Encode)]
247pub enum TypeDef<T: Form = MetaForm> {
248    /// A composite type (e.g. a struct or a tuple)
249    #[codec(index = 0)]
250    Composite(TypeDefComposite<T>),
251    /// A variant type (e.g. an enum)
252    #[codec(index = 1)]
253    Variant(TypeDefVariant<T>),
254    /// A sequence type with runtime known length.
255    #[codec(index = 2)]
256    Sequence(TypeDefSequence<T>),
257    /// An array type with compile-time known length.
258    #[codec(index = 3)]
259    Array(TypeDefArray<T>),
260    /// A tuple type.
261    #[codec(index = 4)]
262    Tuple(TypeDefTuple<T>),
263    /// A Rust primitive type.
264    #[codec(index = 5)]
265    Primitive(TypeDefPrimitive),
266    /// A type using the [`Compact`] encoding
267    #[codec(index = 6)]
268    Compact(TypeDefCompact<T>),
269    /// A type representing a sequence of bits.
270    #[codec(index = 7)]
271    BitSequence(TypeDefBitSequence<T>),
272}
273
274impl IntoPortable for TypeDef {
275    type Output = TypeDef<PortableForm>;
276
277    fn into_portable(self, registry: &mut Registry) -> Self::Output {
278        match self {
279            TypeDef::Composite(composite) => composite.into_portable(registry).into(),
280            TypeDef::Variant(variant) => variant.into_portable(registry).into(),
281            TypeDef::Sequence(sequence) => sequence.into_portable(registry).into(),
282            TypeDef::Array(array) => array.into_portable(registry).into(),
283            TypeDef::Tuple(tuple) => tuple.into_portable(registry).into(),
284            TypeDef::Primitive(primitive) => primitive.into(),
285            TypeDef::Compact(compact) => compact.into_portable(registry).into(),
286            TypeDef::BitSequence(bitseq) => bitseq.into_portable(registry).into(),
287        }
288    }
289}
290
291/// A primitive Rust type.
292///
293/// # Note
294///
295/// Explicit codec indices specified to ensure backwards compatibility. See [`TypeDef`].
296#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
297#[cfg_attr(feature = "serde", serde(rename_all = "lowercase"))]
298#[cfg_attr(any(feature = "std", feature = "decode"), derive(scale::Decode))]
299#[derive(PartialEq, Eq, PartialOrd, Ord, Clone, Encode, Debug)]
300pub enum TypeDefPrimitive {
301    /// `bool` type
302    #[codec(index = 0)]
303    Bool,
304    /// `char` type
305    #[codec(index = 1)]
306    Char,
307    /// `str` type
308    #[codec(index = 2)]
309    Str,
310    /// `u8`
311    #[codec(index = 3)]
312    U8,
313    /// `u16`
314    #[codec(index = 4)]
315    U16,
316    /// `u32`
317    #[codec(index = 5)]
318    U32,
319    /// `u64`
320    #[codec(index = 6)]
321    U64,
322    /// `u128`
323    #[codec(index = 7)]
324    U128,
325    /// 256 bits unsigned int (no rust equivalent)
326    #[codec(index = 8)]
327    U256,
328    /// `i8`
329    #[codec(index = 9)]
330    I8,
331    /// `i16`
332    #[codec(index = 10)]
333    I16,
334    /// `i32`
335    #[codec(index = 11)]
336    I32,
337    /// `i64`
338    #[codec(index = 12)]
339    I64,
340    /// `i128`
341    #[codec(index = 13)]
342    I128,
343    /// 256 bits signed int (no rust equivalent)
344    #[codec(index = 14)]
345    I256,
346    /// `f32`
347    #[codec(index = 15)]
348    F32,
349    /// 256 bits signed int (no rust equivalent)
350    #[codec(index = 16)]
351    F64,
352}
353
354/// An array type.
355#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
356#[cfg_attr(any(feature = "std", feature = "decode"), derive(scale::Decode))]
357#[derive(PartialEq, Eq, PartialOrd, Ord, Clone, Encode, Debug)]
358pub struct TypeDefArray<T: Form = MetaForm> {
359    /// The length of the array type.
360    len: u32,
361    /// The element type of the array type.
362    #[cfg_attr(feature = "serde", serde(rename = "type"))]
363    type_param: T::Type,
364}
365
366impl IntoPortable for TypeDefArray {
367    type Output = TypeDefArray<PortableForm>;
368
369    fn into_portable(self, registry: &mut Registry) -> Self::Output {
370        TypeDefArray {
371            len: self.len,
372            type_param: registry.register_type(&self.type_param),
373        }
374    }
375}
376
377impl TypeDefArray {
378    /// Creates a new array type.
379    pub fn new(len: u32, type_param: MetaType) -> Self {
380        Self { len, type_param }
381    }
382}
383
384#[allow(clippy::len_without_is_empty)]
385impl<T> TypeDefArray<T>
386where
387    T: Form,
388{
389    /// Returns the length of the array type.
390    pub fn len(&self) -> u32 {
391        self.len
392    }
393
394    /// Returns the element type of the array type.
395    pub fn type_param(&self) -> &T::Type {
396        &self.type_param
397    }
398}
399
400/// A type to refer to tuple types.
401#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
402#[cfg_attr(
403    feature = "serde",
404    serde(bound(
405        serialize = "T::Type: Serialize, T::String: Serialize",
406        deserialize = "T::Type: DeserializeOwned, T::String: DeserializeOwned",
407    ))
408)]
409#[cfg_attr(feature = "serde", serde(transparent))]
410#[cfg_attr(any(feature = "std", feature = "decode"), derive(scale::Decode))]
411#[derive(PartialEq, Eq, PartialOrd, Ord, Clone, Encode, Debug)]
412pub struct TypeDefTuple<T: Form = MetaForm> {
413    /// The types of the tuple fields.
414    fields: Vec<T::Type>,
415}
416
417impl IntoPortable for TypeDefTuple {
418    type Output = TypeDefTuple<PortableForm>;
419
420    fn into_portable(self, registry: &mut Registry) -> Self::Output {
421        TypeDefTuple {
422            fields: registry.register_types(self.fields),
423        }
424    }
425}
426
427impl TypeDefTuple {
428    /// Creates a new tuple type definition from the given types.
429    pub fn new<T>(type_params: T) -> Self
430    where
431        T: IntoIterator<Item = MetaType>,
432    {
433        Self {
434            fields: type_params
435                .into_iter()
436                .filter(|ty| !ty.is_phantom())
437                .collect(),
438        }
439    }
440
441    /// Creates a new unit tuple to represent the unit type, `()`.
442    pub fn unit() -> Self {
443        Self::new(vec![])
444    }
445}
446
447impl<T> TypeDefTuple<T>
448where
449    T: Form,
450{
451    /// Returns the types of the tuple fields.
452    pub fn fields(&self) -> &[T::Type] {
453        &self.fields
454    }
455}
456
457/// A type to refer to a sequence of elements of the same type.
458#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
459#[cfg_attr(any(feature = "std", feature = "decode"), derive(scale::Decode))]
460#[derive(PartialEq, Eq, PartialOrd, Ord, Clone, Encode, Debug)]
461pub struct TypeDefSequence<T: Form = MetaForm> {
462    /// The element type of the sequence type.
463    #[cfg_attr(feature = "serde", serde(rename = "type"))]
464    type_param: T::Type,
465}
466
467impl IntoPortable for TypeDefSequence {
468    type Output = TypeDefSequence<PortableForm>;
469
470    fn into_portable(self, registry: &mut Registry) -> Self::Output {
471        TypeDefSequence {
472            type_param: registry.register_type(&self.type_param),
473        }
474    }
475}
476
477impl TypeDefSequence {
478    /// Creates a new sequence type.
479    ///
480    /// Use this constructor if you want to instantiate from a given meta type.
481    pub fn new(type_param: MetaType) -> Self {
482        Self { type_param }
483    }
484
485    /// Creates a new sequence type.
486    ///
487    /// Use this constructor if you want to instantiate from a given
488    /// compile-time type.
489    pub fn of<T>() -> Self
490    where
491        T: TypeInfo + 'static,
492    {
493        Self::new(MetaType::new::<T>())
494    }
495}
496
497impl<T> TypeDefSequence<T>
498where
499    T: Form,
500{
501    /// Returns the element type of the sequence type.
502    pub fn type_param(&self) -> &T::Type {
503        &self.type_param
504    }
505}
506
507/// A type wrapped in [`Compact`].
508#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
509#[cfg_attr(any(feature = "std", feature = "decode"), derive(scale::Decode))]
510#[derive(PartialEq, Eq, PartialOrd, Ord, Clone, Encode, Debug)]
511pub struct TypeDefCompact<T: Form = MetaForm> {
512    /// The type wrapped in [`Compact`], i.e. the `T` in `Compact<T>`.
513    #[cfg_attr(feature = "serde", serde(rename = "type"))]
514    type_param: T::Type,
515}
516
517impl IntoPortable for TypeDefCompact {
518    type Output = TypeDefCompact<PortableForm>;
519
520    fn into_portable(self, registry: &mut Registry) -> Self::Output {
521        TypeDefCompact {
522            type_param: registry.register_type(&self.type_param),
523        }
524    }
525}
526
527impl TypeDefCompact {
528    /// Creates a new type wrapped in [`Compact`].
529    pub fn new(type_param: MetaType) -> Self {
530        Self { type_param }
531    }
532}
533impl<T> TypeDefCompact<T>
534where
535    T: Form,
536{
537    /// Returns the [`Compact`] wrapped type, i.e. the `T` in `Compact<T>`.
538    pub fn type_param(&self) -> &T::Type {
539        &self.type_param
540    }
541}
542
543/// Type describing a [`bitvec::vec::BitVec`].
544///
545/// # Note
546///
547/// This can only be constructed for `TypeInfo` in the `MetaForm` with the `bit-vec` feature
548/// enabled, but can be decoded or deserialized into the `PortableForm` without this feature.
549#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
550#[cfg_attr(any(feature = "std", feature = "decode"), derive(scale::Decode))]
551#[derive(PartialEq, Eq, PartialOrd, Ord, Clone, Encode, Debug)]
552pub struct TypeDefBitSequence<T: Form = MetaForm> {
553    /// The type implementing [`bitvec::store::BitStore`].
554    bit_store_type: T::Type,
555    /// The type implementing [`bitvec::order::BitOrder`].
556    bit_order_type: T::Type,
557}
558
559impl IntoPortable for TypeDefBitSequence {
560    type Output = TypeDefBitSequence<PortableForm>;
561
562    fn into_portable(self, registry: &mut Registry) -> Self::Output {
563        TypeDefBitSequence {
564            bit_store_type: registry.register_type(&self.bit_store_type),
565            bit_order_type: registry.register_type(&self.bit_order_type),
566        }
567    }
568}
569
570impl<T> TypeDefBitSequence<T>
571where
572    T: Form,
573{
574    /// Returns the type of the bit ordering of the [`::bitvec::vec::BitVec`].
575    pub fn bit_order_type(&self) -> &T::Type {
576        &self.bit_order_type
577    }
578
579    /// Returns underlying type used to store the [`::bitvec::vec::BitVec`].
580    pub fn bit_store_type(&self) -> &T::Type {
581        &self.bit_store_type
582    }
583}
584
585#[cfg(feature = "bit-vec")]
586impl TypeDefBitSequence {
587    /// Creates a new [`TypeDefBitSequence`] for the supplied bit order and bit store types.
588    pub fn new<T, O>() -> Self
589    where
590        T: bitvec::store::BitStore + TypeInfo + 'static,
591        O: bitvec::order::BitOrder + TypeInfo + 'static,
592    {
593        Self {
594            bit_store_type: MetaType::new::<T>(),
595            bit_order_type: MetaType::new::<O>(),
596        }
597    }
598}