heap_array/lib.rs
1#![cfg_attr(feature = "allocator-api", feature(allocator_api))]
2#![cfg_attr(feature = "dropck", feature(dropck_eyepatch))]
3
4#![warn(missing_docs)]
5#![no_std]
6
7//! # HeapArray
8//! An Implementation of a variable length array, with its main benefit over [`Vec`] is taking up less space
9//! as [`HeapArray`] is represented as (pointer, len) while [`Vec`] is a (pointer, len, capacity)
10//! and is meant as a replacement for `Box<[T]>`
11//!
12//! nice to have: compatible with serde
13//!
14//! # Examples
15//! ```
16//! use heap_array::{heap_array, HeapArray};
17//! let arr = heap_array![1, 2, 5, 8];
18//!
19//! assert_eq!(arr[0], 1);
20//! assert_eq!(arr[1], 2);
21//! assert_eq!(arr[2], 5);
22//! assert_eq!(arr[3], 8);
23//! assert_eq!(arr.len(), 4);
24//!
25//! let arr = HeapArray::from_fn(10, |i| i);
26//! assert_eq!(*arr, [0, 1, 2, 3, 4, 5, 6, 7, 8, 9])
27//! ```
28//!
29//! [`Vec`]: Vec
30//! [`HeapArray`]: HeapArray
31
32mod try_me;
33mod guard;
34
35#[cfg(feature = "serde")]
36extern crate serde;
37extern crate alloc;
38
39use core::{
40 ptr::{self, NonNull},
41 fmt::{Debug, Formatter},
42 mem::{self, ManuallyDrop, MaybeUninit},
43 ops::{Deref, DerefMut, ControlFlow},
44 cmp::Ordering,
45 slice::{Iter, IterMut},
46 marker::PhantomData,
47 panic::{RefUnwindSafe, UnwindSafe},
48 alloc::Layout,
49 fmt
50};
51
52use alloc::{
53 boxed::Box,
54 vec::Vec,
55 alloc::{handle_alloc_error},
56 vec::IntoIter,
57 vec
58};
59
60#[cfg(feature = "allocator-api")]
61use alloc::alloc::{Allocator, Global};
62use core::slice::SliceIndex;
63use core::ops::{Index, IndexMut};
64use core::hash::{Hash, Hasher};
65use likely_stable::unlikely;
66use crate::guard::Guard;
67use crate::try_me::{NeverShortCircuit, Try};
68
69/// # HeapArray
70/// An Implementation of a variable length array, with its main benefit over [`Vec`] is taking up less space
71/// as [`HeapArray`] is represented as (pointer, len) while [`Vec`] is a (pointer, len, capacity)
72/// and is meant as a replacement for `Box<[T]>`
73///
74/// nice to have: compatible with serde
75///
76/// # Examples
77/// ```
78/// use heap_array::{heap_array, HeapArray};
79/// let arr = heap_array![1, 2, 5, 8];
80///
81/// assert_eq!(arr[0], 1);
82/// assert_eq!(arr[1], 2);
83/// assert_eq!(arr[2], 5);
84/// assert_eq!(arr[3], 8);
85/// assert_eq!(arr.len(), 4);
86///
87/// let arr = HeapArray::from_fn(10, |i| i);
88/// assert_eq!(*arr, [0, 1, 2, 3, 4, 5, 6, 7, 8, 9])
89/// ```
90///
91/// [`Vec`]: Vec
92/// [`HeapArray`]: HeapArray
93
94#[cfg(not(feature = "allocator-api"))]
95pub struct HeapArray<T> {
96 ptr: NonNull<T>,
97 len: usize,
98
99 // NOTE: this marker has no consequences for variance, but is necessary
100 // for dropck to understand that we logically own a `T`.
101 //
102 // For details, see:
103 // https://github.com/rust-lang/rfcs/blob/master/text/0769-sound-generic-drop.md#phantom-data
104 __marker: PhantomData<T>
105}
106
107/// # HeapArray
108/// An Implementation of a variable length array, with its main benefit over [`Vec`] is taking up less space
109/// as [`HeapArray`] is represented as (pointer, len) while [`Vec`] is a (pointer, len, capacity)
110/// and is meant as a replacement for `Box<[T]>`
111///
112/// nice to have: compatible with serde
113///
114/// # Examples
115/// ```
116/// use heap_array::{heap_array, HeapArray};
117/// let arr = heap_array![1, 2, 5, 8];
118///
119/// assert_eq!(arr[0], 1);
120/// assert_eq!(arr[1], 2);
121/// assert_eq!(arr[2], 5);
122/// assert_eq!(arr[3], 8);
123/// assert_eq!(arr.len(), 4);
124///
125/// let arr = HeapArray::from_fn(10, |i| i);
126/// assert_eq!(*arr, [0, 1, 2, 3, 4, 5, 6, 7, 8, 9])
127/// ```
128///
129/// [`Vec`]: Vec
130/// [`HeapArray`]: HeapArray
131#[cfg(feature = "allocator-api")]
132pub struct HeapArray<T, #[cfg(feature = "allocator-api")] A: Allocator = Global> {
133 ptr: NonNull<T>,
134 len: usize,
135
136
137 // this is manually drop, so we can run the destructor for the allocation but not the [T] we own
138 #[cfg(feature = "allocator-api")]
139 alloc: ManuallyDrop<A>,
140
141 // NOTE: this marker has no consequences for variance, but is necessary
142 // for dropck to understand that we logically own a `T`.
143 //
144 // For details, see:
145 // https://github.com/rust-lang/rfcs/blob/master/text/0769-sound-generic-drop.md#phantom-data
146 __marker: PhantomData<T>
147}
148
149
150macro_rules! assume {
151 ($cond:expr $(,)?) => {
152 match cfg!(debug_assertions) {
153 true => assert!($cond, "bad assumption"),
154 false => if !$cond { core::hint::unreachable_unchecked() },
155 }
156 };
157}
158
159pub(crate) use assume;
160
161
162macro_rules! try_from_fn_impl {
163 ($T: ty, $R: ty, $len:expr, $f: expr $(, $alloc:ident)?) => {{
164 let len = $len;
165
166 if mem::size_of::<$T>() == 0 {
167 for i in 0..len {
168 // Safety: this loop runs from 0..len
169 unsafe { assume!(i < len) }
170 if let ControlFlow::Break(r) = $f(i).branch() {
171 return <$R>::from_residual(r)
172 }
173 }
174
175 let ret = 'scope: {
176 #[cfg(feature = "allocator-api")]
177 break 'scope (unsafe { Self::from_raw_parts_in(NonNull::dangling(), len, $($alloc)?) });
178
179 #[cfg(not(feature = "allocator-api"))]
180 break 'scope (unsafe { Self::from_raw_parts(NonNull::dangling(), len) });
181 };
182
183 return <$R>::from_element(ret);
184 }
185
186
187 let ptr: NonNull<MaybeUninit<$T>> = match alloc_uninit(len $(, &$alloc)?) {
188 Some(ptr) => ptr,
189 None => {
190 #[cfg(feature = "allocator-api")]
191 return <$R>::from_element(Self::new_in($($alloc)?));
192
193 #[cfg(not(feature = "allocator-api"))]
194 return <$R>::from_element(Self::new());
195 },
196 };
197
198 // We use Guard to avoid memory leak in panic's
199 let mut guard = Guard {
200 ptr,
201 len,
202 $(alloc: $alloc,)?
203 initialized: 0
204 };
205 for i in 0..len {
206 // Safety: this loop runs from 0..len
207 unsafe { assume!(i < len) }
208 match $f(i).branch() {
209 ControlFlow::Continue(output) => unsafe { guard.push_unchecked(output) }
210 ControlFlow::Break(r) => { return <$R>::from_residual(r) }
211 }
212 }
213
214 // SAFETY: All elements are initialized
215 <$R>::from_element(unsafe { guard.into_heap_array_unchecked() })
216 }};
217}
218
219macro_rules! from_array_impl {
220 ($T:ty, $array:ident, $N:ident $(, $alloc:ident)?) => {{
221 if mem::size_of::<$T>() == 0 {
222 #[cfg(feature = "allocator-api")]
223 return unsafe { Self::from_raw_parts_in(NonNull::dangling(), $N, $($alloc)?) };
224
225 #[cfg(not(feature = "allocator-api"))]
226 return unsafe { Self::from_raw_parts(NonNull::dangling(), $N) };
227 }
228
229 let ptr: NonNull<MaybeUninit<$T>> = match alloc_uninit($N $(, &$alloc)?) {
230 Some(ptr) => ptr,
231 None => {
232 #[cfg(feature = "allocator-api")]
233 return Self::new_in($($alloc)?);
234
235 #[cfg(not(feature = "allocator-api"))]
236 return Self::new();
237 }
238 };
239
240 let array = ManuallyDrop::new($array);
241 unsafe { ptr::copy_nonoverlapping(array.as_ptr(), ptr.as_ptr() as *mut $T, $N) }
242
243 #[cfg(feature = "allocator-api")]
244 return unsafe { Self::from_raw_parts_in(ptr.cast(), $N, $($alloc)?) };
245
246 #[cfg(not(feature = "allocator-api"))]
247 return unsafe { Self::from_raw_parts(ptr.cast(), $N) };
248 }};
249}
250
251macro_rules! impl_heap_array_inner {
252 // base case for recursion
253 () => {};
254
255 ($(#[$($meta_data:tt)*])* both $item:item $($rest:tt)*) => {
256 $(#[$($meta_data)*])*
257 $item
258
259 impl_heap_array_inner! {$($rest)*}
260 };
261
262 ($(#[$($meta_data:tt)*])* allocator-api $item:item $($rest:tt)*) => {
263 #[cfg(feature = "allocator-api")]
264 $(#[$($meta_data)*])*
265 $item
266
267 impl_heap_array_inner! {$($rest)*}
268 };
269 ($(#[$($meta_data:tt)*])* not(allocator-api) $item:item $($rest:tt)*) => {
270 #[cfg(not(feature = "allocator-api"))]
271 $(#[$($meta_data)*])*
272 $item
273
274
275 impl_heap_array_inner! {$($rest)*}
276 };
277}
278
279macro_rules! impl_heap_array {
280 (impl<$T:ident, Maybe<$A:ident>> HeapArray { $($rest:tt)* } ) => {
281 #[cfg(feature = "allocator-api")]
282 impl<$T, $A: Allocator> HeapArray<$T, $A> {
283 impl_heap_array_inner! {$($rest)*}
284 }
285
286 #[cfg(not(feature = "allocator-api"))]
287 impl<$T> HeapArray<$T> {
288 impl_heap_array_inner! {$($rest)*}
289 }
290 };
291}
292
293impl_heap_array! {
294 impl<T, Maybe<A>> HeapArray {
295 /// Constructs a new, empty [`HeapArray`] without allocating, but bound to an allocator.
296 /// you can get back the allocator by calling [`into_raw_parts_with_alloc`]
297 /// or get a reference to the
298 /// # Examples
299 ///
300 /// ```
301 /// use std::alloc::System;
302 /// use heap_array::HeapArray;
303 /// let vec: HeapArray<i32, System> = HeapArray::new_in(System);
304 /// ```
305 /// [`HeapArray`]: HeapArray
306 /// [`into_raw_parts_with_alloc`]: HeapArray::into_raw_parts_with_alloc
307 #[inline]
308 allocator-api pub const fn new_in(alloc: A) -> Self {
309 unsafe { Self::from_raw_parts_in(NonNull::<T>::dangling(), 0, alloc) }
310 }
311
312 /// Returns `true` if the vector contains no elements.
313 ///
314 /// # Examples
315 ///
316 /// ```
317 /// # use std::any::Any;
318 /// # use heap_array::{heap_array, HeapArray};
319 /// let av: HeapArray<&dyn Any> = HeapArray::new();
320 /// assert!(av.is_empty());
321 ///
322 /// let av = heap_array![1, 2, 3];
323 /// assert!(!av.is_empty());
324 /// ```
325 #[inline]
326 both pub const fn is_empty(&self) -> bool { self.len == 0 }
327
328 /// Returns the number of elements in the heap-array, also referred to
329 /// as its 'length'.
330 ///
331 /// # Examples
332 ///
333 /// ```
334 /// # use heap_array::heap_array;
335 /// let a = heap_array![1, 2, 3];
336 /// assert_eq!(a.len(), 3);
337 /// ```
338 #[inline]
339 both pub const fn len(&self) -> usize { self.len }
340
341 /// Returns a reference to the underlying allocator.
342 #[inline]
343 allocator-api pub fn allocator(&self) -> &A { &self.alloc }
344
345 /// Returns an unsafe mutable pointer to the heap-array's buffer, or a dangling
346 /// raw pointer valid for zero sized reads if the heap-array didn't allocate.
347 ///
348 /// The caller must ensure that the heap-array outlives the pointer this
349 /// function returns, or else it will end up pointing to garbage.
350 /// making any pointers to it invalid.
351 ///
352 /// # Examples
353 ///
354 /// ```
355 /// # use heap_array::HeapArray;
356 /// let len = 6;
357 /// let mut arr: HeapArray<u8> = HeapArray::from_element(len, 0);
358 /// let arr_ptr = arr.as_mut_ptr();
359 ///
360 /// // Change elements via raw pointer writes
361 /// for i in 0..len {
362 /// unsafe {*arr_ptr.add(i) = i as u8;}
363 /// }
364 /// assert_eq!(*arr, [0, 1, 2, 3, 4, 5]);
365 /// ```
366 #[inline(always)]
367 both pub fn as_mut_ptr(&mut self) -> *mut T {
368 // We shadow the slice method of the same name to avoid going through
369 // `deref_mut`, which creates an intermediate reference.
370 self.ptr.as_ptr()
371 }
372
373 /// Returns a raw pointer to the heap-array's buffer, or a dangling raw pointer
374 /// valid for zero sized reads if the heap-array didn't allocate.
375 ///
376 /// The caller must ensure that the heap-array outlives the pointer this
377 /// function returns, or else it will end up pointing to garbage.
378 /// Modifying the heap-array may cause it's buffer to be reallocated,
379 /// which would also make any pointers to it invalid.
380 ///
381 /// The caller must also ensure that the memory the pointer (non-transitively) points to
382 /// is never written to (except inside an `UnsafeCell`) using this pointer or any pointer
383 /// derived from it. If you need to mutate the contents of the slice, use [`as_mut_ptr`].
384 ///
385 /// # Examples
386 ///
387 /// ```
388 /// # use heap_array::heap_array;
389 /// let x = heap_array![0, 2, 4, 6, 8];
390 /// let x_ptr = x.as_ptr();
391 ///
392 /// for i in 0..x.len() {
393 /// unsafe {assert_eq!(*x_ptr.add(i), i * 2);}
394 /// }
395 /// ```
396 ///
397 /// [`as_mut_ptr`]: HeapArray::as_mut_ptr
398 #[inline(always)]
399 both pub const fn as_ptr(&self) -> *const T {
400 // We shadow the slice method of the same name to avoid going through
401 // `deref`, which creates an intermediate reference.
402 self.ptr.as_ptr()
403 }
404
405 /// Extracts a slice containing the entire array.
406 ///
407 /// Equivalent to `&s[..]`.
408 ///
409 /// # Examples
410 ///
411 /// ```
412 /// # use heap_array::heap_array;
413 /// use std::io::{self, Write};
414 /// let buffer = heap_array![1, 2, 3, 5, 8];
415 /// io::sink().write(buffer.as_slice()).unwrap();
416 /// ```
417 #[inline(always)]
418 both pub fn as_slice(&self) -> &[T] { self }
419
420 /// Extracts a mutable slice of the entire array.
421 ///
422 /// Equivalent to `&mut s[..]`.
423 ///
424 /// # Examples
425 ///
426 /// ```
427 /// use std::io::{self, Read};
428 /// # use heap_array::heap_array;
429 /// let mut buffer = heap_array![0; 3];
430 /// io::repeat(0b101).read_exact(buffer.as_mut_slice()).unwrap();
431 /// ```
432 #[inline(always)]
433 both pub fn as_mut_slice(&mut self) -> &mut [T] { self }
434
435 /// Consumes and leaks the [`HeapArray`], returning a mutable reference to the contents,
436 /// `&'a mut [T]`. Note that the type `T` must outlive the chosen lifetime
437 /// `'a`. If the type has only static references, or none at all, then this
438 /// may be chosen to be `'static`.
439 ///
440 /// This function is mainly useful for data that lives for the remainder of
441 /// the program's life. Dropping the returned reference will cause a memory
442 /// leak.
443 ///
444 /// # Examples
445 ///
446 /// Simple usage:
447 ///
448 /// ```
449 /// # use heap_array::heap_array;
450 /// # if cfg!(miri) { std::process::exit(0) } // miri doesn't like the leak
451 /// let x = heap_array![1, 2, 3];
452 /// let static_ref: &'static mut [usize] = x.leak();
453 /// static_ref[0] += 1;
454 /// assert_eq!(static_ref, &[2, 2, 3]);
455 /// ```
456 /// [`HeapArray`]: HeapArray
457 allocator-api pub fn leak<'a>(self) -> &'a mut [T] where A: 'a {
458 let (ptr, len) = self.into_raw_parts();
459 unsafe { core::slice::from_raw_parts_mut(ptr.as_ptr(), len) }
460 }
461
462 /// Consumes and leaks the [`HeapArray`], returning a mutable reference to the contents,
463 /// `&'a mut [T]`. Note that the type `T` must outlive the chosen lifetime
464 /// `'a`. If the type has only static references, or none at all, then this
465 /// may be chosen to be `'static`.
466 ///
467 /// This function is mainly useful for data that lives for the remainder of
468 /// the program's life. Dropping the returned reference will cause a memory
469 /// leak.
470 ///
471 /// # Examples
472 ///
473 /// Simple usage:
474 ///
475 /// ```
476 /// # use heap_array::heap_array;
477 /// # if cfg!(miri) { std::process::exit(0) } // miri doesn't like the leak
478 /// let x = heap_array![1, 2, 3];
479 /// let static_ref: &'static mut [usize] = x.leak();
480 /// static_ref[0] += 1;
481 /// assert_eq!(static_ref, &[2, 2, 3]);
482 /// ```
483 /// [`HeapArray`]: HeapArray
484 #[inline]
485 not(allocator-api) pub fn leak<'a>(self) -> &'a mut [T] {
486 let (ptr, len) = self.into_raw_parts();
487 unsafe { core::slice::from_raw_parts_mut(ptr.as_ptr(), len) }
488 }
489
490 /// Decomposes a [`HeapArray`] into its raw components.
491 ///
492 /// Returns the raw pointer to the underlying data, the length of
493 /// the heap-array (in elements) These are the same arguments in the same
494 /// order as the arguments to [`from_raw_parts`].
495 ///
496 /// After calling this function, the caller is responsible for the
497 /// memory previously managed by the [`HeapArray`]. The only way to do
498 /// this is to convert the raw pointer, length back
499 /// into a [`HeapArray`] with the [`from_raw_parts`] function, allowing
500 /// the destructor to perform the cleanup.
501 ///
502 /// # Examples
503 ///
504 /// ```
505 /// # use heap_array::{heap_array, HeapArray};
506 /// let v: HeapArray<i32> = heap_array![-1, 0, 1];
507 ///
508 /// let (ptr, len) = v.into_raw_parts();
509 ///
510 /// let rebuilt = unsafe {
511 /// // We can now make changes to the components, such as
512 /// // transmuting the raw pointer to a compatible type.
513 /// let ptr = ptr.cast::<u32>();
514 ///
515 /// HeapArray::from_raw_parts(ptr, len)
516 /// };
517 /// assert_eq!(*rebuilt, [4294967295, 0, 1]);
518 /// ```
519 /// [`from_raw_parts`]: HeapArray::from_raw_parts
520 /// [`HeapArray`]: HeapArray
521 #[inline]
522 both pub fn into_raw_parts(self) -> (NonNull<T>, usize) {
523 let this = ManuallyDrop::new(self);
524 (this.ptr, this.len)
525 }
526
527 /// Decomposes a `HeapArray<T>` into its raw components.
528 ///
529 /// Returns the raw pointer to the underlying data, the length of the vector (in elements),
530 /// and the allocator. These are the same arguments in the same order as the arguments to
531 /// [`from_raw_parts_in`].
532 ///
533 /// After calling this function, the caller is responsible for the
534 /// memory previously managed by the `HeapArray`. The only way to do
535 /// this is to convert the raw pointer, length, and capacity back
536 /// into a `HeapArray` with the [`from_raw_parts_in`] function, allowing
537 /// the destructor to perform the cleanup.
538 ///
539 /// [`from_raw_parts_in`]: HeapArray::from_raw_parts_in
540 ///
541 /// # Examples
542 ///
543 /// ```
544 /// #![feature(allocator_api)]
545 ///
546 /// use std::alloc::System;
547 /// use heap_array::HeapArray;
548 ///
549 /// let mut v: HeapArray<i32, System> = HeapArray::from_array_in([-1, 0, 1], System);
550 ///
551 /// let (ptr, len, alloc) = v.into_raw_parts_with_alloc();
552 ///
553 /// let rebuilt = unsafe {
554 /// // We can now make changes to the components, such as
555 /// // transmuting the raw pointer to a compatible type.
556 /// let ptr = ptr.cast::<u32>();
557 ///
558 /// HeapArray::from_raw_parts_in(ptr, len, alloc)
559 /// };
560 ///
561 /// assert_eq!(*rebuilt, [4294967295, 0, 1]);
562 /// ```
563 #[inline]
564 allocator-api pub fn into_raw_parts_with_alloc(self) -> (NonNull<T>, usize, A) {
565 let this = ManuallyDrop::new(self);
566 // we never use alloc again, and it doesn't get dropped
567 (this.ptr, this.len, unsafe { ptr::read(&*this.alloc) })
568 }
569
570 /// Composes a [`HeapArray`] from its raw components, with an allocator.
571 ///
572 /// After calling this function, the [`HeapArray`] is responsible for the
573 /// memory management. The only way to get this back and get back
574 /// the raw pointer, length and allocator back is with the [`into_raw_parts_with_alloc`] function, granting you
575 /// control of the allocation, and allocator again.
576 ///
577 /// # Safety:
578 /// must be given from [`into_raw_parts_with_alloc`]
579 ///
580 /// # Examples
581 ///
582 /// ```
583 /// #![feature(allocator_api)]
584 ///
585 /// use std::alloc::System;
586 /// use heap_array::HeapArray;
587 ///
588 /// let mut v: HeapArray<i32, System> = HeapArray::from_array_in([-1, 0, 1], System);
589 ///
590 /// let (ptr, len, alloc) = v.into_raw_parts_with_alloc();
591 ///
592 /// let rebuilt = unsafe {
593 /// // We can now make changes to the components, such as
594 /// // transmuting the raw pointer to a compatible type.
595 /// let ptr = ptr.cast::<u32>();
596 ///
597 /// HeapArray::from_raw_parts_in(ptr, len, alloc)
598 /// };
599 ///
600 /// assert_eq!(*rebuilt, [4294967295, 0, 1]);
601 /// ```
602 /// [`into_raw_parts`]: HeapArray::into_raw_parts_with_alloc
603 /// [`HeapArray`]: HeapArray
604 #[inline(always)]
605 allocator-api pub const unsafe fn from_raw_parts_in(ptr: NonNull<T>, len: usize, alloc: A) -> Self {
606 Self { ptr, len, __marker: PhantomData, alloc: ManuallyDrop::new(alloc) }
607 }
608
609 /// Composes a [`HeapArray`] from its raw components.
610 ///
611 /// After calling this function, the [`HeapArray`] is responsible for the
612 /// memory management. The only way to get this back and get back
613 /// the raw pointer and length back is with the [`into_raw_parts`] function, granting you
614 /// control of the allocation again.
615 ///
616 /// # Safety:
617 /// must be given from [`into_raw_parts`]
618 ///
619 /// # Examples
620 ///
621 /// ```
622 /// # use heap_array::{heap_array, HeapArray};
623 /// let v: HeapArray<i32> = heap_array![-1, 0, 1];
624 ///
625 /// let (ptr, len) = v.into_raw_parts();
626 ///
627 /// let rebuilt = unsafe {
628 /// // We can now make changes to the components, such as
629 /// // transmuting the raw pointer to a compatible type.
630 /// let ptr = ptr.cast::<u32>();
631 ///
632 /// HeapArray::from_raw_parts(ptr, len)
633 /// };
634 /// assert_eq!(*rebuilt, [4294967295, 0, 1]);
635 /// ```
636 /// [`into_raw_parts`]: HeapArray::into_raw_parts
637 /// [`HeapArray`]: HeapArray
638 #[inline(always)]
639 not(allocator-api) pub const unsafe fn from_raw_parts(ptr: NonNull<T>, len: usize) -> Self {
640 Self { ptr, len, __marker: PhantomData }
641 }
642
643 /// Converts `self` into a Box<[T]> without clones or allocation.
644 ///
645 /// The resulting box can be converted back into an [`HeapArray`] via
646 /// `Box<[T]>`'s `into()` method or by calling `HeapArray::from(box)`.
647 ///
648 /// this is usually due to a library requiring `Box<[T]>` to be used
649 /// as HeapArray is supposed to be the replacement for `Box<[T]>`
650 ///
651 /// # Examples
652 ///
653 /// ```
654 /// # use heap_array::{heap_array, HeapArray};
655 /// let s: HeapArray<u32> = heap_array![10, 40, 30];
656 /// let x = s.into_boxed_slice();
657 /// // `s` cannot be used anymore because it has been converted into `x`.
658 ///
659 /// let y: Box<[u32]> = Box::new([10, 40, 30]);
660 /// assert_eq!(x, y);
661 /// ```
662 #[inline]
663 allocator-api pub fn into_boxed_slice(self) -> Box<[T], A> {
664 let (ptr, len, alloc) = self.into_raw_parts_with_alloc();
665 let ptr = ptr::slice_from_raw_parts_mut(ptr.as_ptr(), len);
666 unsafe { Box::from_raw_in(ptr, alloc) }
667 }
668
669 /// Converts `self` into a Box<[T]> without clones or allocation.
670 ///
671 /// The resulting box can be converted back into an [`HeapArray`] via
672 /// `Box<[T]>`'s `into()` method or by calling `HeapArray::from(box)`.
673 ///
674 /// this is usually due to a library requiring `Box<[T]>` to be used
675 /// as HeapArray is supposed to be the replacement for `Box<[T]>`
676 ///
677 /// # Examples
678 ///
679 /// ```
680 /// # use heap_array::{heap_array, HeapArray};
681 /// let s: HeapArray<u32> = heap_array![10, 40, 30];
682 /// let x = s.into_boxed_slice();
683 /// // `s` cannot be used anymore because it has been converted into `x`.
684 ///
685 /// let y: Box<[u32]> = Box::new([10, 40, 30]);
686 /// assert_eq!(x, y);
687 /// ```
688 #[inline]
689 not(allocator-api) pub fn into_boxed_slice(self) -> Box<[T]> {
690 let (ptr, len) = self.into_raw_parts();
691 let ptr = ptr::slice_from_raw_parts_mut(ptr.as_ptr(), len);
692 unsafe { Box::from_raw(ptr) }
693 }
694
695 /// Converts `self` into a vector without clones or allocation.
696 ///
697 /// The resulting vector can be converted back into an [`HeapArray`] via
698 /// `Vec<T>`'s `into()` method or by calling `HeapArray::from(vec)`.
699 ///
700 /// Should only be used if you plan to resizing, otherwise use `into_boxed_slice` for a smaller
701 /// type
702 /// # Examples
703 ///
704 /// ```
705 /// # use heap_array::{heap_array, HeapArray};
706 /// let s: HeapArray<u32> = heap_array![10, 40, 30];
707 /// let x = s.into_vec();
708 /// // `s` cannot be used anymore because it has been converted into `x`.
709 ///
710 /// assert_eq!(x, vec![10, 40, 30]);
711 /// ```
712 #[inline]
713 allocator-api pub fn into_vec(self) -> Vec<T, A> {
714 self.into()
715 }
716
717 /// Converts `self` into a vector without clones or allocation.
718 ///
719 /// The resulting vector can be converted back into an [`HeapArray`] via
720 /// `Vec<T>`'s `into()` method or by calling `HeapArray::from(vec)`.
721 ///
722 /// Should only be used if you plan to resizing, otherwise use `into_boxed_slice` for a smaller
723 /// type
724 /// # Examples
725 ///
726 /// ```
727 /// # use heap_array::{heap_array, HeapArray};
728 /// let s: HeapArray<u32> = heap_array![10, 40, 30];
729 /// let x = s.into_vec();
730 /// // `s` cannot be used anymore because it has been converted into `x`.
731 ///
732 /// assert_eq!(x, vec![10, 40, 30]);
733 /// ```
734 #[inline]
735 not(allocator-api) pub fn into_vec(self) -> Vec<T> {
736 self.into()
737 }
738
739 /// Creates a [`HeapArray`], where each element `T` is the returned value from `f`
740 /// using that element's index.
741 ///
742 /// # Arguments
743 ///
744 /// * `len`: length of the array.
745 /// * `f`: function where the passed argument is the current array index.
746 /// * `alloc`: the allocator used to allocate the heap array
747 ///
748 /// # Example
749 ///
750 /// ```rust
751 /// #![feature(allocator_api)]
752 ///
753 /// use std::alloc::{System};
754 /// use heap_array::HeapArray;
755 /// let array: HeapArray<i32, System> = HeapArray::from_fn_in(5, |i| i as i32, System);
756 /// // indexes are: 0 1 2 3 4
757 /// assert_eq!(*array, [0, 1, 2, 3, 4]);
758 ///
759 /// let array2: HeapArray<i32, System> = HeapArray::from_fn_in(8, |i| i as i32 * 2, System);
760 /// // indexes are: 0 1 2 3 4 5 6 7
761 /// assert_eq!(*array2, [0, 2, 4, 6, 8, 10, 12, 14]);
762 ///
763 /// let bool_arr: HeapArray<bool, System> = HeapArray::from_fn_in(5, |i| i % 2 == 0, System);
764 /// // indexes are: 0 1 2 3 4
765 /// assert_eq!(*bool_arr, [true, false, true, false, true]);
766 /// ```
767 /// [`HeapArray`]: HeapArray
768 #[inline]
769 allocator-api pub fn from_fn_in(len: usize, f: impl FnMut(usize) -> T, alloc: A) -> Self {
770 Self::try_from_fn_in(len, NeverShortCircuit::wrap_fn(f), alloc)
771 }
772
773 /// Creates a [`HeapArray`] in an allocator, where each element `T` is the returned value from `cb`
774 /// using that element's index.
775 /// Unlike [`from_fn_in`], where the element creation can't fail, this version will return an error
776 /// if any element creation was unsuccessful.
777 ///
778 /// The return type of this function depends on the return type of the closure.
779 /// If you return `Result<T, E>` from the closure, you'll get a `Result<HeapArray<T>, E>`.
780 /// If you return `Option<T>` from the closure, you'll get an `Option<HeapArray<T>>`.
781 /// # Arguments
782 ///
783 /// * `len`: length of the array.
784 /// * `f`: function where the passed argument is the current array index, and it is guaranteed to run with values from 0..`len` in ascending order.
785 /// * `alloc`: allocator used to allocate the array
786 ///
787 /// # Example
788 ///
789 /// ```rust
790 /// use std::alloc::System;
791 /// use heap_array::HeapArray;
792 /// let array: Result<HeapArray<u8, System>, _> = HeapArray::try_from_fn_in(5, |i| i.try_into(), System);
793 /// assert_eq!(array.as_deref(), Ok([0, 1, 2, 3, 4].as_ref()));
794 ///
795 /// let array: Result<HeapArray<i8, System>, _> = HeapArray::try_from_fn_in(200, |i| i.try_into(), System);
796 /// assert!(array.is_err());
797 ///
798 /// let array: Option<HeapArray<usize, System>> = HeapArray::try_from_fn_in(4, |i| i.checked_add(100), System);
799 /// assert_eq!(array.as_deref(), Some([100, 101, 102, 103].as_ref()));
800 ///
801 /// let array: Option<HeapArray<usize, System>> = HeapArray::try_from_fn_in(4, |i| i.checked_sub(100), System);
802 /// assert_eq!(array, None);
803 /// ```
804 /// [`HeapArray`]: HeapArray
805 /// [`from_fn`]: HeapArray::from_fn
806 allocator-api pub fn try_from_fn_in<R>(
807 len: usize,
808 mut f: impl FnMut(usize) -> R,
809 alloc: A
810 ) -> R::TryType<Self> where R: Try<Output=T>
811 { try_from_fn_impl!(T, R, len, f, alloc) }
812
813 /// Create a [`HeapArray`] from a given element and size.
814 ///
815 ///
816 /// This is a specialization of `HeapArray::from_fn(len, |_| element.clone())`
817 /// and may result in a minor speed up over it.
818 ///
819 /// This will use `clone` to duplicate an expression, so one should be careful
820 /// using this with types having a nonstandard `Clone` implementation. For
821 /// example, `HeapArray::from_element(5, Rc::new(1))` will create a heap-array of five references
822 /// to the same boxed integer value, not five references pointing to independently
823 /// boxed integers.
824 ///
825 /// Also, note that `HeapArray::from_element(0, expr)` is allowed, and produces an empty HeapArray.
826 /// This will still evaluate `expr`, however, and immediately drop the resulting value, so
827 /// be mindful of side effects.
828 ///
829 /// # Example
830 ///
831 /// ```rust
832 /// # use heap_array::HeapArray;
833 /// let array: HeapArray<u8> = HeapArray::from_element(5, 68);
834 /// assert_eq!(*array, [68, 68, 68, 68, 68])
835 /// ```
836 /// [`HeapArray`]: HeapArray
837 /// [`heap_array`]: heap_array
838 #[inline]
839 allocator-api pub fn from_element_in(len: usize, element: T, alloc: A) -> Self
840 where T: Clone
841 {
842 // We use vec![] rather than Self::from_fn(len, |_| element.clone())
843 // as it has specialization traits for manny things Such as zero initialization
844 // as well as avoid an extra copy (caused by not using element except for cloning)
845 vec::from_elem_in(element, len, alloc).into()
846 }
847 /// Copies a slice into a new `HeapArray` with an allocator.
848 ///
849 /// # Examples
850 ///
851 /// ```
852 /// #![feature(allocator_api)]
853 ///
854 /// use std::alloc::System;
855 /// use heap_array::HeapArray;
856 ///
857 /// let s = [10, 40, 30];
858 /// let x = HeapArray::from_slice_in(&s, System);
859 /// // Here, `s` and `x` can be modified independently.
860 /// ```
861 #[inline]
862 allocator-api pub fn from_slice_in(slice: &[T], alloc: A) -> HeapArray<T, A>
863 where T: Clone
864 {
865 // HeapArray::from_fn_in(slice.len(), |i| {
866 // // Safety: from_fn provides values 0..len
867 // // and all values gotten should be within that range
868 // match cfg!(debug_assertions) {
869 // true => slice.get(i).expect("heapArray cloning out of bounds").clone(),
870 // false => unsafe { slice.get_unchecked(i).clone() }
871 // }
872 // }, alloc)
873
874
875 // we use this for specialization on Copy T
876 <[T]>::to_vec_in(slice, alloc).into()
877 }
878
879 /// Allocate a `HeapArray<T>` with a custom allocator and move the array's items into it.
880 ///
881 /// # Examples
882 ///
883 /// ```
884 /// use heap_array::{heap_array, HeapArray};
885 ///
886 /// assert_eq!(HeapArray::from_array([1, 2, 3]), heap_array![1, 2, 3]);
887 /// ```
888 allocator-api pub fn from_array_in<const N: usize>(array: [T; N], alloc: A) -> HeapArray<T, A> {
889 from_array_impl!(T, array, N, alloc)
890 }
891
892 /// Constructs a new, empty [`HeapArray`] without allocating.
893 ///
894 /// # Examples
895 ///
896 /// ```
897 /// # use heap_array::HeapArray;
898 /// let vec: HeapArray<i32> = HeapArray::new();
899 /// ```
900 /// [`HeapArray`]: HeapArray
901 #[inline(always)]
902 not(allocator-api) pub const fn new() -> Self {
903 unsafe { HeapArray::from_raw_parts(NonNull::<T>::dangling(), 0) }
904 }
905
906 /// Creates a [`HeapArray`], where each element `T` is the returned value from `cb`
907 /// using that element's index.
908 ///
909 /// # Arguments
910 ///
911 /// * `len`: length of the array.
912 /// * `f`: function where the passed argument is the current array index.
913 ///
914 /// # Example
915 ///
916 /// ```rust
917 /// # use heap_array::HeapArray;
918 /// let array = HeapArray::from_fn(5, |i| i);
919 /// // indexes are: 0 1 2 3 4
920 /// assert_eq!(*array, [0, 1, 2, 3, 4]);
921 ///
922 /// let array2 = HeapArray::from_fn(8, |i| i * 2);
923 /// // indexes are: 0 1 2 3 4 5 6 7
924 /// assert_eq!(*array2, [0, 2, 4, 6, 8, 10, 12, 14]);
925 ///
926 /// let bool_arr = HeapArray::from_fn(5, |i| i % 2 == 0);
927 /// // indexes are: 0 1 2 3 4
928 /// assert_eq!(*bool_arr, [true, false, true, false, true]);
929 /// ```
930 /// [`HeapArray`]: HeapArray
931 #[inline]
932 not(allocator-api) pub fn from_fn(len: usize, f: impl FnMut(usize) -> T) -> Self {
933 HeapArray::try_from_fn(len, NeverShortCircuit::wrap_fn(f))
934 }
935
936 /// Creates a [`HeapArray`], where each element `T` is the returned value from `cb`
937 /// using that element's index.
938 /// Unlike [`from_fn`], where the element creation can't fail, this version will return an error
939 /// if any element creation was unsuccessful.
940 ///
941 /// The return type of this function depends on the return type of the closure.
942 /// If you return `Result<T, E>` from the closure, you'll get a `Result<HeapArray<T>, E>`.
943 /// If you return `Option<T>` from the closure, you'll get an `Option<HeapArray<T>>`.
944 /// # Arguments
945 ///
946 /// * `len`: length of the array.
947 /// * `f`: function where the passed argument is the current array index, and it is guaranteed to run with values from 0..`len` in ascending order.
948 ///
949 /// # Example
950 ///
951 /// ```rust
952 /// # use heap_array::HeapArray;
953 /// let array: Result<HeapArray<u8>, _> = HeapArray::try_from_fn(5, |i| i.try_into());
954 /// assert_eq!(array.as_deref(), Ok([0, 1, 2, 3, 4].as_ref()));
955 ///
956 /// let array: Result<HeapArray<i8>, _> = HeapArray::try_from_fn(200, |i| i.try_into());
957 /// assert!(array.is_err());
958 ///
959 /// let array: Option<HeapArray<usize>> = HeapArray::try_from_fn(4, |i| i.checked_add(100));
960 /// assert_eq!(array.as_deref(), Some([100, 101, 102, 103].as_ref()));
961 ///
962 /// let array: Option<HeapArray<usize>> = HeapArray::try_from_fn(4, |i| i.checked_sub(100));
963 /// assert_eq!(array, None);
964 /// ```
965 /// [`HeapArray`]: HeapArray
966 /// [`from_fn`]: HeapArray::from_fn
967 not(allocator-api) pub fn try_from_fn<R>(len: usize, mut f: impl FnMut(usize) -> R) -> R::TryType<Self>
968 where R: Try<Output=T>
969 {
970 try_from_fn_impl!(T, R, len, f)
971 }
972
973 /// Create a [`HeapArray`] from a given element and size.
974 ///
975 ///
976 /// This is a specialization of `HeapArray::from_fn(len, |_| element.clone())`
977 /// and may result in a minor speed up over it.
978 ///
979 /// This will use `clone` to duplicate an expression, so one should be careful
980 /// using this with types having a nonstandard `Clone` implementation. For
981 /// example, `Self::from_element(5, Rc::new(1))` will create a heap-array of five references
982 /// to the same boxed integer value, not five references pointing to independently
983 /// boxed integers.
984 ///
985 /// Also, note that `Self::from_element(0, expr)` is allowed, and produces an empty HeapArray.
986 /// This will still evaluate `expr`, however, and immediately drop the resulting value, so
987 /// be mindful of side effects.
988 ///
989 /// Also, note `Self::from_element(n, expr)` can always be replaced with `heap_array![expr; n]`
990 /// # Example
991 ///
992 /// ```rust
993 /// # use heap_array::HeapArray;
994 /// let array: HeapArray<u8> = HeapArray::from_element(5, 68);
995 /// assert_eq!(*array, [68, 68, 68, 68, 68])
996 /// ```
997 /// [`HeapArray`]: HeapArray
998 /// [`heap_array`]: heap_array
999 #[inline(always)]
1000 not(allocator-api) pub fn from_element(len: usize, element: T) -> Self
1001 where T: Clone
1002 {
1003 // We use vec![] rather than Self::from_fn(len, |_| element.clone())
1004 // as it has specialization traits for manny things Such as zero initialization
1005 // as well as avoid an extra clone (caused by not using element except for cloning)
1006 vec::from_elem(element, len).into()
1007 }
1008
1009 /// Copies a slice into a new `HeapArray`.
1010 ///
1011 /// # Examples
1012 ///
1013 /// ```
1014 /// #![feature(allocator_api)]
1015 ///
1016 /// use std::alloc::System;
1017 /// use heap_array::HeapArray;
1018 ///
1019 /// let s = [10, 40, 30];
1020 /// let x = HeapArray::from_slice(&s);
1021 /// // Here, `s` and `x` can be modified independently.
1022 /// ```
1023 #[inline(always)]
1024 not(allocator-api) pub fn from_slice(slice: &[T]) -> Self
1025 where T: Clone
1026 {
1027 // we use this for specialization on Copy T
1028 <[T]>::to_vec(slice).into()
1029 }
1030
1031 /// Allocate a `HeapArray<T>` and move the array's items into it.
1032 ///
1033 /// # Examples
1034 ///
1035 /// ```
1036 /// use heap_array::{heap_array, HeapArray};
1037 ///
1038 /// assert_eq!(HeapArray::from_array([1, 2, 3]), heap_array![1, 2, 3]);
1039 /// ```
1040 not(allocator-api) pub fn from_array<const N: usize>(array: [T; N]) -> Self {
1041 from_array_impl!(T, array, N)
1042 }
1043
1044 /// Safety: Caller must uphold
1045 /// Must ensure the HeapArray won't be dropped afterward
1046 /// and that it won't be accessed later
1047 #[inline]
1048 both pub(crate) unsafe fn drop_memory(&mut self) {
1049 if self.len != 0 {
1050 // size is always less than isize::MAX we checked that already
1051 // By using Layout::array::<T> to allocate
1052 let size = mem::size_of::<T>().unchecked_mul(self.len);
1053 let align = mem::align_of::<T>();
1054
1055 let layout = Layout::from_size_align_unchecked(size, align);
1056 #[cfg(feature = "allocator-api")]
1057 self.alloc.deallocate(self.ptr.cast(), layout);
1058 #[cfg(not(feature = "allocator-api"))]
1059 alloc::alloc::dealloc(self.ptr.as_ptr() as *mut u8, layout);
1060 }
1061 #[cfg(feature = "allocator-api")]
1062 if mem::needs_drop::<A>() { unsafe { ManuallyDrop::drop(&mut self.alloc) } }
1063 }
1064 }
1065}
1066
1067#[cfg(feature = "allocator-api")]
1068impl<T> HeapArray<T, Global> {
1069 /// Copies a slice into a new `HeapArray`.
1070 ///
1071 /// # Examples
1072 ///
1073 /// ```
1074 /// #![feature(allocator_api)]
1075 ///
1076 /// use std::alloc::System;
1077 /// use heap_array::HeapArray;
1078 ///
1079 /// let s = [10, 40, 30];
1080 /// let x = HeapArray::from_slice(&s);
1081 /// // Here, `s` and `x` can be modified independently.
1082 /// ```
1083 #[inline(always)]
1084 pub fn from_slice(slice: &[T]) -> Self
1085 where T: Clone
1086 { HeapArray::<T, Global>::from_slice_in(slice, Global) }
1087
1088 /// Create a [`HeapArray`] from a given element and size.
1089 ///
1090 ///
1091 /// This is a specialization of `HeapArray::from_fn(len, |_| element.clone())`
1092 /// and may result in a minor speed up over it.
1093 ///
1094 /// This will use `clone` to duplicate an expression, so one should be careful
1095 /// using this with types having a nonstandard `Clone` implementation. For
1096 /// example, `Self::from_element(5, Rc::new(1))` will create a heap-array of five references
1097 /// to the same boxed integer value, not five references pointing to independently
1098 /// boxed integers.
1099 ///
1100 /// Also, note that `Self::from_element(0, expr)` is allowed, and produces an empty HeapArray.
1101 /// This will still evaluate `expr`, however, and immediately drop the resulting value, so
1102 /// be mindful of side effects.
1103 ///
1104 /// Also, note `Self::from_element(n, expr)` can always be replaced with `heap_array![expr; n]`
1105 /// # Example
1106 ///
1107 /// ```rust
1108 /// # use heap_array::HeapArray;
1109 /// let array: HeapArray<u8> = HeapArray::from_element(5, 68);
1110 /// assert_eq!(*array, [68, 68, 68, 68, 68])
1111 /// ```
1112 /// [`HeapArray`]: HeapArray
1113 /// [`heap_array`]: heap_array
1114 #[inline(always)]
1115 pub fn from_element(len: usize, element: T) -> Self
1116 where T: Clone
1117 { HeapArray::<T, Global>::from_element_in(len, element, Global) }
1118
1119 /// Allocate a `HeapArray<T>` and move the array's items into it.
1120 ///
1121 /// # Examples
1122 ///
1123 /// ```
1124 /// use heap_array::{heap_array, HeapArray};
1125 ///
1126 /// assert_eq!(HeapArray::from_array([1, 2, 3]), heap_array![1, 2, 3]);
1127 /// ```
1128 #[inline(always)]
1129 pub fn from_array<const N: usize>(array: [T; N]) -> Self
1130 { HeapArray::<T, Global>::from_array_in(array, Global) }
1131
1132 /// Creates a [`HeapArray`], where each element `T` is the returned value from `cb`
1133 /// using that element's index.
1134 /// Unlike [`from_fn`], where the element creation can't fail, this version will return an error
1135 /// if any element creation was unsuccessful.
1136 ///
1137 /// The return type of this function depends on the return type of the closure.
1138 /// If you return `Result<T, E>` from the closure, you'll get a `Result<HeapArray<T>, E>`.
1139 /// If you return `Option<T>` from the closure, you'll get an `Option<HeapArray<T>>`.
1140 /// # Arguments
1141 ///
1142 /// * `len`: length of the array.
1143 /// * `f`: function where the passed argument is the current array index, and it is guaranteed to run with values from 0..`len` in ascending order.
1144 ///
1145 /// # Example
1146 ///
1147 /// ```rust
1148 /// # use heap_array::HeapArray;
1149 /// let array: Result<HeapArray<u8>, _> = HeapArray::try_from_fn(5, |i| i.try_into());
1150 /// assert_eq!(array.as_deref(), Ok([0, 1, 2, 3, 4].as_ref()));
1151 ///
1152 /// let array: Result<HeapArray<i8>, _> = HeapArray::try_from_fn(200, |i| i.try_into());
1153 /// assert!(array.is_err());
1154 ///
1155 /// let array: Option<HeapArray<usize>> = HeapArray::try_from_fn(4, |i| i.checked_add(100));
1156 /// assert_eq!(array.as_deref(), Some([100, 101, 102, 103].as_ref()));
1157 ///
1158 /// let array: Option<HeapArray<usize>> = HeapArray::try_from_fn(4, |i| i.checked_sub(100));
1159 /// assert_eq!(array, None);
1160 /// ```
1161 /// [`HeapArray`]: HeapArray
1162 /// [`from_fn`]: HeapArray::from_fn
1163 #[inline(always)]
1164 pub fn try_from_fn<R>(len: usize, f: impl FnMut(usize) -> R) -> R::TryType<Self>
1165 where R: Try<Output=T>
1166 { HeapArray::<T, Global>::try_from_fn_in(len, f, Global) }
1167
1168 /// Creates a [`HeapArray`], where each element `T` is the returned value from `cb`
1169 /// using that element's index.
1170 ///
1171 /// # Arguments
1172 ///
1173 /// * `len`: length of the array.
1174 /// * `f`: function where the passed argument is the current array index.
1175 ///
1176 /// # Example
1177 ///
1178 /// ```rust
1179 /// # use heap_array::HeapArray;
1180 /// let array = HeapArray::from_fn(5, |i| i);
1181 /// // indexes are: 0 1 2 3 4
1182 /// assert_eq!(*array, [0, 1, 2, 3, 4]);
1183 ///
1184 /// let array2 = HeapArray::from_fn(8, |i| i * 2);
1185 /// // indexes are: 0 1 2 3 4 5 6 7
1186 /// assert_eq!(*array2, [0, 2, 4, 6, 8, 10, 12, 14]);
1187 ///
1188 /// let bool_arr = HeapArray::from_fn(5, |i| i % 2 == 0);
1189 /// // indexes are: 0 1 2 3 4
1190 /// assert_eq!(*bool_arr, [true, false, true, false, true]);
1191 /// ```
1192 /// [`HeapArray`]: HeapArray
1193 #[inline(always)]
1194 pub fn from_fn(len: usize, f: impl FnMut(usize) -> T) -> Self {
1195 HeapArray::<T, Global>::from_fn_in(len, f, Global)
1196 }
1197
1198 /// Constructs a new, empty [`HeapArray`] without allocating.
1199 ///
1200 /// # Examples
1201 ///
1202 /// ```
1203 /// # use heap_array::HeapArray;
1204 /// let vec: HeapArray<i32> = HeapArray::new();
1205 /// ```
1206 /// [`HeapArray`]: HeapArray
1207 #[inline(always)]
1208 pub const fn new() -> Self {
1209 HeapArray::<T, Global>::new_in(Global)
1210 }
1211
1212 /// Composes a [`HeapArray`] from its raw components.
1213 ///
1214 /// After calling this function, the [`HeapArray`] is responsible for the
1215 /// memory management. The only way to get this back and get back
1216 /// the raw pointer and length back is with the [`into_raw_parts`] function, granting you
1217 /// control of the allocation again.
1218 ///
1219 /// # Safety:
1220 /// must be given from [`into_raw_parts`]
1221 ///
1222 /// # Examples
1223 ///
1224 /// ```
1225 /// # use heap_array::{heap_array, HeapArray};
1226 /// let v: HeapArray<i32> = heap_array![-1, 0, 1];
1227 ///
1228 /// let (ptr, len) = v.into_raw_parts();
1229 ///
1230 /// let rebuilt = unsafe {
1231 /// // We can now make changes to the components, such as
1232 /// // transmuting the raw pointer to a compatible type.
1233 /// let ptr = ptr.cast::<u32>();
1234 ///
1235 /// HeapArray::from_raw_parts(ptr, len)
1236 /// };
1237 /// assert_eq!(*rebuilt, [4294967295, 0, 1]);
1238 /// ```
1239 /// [`into_raw_parts`]: HeapArray::into_raw_parts
1240 /// [`HeapArray`]: HeapArray
1241 #[inline(always)]
1242 pub const unsafe fn from_raw_parts(ptr: NonNull<T>, len: usize) -> HeapArray<T> {
1243 HeapArray::<T, Global>::from_raw_parts_in(ptr, len, Global)
1244 }
1245}
1246
1247macro_rules! identical_impl {
1248 // base case for recursion
1249 () => { };
1250 (
1251 impl<$($time: lifetime, )? T $(: {$($t_restrict:tt)+})?, $({$($generics:tt)*},)? Maybe<A $(: {$( $($alloc_restrict:tt)+ )&+})?>> {$($Trait:tt)+} for HeapArray<T, Maybe<A>> $(where {$($restrict:tt)*})? {
1252 $($r#impl:tt)*
1253 }
1254 $($rest:tt)*
1255 ) => {
1256 #[cfg(not(feature = "allocator-api"))]
1257 impl<$($time, )? T $(: $($t_restrict)+)?, $($($generics)*,)?> $($Trait)+ for HeapArray<T> $(where $($restrict)*)? {
1258 $($r#impl)*
1259 }
1260 #[cfg(feature = "allocator-api")]
1261 impl<$($time, )? T $(: $($t_restrict)+)?, $($($generics)*,)? A: Allocator $(+ $($($alloc_restrict)*)+)?> $($Trait)+ for HeapArray<T, A> $(where $($restrict)*)? {
1262 $($r#impl)*
1263 }
1264
1265 identical_impl! { $($rest)* }
1266 };
1267 (
1268 impl<$($time: lifetime, )? T $(: {$($t_restrict:tt)+})?, $({$($generics:tt)*},)? Maybe<A $(: {$( $($alloc_restrict:tt)+ )&+})?>> {$($Trait:tt)+} for &$other_time:lifetime $(($mut:tt))? HeapArray<T, Maybe<A>> $(where {$($restrict:tt)*})? {
1269 $($r#impl:tt)*
1270 }
1271 $($rest:tt)*
1272 ) => {
1273 #[cfg(not(feature = "allocator-api"))]
1274 impl<$($time, )? T $(: $($t_restrict)+)?, $($($generics)*,)?> $($Trait)+ for &$other_time $($mut)? HeapArray<T> $(where $($restrict)*)? {
1275 $($r#impl)*
1276 }
1277 #[cfg(feature = "allocator-api")]
1278 impl<$($time, )? T $(: $($t_restrict)+)?, $($($generics)*,)? A: Allocator $(+ $($($alloc_restrict)*)+)?> $($Trait)+ for &$other_time $($mut)? HeapArray<T, A> $(where $($restrict)*)? {
1279 $($r#impl)*
1280 }
1281
1282 identical_impl! { $($rest)* }
1283 };
1284 (
1285 unsafe impl<$($time: lifetime, )? T $(: {$($t_restrict:tt)+})?, $({$($generics:tt)*},)? Maybe<A$(: {$( $($alloc_restrict:tt)+ )&+})?>> {$($Trait:tt)+} for HeapArray<T, Maybe<A>> $(where {$($restrict:tt)*})? {
1286 $($r#impl:tt)*
1287 }
1288 $($rest:tt)*
1289 ) => {
1290 #[cfg(not(feature = "allocator-api"))]
1291 unsafe impl<$($time, )? T $(: $($t_restrict)+)?, $($($generics)*,)?> $($Trait)+ for HeapArray<T> $(where $($restrict)*)? {
1292 $($r#impl)*
1293 }
1294 #[cfg(feature = "allocator-api")]
1295 unsafe impl<$($time, )? T $(: $($t_restrict)+)?, $($($generics)*,)? A: Allocator $(+ $($($alloc_restrict)*)+)?> $($Trait)+ for HeapArray<T, A> $(where $($restrict)*)? {
1296 $($r#impl)*
1297 }
1298
1299 identical_impl! {$($rest)*}
1300 };
1301}
1302
1303
1304impl<T> Default for HeapArray<T> {
1305 #[inline]
1306 fn default() -> Self {
1307 Self::new()
1308 }
1309}
1310
1311impl<T: Clone> From<&[T]> for HeapArray<T> {
1312 #[inline(always)]
1313 fn from(slice: &[T]) -> Self { HeapArray::from_slice(slice) }
1314}
1315
1316impl<T, const N: usize> From<[T; N]> for HeapArray<T> {
1317 fn from(values: [T; N]) -> Self {
1318 Self::from_array(values)
1319 }
1320}
1321
1322#[cfg(not(feature = "allocator-api"))]
1323impl<T> From<Box<[T]>> for HeapArray<T> {
1324 #[inline]
1325 fn from(value: Box<[T]>) -> Self {
1326 let raw = Box::into_raw(value);
1327 unsafe {
1328 // A box pointer will always be a properly aligned non-null pointer.
1329 Self::from_raw_parts(NonNull::new_unchecked(raw.cast()), (*raw).len())
1330 }
1331 }
1332}
1333
1334#[cfg(feature = "allocator-api")]
1335impl<T, A: Allocator> From<Box<[T], A>> for HeapArray<T, A> {
1336 #[inline]
1337 fn from(value: Box<[T], A>) -> Self {
1338 let (parts, alloc) = Box::into_raw_with_allocator(value);
1339 unsafe {
1340 // A box pointer will always be a properly aligned non-null pointer.
1341 Self::from_raw_parts_in(NonNull::new_unchecked(parts.cast()), (*parts).len(), alloc)
1342 }
1343 }
1344}
1345
1346#[cfg(not(feature = "allocator-api"))]
1347impl<T> From<Vec<T>> for HeapArray<T> {
1348 #[inline]
1349 fn from(value: Vec<T>) -> Self {
1350 Self::from(value.into_boxed_slice())
1351 }
1352}
1353
1354#[cfg(feature = "allocator-api")]
1355impl<T, A: Allocator> From<Vec<T, A>> for HeapArray<T, A> {
1356 #[inline]
1357 fn from(value: Vec<T, A>) -> Self {
1358 Self::from(value.into_boxed_slice())
1359 }
1360}
1361
1362
1363
1364// error[E0210] when trying to do these with alloc-api
1365impl<T> From<HeapArray<T>> for Box<[T]> {
1366 #[inline]
1367 fn from(value: HeapArray<T>) -> Self {
1368 value.into_boxed_slice()
1369 }
1370}
1371
1372impl<T, const N: usize> TryFrom<HeapArray<T>> for Box<[T; N]> {
1373 type Error = HeapArray<T>;
1374
1375 fn try_from(value: HeapArray<T>) -> Result<Self, Self::Error> {
1376 if value.len != N {
1377 Err(value)
1378 } else {
1379 let value = ManuallyDrop::new(value);
1380 let ptr = value.ptr;
1381
1382 let ptr = ptr.as_ptr() as *mut [T; N];
1383 Ok(unsafe { Box::from_raw(ptr) })
1384 }
1385 }
1386}
1387
1388
1389
1390#[cfg(not(feature = "allocator-api"))]
1391impl<T> From<HeapArray<T>> for Vec<T> {
1392 #[inline]
1393 fn from(value: HeapArray<T>) -> Self {
1394 let (ptr, len) = value.into_raw_parts();
1395 unsafe { Vec::from_raw_parts(ptr.as_ptr(), len, len) }
1396 }
1397}
1398
1399#[cfg(feature = "allocator-api")]
1400impl<T, A: Allocator> From<HeapArray<T, A>> for Vec<T, A> {
1401 #[inline]
1402 fn from(value: HeapArray<T, A>) -> Self {
1403 let (ptr, len, alloc) = value.into_raw_parts_with_alloc();
1404 unsafe { Vec::from_raw_parts_in(ptr.as_ptr(), len, len, alloc) }
1405 }
1406}
1407
1408
1409macro_rules! try_to_array_impl {
1410 ($T: ty, $N: expr, $value: ident) => {{
1411 if $value.len != $N {
1412 return Err($value)
1413 }
1414
1415 let mut value = ManuallyDrop::new($value);
1416 // valid ptr for at least $N values
1417 let data: [$T; $N] = unsafe { ptr::read(value.as_ptr() as *const [$T; $N]) };
1418 // Safety: value is a ManuallyDrop and so it wont be dropped
1419 // and since we take ownership of value it wont be accessed after this
1420 unsafe { value.drop_memory() }
1421
1422 Ok(data)
1423 }};
1424}
1425
1426#[cfg(feature = "allocator-api")]
1427impl<T, A: Allocator, const N: usize> TryFrom<HeapArray<T, A>> for [T; N] {
1428 type Error = HeapArray<T, A>;
1429
1430 fn try_from(value: HeapArray<T, A>) -> Result<[T; N], Self::Error> {
1431 try_to_array_impl! (T, N, value)
1432 }
1433}
1434
1435#[cfg(not(feature = "allocator-api"))]
1436impl<T, const N: usize> TryFrom<HeapArray<T>> for [T; N] {
1437 type Error = HeapArray<T>;
1438
1439 fn try_from(value: HeapArray<T>) -> Result<[T; N], Self::Error> {
1440 try_to_array_impl! (T, N, value)
1441 }
1442}
1443
1444
1445identical_impl! {
1446 impl<T: {Clone}, Maybe<A: {Clone}>> {Clone} for HeapArray<T, Maybe<A>> {
1447 fn clone(&self) -> Self {
1448 #[cfg(not(feature = "allocator-api"))]
1449 {HeapArray::from_slice(self)}
1450 #[cfg(feature = "allocator-api")]
1451 {HeapArray::from_slice_in(self, self.allocator().clone())}
1452 }
1453 }
1454
1455}
1456
1457
1458identical_impl! {
1459 impl<T: {Hash}, Maybe<A>> {Hash} for HeapArray<T, Maybe<A>> {
1460 fn hash<H: Hasher>(&self, state: &mut H) {
1461 <[T] as Hash>::hash(self.deref(), state)
1462 }
1463 }
1464
1465 impl<T, Maybe<A>> {Deref} for HeapArray<T, Maybe<A>> {
1466 type Target = [T];
1467
1468 fn deref(&self) -> &Self::Target {
1469 unsafe { core::slice::from_raw_parts(self.ptr.as_ptr(), self.len) }
1470 }
1471 }
1472
1473 impl<T, Maybe<A>> {DerefMut} for HeapArray<T, Maybe<A>> {
1474 fn deref_mut(&mut self) -> &mut Self::Target {
1475 unsafe { core::slice::from_raw_parts_mut(self.ptr.as_ptr(), self.len) }
1476 }
1477 }
1478
1479 impl<T, Maybe<A>> {AsRef<[T]>} for HeapArray<T, Maybe<A>> {
1480 fn as_ref(&self) -> &[T] { self }
1481 }
1482
1483 impl<T, Maybe<A>> {AsMut<[T]>} for HeapArray<T, Maybe<A>> {
1484 fn as_mut(&mut self) -> &mut [T] { self }
1485 }
1486
1487 impl<T: {Debug}, Maybe<A>> {Debug} for HeapArray<T, Maybe<A>> {
1488 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { self.deref().fmt(f) }
1489 }
1490
1491 impl<T, {I: SliceIndex<[T]>}, Maybe<A>> {Index<I>} for HeapArray<T, Maybe<A>> {
1492 type Output = I::Output;
1493
1494 fn index(&self, index: I) -> &Self::Output {
1495 <[T] as Index<I>>::index(self.deref(), index)
1496 }
1497 }
1498
1499 impl<T, {I: SliceIndex<[T]>}, Maybe<A>> {IndexMut<I>} for HeapArray<T, Maybe<A>> {
1500 fn index_mut(&mut self, index: I) -> &mut Self::Output {
1501 <[T] as IndexMut<I>>::index_mut(self.deref_mut(), index)
1502 }
1503 }
1504}
1505
1506
1507macro_rules! impl_deref_comp_trait {
1508 ($trait_name: ident |> fn $fn_name:ident(&self, other: &Self) -> $t: ty) => {
1509 identical_impl! {
1510 impl<T: {$trait_name}, Maybe<A>> {$trait_name} for HeapArray<T, Maybe<A>> {
1511 fn $fn_name(&self, other: &Self) -> $t { self.deref().$fn_name(other.deref()) }
1512 }
1513 }
1514 };
1515}
1516
1517impl_deref_comp_trait!(PartialEq |> fn eq(&self, other: &Self) -> bool);
1518impl_deref_comp_trait!(Ord |> fn cmp(&self, other: &Self) -> Ordering);
1519impl_deref_comp_trait!(PartialOrd |> fn partial_cmp(&self, other: &Self) -> Option<Ordering>);
1520identical_impl! {
1521 impl<T: {Eq}, Maybe<A>> {Eq} for HeapArray<T, Maybe<A>> {}
1522}
1523
1524macro_rules! drop_impl {
1525 () => {
1526 fn drop(&mut self) {
1527 if mem::needs_drop::<T>() {
1528 unsafe { ptr::drop_in_place(ptr::slice_from_raw_parts_mut(self.as_mut_ptr(), self.len)) };
1529 }
1530
1531 unsafe { self.drop_memory() }
1532 }
1533 };
1534}
1535
1536#[allow(missing_docs)]
1537#[cfg(all(feature = "dropck", feature = "allocator-api"))]
1538unsafe impl<#[may_dangle] T, A: Allocator> Drop for HeapArray<T, A> {
1539 drop_impl! { }
1540}
1541
1542#[allow(missing_docs)]
1543#[cfg(all(feature = "dropck", not(feature = "allocator-api")))]
1544unsafe impl<#[may_dangle] T> Drop for HeapArray<T> {
1545 drop_impl! { }
1546}
1547
1548#[allow(missing_docs)]
1549#[cfg(all(not(feature = "dropck"), feature = "allocator-api"))]
1550impl<T, A: Allocator> Drop for HeapArray<T, A> {
1551 drop_impl! { }
1552}
1553
1554#[allow(missing_docs)]
1555#[cfg(all(not(feature = "dropck"), not(feature = "allocator-api")))]
1556impl<T> Drop for HeapArray<T> {
1557 drop_impl! { }
1558}
1559
1560#[allow(unused)]
1561fn validate() {
1562 #[allow(drop_bounds)]
1563 fn check<T: Drop>() {};
1564 // can be any type
1565 check::<HeapArray<u8>>();
1566}
1567
1568identical_impl! {
1569 // Safety: the pointer we hold is unique to us and so send data is ok to be sent
1570 // and sync data is ok to be synced same goes for Unpin, RefUnwindSafe and UnwindSafe
1571 unsafe impl<T: {Send}, Maybe<A: {Send}>> {Send} for HeapArray<T, Maybe<A>> {}
1572 unsafe impl<T: {Sync}, Maybe<A: {Sync}>> {Sync} for HeapArray<T, Maybe<A>> {}
1573
1574 impl<T: {Unpin}, Maybe<A: {Unpin}>> {Unpin} for HeapArray<T, Maybe<A>>{}
1575 impl<T: {RefUnwindSafe}, Maybe<A: {RefUnwindSafe}>> {RefUnwindSafe} for HeapArray<T, Maybe<A>> {}
1576 impl<T: {UnwindSafe}, Maybe<A: {UnwindSafe}>> {UnwindSafe} for HeapArray<T, Maybe<A>> {}
1577}
1578
1579// vec dependent impls
1580#[allow(missing_docs)]
1581impl<T> FromIterator<T> for HeapArray<T> {
1582 fn from_iter<I: IntoIterator<Item=T>>(iter: I) -> Self {
1583 Vec::from_iter(iter).into()
1584 }
1585}
1586
1587#[cfg(feature = "allocator-api")]
1588#[allow(missing_docs)]
1589impl<T, A: Allocator> IntoIterator for HeapArray<T, A> {
1590 type Item = T;
1591 type IntoIter = IntoIter<Self::Item, A>;
1592
1593 fn into_iter(self) -> Self::IntoIter {
1594 self.into_vec().into_iter()
1595 }
1596}
1597
1598#[cfg(not(feature = "allocator-api"))]
1599#[allow(missing_docs)]
1600impl<T> IntoIterator for HeapArray<T> {
1601 type Item = T;
1602 type IntoIter = IntoIter<Self::Item>;
1603
1604 fn into_iter(self) -> Self::IntoIter {
1605 self.into_vec().into_iter()
1606 }
1607}
1608
1609identical_impl! {
1610 impl<'a, T, Maybe<A>> {IntoIterator} for &'a HeapArray<T, Maybe<A>> {
1611 type Item = &'a T;
1612 type IntoIter = Iter<'a, T>;
1613
1614 #[inline(always)]
1615 fn into_iter(self) -> Self::IntoIter {
1616 self.iter()
1617 }
1618 }
1619
1620 impl<'a, T, Maybe<A>> {IntoIterator} for &'a (mut) HeapArray<T, Maybe<A>> {
1621 type Item = &'a mut T;
1622 type IntoIter = IterMut<'a, T>;
1623
1624 #[inline(always)]
1625 fn into_iter(self) -> Self::IntoIter {
1626 self.iter_mut()
1627 }
1628 }
1629}
1630
1631
1632#[allow(missing_docs)]
1633#[doc(hidden)]
1634#[inline]
1635fn alloc_uninit<T, #[cfg(feature = "allocator-api")] A: Allocator>(
1636 len: usize,
1637 #[cfg(feature = "allocator-api")]
1638 alloc: &A
1639) -> Option<NonNull<MaybeUninit<T>>>
1640{
1641 if len == 0 {
1642 return None
1643 }
1644
1645 #[cold]
1646 const fn capacity_overflow() -> ! {
1647 panic!("capacity overflow")
1648 }
1649
1650 // We avoid `unwrap_or_else` here because it bloats the LLVM IR generated
1651 let layout = match Layout::array::<T>(len) {
1652 Ok(layout) => layout,
1653 Err(_) => capacity_overflow(),
1654 };
1655
1656 if usize::BITS < 64 && unlikely(layout.size() > isize::MAX as usize) {
1657 capacity_overflow()
1658 }
1659
1660 #[cfg(feature = "allocator-api")]
1661 {
1662 Some(match A::allocate(alloc, layout) {
1663 // currently allocate returns a [u8] with the same size as the one requested
1664 // and, so we can safely discard its length
1665 Ok(ptr) => NonNull::<[u8]>::cast::<MaybeUninit<T>>(ptr),
1666 Err(_) => handle_alloc_error(layout)
1667 })
1668 }
1669
1670 #[cfg(not(feature = "allocator-api"))]
1671 {
1672 Some(match NonNull::new(unsafe { alloc::alloc::alloc(layout) }) {
1673 Some(ptr) => ptr.cast(),
1674 None => handle_alloc_error(layout)
1675 })
1676 }
1677}
1678
1679
1680#[cfg(feature = "serde")]
1681use serde::{
1682 Deserialize, Deserializer, Serialize, Serializer,
1683 de::{SeqAccess, Visitor, Error, Expected},
1684};
1685
1686#[cfg(feature = "serde")]
1687identical_impl! {
1688 impl<T: {Serialize}, Maybe<A>> {Serialize} for HeapArray<T, Maybe<A>> {
1689 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> where S: Serializer {
1690 serializer.collect_seq(self)
1691 }
1692 }
1693}
1694
1695
1696
1697#[cfg(feature = "serde")]
1698impl<'a, T: Deserialize<'a>> HeapArray<T> {
1699 /// Deserializes the heap array from a [`SeqAccess`]
1700 pub fn from_sequence<A: SeqAccess<'a>>(mut sequence: A) -> Result<Self, A::Error> {
1701 #[repr(transparent)]
1702 struct ExpectedLen(usize);
1703
1704 impl Expected for ExpectedLen {
1705 #[inline]
1706 fn fmt(&self, formatter: &mut Formatter) -> fmt::Result {
1707 formatter.write_str("a length of ")?;
1708 fmt::Display::fmt(&self.0, formatter)
1709 }
1710 }
1711
1712 if let Some(len) = sequence.size_hint() {
1713 HeapArray::try_from_fn(len, |i| sequence.next_element::<T>().and_then(|res| match res {
1714 Some(out) => Ok(out),
1715 None => Err(Error::invalid_length(i+1, &ExpectedLen(len)))
1716 }))
1717 } else {
1718 let mut values = Vec::<T>::new();
1719 while let Some(value) = sequence.next_element()? {
1720 values.push(value);
1721 }
1722
1723 Ok(HeapArray::from(values))
1724 }
1725 }
1726}
1727
1728
1729#[cfg(feature = "serde")]
1730impl<'de, T: Deserialize<'de>> Deserialize<'de> for HeapArray<T> {
1731 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error> where D: Deserializer<'de> {
1732 struct HeapArrayVisitor<T> {
1733 marker: PhantomData<T>,
1734 }
1735
1736 impl<'a, T: Deserialize<'a>> Visitor<'a> for HeapArrayVisitor<T> {
1737 type Value = HeapArray<T>;
1738
1739 fn expecting(&self, formatter: &mut Formatter) -> fmt::Result {
1740 formatter.write_str("a sequence")
1741 }
1742
1743 #[inline(always)]
1744 fn visit_seq<A>(self, seq: A) -> Result<Self::Value, A::Error>
1745 where A: SeqAccess<'a>,
1746 { HeapArray::from_sequence(seq) }
1747 }
1748
1749 let visitor = HeapArrayVisitor {
1750 marker: PhantomData
1751 };
1752
1753 deserializer.deserialize_seq(visitor)
1754 }
1755}
1756
1757#[cfg(feature = "simd-json")]
1758use simd_json_derive::{Serialize as SimdSerialize, Deserialize as SimdDeserialize, Tape};
1759
1760#[cfg(feature = "simd-json")]
1761extern crate std;
1762
1763#[cfg(feature = "simd-json")]
1764identical_impl! {
1765 impl<T: {SimdSerialize}, Maybe<A>> {SimdSerialize} for HeapArray<T, Maybe<A>> {
1766 fn json_write<W>(&self, writer: &mut W) -> simd_json_derive::Result where W: std::io::Write {
1767 let mut i = self.iter();
1768 if let Some(first) = i.next() {
1769 writer.write_all(b"[")?;
1770 first.json_write(writer)?;
1771 for e in i {
1772 writer.write_all(b",")?;
1773 e.json_write(writer)?;
1774 }
1775 writer.write_all(b"]")
1776 } else {
1777 writer.write_all(b"[]")
1778 }
1779 }
1780 }
1781}
1782
1783
1784#[cfg(feature = "simd-json")]
1785impl<'input, T: SimdDeserialize<'input> + 'input> SimdDeserialize<'input> for HeapArray<T> {
1786 fn from_tape(tape: &mut Tape<'input>) -> simd_json::Result<Self> {
1787 if let Some(simd_json::Node::Array { len, .. }) = tape.next() {
1788 HeapArray::try_from_fn(len, |_| T::from_tape(tape))
1789 } else {
1790 Err(simd_json::Error::generic(simd_json::ErrorType::ExpectedArray))
1791 }
1792 }
1793}
1794
1795/// Creates a [`HeapArray`] containing the arguments.
1796///
1797/// `heap_array!` allows `HeapArray`'s to be defined with the same syntax as array expressions.
1798/// There are two forms of this macro:
1799///
1800/// - Create a [`HeapArray`] containing a given list of elements:
1801///
1802/// ```
1803/// # use heap_array::heap_array;
1804/// let v = heap_array![1, 2, 3];
1805/// assert_eq!(v[0], 1);
1806/// assert_eq!(v[1], 2);
1807/// assert_eq!(v[2], 3);
1808/// ```
1809///
1810/// - Create a [`HeapArray`] from a given element and size:
1811///
1812/// ```
1813/// # use heap_array::heap_array;
1814/// let v = heap_array![1; 3];
1815/// assert_eq!(*v, [1, 1, 1]);
1816/// ```
1817///
1818/// Note that unlike array expressions this syntax supports all elements
1819/// which implement [`Clone`] and the number of elements doesn't have to be
1820/// a constant.
1821///
1822/// This will use `clone` to duplicate an expression, so one should be careful
1823/// using this with types having a nonstandard `Clone` implementation. For
1824/// example, `heap_array![Rc::new(1); 5]` will create a heap-array of five references
1825/// to the same boxed integer value, not five references pointing to independently
1826/// boxed integers.
1827///
1828/// Also, note that `heap_array![expr; 0]` is allowed, and produces an empty HeapArray.
1829/// This will still evaluate `expr`, however, and immediately drop the resulting value, so
1830/// be mindful of side effects.
1831///
1832/// [`HeapArray`]: HeapArray
1833#[macro_export]
1834macro_rules! heap_array {
1835 [] => { $crate::HeapArray::new() };
1836 [$($x:expr),+] => { $crate::HeapArray::from([$($x),+]) };
1837 [$elem:expr; 0] => {{$elem; $crate::HeapArray::new()}};
1838 [$elem:expr; $n:expr] => { $crate::HeapArray::from_element($n, $elem) };
1839}