use crate::error::OutOfMemory; use core::mem; use std_alloc::sync::Arc; /// A trait for values that can be cloned, but contain owned, heap-allocated /// values whose allocations may fail during cloning. pub trait TryClone: Sized { /// Attempt to clone `self`, returning an error if any allocation fails /// during cloning. fn try_clone(&self) -> Result; /// Clone `self`, panicking on allocation failure. fn clone_panic_on_oom(&self) -> Self { use super::PanicOnOom as _; self.try_clone().panic_on_oom() } } impl TryClone for *mut T where T: ?Sized, { #[inline] fn try_clone(&self) -> Result { Ok(*self) } } impl TryClone for core::ptr::NonNull where T: ?Sized, { #[inline] fn try_clone(&self) -> Result { Ok(*self) } } impl<'a, T> TryClone for &'a T where T: ?Sized, { #[inline] fn try_clone(&self) -> Result { Ok(*self) } } impl TryClone for Result where T: TryClone, E: TryClone, { #[inline] fn try_clone(&self) -> Result { match self { Ok(x) => Ok(Ok(x.try_clone()?)), Err(e) => Ok(Err(e.try_clone()?)), } } } impl TryClone for Option where T: TryClone, { #[inline] fn try_clone(&self) -> Result { match self { Some(x) => Ok(Some(x.try_clone()?)), None => Ok(None), } } } impl TryClone for Arc { #[inline] fn try_clone(&self) -> Result { Ok(self.clone()) } } macro_rules! impl_try_clone_via_clone { ( $( $ty:ty ),* $(,)? ) => { $( impl TryClone for $ty { #[inline] fn try_clone(&self) -> Result { Ok(self.clone()) } } )* }; } impl_try_clone_via_clone! { bool, char, u8, u16, u32, u64, u128, usize, i8, i16, i32, i64, i128, isize, f32, f64, } macro_rules! tuples { ( $( $( $t:ident ),* );*) => { $( impl<$($t),*> TryClone for ( $($t,)* ) where $( $t: TryClone ),* { #[inline] fn try_clone(&self) -> Result { #[allow(non_snake_case, reason = "macro code")] let ( $($t,)* ) = self; Ok(( $( $t.try_clone()?, )* )) } } )* }; } tuples! { A; A, B; A, B, C; A, B, C, D; A, B, C, D, E; A, B, C, D, E, F; A, B, C, D, E, F, G; A, B, C, D, E, F, G, H; A, B, C, D, E, F, G, H, I; A, B, C, D, E, F, G, H, I, J; } impl TryClone for mem::ManuallyDrop where T: TryClone, { fn try_clone(&self) -> Result { Ok(mem::ManuallyDrop::new((**self).try_clone()?)) } } #[cfg(feature = "std")] impl_try_clone_via_clone! { std::hash::RandomState } impl_try_clone_via_clone! { hashbrown::DefaultHashBuilder }