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