Skip to main content

wasmtime_internal_core/alloc/
try_clone.rs

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