1 //! This crate provides a [`DynClone`] trait that can be used in trait objects,
2 //! and a [`clone_box`] function that can clone any sized or dynamically sized
3 //! implementation of `DynClone`. Types that implement the standard library's
4 //! [`std::clone::Clone`] trait are automatically usable by a `DynClone` trait
5 //! object.
6 //!
7 //! [`DynClone`]: trait.DynClone.html
8 //! [`clone_box`]: fn.clone_box.html
9 //! [`std::clone::Clone`]: https://doc.rust-lang.org/std/clone/trait.Clone.html
10 //!
11 //! # Example
12 //!
13 //! ```
14 //! use dyn_clone::DynClone;
15 //!
16 //! trait MyTrait: DynClone {
17 //!     fn recite(&self);
18 //! }
19 //!
20 //! impl MyTrait for String {
21 //!     fn recite(&self) {
22 //!         println!("{} ♫", self);
23 //!     }
24 //! }
25 //!
26 //! fn main() {
27 //!     let line = "The slithy structs did gyre and gimble the namespace";
28 //!
29 //!     // Build a trait object holding a String.
30 //!     // This requires String to implement MyTrait and std::clone::Clone.
31 //!     let x: Box<dyn MyTrait> = Box::new(String::from(line));
32 //!
33 //!     x.recite();
34 //!
35 //!     // The type of x2 is a Box<dyn MyTrait> cloned from x.
36 //!     let x2 = dyn_clone::clone_box(&*x);
37 //!
38 //!     x2.recite();
39 //! }
40 //! ```
41 //!
42 //! This crate includes a macro for concisely implementing `impl
43 //! std::clone::Clone for Box<dyn MyTrait>` in terms of `dyn_clone::clone_box`.
44 //!
45 //! ```
46 //! # use dyn_clone::DynClone;
47 //! #
48 //! // As before.
49 //! trait MyTrait: DynClone {
50 //!     /* ... */
51 //! }
52 //!
53 //! dyn_clone::clone_trait_object!(MyTrait);
54 //!
55 //! // Now data structures containing Box<dyn MyTrait> can derive Clone:
56 //! #[derive(Clone)]
57 //! struct Container {
58 //!     trait_object: Box<dyn MyTrait>,
59 //! }
60 //! ```
61 
62 #![doc(html_root_url = "https://docs.rs/dyn_clone/1.0.1")]
63 
64 #[macro_use]
65 mod macros;
66 
67 #[doc(hidden)]
68 pub use std as private;
69 
70 /// This trait is implemented by any type that implements [`std::clone::Clone`].
71 ///
72 /// [`std::clone::Clone`]: https://doc.rust-lang.org/std/clone/trait.Clone.html
73 pub trait DynClone {
74     // Not public API
75     #[doc(hidden)]
clone_box(&self) -> *mut ()76     unsafe fn clone_box(&self) -> *mut ();
77 }
78 
clone<T>(t: &T) -> T where T: DynClone,79 pub fn clone<T>(t: &T) -> T
80 where
81     T: DynClone,
82 {
83     unsafe {
84         *Box::from_raw(<T as DynClone>::clone_box(t) as *mut T)
85     }
86 }
87 
clone_box<T>(t: &T) -> Box<T> where T: ?Sized + DynClone,88 pub fn clone_box<T>(t: &T) -> Box<T>
89 where
90     T: ?Sized + DynClone,
91 {
92     let mut fat_ptr = t as *const T;
93     unsafe {
94         let data_ptr = &mut fat_ptr as *mut *const T as *mut *mut ();
95         assert_eq!(*data_ptr as *const (), t as *const T as *const ());
96         *data_ptr = <T as DynClone>::clone_box(t);
97     }
98     unsafe {
99         Box::from_raw(fat_ptr as *mut T)
100     }
101 }
102 
103 impl<T> DynClone for T
104 where
105     T: std::clone::Clone,
106 {
clone_box(&self) -> *mut ()107     unsafe fn clone_box(&self) -> *mut () {
108         Box::into_raw(Box::new(self.clone())) as *mut ()
109     }
110 }
111 
112 #[cfg(test)]
113 mod tests {
114     use super::DynClone;
115     use std::fmt::{self, Display};
116     use std::sync::{Arc, Mutex};
117 
118     struct Log {
119         id: u64,
120         events: Arc<Mutex<Vec<String>>>,
121     }
122 
123     impl Clone for Log {
clone(&self) -> Self124         fn clone(&self) -> Self {
125             Log {
126                 id: self.id + 1,
127                 events: self.events.clone(),
128             }
129         }
130     }
131 
132     impl Display for Log {
fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result133         fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
134             write!(formatter, "id={}", self.id)
135         }
136     }
137 
138     impl Drop for Log {
drop(&mut self)139         fn drop(&mut self) {
140             self.events.lock().unwrap().push(format!("dropping {}", self))
141         }
142     }
143 
144     #[test]
clone_sized()145     fn clone_sized() {
146         let arc = Arc::new(0);
147         assert_eq!(Arc::strong_count(&arc), 1);
148 
149         let c = crate::clone(&arc);
150         assert_eq!(Arc::strong_count(&arc), 2);
151         drop(c);
152         assert_eq!(Arc::strong_count(&arc), 1);
153     }
154 
155     #[test]
clone_trait_object()156     fn clone_trait_object() {
157         trait MyTrait: Display + Sync + DynClone {}
158 
159         impl MyTrait for Log {}
160 
161         let events = Arc::new(Mutex::new(Vec::new()));
162         let mut expected = Vec::new();
163         {
164             let b11: Box<dyn MyTrait> = Box::new(Log {
165                 id: 11,
166                 events: events.clone(),
167             });
168             let b12 = crate::clone_box(&*b11);
169             assert_eq!(b11.to_string(), "id=11");
170             assert_eq!(b12.to_string(), "id=12");
171             expected.push("dropping id=12".to_owned());
172             expected.push("dropping id=11".to_owned());
173         }
174         assert_eq!(*events.lock().unwrap(), expected);
175     }
176 }
177