Skip to main content

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