1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132
//! [![github]](https://github.com/dtolnay/dyn-clone) [![crates-io]](https://crates.io/crates/dyn-clone) [![docs-rs]](https://docs.rs/dyn-clone)
//!
//! [github]: https://img.shields.io/badge/github-8da0cb?style=for-the-badge&labelColor=555555&logo=github
//! [crates-io]: https://img.shields.io/badge/crates.io-fc8d62?style=for-the-badge&labelColor=555555&logo=rust
//! [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
//!
//! <br>
//!
//! This crate provides a [`DynClone`] trait that can be used in trait objects,
//! and a [`clone_box`] function that can clone any sized or dynamically sized
//! implementation of `DynClone`. Types that implement the standard library's
//! [`std::clone::Clone`] trait are automatically usable by a `DynClone` trait
//! object.
//!
//! [`DynClone`]: trait.DynClone.html
//! [`clone_box`]: fn.clone_box.html
//! [`std::clone::Clone`]: https://doc.rust-lang.org/std/clone/trait.Clone.html
//!
//! # Example
//!
//! ```
//! use dyn_clone::DynClone;
//!
//! trait MyTrait: DynClone {
//! fn recite(&self);
//! }
//!
//! impl MyTrait for String {
//! fn recite(&self) {
//! println!("{} ♫", self);
//! }
//! }
//!
//! fn main() {
//! let line = "The slithy structs did gyre and gimble the namespace";
//!
//! // Build a trait object holding a String.
//! // This requires String to implement MyTrait and std::clone::Clone.
//! let x: Box<dyn MyTrait> = Box::new(String::from(line));
//!
//! x.recite();
//!
//! // The type of x2 is a Box<dyn MyTrait> cloned from x.
//! let x2 = dyn_clone::clone_box(&*x);
//!
//! x2.recite();
//! }
//! ```
//!
//! This crate includes a macro for concisely implementing `impl
//! std::clone::Clone for Box<dyn MyTrait>` in terms of `dyn_clone::clone_box`.
//!
//! ```
//! # use dyn_clone::DynClone;
//! #
//! // As before.
//! trait MyTrait: DynClone {
//! /* ... */
//! }
//!
//! dyn_clone::clone_trait_object!(MyTrait);
//!
//! // Now data structures containing Box<dyn MyTrait> can derive Clone:
//! #[derive(Clone)]
//! struct Container {
//! trait_object: Box<dyn MyTrait>,
//! }
//! ```
#![doc(html_root_url = "https://docs.rs/dyn_clone/1.0.5")]
#![no_std]
#![allow(clippy::missing_panics_doc)]
extern crate alloc;
use crate::sealed::{Private, Sealed};
#[macro_use]
mod macros;
#[doc(hidden)]
pub mod private {
pub use alloc::boxed::Box;
pub use core::clone::Clone;
pub use core::marker::{Send, Sync};
}
mod sealed {
pub trait Sealed {}
impl<T: Clone> Sealed for T {}
pub struct Private;
}
/// This trait is implemented by any type that implements [`std::clone::Clone`].
///
/// [`std::clone::Clone`]: https://doc.rust-lang.org/std/clone/trait.Clone.html
pub trait DynClone: Sealed {
// Not public API
#[doc(hidden)]
fn __clone_box(&self, _: Private) -> *mut ();
}
use alloc::boxed::Box;
pub fn clone<T>(t: &T) -> T
where
T: DynClone,
{
unsafe { *Box::from_raw(<T as DynClone>::__clone_box(t, Private) as *mut T) }
}
pub fn clone_box<T>(t: &T) -> Box<T>
where
T: ?Sized + DynClone,
{
let mut fat_ptr = t as *const T;
unsafe {
let data_ptr = &mut fat_ptr as *mut *const T as *mut *mut ();
assert_eq!(*data_ptr as *const (), t as *const T as *const ());
*data_ptr = <T as DynClone>::__clone_box(t, Private);
}
unsafe { Box::from_raw(fat_ptr as *mut T) }
}
impl<T> DynClone for T
where
T: Clone,
{
fn __clone_box(&self, _: Private) -> *mut () {
Box::into_raw(Box::new(self.clone())) as *mut ()
}
}