metacall/
helpers.rs

1use crate::types::MetaCallValue;
2use std::any::Any;
3
4pub trait MetaCallDowncast: Any {
5    fn into_any(self: Box<Self>) -> Box<dyn Any>;
6    fn as_any(&self) -> &dyn Any;
7    fn as_any_mut(&mut self) -> &mut dyn Any;
8}
9impl<T: Any> MetaCallDowncast for T {
10    fn into_any(self: Box<Self>) -> Box<dyn Any> {
11        self
12    }
13    fn as_any(&self) -> &dyn Any {
14        self
15    }
16    fn as_any_mut(&mut self) -> &mut dyn Any {
17        self
18    }
19}
20impl dyn MetaCallValue {
21    /// Checks if the trait object is having the given type.
22    pub fn is<T: MetaCallValue>(&self) -> bool {
23        MetaCallDowncast::as_any(self).is::<T>()
24    }
25
26    /// Downcasts the inner value of the trait object and returns the ownership.
27    pub fn downcast<T: MetaCallValue>(self: Box<Self>) -> Result<T, Box<Self>> {
28        if self.is::<T>() {
29            Ok(*MetaCallDowncast::into_any(self).downcast::<T>().unwrap())
30        } else {
31            Err(self)
32        }
33    }
34
35    /// Downcasts the inner value of the trait object and returns a reference.
36    pub fn downcast_ref<T: MetaCallValue>(&self) -> Option<&T> {
37        MetaCallDowncast::as_any(self).downcast_ref::<T>()
38    }
39
40    /// Downcasts the inner value of the trait object and returns a mutable reference.
41    pub fn downcast_mut<T: MetaCallValue>(&mut self) -> Option<&mut T> {
42        MetaCallDowncast::as_any_mut(self).downcast_mut::<T>()
43    }
44}
45
46pub trait MetaCallSealed {}
47impl<T: Clone> MetaCallSealed for T {}
48impl MetaCallSealed for str {}
49impl<T: Clone> MetaCallSealed for [T] {}
50
51pub fn clone_box<T>(t: &T) -> Box<T>
52where
53    T: ?Sized + MetaCallClone,
54{
55    unsafe {
56        let mut fat_ptr = t as *const T;
57        let data_ptr = &mut fat_ptr as *mut *const T as *mut *mut ();
58
59        assert_eq!(*data_ptr as *const (), t as *const T as *const ());
60
61        *data_ptr = <T as MetaCallClone>::clone_box(t);
62
63        Box::from_raw(fat_ptr as *mut T)
64    }
65}
66
67pub trait MetaCallClone: MetaCallSealed {
68    fn clone_box(&self) -> *mut ();
69}
70impl<T> MetaCallClone for T
71where
72    T: Clone,
73{
74    fn clone_box(&self) -> *mut () {
75        Box::<T>::into_raw(Box::new(self.clone())) as *mut ()
76    }
77}
78
79impl MetaCallClone for str {
80    fn clone_box(&self) -> *mut () {
81        Box::<str>::into_raw(Box::from(self)) as *mut ()
82    }
83}
84impl<T> MetaCallClone for [T]
85where
86    T: Clone,
87{
88    fn clone_box(&self) -> *mut () {
89        Box::<[T]>::into_raw(self.iter().cloned().collect()) as *mut ()
90    }
91}
92impl Clone for Box<dyn MetaCallValue + '_> {
93    fn clone(&self) -> Self {
94        clone_box(&**self)
95    }
96}
97impl Clone for Box<dyn MetaCallValue + Send + '_> {
98    fn clone(&self) -> Self {
99        clone_box(&**self)
100    }
101}
102impl Clone for Box<dyn MetaCallValue + Sync + '_> {
103    fn clone(&self) -> Self {
104        clone_box(&**self)
105    }
106}
107impl Clone for Box<dyn MetaCallValue + Send + Sync + '_> {
108    fn clone(&self) -> Self {
109        clone_box(&**self)
110    }
111}