clone_dyn_types/
lib.rs

1#![no_std]
2#![doc(html_logo_url = "https://raw.githubusercontent.com/Wandalen/wTools/master/asset/img/logo_v3_trans_square.png")]
3#![doc(
4  html_favicon_url = "https://raw.githubusercontent.com/Wandalen/wTools/alpha/asset/img/logo_v3_trans_square_icon_small_v2.ico"
5)]
6#![doc(html_root_url = "https://docs.rs/clone_dyn_types/latest/clone_dyn_types/")]
7#![ cfg_attr( doc, doc = include_str!( concat!( env!( "CARGO_MANIFEST_DIR" ), "/", "readme.md" ) ) ) ]
8#![ cfg_attr( not( doc ), doc = "Clone trait object types" ) ]
9
10/// Namespace with dependencies.
11#[ cfg( feature = "enabled" ) ]
12pub mod dependency
13{
14}
15
16/// Define a private namespace for all its items.
17// #[ cfg( any( not( feature = "no_std" ), feature = "use_alloc" ) ) ]
18#[ cfg( feature = "enabled" ) ]
19mod private
20{
21
22  // xxx: ?
23  // #[ cfg( any( not( feature = "no_std" ), feature = "use_alloc" ) ) ]
24  extern crate alloc;
25  // #[ cfg( any( not( feature = "no_std" ), feature = "use_alloc" ) ) ]
26  // #[ allow( unused_imports ) ]
27  use alloc::boxed::Box;
28  // #[ cfg( all( feature = "use_std", not( feature = "use_alloc" ) ) ) ]
29  // use std::boxed::Box;
30
31  /// A trait to upcast a clonable entity and clone it.
32  /// It's implemented for all entities which can be cloned.
33  pub trait CloneDyn: Sealed {
34  #[ doc( hidden ) ]
35  fn __clone_dyn(&self, _ : DontCallMe) -> *mut ();
36 }
37
38  // clonable
39  impl< T > CloneDyn for T
40  where
41  T: Clone,
42  {
43  #[ inline ]
44  #[ allow( clippy::implicit_return, clippy::as_conversions, clippy::ptr_as_ptr ) ]
45  fn __clone_dyn(&self, _ : DontCallMe) -> *mut ()
46  {
47   Box::< T >::into_raw(Box::new(self.clone())) as *mut ()
48  }
49 }
50
51  // slice
52  impl< T > CloneDyn for [T]
53  where
54  T: Clone,
55  {
56  #[ inline ]
57  #[ allow( clippy::implicit_return, clippy::as_conversions, clippy::ptr_as_ptr ) ]
58  fn __clone_dyn(&self, _ : DontCallMe) -> *mut ()
59  {
60   Box::< [T] >::into_raw(self.iter().cloned().collect()) as *mut ()
61  }
62 }
63
64  // str slice
65  impl CloneDyn for str 
66  {
67  #[ inline ]
68  #[ allow( clippy ::as_conversions, clippy ::ptr_as_ptr, clippy ::implicit_return ) ]
69  fn __clone_dyn(&self, _: DontCallMe) -> *mut () 
70  {
71   Box::< str >::into_raw(Box::from(self)) as *mut ()
72 }
73 }
74
75  ///
76  /// True clone which is applicable not only to clonable entities, but to trait objects implementing `CloneDyn`.
77  ///
78  /// # Example
79  ///
80  /// ```
81  /// use clone_dyn_types::clone;
82  ///
83  /// #[ derive( Clone ) ]
84  /// struct MyStruct
85  /// {
86  ///   value: i32,
87  /// }
88  ///
89  /// let original = MyStruct { value: 42 };
90  /// let cloned = clone( &original );
91  ///
92  /// assert_eq!( original.value, cloned.value );
93  /// ```
94  #[ inline ]
95  pub fn clone< T >(src : &T) -> T
96  where
97  T: CloneDyn,
98  {
99  // # Safety
100  //
101  // This function uses an `unsafe` block because it performs low-level memory manipulations. Specifically, it handles
102  // raw pointers and converts them to and from `Box< T >`. This is necessary to dynamically clone a trait object, which
103  // does not support cloning through the standard `Clone` trait. The safety of this function depends on the guarantee
104  // that the `CloneDyn` trait is correctly implemented for the given type `T`, ensuring that `__clone_dyn` returns a
105  // valid pointer to a cloned instance of `T`.
106  //
107  #[ allow( unsafe_code,
108   clippy::as_conversions,
109   clippy::ptr_as_ptr,
110   clippy::implicit_return,
111   clippy::undocumented_unsafe_blocks ) ]
112  unsafe
113  {
114   *Box::from_raw(< T as CloneDyn >::__clone_dyn(src, DontCallMe) as *mut T)
115 }
116 }
117
118  ///
119  /// Clone boxed dyn.
120  ///
121  /// Clones a dynamically sized trait object into a `Box< T >`.
122  ///
123  /// # Example
124  ///
125  /// ```
126  /// use clone_dyn_types::{ CloneDyn, clone_into_box };
127  ///
128  /// #[ derive( Clone ) ]
129  /// struct MyStruct
130  /// {
131  ///   value: i32,
132  /// }
133  ///
134  /// trait MyTrait: CloneDyn
135  /// {
136  ///   fn val( &self ) -> i32;
137  /// }
138  ///
139  /// impl MyTrait for MyStruct
140  /// {
141  ///   fn val( &self ) -> i32
142  ///   {
143  ///     self.value
144  /// }
145  /// }
146  ///
147  /// #[ allow( non_local_definitions ) ]
148  /// impl < 'c > Clone
149  /// for Box< dyn MyTrait + 'c >
150  /// {
151  ///   #[ inline ]
152  ///   fn clone( &self ) -> Self { clone_into_box( &**self ) }
153  /// }
154  ///
155  /// #[ allow( non_local_definitions ) ]
156  /// impl < 'c > Clone
157  /// for Box< dyn MyTrait + Send + 'c >
158  /// {
159  ///   #[ inline ]
160  ///   fn clone( &self ) -> Self { clone_into_box( &**self ) }
161  /// }
162  ///
163  /// #[ allow( non_local_definitions ) ]
164  /// impl < 'c > Clone
165  /// for Box< dyn MyTrait + Sync + 'c >
166  /// {
167  ///   #[ inline ]
168  ///   fn clone( &self ) -> Self { clone_into_box( &**self ) }
169  /// }
170  ///
171  /// #[ allow( non_local_definitions ) ]
172  /// impl < 'c > Clone
173  /// for Box< dyn MyTrait + Send + Sync + 'c >
174  /// {
175  ///   #[ inline ]
176  ///   fn clone( &self ) -> Self { clone_into_box( &**self ) }
177  /// }
178  ///
179  /// let cloned: Box< dyn MyTrait > = clone_into_box( &MyStruct { value: 42 } );
180  ///
181  /// ```
182  #[ inline ]
183  pub fn clone_into_box< T >(ref_dyn : &T) -> Box< T >
184  where
185  T: ?Sized + CloneDyn,
186  {
187  // # Safety
188  //
189  // This function uses an `unsafe` block because it performs low-level memory manipulations involving raw pointers.
190  // The `unsafe` block is necessary here because we're manually handling raw pointers and converting them to and from
191  // `Box< T >`. This bypasses Rust's ownership and borrowing rules to achieve dynamic cloning of a boxed trait object.
192  // The safety of this function relies on the correct implementation of the `CloneDyn` trait for the given type `T`.
193  // Specifically, `__clone_dyn` must return a valid pointer to a cloned instance of `T`.
194  //
195  #[ allow( unsafe_code,
196   clippy::implicit_return,
197   clippy::as_conversions,
198   clippy::ptr_cast_constness,
199   clippy::ptr_as_ptr,
200   clippy::multiple_unsafe_ops_per_block,
201   clippy::undocumented_unsafe_blocks,
202   clippy::ref_as_ptr,
203   clippy::borrow_as_ptr ) ]
204  unsafe
205  {
206   let mut ptr = ref_dyn as *const T;
207   #[ allow( clippy::borrow_as_ptr ) ]
208   let data_ptr = &mut ptr as *mut *const T as *mut *mut (); // don't change it
209          // qqq: xxx: after atabilization try `&raw mut ptr` instead
210          // let data_ptr = &raw mut ptr as *mut *mut (); // fix clippy
211   *data_ptr = < T as CloneDyn >::__clone_dyn(ref_dyn, DontCallMe);
212   Box::from_raw(ptr as *mut T)
213 }
214 }
215
216  #[ doc( hidden ) ]
217  mod sealed
218  {
219  #[ doc( hidden ) ]
220  #[ allow( missing_debug_implementations ) ]
221  pub struct DontCallMe;
222  #[ doc( hidden ) ]
223  pub trait Sealed {}
224  impl< T: Clone > Sealed for T {}
225  impl< T: Clone > Sealed for [T] {}
226  impl Sealed for str {}
227 }
228  use sealed :: { DontCallMe, Sealed };
229}
230
231#[ cfg( feature = "enabled" ) ]
232#[ doc( inline ) ]
233#[ allow( unused_imports ) ]
234#[ allow( clippy ::pub_use ) ]
235pub use own :: *;
236
237/// Own namespace of the module.
238#[ cfg( feature = "enabled" ) ]
239#[ allow( unused_imports ) ]
240pub mod own 
241{
242  use super ::orphan;
243  #[ doc( inline ) ]
244  #[ allow( clippy ::useless_attribute, clippy ::pub_use ) ]
245  pub use orphan :: *;
246}
247
248/// Orphan namespace of the module.
249#[ cfg( feature = "enabled" ) ]
250#[ allow( unused_imports ) ]
251pub mod orphan 
252{
253  use super ::exposed;
254  #[ doc( inline ) ]
255  #[ allow( clippy ::useless_attribute, clippy ::pub_use ) ]
256  pub use exposed :: *;
257}
258
259/// Exposed namespace of the module.
260#[ cfg( feature = "enabled" ) ]
261#[ allow( unused_imports ) ]
262pub mod exposed 
263{
264  use super ::prelude;
265  #[ doc( inline ) ]
266  #[ allow( clippy ::useless_attribute, clippy ::pub_use ) ]
267  pub use prelude :: *;
268}
269
270/// Prelude to use essentials: `use my_module ::prelude :: *`.
271#[ cfg( feature = "enabled" ) ]
272#[ allow( unused_imports ) ]
273pub mod prelude 
274{
275  use super ::private;
276  #[ doc( inline ) ]
277  #[ allow( clippy ::useless_attribute, clippy ::pub_use ) ]
278  pub use private :: { CloneDyn, clone_into_box, clone };
279}