1 use crate::error::OutOfMemory; 2 3 /// A trait for values that can be cloned, but contain owned, heap-allocated 4 /// values whose allocations may fail during cloning. 5 pub trait TryClone: Sized { 6 /// Attempt to clone `self`, returning an error if any allocation fails 7 /// during cloning. 8 fn try_clone(&self) -> Result<Self, OutOfMemory>; 9 } 10 11 impl<T> TryClone for *mut T { 12 #[inline] 13 fn try_clone(&self) -> Result<Self, OutOfMemory> { 14 Ok(*self) 15 } 16 } 17 18 impl<T> TryClone for core::ptr::NonNull<T> { 19 #[inline] 20 fn try_clone(&self) -> Result<Self, OutOfMemory> { 21 Ok(*self) 22 } 23 } 24 25 macro_rules! impl_try_clone_via_clone { 26 ( $( $ty:ty ),* $(,)? ) => { 27 $( 28 impl TryClone for $ty { 29 #[inline] 30 fn try_clone(&self) -> Result<Self, OutOfMemory> { 31 Ok(self.clone()) 32 } 33 } 34 )* 35 }; 36 } 37 38 impl_try_clone_via_clone! { 39 bool, char, 40 u8, u16, u32, u64, u128, usize, 41 i8, i16, i32, i64, i128, isize, 42 f32, f64, 43 } 44 45 macro_rules! tuples { 46 ( $( $( $t:ident ),* );*) => { 47 $( 48 impl<$($t),*> TryClone for ( $($t,)* ) 49 where 50 $( $t: TryClone ),* 51 { 52 #[inline] 53 fn try_clone(&self) -> Result<Self, OutOfMemory> { 54 #[allow(non_snake_case, reason = "macro code")] 55 let ( $($t,)* ) = self; 56 Ok(( $( $t.try_clone()?, )* )) 57 } 58 } 59 )* 60 }; 61 } 62 63 tuples! { 64 A; 65 A, B; 66 A, B, C; 67 A, B, C, D; 68 A, B, C, D, E; 69 A, B, C, D, E, F; 70 A, B, C, D, E, F, G; 71 A, B, C, D, E, F, G, H; 72 A, B, C, D, E, F, G, H, I; 73 A, B, C, D, E, F, G, H, I, J; 74 } 75