1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
// Copyright 2019-2020 Parity Technologies (UK) Ltd.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

use crate::tm_std::*;
use crate::{form::MetaForm, Type, TypeInfo};

/// A metatype abstraction.
///
/// Allows to store compile-time type information at runtime.
/// This again allows to derive type ID and type definition from it.
///
/// This needs a conversion to another representation of types
/// in order to be serializable.
#[derive(Clone, Copy)]
pub struct MetaType {
	/// Function pointer to get type information.
	fn_type_info: fn() -> Type<MetaForm>,
	// The standard type ID (ab)used in order to provide
	// cheap implementations of the standard traits
	// such as `PartialEq`, `PartialOrd`, `Debug` and `Hash`.
	type_id: TypeId,
}

impl PartialEq for MetaType {
	fn eq(&self, other: &Self) -> bool {
		self.type_id == other.type_id
	}
}

impl Eq for MetaType {}

impl PartialOrd for MetaType {
	fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
		self.type_id.partial_cmp(&other.type_id)
	}
}

impl Ord for MetaType {
	fn cmp(&self, other: &Self) -> Ordering {
		self.type_id.cmp(&other.type_id)
	}
}

impl Hash for MetaType {
	fn hash<H>(&self, state: &mut H)
	where
		H: Hasher,
	{
		self.type_id.hash(state)
	}
}

impl Debug for MetaType {
	fn fmt(&self, f: &mut Formatter) -> Result<(), FmtError> {
		self.type_id.fmt(f)
	}
}

impl MetaType {
	/// Creates a new meta type from the given compile-time known type.
	pub fn new<T>() -> Self
	where
		T: TypeInfo + ?Sized + 'static,
	{
		Self {
			fn_type_info: <T as TypeInfo>::type_info,
			type_id: TypeId::of::<T>(),
		}
	}

	/// Creates a new meta types from the type of the given reference.
	pub fn of<T>(_elem: &T) -> Self
	where
		T: TypeInfo + ?Sized + 'static,
	{
		Self::new::<T>()
	}

	/// Returns the meta type information.
	pub fn type_info(&self) -> Type<MetaForm> {
		(self.fn_type_info)()
	}

	/// Returns the type identifier provided by `core::any`.
	pub fn type_id(&self) -> TypeId {
		self.type_id
	}
}