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