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