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&logoColor=white&logo=data:image/svg+xml;base64,PHN2ZyByb2xlPSJpbWciIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgdmlld0JveD0iMCAwIDUxMiA1MTIiPjxwYXRoIGZpbGw9IiNmNWY1ZjUiIGQ9Ik00ODguNiAyNTAuMkwzOTIgMjE0VjEwNS41YzAtMTUtOS4zLTI4LjQtMjMuNC0zMy43bC0xMDAtMzcuNWMtOC4xLTMuMS0xNy4xLTMuMS0yNS4zIDBsLTEwMCAzNy41Yy0xNC4xIDUuMy0yMy40IDE4LjctMjMuNCAzMy43VjIxNGwtOTYuNiAzNi4yQzkuMyAyNTUuNSAwIDI2OC45IDAgMjgzLjlWMzk0YzAgMTMuNiA3LjcgMjYuMSAxOS45IDMyLjJsMTAwIDUwYzEwLjEgNS4xIDIyLjEgNS4xIDMyLjIgMGwxMDMuOS01MiAxMDMuOSA1MmMxMC4xIDUuMSAyMi4xIDUuMSAzMi4yIDBsMTAwLTUwYzEyLjItNi4xIDE5LjktMTguNiAxOS45LTMyLjJWMjgzLjljMC0xNS05LjMtMjguNC0yMy40LTMzLjd6TTM1OCAyMTQuOGwtODUgMzEuOXYtNjguMmw4NS0zN3Y3My4zek0xNTQgMTA0LjFsMTAyLTM4LjIgMTAyIDM4LjJ2LjZsLTEwMiA0MS40LTEwMi00MS40di0uNnptODQgMjkxLjFsLTg1IDQyLjV2LTc5LjFsODUtMzguOHY3NS40em0wLTExMmwtMTAyIDQxLjQtMTAyLTQxLjR2LS42bDEwMi0zOC4yIDEwMiAzOC4ydi42em0yNDAgMTEybC04NSA0Mi41di03OS4xbDg1LTM4Ljh2NzUuNHptMC0xMTJsLTEwMiA0MS40LTEwMi00MS40di0uNmwxMDItMzguMiAxMDIgMzguMnYuNnoiPjwvcGF0aD48L3N2Zz4K
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#![doc(html_root_url = "https://docs.rs/dyn_clone/1.0.5")]
71#![no_std]
72#![allow(clippy::missing_panics_doc)]
73
74extern crate alloc;
75
76use crate::sealed::{Private, Sealed};
77
78#[macro_use]
79mod macros;
80
81#[doc(hidden)]
82pub mod private {
83 pub use alloc::boxed::Box;
84 pub use core::clone::Clone;
85 pub use core::marker::{Send, Sync};
86}
87
88mod sealed {
89 pub trait Sealed {}
90 impl<T: Clone> Sealed for T {}
91 pub struct Private;
92}
93
94/// This trait is implemented by any type that implements [`std::clone::Clone`].
95///
96/// [`std::clone::Clone`]: https://doc.rust-lang.org/std/clone/trait.Clone.html
97pub trait DynClone: Sealed {
98 // Not public API
99 #[doc(hidden)]
100 fn __clone_box(&self, _: Private) -> *mut ();
101}
102
103use alloc::boxed::Box;
104
105pub fn clone<T>(t: &T) -> T
106where
107 T: DynClone,
108{
109 unsafe { *Box::from_raw(<T as DynClone>::__clone_box(t, Private) as *mut T) }
110}
111
112pub fn clone_box<T>(t: &T) -> Box<T>
113where
114 T: ?Sized + DynClone,
115{
116 let mut fat_ptr = t as *const T;
117 unsafe {
118 let data_ptr = &mut fat_ptr as *mut *const T as *mut *mut ();
119 assert_eq!(*data_ptr as *const (), t as *const T as *const ());
120 *data_ptr = <T as DynClone>::__clone_box(t, Private);
121 }
122 unsafe { Box::from_raw(fat_ptr as *mut T) }
123}
124
125impl<T> DynClone for T
126where
127 T: Clone,
128{
129 fn __clone_box(&self, _: Private) -> *mut () {
130 Box::into_raw(Box::new(self.clone())) as *mut ()
131 }
132}