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