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}