scale_info/meta_type.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 any::TypeId,
17 cmp::Ordering,
18 fmt::{Debug, Error as FmtError, Formatter},
19 hash::{Hash, Hasher},
20};
21
22use crate::{Type, TypeInfo};
23
24/// A metatype abstraction.
25///
26/// Allows to store compile-time type information at runtime.
27/// This again allows to derive type ID and type definition from it.
28///
29/// This needs a conversion to another representation of types
30/// in order to be serializable.
31#[derive(Clone, Copy)]
32pub struct MetaType {
33 /// Function pointer to get type information.
34 fn_type_info: fn() -> Type,
35 // The standard type ID (ab)used in order to provide
36 // cheap implementations of the standard traits
37 // such as `PartialEq`, `PartialOrd`, `Debug` and `Hash`.
38 type_id: TypeId,
39}
40
41impl PartialEq for MetaType {
42 fn eq(&self, other: &Self) -> bool {
43 self.type_id == other.type_id
44 }
45}
46
47impl Eq for MetaType {}
48
49impl PartialOrd for MetaType {
50 fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
51 Some(self.cmp(other))
52 }
53}
54
55impl Ord for MetaType {
56 fn cmp(&self, other: &Self) -> Ordering {
57 self.type_id.cmp(&other.type_id)
58 }
59}
60
61impl Hash for MetaType {
62 fn hash<H>(&self, state: &mut H)
63 where
64 H: Hasher,
65 {
66 self.type_id.hash(state)
67 }
68}
69
70impl Debug for MetaType {
71 fn fmt(&self, f: &mut Formatter) -> Result<(), FmtError> {
72 self.type_id.fmt(f)
73 }
74}
75
76impl MetaType {
77 /// Creates a new meta type from the given compile-time known type.
78 pub fn new<T>() -> Self
79 where
80 T: TypeInfo + ?Sized + 'static,
81 {
82 Self {
83 fn_type_info: <T as TypeInfo>::type_info,
84 type_id: TypeId::of::<T::Identity>(),
85 }
86 }
87
88 /// Returns the meta type information.
89 pub fn type_info(&self) -> Type {
90 (self.fn_type_info)()
91 }
92
93 /// Returns the type identifier provided by `core::any`.
94 pub fn type_id(&self) -> TypeId {
95 self.type_id
96 }
97
98 /// Returns true if this represents a type of [`core::marker::PhantomData`].
99 pub(crate) fn is_phantom(&self) -> bool {
100 self == &MetaType::new::<crate::impls::PhantomIdentity>()
101 }
102}
103
104#[cfg(feature = "schema")]
105impl schemars::JsonSchema for MetaType {
106 fn schema_name() -> String {
107 "MetaType".into()
108 }
109
110 fn json_schema(gen: &mut schemars::gen::SchemaGenerator) -> schemars::schema::Schema {
111 // since MetaType does not really get serialized, we don't care about its actual schema
112 gen.subschema_for::<u64>()
113 }
114}