1#![expect(clippy::absolute_paths, reason = "there's a lot of random types used")]
2#![warn(clippy::missing_inline_in_public_items, reason = "almost everything is very short")]
3
4use crate::call_varargs_macro;
5use crate::speed::{Fast, MaybeSlow, Speed};
6
7
8pub trait DeepClone<S: Speed>: Sized {
44 #[must_use]
52 fn deep_clone(&self) -> Self;
53}
54
55pub trait FastDeepClone: DeepClone<Fast> {
59 #[must_use]
67 fn fast_deep_clone(&self) -> Self;
68}
69
70impl<T: DeepClone<Fast>> FastDeepClone for T {
71 #[inline]
72 fn fast_deep_clone(&self) -> Self {
73 self.deep_clone()
74 }
75}
76
77
78macro_rules! impl_copy {
79 ($($types:ty),*) => {
80 $(
81 impl<S: Speed> DeepClone<S> for $types {
82 #[inline]
83 fn deep_clone(&self) -> Self {
84 *self
85 }
86 }
87 )*
88 };
89}
90
91macro_rules! int_impls {
92 ($($num:ident),* $(,)?) => {
93 $(
94 impl_copy!($num, ::core::num::NonZero<$num>);
95 )*
96 };
97}
98
99int_impls!(
100 i8, i16, i32, i64, i128, isize,
101 u8, u16, u32, u64, u128, usize,
102);
103
104macro_rules! non_recursive_fast {
105 ($($({for $($bounds:tt)+})? $type:ty),* $(,)?) => {
106 $(
107 impl<S: Speed, $($($bounds)+)?> DeepClone<S> for $type {
108 #[inline]
109 fn deep_clone(&self) -> Self {
110 self.clone()
111 }
112 }
113 )*
114 };
115}
116
117non_recursive_fast! {
118 f32, f64, bool, char, (),
119 core::alloc::Layout,
120 core::any::TypeId,
121 core::cmp::Ordering,
122 {for T} core::iter::Empty<T>,
123 {for T: ?Sized} core::marker::PhantomData<T>,
124 core::marker::PhantomPinned,
125 {for T} core::mem::Discriminant<T>,
126 core::ops::RangeFull,
127 core::sync::atomic::Ordering,
128 core::time::Duration,
129}
130
131#[cfg(feature = "std")]
132non_recursive_fast! {
133 std::time::Instant,
134 std::thread::ThreadId,
135}
136
137macro_rules! atomic {
138 ($($name:ident $bits:literal),* $(,)?) => {
139 $(
140 #[cfg(target_has_atomic = $bits)]
141 impl<S: Speed> DeepClone<S> for core::sync::atomic::$name {
142 #[inline]
143 fn deep_clone(&self) -> Self {
144 Self::new(self.load(core::sync::atomic::Ordering::Relaxed))
145 }
146 }
147 )*
148 };
149}
150
151atomic! {
152 AtomicBool "8",
153 AtomicI8 "8", AtomicU8 "8",
154 AtomicI16 "16", AtomicU16 "16",
155 AtomicI32 "32", AtomicU32 "32",
156 AtomicI64 "64", AtomicU64 "64",
157 AtomicIsize "ptr", AtomicUsize "ptr",
158}
159
160macro_rules! function {
161 ($($args:ident),*) => {
162 impl<S: Speed, R, $($args),*> DeepClone<S> for fn($($args),*) -> R {
163 #[inline]
164 fn deep_clone(&self) -> Self {
165 *self
166 }
167 }
168 };
169}
170
171function!();
172call_varargs_macro!(function);
173
174macro_rules! make_tuple_macro {
175 ($name:ident, $speed:ident, $dollar:tt) => {
176 macro_rules! $name {
177 ($dollar($dollar args:ident),+) => {
178 impl<$dollar($dollar args: DeepClone<$speed>),+> DeepClone<$speed>
179 for ($dollar($dollar args,)+)
180 {
181 #[inline]
182 fn deep_clone(&self) -> Self {
183 #[expect(
184 non_snake_case,
185 reason = "using `Tn` as the variable of type `Tn`",
186 )]
187 let ($dollar($dollar args,)+) = self;
188 (
189 $dollar($dollar args.deep_clone(),)+
190 )
191 }
192 }
193 };
194 }
195 };
196}
197
198make_tuple_macro!(tuple_fast, Fast, $);
199make_tuple_macro!(tuple_slow, MaybeSlow, $);
200
201call_varargs_macro!(tuple_fast);
202call_varargs_macro!(tuple_slow);
203
204macro_rules! recursive {
205 (
206 $(
207 $(#[$meta:meta])*
208 $({for ($($special_bounds:ident)*) {$($where_bounds:tt)*} $($bounds:tt)*})?
209 $type:ty
210 {|$self:ident| $($body:tt)*}
211 ),*
212 $(,)?
213 ) => {
214 $(
215 impl<$($($special_bounds: DeepClone<Fast>,)* $($bounds)*)?> DeepClone<Fast>
216 for $type
217 where
218 $($($where_bounds)*)?
219 {
220 $(#[$meta])*
221 #[inline]
222 fn deep_clone(&$self) -> Self {
223 $($body)*
224 }
225 }
226
227
228 impl<$($($special_bounds: DeepClone<MaybeSlow>,)* $($bounds)*)?> DeepClone<MaybeSlow>
229 for $type
230 where
231 $($($where_bounds)*)?
232 {
233 $(#[$meta])*
234 #[inline]
235 fn deep_clone(&$self) -> Self {
236 $($body)*
237 }
238 }
239 )*
240 };
241}
242
243recursive! {
244 {for (T) {T: ?Sized} const N: usize} [T; N] {|self| {
245 self.each_ref().map(T::deep_clone)
246 }},
247 {for (T) {}} Option<T> {|self| {
248 self.as_ref().map(T::deep_clone)
249 }},
250 {for (T E) {}} Result<T, E> {|self| {
251 self.as_ref()
252 .map(T::deep_clone)
253 .map_err(E::deep_clone)
254 }},
255 {for (T) {}} core::mem::ManuallyDrop<T> {|self| {
256 Self::new(T::deep_clone(self))
257 }},
258 {for (T) {T: Copy}} core::cell::Cell<T> {|self| {
259 Self::new(T::deep_clone(&self.get()))
260 }},
261 {for (T) {}} core::cell::RefCell<T> {|self| {
264 Self::new(T::deep_clone(&self.borrow()))
265 }},
266}
267
268#[cfg(feature = "alloc")]
269recursive! {
270 {for (T) {T: ?Sized}} alloc::rc::Rc<T> {|self| {
271 Self::new(T::deep_clone(self))
272 }},
273 {for (T) {T:}} alloc::boxed::Box<T> {|self| {
274 Self::new(T::deep_clone(self))
275 }},
276 {for (T) {T: ?Sized}} core::pin::Pin<alloc::rc::Rc<T>> {|self| {
277 alloc::rc::Rc::pin(T::deep_clone(self))
278 }},
279 {for (T) {T: ?Sized}} alloc::rc::Weak<T> {|self| {
280 if let Some(rc) = self.upgrade() {
281 alloc::rc::Rc::downgrade(&alloc::rc::Rc::new(T::deep_clone(&rc)))
282 } else {
283 Self::new()
284 }
285 }},
286 {for (T) {T: ?Sized}} alloc::sync::Arc<T> {|self| {
287 Self::new(T::deep_clone(self))
288 }},
289 {for (T) {T: ?Sized}} core::pin::Pin<alloc::sync::Arc<T>> {|self| {
290 alloc::sync::Arc::pin(T::deep_clone(self))
291 }},
292 {for (T) {T: ?Sized}} alloc::sync::Weak<T> {|self| {
293 if let Some(arc) = self.upgrade() {
294 alloc::sync::Arc::downgrade(&alloc::sync::Arc::new(T::deep_clone(&arc)))
295 } else {
296 Self::new()
297 }
298 }},
299}
300
301#[cfg(feature = "std")]
302recursive! {
303 {for (T) {}} std::sync::RwLock<T> {|self| {
306 let lock_result: Result<_, std::sync::PoisonError<_>> = self.read();
307 #[expect(clippy::unwrap_used, reason = "Unwrapping poison")]
308 Self::new(T::deep_clone(&lock_result.unwrap()))
309 }},
310 {for (T) {}} std::sync::Mutex<T> {|self| {
315 let lock_result: Result<_, std::sync::PoisonError<_>> = self.lock();
316 #[expect(clippy::unwrap_used, reason = "Unwrapping poison")]
317 Self::new(T::deep_clone(&lock_result.unwrap()))
318 }},
319}
320
321macro_rules! map_and_collect {
324 ($($t:ident $({$($where_bounds:tt)*})? $type:ty),* $(,)?) => {
325 $(
326 #[cfg(feature = "alloc")]
327 impl<$t: DeepClone<MaybeSlow>> DeepClone<MaybeSlow>
328 for $type
329 where
330 $($($where_bounds)*)?
331 {
332 #[inline]
333 fn deep_clone(&self) -> Self {
334 self.iter()
335 .map($t::deep_clone)
336 .collect()
337 }
338 }
339 )*
340 };
341}
342
343map_and_collect! {
344 T alloc::boxed::Box<[T]>,
345 T alloc::vec::Vec<T>,
346 T alloc::collections::VecDeque<T>,
347 T alloc::collections::LinkedList<T>,
348 T {T: Ord} alloc::collections::BTreeSet<T>,
349 T {T: Ord} alloc::collections::BinaryHeap<T>,
350}
351
352#[cfg(feature = "alloc")]
353impl<T: DeepClone<MaybeSlow>> DeepClone<MaybeSlow>
354for core::pin::Pin<alloc::boxed::Box<[T]>>
355{
356 #[inline]
357 fn deep_clone(&self) -> Self {
358 let new_box = self.iter()
359 .map(T::deep_clone)
360 .collect::<alloc::boxed::Box<[T]>>();
361
362 alloc::boxed::Box::into_pin(new_box)
363 }
364}
365
366#[cfg(feature = "alloc")]
367impl DeepClone<MaybeSlow> for alloc::boxed::Box<str> {
368 #[inline]
369 fn deep_clone(&self) -> Self {
370 self.clone()
371 }
372}
373
374#[cfg(feature = "alloc")]
375impl DeepClone<MaybeSlow> for core::pin::Pin<alloc::boxed::Box<str>> {
376 #[inline]
377 fn deep_clone(&self) -> Self {
378 self.clone()
379 }
380}
381
382#[cfg(feature = "alloc")]
383impl<K, V> DeepClone<MaybeSlow> for alloc::collections::BTreeMap<K, V>
384where
385 K: DeepClone<MaybeSlow> + Ord,
386 V: DeepClone<MaybeSlow>,
387{
388 #[inline]
389 fn deep_clone(&self) -> Self {
390 self.iter()
391 .map(|(key, val)| {
392 (
393 K::deep_clone(key),
394 V::deep_clone(val),
395 )
396 })
397 .collect()
398 }
399}
400
401#[cfg(feature = "std")]
402impl<T, S> DeepClone<MaybeSlow> for std::collections::HashSet<T, S>
403where
404 T: DeepClone<MaybeSlow> + Eq + core::hash::Hash,
405 S: core::hash::BuildHasher + Default,
406{
407 #[inline]
408 fn deep_clone(&self) -> Self {
409 self.iter()
410 .map(T::deep_clone)
411 .collect()
412 }
413}
414
415#[cfg(feature = "std")]
416impl<K, V, S> DeepClone<MaybeSlow> for std::collections::HashMap<K, V, S>
417where
418 K: DeepClone<MaybeSlow> + Eq + core::hash::Hash,
419 V: DeepClone<MaybeSlow>,
420 S: core::hash::BuildHasher + Default,
421{
422 #[inline]
423 fn deep_clone(&self) -> Self {
424 self.iter()
425 .map(|(key, val)| {
426 (
427 K::deep_clone(key),
428 V::deep_clone(val),
429 )
430 })
431 .collect()
432 }
433}
434
435impl<S: Speed> DeepClone<S> for core::convert::Infallible {
436 #[expect(
437 clippy::missing_inline_in_public_items,
438 clippy::uninhabited_references,
439 reason = "this is unreachable",
440 )]
441 fn deep_clone(&self) -> Self {
442 *self
443 }
444}
445
446