1#![cfg_attr(nightly, feature(allocator_api))]
4
5pub use fallacy_alloc::AllocError;
6use std::sync::{Arc, Weak};
7
8#[cfg(feature = "derive")]
9pub use fallacy_clone_derive::TryClone;
10
11pub trait TryClone: Sized {
13 fn try_clone(&self) -> Result<Self, AllocError>;
14
15 #[inline]
21 fn try_clone_from(&mut self, source: &Self) -> Result<(), AllocError> {
22 *self = source.try_clone()?;
23 Ok(())
24 }
25}
26
27macro_rules! impl_try_clone {
28 ($($val: ty),*) => {
29 $(impl TryClone for $val {
30 #[inline(always)]
31 fn try_clone(&self) -> Result<Self, AllocError> {
32 Ok(*self)
33 }
34 #[inline(always)]
35 fn try_clone_from(&mut self, source: &Self) -> Result<(), AllocError> {
36 *self = *source;
37 Ok(())
38 }
39 })*
40 }
41}
42
43impl_try_clone!(bool, u8, u16, u32, u64, u128, i8, i16, i32, i64, i128, usize, isize);
44
45impl<T: ?Sized> TryClone for &T {
46 #[inline(always)]
47 fn try_clone(&self) -> Result<Self, AllocError> {
48 Ok(*self)
49 }
50
51 #[inline(always)]
52 fn try_clone_from(&mut self, source: &Self) -> Result<(), AllocError> {
53 *self = *source;
54 Ok(())
55 }
56}
57
58impl<T: TryClone> TryClone for Option<T> {
59 #[inline]
60 fn try_clone(&self) -> Result<Self, AllocError> {
61 Ok(match self {
62 Some(t) => Some(t.try_clone()?),
63 None => None,
64 })
65 }
66
67 #[inline]
68 fn try_clone_from(&mut self, source: &Self) -> Result<(), AllocError> {
69 match source {
70 None => *self = None,
71 Some(src) => match self {
72 None => *self = Some(src.try_clone()?),
73 Some(dest) => dest.try_clone_from(src)?,
74 },
75 }
76 Ok(())
77 }
78}
79
80impl TryClone for String {
81 #[inline]
82 fn try_clone(&self) -> Result<Self, AllocError> {
83 let mut s = String::new();
84 s.try_reserve(s.len())?;
85 s.push_str(self);
86 Ok(s)
87 }
88
89 #[inline]
90 fn try_clone_from(&mut self, source: &Self) -> Result<(), AllocError> {
91 self.clear();
92 self.try_reserve(source.len())?;
93 self.push_str(source);
94 Ok(())
95 }
96}
97
98impl<T: ?Sized> TryClone for Arc<T> {
99 #[inline]
100 fn try_clone(&self) -> Result<Self, AllocError> {
101 Ok(self.clone())
102 }
103}
104
105impl<T: ?Sized> TryClone for Weak<T> {
106 #[inline]
107 fn try_clone(&self) -> Result<Self, AllocError> {
108 Ok(self.clone())
109 }
110}
111
112#[cfg(nightly)]
113mod nightly {
114 use crate::TryClone;
115 use fallacy_alloc::AllocError;
116 use std::alloc::{Allocator, Global, Layout};
117
118 impl TryClone for Global {
119 #[inline(always)]
120 fn try_clone(&self) -> Result<Self, AllocError> {
121 Ok(Global)
122 }
123 }
124
125 impl<T: TryClone, A: Allocator + TryClone> TryClone for Box<T, A> {
126 #[inline]
127 fn try_clone(&self) -> Result<Self, AllocError> {
128 let alloc = Box::allocator(self).try_clone()?;
129 let t = self.as_ref().try_clone()?;
130 let b = Box::try_new_in(t, alloc).map_err(|_| AllocError::new(Layout::new::<T>()))?;
131 Ok(b)
132 }
133 }
134}