2020-03-08 12:54:02 +01:00
|
|
|
//! Helper module which defines the `Any` trait to to allow dynamic value handling.
|
|
|
|
|
2020-03-17 19:26:11 +01:00
|
|
|
use crate::stdlib::{
|
2020-04-02 13:40:02 +02:00
|
|
|
any::{type_name, TypeId},
|
2020-03-17 19:26:11 +01:00
|
|
|
boxed::Box,
|
2020-03-10 03:07:44 +01:00
|
|
|
fmt,
|
|
|
|
};
|
2017-12-20 12:16:14 +01:00
|
|
|
|
2020-03-04 15:00:01 +01:00
|
|
|
/// An raw value of any type.
|
2020-02-25 08:02:27 +01:00
|
|
|
pub type Variant = dyn Any;
|
2020-03-04 15:00:01 +01:00
|
|
|
|
|
|
|
/// A boxed dynamic type containing any value.
|
2020-02-25 08:02:27 +01:00
|
|
|
pub type Dynamic = Box<Variant>;
|
|
|
|
|
2020-03-04 15:00:01 +01:00
|
|
|
/// A trait covering any type.
|
2020-04-02 13:40:02 +02:00
|
|
|
#[cfg(feature = "sync")]
|
|
|
|
pub trait Any: crate::stdlib::any::Any + Send + Sync {
|
2020-03-04 15:00:01 +01:00
|
|
|
/// Get the `TypeId` of this type.
|
2017-12-20 12:16:14 +01:00
|
|
|
fn type_id(&self) -> TypeId;
|
|
|
|
|
2020-03-04 15:00:01 +01:00
|
|
|
/// Get the name of this type.
|
2020-03-03 09:24:03 +01:00
|
|
|
fn type_name(&self) -> &'static str;
|
2019-09-30 19:57:21 +02:00
|
|
|
|
2020-03-04 15:00:01 +01:00
|
|
|
/// Convert into `Dynamic`.
|
2020-02-25 08:02:27 +01:00
|
|
|
fn into_dynamic(&self) -> Dynamic;
|
2017-12-20 12:16:14 +01:00
|
|
|
|
2020-03-18 03:36:50 +01:00
|
|
|
/// This trait may only be implemented by `rhai`.
|
2017-12-20 12:16:14 +01:00
|
|
|
#[doc(hidden)]
|
|
|
|
fn _closed(&self) -> _Private;
|
|
|
|
}
|
|
|
|
|
2020-04-02 13:40:02 +02:00
|
|
|
#[cfg(feature = "sync")]
|
|
|
|
impl<T: crate::stdlib::any::Any + Clone + Send + Sync + ?Sized> Any for T {
|
|
|
|
fn type_id(&self) -> TypeId {
|
|
|
|
TypeId::of::<T>()
|
|
|
|
}
|
|
|
|
|
|
|
|
fn type_name(&self) -> &'static str {
|
|
|
|
type_name::<T>()
|
|
|
|
}
|
|
|
|
|
|
|
|
fn into_dynamic(&self) -> Dynamic {
|
|
|
|
Box::new(self.clone())
|
|
|
|
}
|
|
|
|
|
|
|
|
fn _closed(&self) -> _Private {
|
|
|
|
_Private
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#[cfg(not(feature = "sync"))]
|
|
|
|
pub trait Any: crate::stdlib::any::Any {
|
|
|
|
/// Get the `TypeId` of this type.
|
|
|
|
fn type_id(&self) -> TypeId;
|
|
|
|
|
|
|
|
/// Get the name of this type.
|
|
|
|
fn type_name(&self) -> &'static str;
|
|
|
|
|
|
|
|
/// Convert into `Dynamic`.
|
|
|
|
fn into_dynamic(&self) -> Dynamic;
|
|
|
|
|
|
|
|
/// This trait may only be implemented by `rhai`.
|
|
|
|
#[doc(hidden)]
|
|
|
|
fn _closed(&self) -> _Private;
|
|
|
|
}
|
|
|
|
|
|
|
|
#[cfg(not(feature = "sync"))]
|
|
|
|
impl<T: crate::stdlib::any::Any + Clone + ?Sized> Any for T {
|
2017-12-20 12:16:14 +01:00
|
|
|
fn type_id(&self) -> TypeId {
|
|
|
|
TypeId::of::<T>()
|
|
|
|
}
|
|
|
|
|
2020-03-03 09:24:03 +01:00
|
|
|
fn type_name(&self) -> &'static str {
|
|
|
|
type_name::<T>()
|
2019-09-30 19:57:21 +02:00
|
|
|
}
|
|
|
|
|
2020-02-25 08:02:27 +01:00
|
|
|
fn into_dynamic(&self) -> Dynamic {
|
2017-12-20 12:16:14 +01:00
|
|
|
Box::new(self.clone())
|
|
|
|
}
|
|
|
|
|
2019-09-18 12:21:07 +02:00
|
|
|
fn _closed(&self) -> _Private {
|
|
|
|
_Private
|
2017-12-20 12:16:14 +01:00
|
|
|
}
|
2019-09-18 12:21:07 +02:00
|
|
|
}
|
2017-12-20 12:16:14 +01:00
|
|
|
|
2020-02-25 08:02:27 +01:00
|
|
|
impl Variant {
|
2020-03-04 15:00:01 +01:00
|
|
|
/// Is this `Variant` a specific type?
|
|
|
|
pub(crate) fn is<T: Any>(&self) -> bool {
|
2017-12-20 12:16:14 +01:00
|
|
|
let t = TypeId::of::<T>();
|
2020-02-25 08:02:27 +01:00
|
|
|
let boxed = <Variant as Any>::type_id(self);
|
2017-12-20 12:16:14 +01:00
|
|
|
|
|
|
|
t == boxed
|
|
|
|
}
|
|
|
|
|
2020-03-04 15:00:01 +01:00
|
|
|
/// Get a reference of a specific type to the `Variant`.
|
|
|
|
pub(crate) fn downcast_ref<T: Any>(&self) -> Option<&T> {
|
2017-12-20 12:16:14 +01:00
|
|
|
if self.is::<T>() {
|
2020-02-25 08:02:27 +01:00
|
|
|
unsafe { Some(&*(self as *const Variant as *const T)) }
|
2017-12-20 12:16:14 +01:00
|
|
|
} else {
|
|
|
|
None
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-03-04 15:00:01 +01:00
|
|
|
/// Get a mutable reference of a specific type to the `Variant`.
|
|
|
|
pub(crate) fn downcast_mut<T: Any>(&mut self) -> Option<&mut T> {
|
2017-12-20 12:16:14 +01:00
|
|
|
if self.is::<T>() {
|
2020-02-25 08:02:27 +01:00
|
|
|
unsafe { Some(&mut *(self as *mut Variant as *mut T)) }
|
2017-12-20 12:16:14 +01:00
|
|
|
} else {
|
|
|
|
None
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-02-25 08:02:27 +01:00
|
|
|
impl fmt::Debug for Variant {
|
2019-09-18 12:21:07 +02:00
|
|
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
2020-02-23 15:48:46 +01:00
|
|
|
f.pad("?")
|
2017-12-20 12:16:14 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-03-04 15:00:01 +01:00
|
|
|
impl Clone for Dynamic {
|
|
|
|
fn clone(&self) -> Self {
|
|
|
|
Any::into_dynamic(self.as_ref())
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/// An extension trait that allows down-casting a `Dynamic` value to a specific type.
|
2017-12-20 12:16:14 +01:00
|
|
|
pub trait AnyExt: Sized {
|
2020-03-04 15:00:01 +01:00
|
|
|
/// Get a copy of a `Dynamic` value as a specific type.
|
2020-04-02 06:35:44 +02:00
|
|
|
fn try_cast<T: Any + Clone>(self) -> Result<T, Self>;
|
|
|
|
|
|
|
|
/// Get a copy of a `Dynamic` value as a specific type.
|
|
|
|
///
|
|
|
|
/// # Panics
|
|
|
|
///
|
|
|
|
/// Panics if the cast fails (e.g. the type of the actual value is not the same as the specified type).
|
|
|
|
fn cast<T: Any + Clone>(self) -> T;
|
2020-03-04 15:00:01 +01:00
|
|
|
|
2020-03-18 03:36:50 +01:00
|
|
|
/// This trait may only be implemented by `rhai`.
|
2020-03-04 15:00:01 +01:00
|
|
|
#[doc(hidden)]
|
|
|
|
fn _closed(&self) -> _Private;
|
2017-12-20 12:16:14 +01:00
|
|
|
}
|
|
|
|
|
2020-02-25 08:02:27 +01:00
|
|
|
impl AnyExt for Dynamic {
|
2020-03-04 15:00:01 +01:00
|
|
|
/// Get a copy of the `Dynamic` value as a specific type.
|
|
|
|
///
|
|
|
|
/// # Example
|
|
|
|
///
|
2020-03-19 06:52:10 +01:00
|
|
|
/// ```
|
2020-03-04 15:00:01 +01:00
|
|
|
/// use rhai::{Dynamic, Any, AnyExt};
|
|
|
|
///
|
|
|
|
/// let x: Dynamic = 42_u32.into_dynamic();
|
|
|
|
///
|
2020-04-02 06:35:44 +02:00
|
|
|
/// assert_eq!(x.try_cast::<u32>().unwrap(), 42);
|
2020-03-04 15:00:01 +01:00
|
|
|
/// ```
|
2020-04-02 06:35:44 +02:00
|
|
|
fn try_cast<T: Any + Clone>(self) -> Result<T, Self> {
|
2017-12-20 12:16:14 +01:00
|
|
|
if self.is::<T>() {
|
|
|
|
unsafe {
|
2020-02-25 08:02:27 +01:00
|
|
|
let raw: *mut Variant = Box::into_raw(self);
|
2020-04-02 06:35:44 +02:00
|
|
|
Ok(*Box::from_raw(raw as *mut T))
|
2017-12-20 12:16:14 +01:00
|
|
|
}
|
|
|
|
} else {
|
|
|
|
Err(self)
|
|
|
|
}
|
|
|
|
}
|
2020-03-04 15:00:01 +01:00
|
|
|
|
2020-04-02 06:35:44 +02:00
|
|
|
/// Get a copy of the `Dynamic` value as a specific type.
|
|
|
|
///
|
|
|
|
/// # Panics
|
|
|
|
///
|
|
|
|
/// Panics if the cast fails (e.g. the type of the actual value is not the same as the specified type).
|
|
|
|
///
|
|
|
|
/// # Example
|
|
|
|
///
|
|
|
|
/// ```
|
|
|
|
/// use rhai::{Dynamic, Any, AnyExt};
|
|
|
|
///
|
|
|
|
/// let x: Dynamic = 42_u32.into_dynamic();
|
|
|
|
///
|
|
|
|
/// assert_eq!(x.cast::<u32>(), 42);
|
|
|
|
/// ```
|
|
|
|
fn cast<T: Any + Clone>(self) -> T {
|
|
|
|
self.try_cast::<T>().expect("cast failed")
|
|
|
|
}
|
|
|
|
|
2020-03-04 15:00:01 +01:00
|
|
|
fn _closed(&self) -> _Private {
|
|
|
|
_Private
|
|
|
|
}
|
2017-12-20 12:16:14 +01:00
|
|
|
}
|
|
|
|
|
2020-03-04 15:00:01 +01:00
|
|
|
/// Private type which ensures that `rhai::Any` and `rhai::AnyExt` can only
|
2017-12-20 12:16:14 +01:00
|
|
|
/// be implemented by this crate.
|
|
|
|
#[doc(hidden)]
|
|
|
|
pub struct _Private;
|