multi_trait_object/trait_impl/
try_clone.rs

1use crate::{MultitraitObject};
2
3pub trait TryClone: Sized {
4    fn try_clone(&self) -> Option<Self>;
5}
6
7/// Returns a raw pointer to the cloned data.
8/// This will leak the memory of the underlying pointer.
9/// This trait is implemented for all types that implement clone
10/// so you can pass this trait to the object constructor. This
11/// way the given object can be cloned with [TryClone].
12pub unsafe trait RawClone {
13    #[doc(hidden)]
14    #[must_use]
15    unsafe fn raw_clone(&self) -> *mut ();
16}
17
18/// A trait that tries cloning an object and returns an option
19/// with the variant depending on the result. For a multitrait object
20/// to be clonable it needs to have the [RawClone] trait registered.
21unsafe impl<T: Clone> RawClone for T {
22    unsafe fn raw_clone(&self) -> *mut () {
23        Box::into_raw(Box::new(self.clone())) as *mut ()
24    }
25}
26
27impl TryClone for MultitraitObject {
28    fn try_clone(&self) -> Option<Self> {
29        let clone = self.downcast_trait::<dyn RawClone>()?;
30        let data_ptr = unsafe {
31            // SAFETY: We're using the pointer in the multitrait object so
32            // it won't leak memory
33            clone.raw_clone()
34        };
35        Some(MultitraitObject {
36            data: data_ptr,
37            original_typeid: self.original_typeid.clone(),
38            traits: self.traits.clone(),
39        })
40    }
41}