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