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