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