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