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}