1use std::{
2 alloc::Layout,
3 cell::Cell,
4 hash::{BuildHasher, Hash},
5 ptr::NonNull,
6 slice,
7};
8
9use crate::{Allocator, Box, HashMap, Vec};
10
11pub trait CloneIn<'new_alloc>: Sized {
32 type Cloned;
36
37 fn clone_in(&self, allocator: &'new_alloc Allocator) -> Self::Cloned;
40
41 #[inline]
44 fn clone_in_with_semantic_ids(&self, allocator: &'new_alloc Allocator) -> Self::Cloned {
45 self.clone_in(allocator)
46 }
47}
48
49impl<'alloc, T, C> CloneIn<'alloc> for Option<T>
50where
51 T: CloneIn<'alloc, Cloned = C>,
52{
53 type Cloned = Option<C>;
54
55 fn clone_in(&self, allocator: &'alloc Allocator) -> Self::Cloned {
56 self.as_ref().map(|it| it.clone_in(allocator))
57 }
58
59 fn clone_in_with_semantic_ids(&self, allocator: &'alloc Allocator) -> Self::Cloned {
60 self.as_ref().map(|it| it.clone_in_with_semantic_ids(allocator))
61 }
62}
63
64impl<'new_alloc, T, C> CloneIn<'new_alloc> for Box<'_, T>
65where
66 T: CloneIn<'new_alloc, Cloned = C>,
67{
68 type Cloned = Box<'new_alloc, C>;
69
70 fn clone_in(&self, allocator: &'new_alloc Allocator) -> Self::Cloned {
71 Box::new_in(self.as_ref().clone_in(allocator), allocator)
72 }
73
74 fn clone_in_with_semantic_ids(&self, allocator: &'new_alloc Allocator) -> Self::Cloned {
75 Box::new_in(self.as_ref().clone_in_with_semantic_ids(allocator), allocator)
76 }
77}
78
79impl<'new_alloc, T, C> CloneIn<'new_alloc> for Box<'_, [T]>
80where
81 T: CloneIn<'new_alloc, Cloned = C>,
82{
83 type Cloned = Box<'new_alloc, [C]>;
84
85 fn clone_in(&self, allocator: &'new_alloc Allocator) -> Self::Cloned {
86 let slice = self.as_ref();
87
88 const {
93 assert!(
94 size_of::<C>() == size_of::<T>() && align_of::<C>() == align_of::<T>(),
95 "Size and alignment of `T` and `<T as CloneIn>::Cloned` must be the same"
96 );
97 }
98 let layout = Layout::for_value(slice);
99
100 let dst_ptr = allocator.alloc_layout(layout).cast::<C>();
101
102 unsafe {
107 let mut ptr = dst_ptr;
108 for item in slice {
109 ptr.write(item.clone_in(allocator));
110 ptr = ptr.add(1);
111 }
112 }
113
114 let new_slice = unsafe { slice::from_raw_parts_mut(dst_ptr.as_ptr(), slice.len()) };
116 unsafe { Box::from_non_null(NonNull::from(new_slice)) }
119 }
120
121 fn clone_in_with_semantic_ids(&self, allocator: &'new_alloc Allocator) -> Self::Cloned {
122 let slice = self.as_ref();
123
124 const {
129 assert!(
130 size_of::<C>() == size_of::<T>() && align_of::<C>() == align_of::<T>(),
131 "Size and alignment of `T` and `<T as CloneIn>::Cloned` must be the same"
132 );
133 }
134 let layout = Layout::for_value(slice);
135
136 let dst_ptr = allocator.alloc_layout(layout).cast::<C>();
137
138 unsafe {
143 let mut ptr = dst_ptr;
144 for item in slice {
145 ptr.write(item.clone_in_with_semantic_ids(allocator));
146 ptr = ptr.add(1);
147 }
148 }
149
150 let new_slice = unsafe { slice::from_raw_parts_mut(dst_ptr.as_ptr(), slice.len()) };
152 unsafe { Box::from_non_null(NonNull::from(new_slice)) }
155 }
156}
157
158impl<'new_alloc, T, C> CloneIn<'new_alloc> for Vec<'_, T>
159where
160 T: CloneIn<'new_alloc, Cloned = C>,
161 C: 'new_alloc,
164{
165 type Cloned = Vec<'new_alloc, C>;
166
167 fn clone_in(&self, allocator: &'new_alloc Allocator) -> Self::Cloned {
168 let slice = self.as_slice();
175
176 let mut vec = Vec::<C>::with_capacity_in(slice.len(), allocator);
177
178 unsafe {
183 let mut ptr = vec.as_mut_ptr();
184 for item in slice {
185 ptr.write(item.clone_in(allocator));
186 ptr = ptr.add(1);
187 }
188 vec.set_len(slice.len());
189 }
190
191 vec
192 }
193
194 fn clone_in_with_semantic_ids(&self, allocator: &'new_alloc Allocator) -> Self::Cloned {
195 let slice = self.as_slice();
196
197 let mut vec = Vec::<C>::with_capacity_in(slice.len(), allocator);
198
199 unsafe {
204 let mut ptr = vec.as_mut_ptr();
205 for item in slice {
206 ptr.write(item.clone_in_with_semantic_ids(allocator));
207 ptr = ptr.add(1);
208 }
209 vec.set_len(slice.len());
210 }
211
212 vec
213 }
214}
215
216impl<'new_alloc, K, V, CK, CV, S> CloneIn<'new_alloc> for HashMap<'_, K, V, S>
217where
218 K: CloneIn<'new_alloc, Cloned = CK>,
219 V: CloneIn<'new_alloc, Cloned = CV>,
220 CK: Hash + Eq,
221 S: Default + BuildHasher,
222{
223 type Cloned = HashMap<'new_alloc, CK, CV, S>;
224
225 fn clone_in(&self, allocator: &'new_alloc Allocator) -> Self::Cloned {
226 let mut cloned = HashMap::with_capacity_in(self.len(), allocator);
234 for (key, value) in self {
235 cloned.insert(key.clone_in(allocator), value.clone_in(allocator));
236 }
237 cloned
238 }
239
240 fn clone_in_with_semantic_ids(&self, allocator: &'new_alloc Allocator) -> Self::Cloned {
241 let mut cloned = HashMap::with_capacity_in(self.len(), allocator);
242 for (key, value) in self {
243 cloned.insert(
244 key.clone_in_with_semantic_ids(allocator),
245 value.clone_in_with_semantic_ids(allocator),
246 );
247 }
248 cloned
249 }
250}
251
252impl<'alloc, T: Copy> CloneIn<'alloc> for Cell<T> {
253 type Cloned = Cell<T>;
254
255 fn clone_in(&self, _: &'alloc Allocator) -> Self::Cloned {
256 Cell::new(self.get())
257 }
258}
259
260impl<'new_alloc> CloneIn<'new_alloc> for &str {
261 type Cloned = &'new_alloc str;
262
263 fn clone_in(&self, allocator: &'new_alloc Allocator) -> Self::Cloned {
264 allocator.alloc_str(self)
265 }
266}
267
268macro_rules! impl_clone_in {
269 ($($t:ty)*) => {
270 $(
271 impl<'alloc> CloneIn<'alloc> for $t {
272 type Cloned = Self;
273 #[inline(always)]
274 fn clone_in(&self, _: &'alloc Allocator) -> Self {
275 *self
276 }
277 }
278 )*
279 }
280}
281
282impl_clone_in! {
283 usize u8 u16 u32 u64 u128
284 isize i8 i16 i32 i64 i128
285 f32 f64
286 bool char
287}
288
289#[cfg(test)]
290mod test {
291 use super::{Allocator, CloneIn, HashMap, Vec};
292
293 #[test]
294 fn clone_in_boxed_slice() {
295 let allocator = Allocator::default();
296
297 let mut original = Vec::from_iter_in([1, 2, 3], &allocator).into_boxed_slice();
298
299 let cloned = original.clone_in(&allocator);
300 let cloned2 = original.clone_in_with_semantic_ids(&allocator);
301 original[1] = 4;
302
303 assert_eq!(original.as_ref(), &[1, 4, 3]);
304 assert_eq!(cloned.as_ref(), &[1, 2, 3]);
305 assert_eq!(cloned2.as_ref(), &[1, 2, 3]);
306 }
307
308 #[test]
309 fn clone_in_vec() {
310 let allocator = Allocator::default();
311
312 let mut original = Vec::with_capacity_in(8, &allocator);
313 original.extend_from_slice(&[1, 2, 3]);
314
315 let cloned = original.clone_in(&allocator);
316 let cloned2 = original.clone_in_with_semantic_ids(&allocator);
317 original[1] = 4;
318
319 assert_eq!(original.as_slice(), &[1, 4, 3]);
320 assert_eq!(cloned.as_slice(), &[1, 2, 3]);
321 assert_eq!(cloned.capacity(), 3);
322 assert_eq!(cloned2.as_slice(), &[1, 2, 3]);
323 assert_eq!(cloned2.capacity(), 3);
324 }
325
326 #[test]
327 fn clone_in_hash_map() {
328 let allocator = Allocator::default();
329
330 let mut original: HashMap<'_, &str, &str> = HashMap::with_capacity_in(8, &allocator);
331 original.extend(&[("x", "xx"), ("y", "yy"), ("z", "zz")]);
332
333 let cloned = original.clone_in(&allocator);
334 let cloned2 = original.clone_in_with_semantic_ids(&allocator);
335 *original.get_mut("y").unwrap() = "changed";
336
337 let mut original_as_vec = original.iter().collect::<std::vec::Vec<_>>();
338 original_as_vec.sort_unstable();
339 assert_eq!(original_as_vec, &[(&"x", &"xx"), (&"y", &"changed"), (&"z", &"zz")]);
340
341 assert_eq!(cloned.capacity(), 3);
342 let mut cloned_as_vec = cloned.iter().collect::<std::vec::Vec<_>>();
343 cloned_as_vec.sort_unstable();
344 assert_eq!(cloned_as_vec, &[(&"x", &"xx"), (&"y", &"yy"), (&"z", &"zz")]);
345
346 assert_eq!(cloned2.capacity(), 3);
347 let mut cloned2_as_vec = cloned2.iter().collect::<std::vec::Vec<_>>();
348 cloned2_as_vec.sort_unstable();
349 assert_eq!(cloned2_as_vec, &[(&"x", &"xx"), (&"y", &"yy"), (&"z", &"zz")]);
350 }
351}