1b8e97b5bSNick Fitzgerald use crate::error::OutOfMemory; 20c673b70SNick Fitzgerald use core::mem; 3b57de80fSNick Fitzgerald use std_alloc::sync::Arc; 4b8e97b5bSNick Fitzgerald 5b8e97b5bSNick Fitzgerald /// A trait for values that can be cloned, but contain owned, heap-allocated 6b8e97b5bSNick Fitzgerald /// values whose allocations may fail during cloning. 7b8e97b5bSNick Fitzgerald pub trait TryClone: Sized { 8b8e97b5bSNick Fitzgerald /// Attempt to clone `self`, returning an error if any allocation fails 9b8e97b5bSNick Fitzgerald /// during cloning. try_clone(&self) -> Result<Self, OutOfMemory>10b8e97b5bSNick Fitzgerald fn try_clone(&self) -> Result<Self, OutOfMemory>; 11*e6948e75SNick Fitzgerald 12*e6948e75SNick Fitzgerald /// Clone `self`, panicking on allocation failure. clone_panic_on_oom(&self) -> Self13*e6948e75SNick Fitzgerald fn clone_panic_on_oom(&self) -> Self { 14*e6948e75SNick Fitzgerald use super::PanicOnOom as _; 15*e6948e75SNick Fitzgerald self.try_clone().panic_on_oom() 16*e6948e75SNick Fitzgerald } 17b8e97b5bSNick Fitzgerald } 18b8e97b5bSNick Fitzgerald 190c673b70SNick Fitzgerald impl<T> TryClone for *mut T 200c673b70SNick Fitzgerald where 210c673b70SNick Fitzgerald T: ?Sized, 220c673b70SNick Fitzgerald { 23b8e97b5bSNick Fitzgerald #[inline] try_clone(&self) -> Result<Self, OutOfMemory>24b8e97b5bSNick Fitzgerald fn try_clone(&self) -> Result<Self, OutOfMemory> { 25b8e97b5bSNick Fitzgerald Ok(*self) 26b8e97b5bSNick Fitzgerald } 27b8e97b5bSNick Fitzgerald } 28b8e97b5bSNick Fitzgerald 290c673b70SNick Fitzgerald impl<T> TryClone for core::ptr::NonNull<T> 300c673b70SNick Fitzgerald where 310c673b70SNick Fitzgerald T: ?Sized, 320c673b70SNick Fitzgerald { 330c673b70SNick Fitzgerald #[inline] try_clone(&self) -> Result<Self, OutOfMemory>340c673b70SNick Fitzgerald fn try_clone(&self) -> Result<Self, OutOfMemory> { 350c673b70SNick Fitzgerald Ok(*self) 360c673b70SNick Fitzgerald } 370c673b70SNick Fitzgerald } 380c673b70SNick Fitzgerald 390c673b70SNick Fitzgerald impl<'a, T> TryClone for &'a T 400c673b70SNick Fitzgerald where 410c673b70SNick Fitzgerald T: ?Sized, 420c673b70SNick Fitzgerald { 43b8e97b5bSNick Fitzgerald #[inline] try_clone(&self) -> Result<Self, OutOfMemory>44b8e97b5bSNick Fitzgerald fn try_clone(&self) -> Result<Self, OutOfMemory> { 45b8e97b5bSNick Fitzgerald Ok(*self) 46b8e97b5bSNick Fitzgerald } 47b8e97b5bSNick Fitzgerald } 48b8e97b5bSNick Fitzgerald 49b57de80fSNick Fitzgerald impl<T, E> TryClone for Result<T, E> 50b57de80fSNick Fitzgerald where 51b57de80fSNick Fitzgerald T: TryClone, 52b57de80fSNick Fitzgerald E: TryClone, 53b57de80fSNick Fitzgerald { 54b57de80fSNick Fitzgerald #[inline] try_clone(&self) -> Result<Self, OutOfMemory>55b57de80fSNick Fitzgerald fn try_clone(&self) -> Result<Self, OutOfMemory> { 56b57de80fSNick Fitzgerald match self { 57b57de80fSNick Fitzgerald Ok(x) => Ok(Ok(x.try_clone()?)), 58b57de80fSNick Fitzgerald Err(e) => Ok(Err(e.try_clone()?)), 59b57de80fSNick Fitzgerald } 60b57de80fSNick Fitzgerald } 61b57de80fSNick Fitzgerald } 62b57de80fSNick Fitzgerald 63b57de80fSNick Fitzgerald impl<T> TryClone for Option<T> 64b57de80fSNick Fitzgerald where 65b57de80fSNick Fitzgerald T: TryClone, 66b57de80fSNick Fitzgerald { 67b57de80fSNick Fitzgerald #[inline] try_clone(&self) -> Result<Self, OutOfMemory>68b57de80fSNick Fitzgerald fn try_clone(&self) -> Result<Self, OutOfMemory> { 69b57de80fSNick Fitzgerald match self { 70b57de80fSNick Fitzgerald Some(x) => Ok(Some(x.try_clone()?)), 71b57de80fSNick Fitzgerald None => Ok(None), 72b57de80fSNick Fitzgerald } 73b57de80fSNick Fitzgerald } 74b57de80fSNick Fitzgerald } 75b57de80fSNick Fitzgerald 76b57de80fSNick Fitzgerald impl<T> TryClone for Arc<T> { 77b57de80fSNick Fitzgerald #[inline] try_clone(&self) -> Result<Self, OutOfMemory>78b57de80fSNick Fitzgerald fn try_clone(&self) -> Result<Self, OutOfMemory> { 79b57de80fSNick Fitzgerald Ok(self.clone()) 80b57de80fSNick Fitzgerald } 81b57de80fSNick Fitzgerald } 82b57de80fSNick Fitzgerald 83b8e97b5bSNick Fitzgerald macro_rules! impl_try_clone_via_clone { 84b8e97b5bSNick Fitzgerald ( $( $ty:ty ),* $(,)? ) => { 85b8e97b5bSNick Fitzgerald $( 86b8e97b5bSNick Fitzgerald impl TryClone for $ty { 87b8e97b5bSNick Fitzgerald #[inline] 88b8e97b5bSNick Fitzgerald fn try_clone(&self) -> Result<Self, OutOfMemory> { 89b8e97b5bSNick Fitzgerald Ok(self.clone()) 90b8e97b5bSNick Fitzgerald } 91b8e97b5bSNick Fitzgerald } 92b8e97b5bSNick Fitzgerald )* 93b8e97b5bSNick Fitzgerald }; 94b8e97b5bSNick Fitzgerald } 95b8e97b5bSNick Fitzgerald 96b8e97b5bSNick Fitzgerald impl_try_clone_via_clone! { 97b8e97b5bSNick Fitzgerald bool, char, 98b8e97b5bSNick Fitzgerald u8, u16, u32, u64, u128, usize, 99b8e97b5bSNick Fitzgerald i8, i16, i32, i64, i128, isize, 100b8e97b5bSNick Fitzgerald f32, f64, 101b8e97b5bSNick Fitzgerald } 102b8e97b5bSNick Fitzgerald 103b8e97b5bSNick Fitzgerald macro_rules! tuples { 104b8e97b5bSNick Fitzgerald ( $( $( $t:ident ),* );*) => { 105b8e97b5bSNick Fitzgerald $( 106b8e97b5bSNick Fitzgerald impl<$($t),*> TryClone for ( $($t,)* ) 107b8e97b5bSNick Fitzgerald where 108b8e97b5bSNick Fitzgerald $( $t: TryClone ),* 109b8e97b5bSNick Fitzgerald { 110b8e97b5bSNick Fitzgerald #[inline] 111b8e97b5bSNick Fitzgerald fn try_clone(&self) -> Result<Self, OutOfMemory> { 112b8e97b5bSNick Fitzgerald #[allow(non_snake_case, reason = "macro code")] 113b8e97b5bSNick Fitzgerald let ( $($t,)* ) = self; 114b8e97b5bSNick Fitzgerald Ok(( $( $t.try_clone()?, )* )) 115b8e97b5bSNick Fitzgerald } 116b8e97b5bSNick Fitzgerald } 117b8e97b5bSNick Fitzgerald )* 118b8e97b5bSNick Fitzgerald }; 119b8e97b5bSNick Fitzgerald } 120b8e97b5bSNick Fitzgerald 121b8e97b5bSNick Fitzgerald tuples! { 122b8e97b5bSNick Fitzgerald A; 123b8e97b5bSNick Fitzgerald A, B; 124b8e97b5bSNick Fitzgerald A, B, C; 125b8e97b5bSNick Fitzgerald A, B, C, D; 126b8e97b5bSNick Fitzgerald A, B, C, D, E; 127b8e97b5bSNick Fitzgerald A, B, C, D, E, F; 128b8e97b5bSNick Fitzgerald A, B, C, D, E, F, G; 129b8e97b5bSNick Fitzgerald A, B, C, D, E, F, G, H; 130b8e97b5bSNick Fitzgerald A, B, C, D, E, F, G, H, I; 131b8e97b5bSNick Fitzgerald A, B, C, D, E, F, G, H, I, J; 132b8e97b5bSNick Fitzgerald } 133f0011184SNick Fitzgerald 1340c673b70SNick Fitzgerald impl<T> TryClone for mem::ManuallyDrop<T> 1350c673b70SNick Fitzgerald where 1360c673b70SNick Fitzgerald T: TryClone, 1370c673b70SNick Fitzgerald { try_clone(&self) -> Result<Self, OutOfMemory>1380c673b70SNick Fitzgerald fn try_clone(&self) -> Result<Self, OutOfMemory> { 1390c673b70SNick Fitzgerald Ok(mem::ManuallyDrop::new((**self).try_clone()?)) 1400c673b70SNick Fitzgerald } 1410c673b70SNick Fitzgerald } 1420c673b70SNick Fitzgerald 143f0011184SNick Fitzgerald #[cfg(feature = "std")] 144f0011184SNick Fitzgerald impl_try_clone_via_clone! { 145f0011184SNick Fitzgerald std::hash::RandomState 146f0011184SNick Fitzgerald } 147f0011184SNick Fitzgerald 148f0011184SNick Fitzgerald impl_try_clone_via_clone! { 149f0011184SNick Fitzgerald hashbrown::DefaultHashBuilder 150f0011184SNick Fitzgerald } 151