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