1 use crate::error::OutOfMemory;
2 use core::mem;
3 
4 /// A trait for values that can be cloned, but contain owned, heap-allocated
5 /// values whose allocations may fail during cloning.
6 pub trait TryClone: Sized {
7     /// Attempt to clone `self`, returning an error if any allocation fails
8     /// during cloning.
9     fn try_clone(&self) -> Result<Self, OutOfMemory>;
10 }
11 
12 impl<T> TryClone for *mut T
13 where
14     T: ?Sized,
15 {
16     #[inline]
17     fn try_clone(&self) -> Result<Self, OutOfMemory> {
18         Ok(*self)
19     }
20 }
21 
22 impl<T> TryClone for core::ptr::NonNull<T>
23 where
24     T: ?Sized,
25 {
26     #[inline]
27     fn try_clone(&self) -> Result<Self, OutOfMemory> {
28         Ok(*self)
29     }
30 }
31 
32 impl<'a, T> TryClone for &'a T
33 where
34     T: ?Sized,
35 {
36     #[inline]
37     fn try_clone(&self) -> Result<Self, OutOfMemory> {
38         Ok(*self)
39     }
40 }
41 
42 macro_rules! impl_try_clone_via_clone {
43     ( $( $ty:ty ),* $(,)? ) => {
44         $(
45             impl TryClone for $ty {
46                 #[inline]
47                 fn try_clone(&self) -> Result<Self, OutOfMemory> {
48                     Ok(self.clone())
49                 }
50             }
51         )*
52     };
53 }
54 
55 impl_try_clone_via_clone! {
56     bool, char,
57     u8, u16, u32, u64, u128, usize,
58     i8, i16, i32, i64, i128, isize,
59     f32, f64,
60 }
61 
62 macro_rules! tuples {
63     ( $( $( $t:ident ),* );*) => {
64         $(
65             impl<$($t),*> TryClone for ( $($t,)* )
66             where
67                 $( $t: TryClone ),*
68             {
69                 #[inline]
70                 fn try_clone(&self) -> Result<Self, OutOfMemory> {
71                     #[allow(non_snake_case, reason = "macro code")]
72                     let ( $($t,)* ) = self;
73                     Ok(( $( $t.try_clone()?, )* ))
74                 }
75             }
76         )*
77     };
78 }
79 
80 tuples! {
81     A;
82     A, B;
83     A, B, C;
84     A, B, C, D;
85     A, B, C, D, E;
86     A, B, C, D, E, F;
87     A, B, C, D, E, F, G;
88     A, B, C, D, E, F, G, H;
89     A, B, C, D, E, F, G, H, I;
90     A, B, C, D, E, F, G, H, I, J;
91 }
92 
93 impl<T> TryClone for mem::ManuallyDrop<T>
94 where
95     T: TryClone,
96 {
97     fn try_clone(&self) -> Result<Self, OutOfMemory> {
98         Ok(mem::ManuallyDrop::new((**self).try_clone()?))
99     }
100 }
101 
102 #[cfg(feature = "std")]
103 impl_try_clone_via_clone! {
104     std::hash::RandomState
105 }
106 
107 impl_try_clone_via_clone! {
108     hashbrown::DefaultHashBuilder
109 }
110