1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
use crate::boxed::ABox;
use crate::fat::{Alloc, Free};
use crate::meta::ZstSupported;
use core::ffi::CStr;
#[cfg(global_oom_handling)] impl<T: Clone, A: Alloc + Free + Clone> Clone for ABox<T, A> {
/// Allocate a new box that clones the contents of `self` using `self.allocator().clone()`
///
/// ## Failure Modes
/// * [`panic!`]s or [`handle_alloc_error`](alloc::alloc::handle_alloc_error)s when out of memory
fn clone(&self) -> Self {
//let _ = Self::ASSERT_A_CAN_ALLOC_T; // implied by `self`
Self::new_in(T::clone(self), Self::allocator(self).clone())
}
/// Clone the contents of `source` into `self` without reallocating the [`ABox`].
fn clone_from(&mut self, source: &Self) {
//let _ = Self::ASSERT_A_CAN_ALLOC_T; // implied by `self`
T::clone_from(self, source)
}
}
#[cfg(global_oom_handling)] impl<T: Clone,A: Alloc + Free + Clone + ZstSupported> Clone for ABox<[T], A> { fn clone(&self) -> Self { Self::try_from_clone_slice_in(self, Self::allocator(self).clone()).unwrap() } } // TODO: clone_from for same-sized slices?
#[cfg(global_oom_handling)] impl< A: Alloc + Free + Clone + ZstSupported> Clone for ABox<str, A> { fn clone(&self) -> Self { Self::try_from_str_in( self, Self::allocator(self).clone()).unwrap() } } // TODO: clone_from for same-sized strs?
#[cfg(global_oom_handling)] impl< A: Alloc + Free + Clone + ZstSupported> Clone for ABox<CStr, A> { fn clone(&self) -> Self { Self::try_from_cstr_in( self, Self::allocator(self).clone()).unwrap() } } // TODO: clone_from for same-sized CStrs?
#[cfg(feature = "std")] #[cfg(global_oom_handling)] impl<A: Alloc + Free + Clone + ZstSupported> Clone for ABox<std::ffi::OsStr, A> { fn clone(&self) -> Self { Self::try_from_osstr_in(self, Self::allocator(self).clone()).unwrap() } } // TODO: clone_from for same-sized OsStrs?
#[cfg(feature = "std")] #[cfg(global_oom_handling)] impl<A: Alloc + Free + Clone + ZstSupported> Clone for ABox<std::path::Path, A> { fn clone(&self) -> Self { Self::try_from_path_in( self, Self::allocator(self).clone()).unwrap() } } // TODO: clone_from for same-sized Paths?
/// Non-panicing alternatives to [`Clone`] / support for alternative allocators.
impl<T: Clone, A: Free> ABox<T, A> {
/// Clone the contents of `source` into `self` without reallocating the [`ABox`].
///
/// ## Examples
/// ```
/// use ialloc::{allocator::{c::Malloc, debug::Null}, boxed::ABox};
/// let mut a = ABox::new_in('a', Malloc);
/// let b = ABox::new_in('b', Malloc);
/// ABox::clone_from(&mut a, &b);
/// assert_eq!(*a, 'b');
/// ```
pub fn clone_from(this: &mut Self, source: &ABox<T, impl Free>) {
//let _ = Self::ASSERT_A_CAN_ALLOC_T; // implied by `self`
T::clone_from(this, source)
}
/// Allocate a new box that clones the contents of `self` using `A::default()`.
///
/// ## Failure Modes
/// * Returns <code>[Err]\(...\)</code> when out of memory
///
/// ## Examples
/// ```
/// use ialloc::{allocator::c::Malloc, boxed::ABox};
/// let a = ABox::new_in('a', Malloc);
/// let b = ABox::try_clone(&a).unwrap();
/// assert_eq!(*b, 'a');
/// ```
// TODO: show failure example via allocator with strict memory limits
pub fn try_clone(this: &Self) -> Result<ABox<T, A>, A::Error> where A : Alloc + Clone {
//let _ = Self::ASSERT_A_CAN_ALLOC_T; // implied by `this`
ABox::try_new_in(T::clone(this), Self::allocator(this).clone())
}
/// Allocate a new box that clones the contents of `self` using `allocator`.
///
/// ## Failure Modes
/// * Fails to compile on impossible alignments (e.g. attempting to allocate 4 KiB alignment pages via 8/16 byte aligned malloc)
/// * Returns <code>[Err]\(...\)</code> when out of memory
///
/// ## Examples
/// ```
/// use ialloc::{allocator::{alloc::Global, c::Malloc, debug::Null}, boxed::ABox};
/// let a = ABox::new_in('a', Malloc);
/// let b = ABox::try_clone_in(&a, Malloc).unwrap();
/// assert_eq!(*b, 'a');
/// ```
///
/// ```
/// // will return Err(...) - Null can't allocate anything
/// # use ialloc::{allocator::{alloc::Global, c::Malloc, debug::Null}, boxed::ABox};
/// # let a = ABox::new_in('a', Malloc);
/// let err = ABox::try_clone_in(&a, Null).unwrap_err();
/// ```
///
/// ```compile_fail,E0080
/// # use ialloc::{allocator::{alloc::Global, c::Malloc, debug::Null}, boxed::ABox};
/// #[derive(Clone)] #[repr(C, align(4096))] pub struct Page([u8; 4096]);
/// let a = ABox::new_in(Page([0u8; 4096]), Global);
///
/// // won't compile - requires too much alignment for Malloc
/// let b = ABox::try_clone_in(&a, Malloc);
/// ```
pub fn try_clone_in<A2>(this: &Self, allocator: A2) -> Result<ABox<T, A2>, A2::Error> where A2 : Alloc + Free {
let _ = ABox::<T, A2>::ASSERT_A_CAN_ALLOC_T;
ABox::try_new_in(T::clone(this), allocator)
}
/// Allocate a new box that clones the contents of `self` using `allocator`.
///
/// ## Failure Modes
/// * Fails to compile on impossible alignments (e.g. attempting to allocate 4 KiB alignment pages via 8/16 byte aligned malloc)
/// * [`panic!`]s or [`handle_alloc_error`](alloc::alloc::handle_alloc_error)s when out of memory
///
/// ## Examples
/// ```
/// use ialloc::{allocator::{alloc::Global, c::Malloc, debug::Null}, boxed::ABox};
/// let a = ABox::new_in('a', Malloc);
/// let b = ABox::clone_in(&a, Malloc);
/// assert_eq!(*b, 'a');
/// ```
///
/// ```should_panic
/// // will panic - Null can't allocate anything
/// # use ialloc::{allocator::{alloc::Global, c::Malloc, debug::Null}, boxed::ABox};
/// # let a = ABox::new_in('a', Malloc);
/// let b = ABox::clone_in(&a, Null);
/// ```
///
/// ```compile_fail,E0080
/// # use ialloc::{allocator::{alloc::Global, c::Malloc, debug::Null}, boxed::ABox};
/// #[derive(Clone)] #[repr(C, align(4096))] pub struct Page([u8; 4096]);
/// let a = ABox::new_in(Page([0u8; 4096]), Global);
///
/// // won't compile - requires too much alignment for Malloc
/// let b = ABox::clone_in(&a, Malloc);
/// ```
#[cfg(global_oom_handling)] pub fn clone_in<A2>(this: &Self, allocator: A2) -> ABox<T, A2> where A2 : Alloc + Free {
let _ = ABox::<T, A2>::ASSERT_A_CAN_ALLOC_T;
ABox::new_in(T::clone(this), allocator)
}
}