dyn_clone/
lib.rs

1//! [![github]](https://github.com/dtolnay/dyn-clone) [![crates-io]](https://crates.io/crates/dyn-clone) [![docs-rs]](https://docs.rs/dyn-clone)
2//!
3//! [github]: https://img.shields.io/badge/github-8da0cb?style=for-the-badge&labelColor=555555&logo=github
4//! [crates-io]: https://img.shields.io/badge/crates.io-fc8d62?style=for-the-badge&labelColor=555555&logo=rust
5//! [docs-rs]: https://img.shields.io/badge/docs.rs-66c2a5?style=for-the-badge&labelColor=555555&logo=docs.rs
6//!
7//! <br>
8//!
9//! This crate provides a [`DynClone`] trait that can be used in trait objects,
10//! and a [`clone_box`] function that can clone any sized or dynamically sized
11//! implementation of `DynClone`. Types that implement the standard library's
12//! [`std::clone::Clone`] trait are automatically usable by a `DynClone` trait
13//! object.
14//!
15//! [`DynClone`]: trait.DynClone.html
16//! [`clone_box`]: fn.clone_box.html
17//! [`std::clone::Clone`]: https://doc.rust-lang.org/std/clone/trait.Clone.html
18//!
19//! # Example
20//!
21//! ```
22//! use dyn_clone::DynClone;
23//!
24//! trait MyTrait: DynClone {
25//!     fn recite(&self);
26//! }
27//!
28//! impl MyTrait for String {
29//!     fn recite(&self) {
30//!         println!("{} ♫", self);
31//!     }
32//! }
33//!
34//! fn main() {
35//!     let line = "The slithy structs did gyre and gimble the namespace";
36//!
37//!     // Build a trait object holding a String.
38//!     // This requires String to implement MyTrait and std::clone::Clone.
39//!     let x: Box<dyn MyTrait> = Box::new(String::from(line));
40//!
41//!     x.recite();
42//!
43//!     // The type of x2 is a Box<dyn MyTrait> cloned from x.
44//!     let x2 = dyn_clone::clone_box(&*x);
45//!
46//!     x2.recite();
47//! }
48//! ```
49//!
50//! This crate includes a macro for concisely implementing `impl
51//! std::clone::Clone for Box<dyn MyTrait>` in terms of `dyn_clone::clone_box`.
52//!
53//! ```
54//! # use dyn_clone::DynClone;
55//! #
56//! // As before.
57//! trait MyTrait: DynClone {
58//!     /* ... */
59//! }
60//!
61//! dyn_clone::clone_trait_object!(MyTrait);
62//!
63//! // Now data structures containing Box<dyn MyTrait> can derive Clone:
64//! #[derive(Clone)]
65//! struct Container {
66//!     trait_object: Box<dyn MyTrait>,
67//! }
68//! ```
69//!
70//! The `clone_trait_object!` macro expands to just the following, which you can
71//! handwrite instead if you prefer:
72//!
73//! ```
74//! # use dyn_clone::DynClone;
75//! #
76//! # trait MyTrait: DynClone {}
77//! #
78//! impl Clone for Box<dyn MyTrait> {
79//!     fn clone(&self) -> Self {
80//!         dyn_clone::clone_box(&**self)
81//!     }
82//! }
83//!
84//! // and similar for Box<dyn MyTrait + Send>, Box<dyn MyTrait + Sync>, Box<dyn MyTrait + Send + Sync>
85//! ```
86
87#![doc(html_root_url = "https://docs.rs/dyn_clone/1.0.9")]
88#![no_std]
89#![allow(clippy::missing_panics_doc, clippy::ptr_as_ptr)]
90
91extern crate alloc;
92
93use crate::sealed::{Private, Sealed};
94
95#[macro_use]
96mod macros;
97
98#[doc(hidden)]
99pub mod private {
100    pub use alloc::boxed::Box;
101    pub use core::clone::Clone;
102    pub use core::marker::{Send, Sync};
103}
104
105mod sealed {
106    pub trait Sealed {}
107    impl<T: Clone> Sealed for T {}
108    impl Sealed for str {}
109    impl<T: Clone> Sealed for [T] {}
110    pub struct Private;
111}
112
113/// This trait is implemented by any type that implements [`std::clone::Clone`].
114///
115/// [`std::clone::Clone`]: https://doc.rust-lang.org/std/clone/trait.Clone.html
116pub trait DynClone: Sealed {
117    // Not public API
118    #[doc(hidden)]
119    fn __clone_box(&self, _: Private) -> *mut ();
120}
121
122use alloc::boxed::Box;
123use alloc::rc::Rc;
124use alloc::sync::Arc;
125
126/// `&T`&ensp;&mdash;&blacktriangleright;&ensp;`T`
127pub fn clone<T>(t: &T) -> T
128where
129    T: DynClone,
130{
131    unsafe { *Box::from_raw(<T as DynClone>::__clone_box(t, Private) as *mut T) }
132}
133
134/// `&T`&ensp;&mdash;&blacktriangleright;&ensp;`Box<T>`
135pub fn clone_box<T>(t: &T) -> Box<T>
136where
137    T: ?Sized + DynClone,
138{
139    let mut fat_ptr = t as *const T;
140    unsafe {
141        let data_ptr = &mut fat_ptr as *mut *const T as *mut *mut ();
142        assert_eq!(*data_ptr as *const (), t as *const T as *const ());
143        *data_ptr = <T as DynClone>::__clone_box(t, Private);
144    }
145    unsafe { Box::from_raw(fat_ptr as *mut T) }
146}
147
148/// `&mut Arc<T>`&ensp;&mdash;&blacktriangleright;&ensp;`&mut T`
149pub fn arc_make_mut<T>(arc: &mut Arc<T>) -> &mut T
150where
151    T: ?Sized + DynClone,
152{
153    // Atomic. Find out whether the Arc in the argument is the single holder of
154    // a reference count (strong or weak) on the target object. If yes, it is
155    // guaranteed to remain that way throughout the rest of this function
156    // because no other threads could bump the reference count through any other
157    // Arc (because no others exist) or through this Arc (because the current
158    // thread holds an exclusive borrow of it).
159    let is_unique = Arc::get_mut(arc).is_some();
160    if !is_unique {
161        // Non-atomic.
162        let clone = Arc::from(clone_box(&**arc));
163        // Atomic. Check the reference counts again to find out whether the old
164        // object needs to be dropped. Probably not, but it can happen if all
165        // the other holders of a reference count went away during the time that
166        // the clone operation took.
167        *arc = clone;
168    }
169    // Non-atomic. TODO: replace with Arc::get_mut_unchecked when stable.
170    let ptr = Arc::as_ptr(arc) as *mut T;
171    unsafe { &mut *ptr }
172}
173
174/// `&mut Rc<T>`&ensp;&mdash;&blacktriangleright;&ensp;`&mut T`
175pub fn rc_make_mut<T>(rc: &mut Rc<T>) -> &mut T
176where
177    T: ?Sized + DynClone,
178{
179    let is_unique = Rc::get_mut(rc).is_some();
180    if !is_unique {
181        let clone = Rc::from(clone_box(&**rc));
182        *rc = clone;
183    }
184    let ptr = Rc::as_ptr(rc) as *mut T;
185    unsafe { &mut *ptr }
186}
187
188impl<T> DynClone for T
189where
190    T: Clone,
191{
192    fn __clone_box(&self, _: Private) -> *mut () {
193        Box::<T>::into_raw(Box::new(self.clone())) as *mut ()
194    }
195}
196
197impl DynClone for str {
198    fn __clone_box(&self, _: Private) -> *mut () {
199        Box::<str>::into_raw(Box::from(self)) as *mut ()
200    }
201}
202
203impl<T> DynClone for [T]
204where
205    T: Clone,
206{
207    fn __clone_box(&self, _: Private) -> *mut () {
208        Box::<[T]>::into_raw(self.iter().cloned().collect()) as *mut ()
209    }
210}