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