tetsy_scale_info/ty/
fields.rs

1// Copyright 2019-2021 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::{
16    form::{
17        Form,
18        MetaForm,
19        PortableForm,
20    },
21    IntoPortable,
22    MetaType,
23    Registry,
24    TypeInfo,
25};
26use scale::{
27    Decode,
28    Encode,
29};
30#[cfg(feature = "serde")]
31use serde::{
32    Deserialize,
33    Serialize,
34};
35
36/// A field of a struct-like data type.
37///
38/// Name is optional so it can represent both named and unnamed fields.
39///
40/// This can be a named field of a struct type or an enum struct variant, or an
41/// unnamed field of a tuple struct.
42///
43/// # Type name
44///
45/// The `type_name` field contains a string which is the name of the type of the
46/// field as it appears in the source code. The exact contents and format of the
47/// type name are not specified, but in practice will be the name of any valid
48/// type for a field e.g.
49///
50///   - Concrete types e.g `"u32"`, `"bool"`, `"Foo"` etc.
51///   - Type parameters e.g `"T"`, `"U"`
52///   - Generic types e.g `"Vec<u32>"`, `"Vec<T>"`
53///   - Associated types e.g. `"T::MyType"`, `"<T as MyTrait>::MyType"`
54///   - Type aliases e.g. `"MyTypeAlias"`, `"MyTypeAlias<T>"`
55///   - Other built in Rust types e.g. arrays, references etc.
56///
57/// Note that the type name doesn't correspond to the underlying type of the
58/// field, unless using a concrete type directly. Any given type may be referred
59/// to by multiple field type names, when using generic type parameters and type
60/// aliases.
61///
62/// This is intended for informational and diagnostic purposes only. Although it
63/// is possible to infer certain properties e.g. whether a type name is a type
64/// alias, there are no guarantees provided, and the type name representation
65/// may change.
66#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
67#[cfg_attr(feature = "serde", serde(rename_all = "camelCase"))]
68#[derive(PartialEq, Eq, PartialOrd, Ord, Clone, Debug, Encode, Decode)]
69pub struct Field<T: Form = MetaForm> {
70    /// The name of the field. None for unnamed fields.
71    #[cfg_attr(
72        feature = "serde",
73        serde(skip_serializing_if = "Option::is_none", default)
74    )]
75    name: Option<T::String>,
76    /// The type of the field.
77    #[cfg_attr(feature = "serde", serde(rename = "type"))]
78    ty: T::Type,
79    /// The name of the type of the field as it appears in the source code.
80    type_name: T::String,
81}
82
83impl IntoPortable for Field {
84    type Output = Field<PortableForm>;
85
86    fn into_portable(self, registry: &mut Registry) -> Self::Output {
87        Field {
88            name: self.name.map(|name| name.into_portable(registry)),
89            ty: registry.register_type(&self.ty),
90            type_name: self.type_name.into_portable(registry),
91        }
92    }
93}
94
95impl Field {
96    /// Creates a new field.
97    ///
98    /// Use this constructor if you want to instantiate from a given meta type.
99    pub fn new(
100        name: Option<&'static str>,
101        ty: MetaType,
102        type_name: &'static str,
103    ) -> Self {
104        Self {
105            name,
106            ty,
107            type_name,
108        }
109    }
110
111    /// Creates a new named field.
112    ///
113    /// Use this constructor if you want to instantiate from a given
114    /// compile-time type.
115    pub fn named_of<T>(name: &'static str, type_name: &'static str) -> Field
116    where
117        T: TypeInfo + ?Sized + 'static,
118    {
119        Self::new(Some(name), MetaType::new::<T>(), type_name)
120    }
121
122    /// Creates a new unnamed field.
123    ///
124    /// Use this constructor if you want to instantiate an unnamed field from a
125    /// given compile-time type.
126    pub fn unnamed_of<T>(type_name: &'static str) -> Field
127    where
128        T: TypeInfo + ?Sized + 'static,
129    {
130        Self::new(None, MetaType::new::<T>(), type_name)
131    }
132}
133
134impl<T> Field<T>
135where
136    T: Form,
137{
138    /// Returns the name of the field. None for unnamed fields.
139    pub fn name(&self) -> Option<&T::String> {
140        self.name.as_ref()
141    }
142
143    /// Returns the type of the field.
144    pub fn ty(&self) -> &T::Type {
145        &self.ty
146    }
147
148    /// Returns a string which is the name of the type of the field as it
149    /// appears in the source code. The exact contents and format of the type
150    /// name are not specified, but in practice will be the name of any valid
151    /// type for a field. This is intended for informational and diagnostic
152    /// purposes only.
153    pub fn type_name(&self) -> &T::String {
154        &self.type_name
155    }
156}