rune/runtime/
type_info.rs

1use core::fmt;
2use core::hash;
3
4use crate as rune;
5use crate::alloc::prelude::*;
6use crate::compile::Named;
7use crate::hash::Hash;
8use crate::{Any, TypeHash};
9
10use ::rust_alloc::sync::Arc;
11
12use super::Rtti;
13
14#[derive(Debug, TryClone, PartialEq, Eq)]
15enum TypeInfoKind {
16    /// Reference to an external type.
17    Any(AnyTypeInfo),
18    /// A named type.
19    Runtime(Arc<Rtti>),
20}
21
22/// Diagnostical type information for a given type.
23///
24/// Has reasonable [`Debug`] and [`Display`] implementations to identify a given
25/// type.
26///
27/// [`Debug`]: core::fmt::Debug
28/// [`Display`]: core::fmt::Display
29#[derive(TryClone, PartialEq, Eq)]
30#[non_exhaustive]
31pub struct TypeInfo {
32    kind: TypeInfoKind,
33}
34
35impl TypeInfo {
36    #[inline]
37    const fn new(kind: TypeInfoKind) -> Self {
38        Self { kind }
39    }
40
41    /// Construct type info for the empty type.
42    pub const fn empty() -> Self {
43        Self::new(TypeInfoKind::Any(AnyTypeInfo {
44            full_name: |f| write!(f, "empty"),
45            hash: crate::hash!(::std::empty::Empty),
46        }))
47    }
48
49    /// Construct type info from an statically known [`Any`] type.
50    #[inline]
51    pub const fn any<T>() -> Self
52    where
53        T: Any,
54    {
55        Self::any_type_info(T::ANY_TYPE_INFO)
56    }
57
58    /// Construct type info from an statically known [`Named`] type.
59    #[inline]
60    pub const fn named<T>() -> Self
61    where
62        T: Named + TypeHash,
63    {
64        Self::any_type_info(AnyTypeInfo::new(T::full_name, T::HASH))
65    }
66
67    /// Construct type info from an statically known [`Any`] type.
68    #[doc(hidden)]
69    #[inline]
70    pub(crate) const fn any_type_info(type_info: AnyTypeInfo) -> Self {
71        Self::new(TypeInfoKind::Any(type_info))
72    }
73
74    #[inline]
75    pub(crate) const fn rtti(rtti: Arc<Rtti>) -> Self {
76        Self::new(TypeInfoKind::Runtime(rtti))
77    }
78
79    #[cfg(feature = "emit")]
80    pub(crate) fn type_hash(&self) -> Hash {
81        match &self.kind {
82            TypeInfoKind::Any(ty) => ty.hash,
83            TypeInfoKind::Runtime(ty) => ty.type_hash(),
84        }
85    }
86}
87
88impl fmt::Debug for TypeInfo {
89    #[inline]
90    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
91        self.kind.fmt(f)
92    }
93}
94
95impl fmt::Display for TypeInfo {
96    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
97        match &self.kind {
98            TypeInfoKind::Runtime(rtti) => {
99                write!(f, "{}", rtti.item)?;
100            }
101            TypeInfoKind::Any(info) => {
102                write!(f, "{info}")?;
103            }
104        }
105
106        Ok(())
107    }
108}
109
110impl From<AnyTypeInfo> for TypeInfo {
111    #[inline]
112    fn from(type_info: AnyTypeInfo) -> Self {
113        Self::any_type_info(type_info)
114    }
115}
116
117/// Type information for the [`Any`][crate::Any] type.
118#[derive(Debug, TryClone, Clone, Copy)]
119#[try_clone(copy)]
120pub struct AnyTypeInfo {
121    /// Formatter to display a full name.
122    pub(crate) full_name: FullNameFn,
123    /// The type hash of the item.
124    pub(crate) hash: Hash,
125}
126
127impl AnyTypeInfo {
128    /// Private constructor, use at your own risk.
129    pub(crate) const fn new(full_name: FullNameFn, hash: Hash) -> Self {
130        Self { full_name, hash }
131    }
132}
133
134impl fmt::Display for AnyTypeInfo {
135    #[inline]
136    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
137        (self.full_name)(f)
138    }
139}
140
141pub type FullNameFn = fn(&mut fmt::Formatter<'_>) -> fmt::Result;
142
143impl PartialEq for AnyTypeInfo {
144    #[inline]
145    fn eq(&self, other: &Self) -> bool {
146        self.hash == other.hash
147    }
148}
149
150impl Eq for AnyTypeInfo {}
151
152impl hash::Hash for AnyTypeInfo {
153    #[inline]
154    fn hash<H: hash::Hasher>(&self, state: &mut H) {
155        self.hash.hash(state);
156    }
157}