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