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