1use alloc::alloc::Layout;
2use alloc::boxed::Box;
3use alloc::string::String;
4use alloc::vec::Vec;
5use core::cmp::Ordering;
6use core::iter::{ExactSizeIterator, Iterator};
7use core::marker::PhantomData;
8use core::mem::{self, ManuallyDrop};
9use core::ptr::{self, addr_of_mut};
10
11use super::{Arc, ArcInner};
12
13#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash, PartialOrd, Ord)]
16#[repr(C)]
17pub struct HeaderSlice<H, T: ?Sized> {
18 pub header: H,
20
21 pub slice: T,
23}
24
25impl<H, T> Arc<HeaderSlice<H, [T]>> {
26 pub fn from_header_and_iter<I>(header: H, mut items: I) -> Self
29 where
30 I: Iterator<Item = T> + ExactSizeIterator,
31 {
32 assert_ne!(mem::size_of::<T>(), 0, "Need to think about ZST");
33
34 let num_items = items.len();
35
36 let inner = Arc::allocate_for_header_and_slice(num_items);
37
38 unsafe {
39 ptr::write(&mut ((*inner.as_ptr()).data.header), header);
44 let mut current = (*inner.as_ptr()).data.slice.as_mut_ptr();
45 for _ in 0..num_items {
46 ptr::write(
47 current,
48 items
49 .next()
50 .expect("ExactSizeIterator over-reported length"),
51 );
52 current = current.offset(1);
53 }
54 assert!(
55 items.next().is_none(),
56 "ExactSizeIterator under-reported length"
57 );
58 }
59
60 Arc {
62 p: inner,
63 phantom: PhantomData,
64 }
65 }
66
67 pub fn from_header_and_slice(header: H, items: &[T]) -> Self
70 where
71 T: Copy,
72 {
73 assert_ne!(mem::size_of::<T>(), 0, "Need to think about ZST");
74
75 let num_items = items.len();
76
77 let inner = Arc::allocate_for_header_and_slice(num_items);
78
79 unsafe {
80 ptr::write(&mut ((*inner.as_ptr()).data.header), header);
82 let dst = (*inner.as_ptr()).data.slice.as_mut_ptr();
83 ptr::copy_nonoverlapping(items.as_ptr(), dst, num_items);
84 }
85
86 Arc {
88 p: inner,
89 phantom: PhantomData,
90 }
91 }
92
93 pub fn from_header_and_vec(header: H, mut v: Vec<T>) -> Self {
96 let len = v.len();
97
98 let inner = Arc::allocate_for_header_and_slice(len);
99
100 unsafe {
101 let dst = addr_of_mut!((*inner.as_ptr()).data.header);
103
104 ptr::write(dst, header);
106 }
107
108 unsafe {
109 let src = v.as_mut_ptr();
110
111 let dst = addr_of_mut!((*inner.as_ptr()).data.slice) as *mut T;
113
114 ptr::copy_nonoverlapping(src, dst, len);
119
120 v.set_len(0);
124 }
125
126 Arc {
128 p: inner,
129 phantom: PhantomData,
130 }
131 }
132}
133
134impl<H> Arc<HeaderSlice<H, str>> {
135 pub fn from_header_and_str(header: H, string: &str) -> Self {
138 let bytes = Arc::from_header_and_slice(header, string.as_bytes());
139
140 unsafe { Arc::from_raw_inner(Arc::into_raw_inner(bytes) as _) }
145 }
146}
147
148#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)]
151#[repr(C)]
152pub struct HeaderWithLength<H> {
153 pub header: H,
155
156 pub length: usize,
158}
159
160impl<H> HeaderWithLength<H> {
161 #[inline]
163 pub fn new(header: H, length: usize) -> Self {
164 HeaderWithLength { header, length }
165 }
166}
167
168impl<T: ?Sized> From<Arc<HeaderSlice<(), T>>> for Arc<T> {
169 fn from(this: Arc<HeaderSlice<(), T>>) -> Self {
170 debug_assert_eq!(
171 Layout::for_value::<HeaderSlice<(), T>>(&this),
172 Layout::for_value::<T>(&this.slice)
173 );
174
175 unsafe { Arc::from_raw_inner(Arc::into_raw_inner(this) as _) }
177 }
178}
179
180impl<T: ?Sized> From<Arc<T>> for Arc<HeaderSlice<(), T>> {
181 fn from(this: Arc<T>) -> Self {
182 unsafe { Arc::from_raw_inner(Arc::into_raw_inner(this) as _) }
184 }
185}
186
187impl<T: Copy> From<&[T]> for Arc<[T]> {
188 fn from(slice: &[T]) -> Self {
189 Arc::from_header_and_slice((), slice).into()
190 }
191}
192
193impl From<&str> for Arc<str> {
194 fn from(s: &str) -> Self {
195 Arc::from_header_and_str((), s).into()
196 }
197}
198
199impl From<String> for Arc<str> {
200 fn from(s: String) -> Self {
201 Self::from(&s[..])
202 }
203}
204
205impl<T> From<Box<T>> for Arc<T> {
209 fn from(b: Box<T>) -> Self {
210 let layout = Layout::for_value::<T>(&b);
211
212 let inner = unsafe { Self::allocate_for_layout(layout, |mem| mem as *mut ArcInner<T>) };
214
215 unsafe {
216 let src = Box::into_raw(b);
217
218 let dst = addr_of_mut!((*inner.as_ptr()).data);
220
221 ptr::copy_nonoverlapping(src, dst, 1);
226
227 drop(Box::<ManuallyDrop<T>>::from_raw(src as _));
233 }
234
235 Arc {
236 p: inner,
237 phantom: PhantomData,
238 }
239 }
240}
241
242impl<T> From<Vec<T>> for Arc<[T]> {
243 fn from(v: Vec<T>) -> Self {
244 Arc::from_header_and_vec((), v).into()
245 }
246}
247
248#[derive(Debug, Hash, Eq, PartialEq, Ord, PartialOrd)]
257#[repr(transparent)]
258pub struct HeaderSliceWithLengthProtected<H, T> {
259 inner: HeaderSliceWithLengthUnchecked<H, T>,
261}
262
263pub(crate) type HeaderSliceWithLengthUnchecked<H, T> = HeaderSlice<HeaderWithLength<H>, [T]>;
264
265impl<H, T> HeaderSliceWithLengthProtected<H, T> {
266 pub fn header(&self) -> &H {
267 &self.inner.header.header
268 }
269 pub fn header_mut(&mut self) -> &mut H {
270 &mut self.inner.header.header
272 }
273 pub fn length(&self) -> usize {
274 self.inner.header.length
275 }
276
277 pub fn slice(&self) -> &[T] {
278 &self.inner.slice
279 }
280 pub fn slice_mut(&mut self) -> &mut [T] {
281 &mut self.inner.slice
283 }
284 pub(crate) fn inner(&self) -> &HeaderSliceWithLengthUnchecked<H, T> {
285 &self.inner
287 }
288}
289
290impl<H: PartialOrd, T: ?Sized + PartialOrd> PartialOrd for HeaderSlice<HeaderWithLength<H>, T> {
291 fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
292 (&self.header.header, &self.slice).partial_cmp(&(&other.header.header, &other.slice))
293 }
294}
295
296impl<H: Ord, T: ?Sized + Ord> Ord for HeaderSlice<HeaderWithLength<H>, T> {
297 fn cmp(&self, other: &Self) -> Ordering {
298 (&self.header.header, &self.slice).cmp(&(&other.header.header, &other.slice))
299 }
300}
301
302#[cfg(test)]
303mod tests {
304 use alloc::boxed::Box;
305 use alloc::string::String;
306 use alloc::vec;
307 use core::iter;
308
309 use crate::{Arc, HeaderSlice};
310
311 #[test]
312 fn from_header_and_iter_smoke() {
313 let arc = Arc::from_header_and_iter(
314 (42u32, 17u8),
315 IntoIterator::into_iter([1u16, 2, 3, 4, 5, 6, 7]),
316 );
317
318 assert_eq!(arc.header, (42, 17));
319 assert_eq!(arc.slice, [1, 2, 3, 4, 5, 6, 7]);
320 }
321
322 #[test]
323 fn from_header_and_slice_smoke() {
324 let arc = Arc::from_header_and_slice((42u32, 17u8), &[1u16, 2, 3, 4, 5, 6, 7]);
325
326 assert_eq!(arc.header, (42, 17));
327 assert_eq!(arc.slice, [1u16, 2, 3, 4, 5, 6, 7]);
328 }
329
330 #[test]
331 fn from_header_and_vec_smoke() {
332 let arc = Arc::from_header_and_vec((42u32, 17u8), vec![1u16, 2, 3, 4, 5, 6, 7]);
333
334 assert_eq!(arc.header, (42, 17));
335 assert_eq!(arc.slice, [1u16, 2, 3, 4, 5, 6, 7]);
336 }
337
338 #[test]
339 fn from_header_and_iter_empty() {
340 let arc = Arc::from_header_and_iter((42u32, 17u8), iter::empty::<u16>());
341
342 assert_eq!(arc.header, (42, 17));
343 assert_eq!(arc.slice, []);
344 }
345
346 #[test]
347 fn from_header_and_slice_empty() {
348 let arc = Arc::from_header_and_slice((42u32, 17u8), &[1u16; 0]);
349
350 assert_eq!(arc.header, (42, 17));
351 assert_eq!(arc.slice, []);
352 }
353
354 #[test]
355 fn from_header_and_vec_empty() {
356 let arc = Arc::from_header_and_vec((42u32, 17u8), vec![1u16; 0]);
357
358 assert_eq!(arc.header, (42, 17));
359 assert_eq!(arc.slice, []);
360 }
361
362 #[test]
363 fn issue_13_empty() {
364 crate::Arc::from_header_and_iter((), iter::empty::<usize>());
365 }
366
367 #[test]
368 fn issue_13_consumption() {
369 let s: &[u8] = &[0u8; 255];
370 crate::Arc::from_header_and_iter((), s.iter().copied());
371 }
372
373 #[test]
374 fn from_header_and_str_smoke() {
375 let a = Arc::from_header_and_str(
376 42,
377 "The answer to the ultimate question of life, the universe, and everything",
378 );
379 assert_eq!(a.header, 42);
380 assert_eq!(
381 &a.slice,
382 "The answer to the ultimate question of life, the universe, and everything"
383 );
384
385 let empty = Arc::from_header_and_str((), "");
386 assert_eq!(&empty.slice, "");
387 }
388
389 #[test]
390 fn erase_and_create_from_thin_air_header() {
391 let a: Arc<HeaderSlice<(), [u32]>> = Arc::from_header_and_slice((), &[12, 17, 16]);
392 let b: Arc<[u32]> = a.into();
393
394 assert_eq!(&*b, [12, 17, 16]);
395
396 let c: Arc<HeaderSlice<(), [u32]>> = b.into();
397
398 assert_eq!(&c.slice, [12, 17, 16]);
399 }
400
401 #[test]
402 fn from_box_and_vec() {
403 let b = Box::new(String::from("xxx"));
404 let b = Arc::<String>::from(b);
405 assert_eq!(&*b, "xxx");
406
407 let v = vec![String::from("1"), String::from("2"), String::from("3")];
408 let v = Arc::<[_]>::from(v);
409 assert_eq!(
410 &*v,
411 [String::from("1"), String::from("2"), String::from("3")]
412 );
413
414 let mut v = vec![String::from("1"), String::from("2"), String::from("3")];
415 v.reserve(10);
416 let v = Arc::<[_]>::from(v);
417 assert_eq!(
418 &*v,
419 [String::from("1"), String::from("2"), String::from("3")]
420 );
421 }
422
423 #[test]
428 fn dst_and_make_mut() {
429 struct MyArc<T: ?Sized>(Arc<HeaderSlice<MyHeader, T>>);
430
431 #[derive(Clone)]
432 struct MyHeader {
433 }
435
436 let dst: MyArc<str> = MyArc(Arc::from_header_and_str(MyHeader {}, "example"));
438 assert_eq!(&dst.0.slice, "example");
439
440 let mut answer: MyArc<u32> = MyArc(Arc::new(HeaderSlice {
442 header: MyHeader {},
443 slice: 6 * 9,
447 }));
448 let mut_ref = Arc::make_mut(&mut answer.0);
449 mut_ref.slice = 42;
450 }
451}