eosio_scale_info/ty/
variant.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::vec::Vec;
16
17use crate::{
18    form::{
19        Form,
20        MetaForm,
21        PortableForm,
22    },
23    Field,
24    IntoPortable,
25    Registry,
26};
27use derive_more::From;
28use scale::Encode;
29#[cfg(feature = "serde")]
30use serde::{
31    de::DeserializeOwned,
32    Deserialize,
33    Serialize,
34};
35
36/// A Enum type (consisting of variants).
37///
38/// # Examples
39///
40/// ## A Rust enum, aka tagged union.
41///
42/// ```
43/// enum MyEnum {
44///     RustAllowsForClikeVariants,
45///     AndAlsoForTupleStructs(i32, bool),
46///     OrStructs {
47///         with: i32,
48///         named: bool,
49///         fields: [u8; 32],
50///     },
51///     ItIsntPossibleToSetADiscriminantThough,
52/// }
53/// ```
54///
55/// ## A C-like enum type.
56///
57/// ```
58/// enum Days {
59///     Monday,
60///     Tuesday,
61///     Wednesday,
62///     Thursday = 42, // Allows setting the discriminant explicitly
63///     Friday,
64///     Saturday,
65///     Sunday,
66/// }
67/// ```
68///
69/// ## An empty enum (for marker purposes)
70///
71/// ```
72/// enum JustAMarker {}
73/// ```
74#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
75#[cfg_attr(
76    feature = "serde",
77    serde(bound(
78        serialize = "T::Type: Serialize, T::String: Serialize",
79        deserialize = "T::Type: DeserializeOwned, T::String: DeserializeOwned",
80    ))
81)]
82#[cfg_attr(feature = "serde", serde(rename_all = "lowercase"))]
83#[cfg_attr(any(feature = "std", feature = "decode"), derive(scale::Decode))]
84#[derive(PartialEq, Eq, PartialOrd, Ord, Clone, Debug, From, Encode)]
85pub struct TypeDefVariant<T: Form = MetaForm> {
86    /// The variants of a variant type
87    #[cfg_attr(
88        feature = "serde",
89        serde(skip_serializing_if = "Vec::is_empty", default)
90    )]
91    variants: Vec<Variant<T>>,
92}
93
94impl IntoPortable for TypeDefVariant {
95    type Output = TypeDefVariant<PortableForm>;
96
97    fn into_portable(self, registry: &mut Registry) -> Self::Output {
98        TypeDefVariant {
99            variants: registry.map_into_portable(self.variants),
100        }
101    }
102}
103
104impl TypeDefVariant {
105    /// Create a new `TypeDefVariant` with the given variants
106    pub fn new<I>(variants: I) -> Self
107    where
108        I: IntoIterator<Item = Variant>,
109    {
110        Self {
111            variants: variants.into_iter().collect(),
112        }
113    }
114}
115
116impl<T> TypeDefVariant<T>
117where
118    T: Form,
119{
120    /// Returns the variants of a variant type
121    pub fn variants(&self) -> &[Variant<T>] {
122        &self.variants
123    }
124}
125
126/// A struct enum variant with either named (struct) or unnamed (tuple struct)
127/// fields.
128///
129/// # Example
130///
131/// ```
132/// enum Operation {
133///     Zero,
134/// //  ^^^^ this is a unit struct enum variant
135///     Add(i32, i32),
136/// //  ^^^^^^^^^^^^^ this is a tuple-struct enum variant
137///     Minus { source: i32 }
138/// //  ^^^^^^^^^^^^^^^^^^^^^ this is a struct enum variant
139/// }
140/// ```
141#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
142#[cfg_attr(
143    feature = "serde",
144    serde(bound(
145        serialize = "T::Type: Serialize, T::String: Serialize",
146        deserialize = "T::Type: DeserializeOwned, T::String: DeserializeOwned",
147    ))
148)]
149#[cfg_attr(any(feature = "std", feature = "decode"), derive(scale::Decode))]
150#[derive(PartialEq, Eq, PartialOrd, Ord, Clone, Debug, Encode)]
151pub struct Variant<T: Form = MetaForm> {
152    /// The name of the variant.
153    name: T::String,
154    /// The fields of the variant.
155    #[cfg_attr(
156        feature = "serde",
157        serde(skip_serializing_if = "Vec::is_empty", default)
158    )]
159    fields: Vec<Field<T>>,
160    /// Index of the variant, used in `parity-scale-codec`.
161    ///
162    /// The value of this will be, in order of precedence:
163    ///     1. The explicit index defined by a `#[codec(index = N)]` attribute.
164    ///     2. The implicit index from the position of the variant in the `enum` definition.
165    index: u8,
166    /// Documentation
167    #[cfg_attr(
168        feature = "serde",
169        serde(skip_serializing_if = "Vec::is_empty", default)
170    )]
171    docs: Vec<T::String>,
172}
173
174impl IntoPortable for Variant {
175    type Output = Variant<PortableForm>;
176
177    fn into_portable(self, registry: &mut Registry) -> Self::Output {
178        Variant {
179            name: self.name.into_portable(registry),
180            fields: registry.map_into_portable(self.fields),
181            index: self.index,
182            docs: registry.map_into_portable(self.docs),
183        }
184    }
185}
186
187impl Variant {
188    /// Creates a new variant.
189    pub(crate) fn new(
190        name: &'static str,
191        fields: Vec<Field<MetaForm>>,
192        index: u8,
193        docs: Vec<&'static str>,
194    ) -> Self {
195        Self {
196            name,
197            fields,
198            index,
199            docs,
200        }
201    }
202}
203
204impl<T> Variant<T>
205where
206    T: Form,
207{
208    /// Returns the name of the variant.
209    pub fn name(&self) -> &T::String {
210        &self.name
211    }
212
213    /// Returns the fields of the struct variant.
214    pub fn fields(&self) -> &[Field<T>] {
215        &self.fields
216    }
217
218    /// Returns the index of the variant.
219    pub fn index(&self) -> u8 {
220        self.index
221    }
222
223    /// Returns the documentation of the variant.
224    pub fn docs(&self) -> &[T::String] {
225        &self.docs
226    }
227}