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