commonlibsse_ng\re\t/
TESBox.rs

1// Unstable Rust code
2//
3// SPDX-FileCopyrightText: (c) The Rust Project Contributors
4// SPDX-License-Identifier: Apache-2.0 OR MIT
5// - https://github.com/rust-lang/rust/blob/master/LICENSE-MIT
6//! The `TESBox<T>` type for heap allocation.
7//!
8//! [`TESBox<T>`], casually referred to as a 'box', provides the simplest form of
9//! heap allocation in Rust. Boxes provide ownership for this allocation, and
10//! drop their contents when they go out of scope. Boxes also ensure that they
11//! never allocate more than `isize::MAX` bytes.
12//!
13//! # Examples
14//!
15//! Move a value from the stack to the heap by creating a [`Box`]:
16//!
17//! ```
18//! # use commonlibsse_ng::re::TESBox::TESBox;
19//! let val: u8 = 5;
20//! let boxed: TESBox<u8> = TESBox::new(val);
21//! ```
22//!
23//! Move a value from a [`Box`] back to the stack by [dereferencing]:
24//!
25//! ```
26//! # use commonlibsse_ng::re::TESBox::TESBox;
27//! let boxed: TESBox<u8> = TESBox::new(5);
28//! let val: u8 = *boxed;
29//! ```
30//!
31//! Creating a recursive data structure:
32//!
33//! ```
34//! # use commonlibsse_ng::re::TESBox::TESBox;
35//! # #[allow(dead_code)]
36//! #[derive(Debug)]
37//! enum List<T> {
38//!     Cons(T, TESBox<List<T>>),
39//!     Nil,
40//! }
41//!
42//! let list: List<i32> = List::Cons(1, TESBox::new(List::Cons(2, TESBox::new(List::Nil))));
43//! println!("{list:?}");
44//! ```
45//!
46//! This will print `Cons(1, Cons(2, Nil))`.
47//!
48//! Recursive structures must be boxed, because if the definition of `Cons`
49//! looked like this:
50//!
51//! ```compile_fail,E0072
52//! # enum List<T> {
53//! Cons(T, List<T>),
54//! # }
55//! ```
56//!
57//! It wouldn't work. This is because the size of a `List` depends on how many
58//! elements are in the list, and so we don't know how much memory to allocate
59//! for a `Cons`. By introducing a [`TESBox<T>`], which has a defined size, we know how
60//! big `Cons` needs to be.
61//!
62//! # Memory layout
63//!
64//! For non-zero-sized values, a [`Box`] will use the [`Global`] allocator for its allocation. It is
65//! valid to convert both ways between a [`Box`] and a raw pointer allocated with the [`Global`]
66//! allocator, given that the [`Layout`] used with the allocator is correct for the type and the raw
67//! pointer points to a valid value of the right type. More precisely, a `value: *mut T` that has
68//! been allocated with the [`Global`] allocator with `Layout::for_value(&*value)` may be converted
69//! into a box using [`Box::<T>::from_raw(value)`]. Conversely, the memory backing a `value: *mut T`
70//! obtained from [`Box::<T>::into_raw`] may be deallocated using the [`Global`] allocator with
71//! [`Layout::for_value(&*value)`].
72//!
73//! For zero-sized values, the `Box` pointer has to be non-null and sufficiently aligned. The
74//! recommended way to build a Box to a ZST if `Box::new` cannot be used is to use
75//! [`ptr::NonNull::dangling`].
76//!
77//! On top of these basic layout requirements, a `TESBox<T>` must point to a valid value of `T`.
78//!
79//! So long as `T: Sized`, a `TESBox<T>` is guaranteed to be represented
80//! as a single pointer and is also ABI-compatible with C pointers
81//! (i.e. the C type `T*`). This means that if you have extern "C"
82//! Rust functions that will be called from C, you can define those
83//! Rust functions using `TESBox<T>` types, and use `T*` as corresponding
84//! type on the C side. As an example, consider this C header which
85//! declares functions that create and destroy some kind of `Foo`
86//! value:
87//!
88//! ```c
89//! /* C header */
90//!
91//! /* Returns ownership to the caller */
92//! struct Foo* foo_new(void);
93//!
94//! /* Takes ownership from the caller; no-op when invoked with null */
95//! void foo_delete(struct Foo*);
96//! ```
97//!
98//! These two functions might be implemented in Rust as follows. Here, the
99//! `struct Foo*` type from C is translated to `TESBox<Foo>`, which captures
100//! the ownership constraints. Note also that the nullable argument to
101//! `foo_delete` is represented in Rust as `Option<TESBox<Foo>>`, since `TESBox<Foo>`
102//! cannot be null.
103//!
104//! ```
105//! # use commonlibsse_ng::re::TESBox::TESBox;
106//! #[repr(C)]
107//! pub struct Foo;
108//!
109//! #[unsafe(no_mangle)]
110//! pub extern "C" fn foo_new() -> TESBox<Foo> {
111//!     TESBox::new(Foo)
112//! }
113//!
114//! #[unsafe(no_mangle)]
115//! pub extern "C" fn foo_delete(_: Option<TESBox<Foo>>) {}
116//! ```
117//!
118//! Even though `TESBox<T>` has the same representation and C ABI as a C pointer,
119//! this does not mean that you can convert an arbitrary `T*` into a `TESBox<T>`
120//! and expect things to work. `TESBox<T>` values will always be fully aligned,
121//! non-null pointers. Moreover, the destructor for `TESBox<T>` will attempt to
122//! free the value with the global allocator. In general, the best practice
123//! is to only use `TESBox<T>` for pointers that originated from the global
124//! allocator.
125//!
126//! **Important.** At least at present, you should avoid using
127//! `TESBox<T>` types for functions that are defined in C but invoked
128//! from Rust. In those cases, you should directly mirror the C types
129//! as closely as possible. Using types like `TESBox<T>` where the C
130//! definition is just using `T*` can lead to undefined behavior, as
131//! described in [rust-lang/unsafe-code-guidelines#198][ucg#198].
132//!
133//! # Considerations for unsafe code
134//!
135//! **Warning: This section is not normative and is subject to change, possibly
136//! being relaxed in the future! It is a simplified summary of the rules
137//! currently implemented in the compiler.**
138//!
139//! The aliasing rules for `TESBox<T>` are the same as for `&mut T`. `TESBox<T>`
140//! asserts uniqueness over its content. Using raw pointers derived from a box
141//! after that box has been mutated through, moved or borrowed as `&mut T`
142//! is not allowed. For more guidance on working with box from unsafe code, see
143//! [rust-lang/unsafe-code-guidelines#326][ucg#326].
144//!
145//! # Editions
146//!
147//! A special case exists for the implementation of `IntoIterator` for arrays on the Rust 2021
148//! edition, as documented [here][array]. Unfortunately, it was later found that a similar
149//! workaround should be added for boxed slices, and this was applied in the 2024 edition.
150//!
151//! Specifically, `IntoIterator` is implemented for `TESBox<[T]>` on all editions, but specific calls
152//! to `into_iter()` for boxed slices will defer to the slice implementation on editions before
153//! 2024:
154//!
155//! ```rust,edition2021
156//! # use commonlibsse_ng::re::TESBox::TESBox;
157//! // Rust 2015, 2018, and 2021:
158//!
159//! // # #![allow(boxed_slice_into_iter)] // override our `deny(warnings)`
160//! let boxed_slice: Box<[i32]> = vec![0; 3].into_boxed_slice();
161//!
162//! // This creates a slice iterator, producing references to each value.
163//! for item in boxed_slice.into_iter().enumerate() {
164//!     let (i, x): (usize, &i32) = item;
165//!     println!("boxed_slice[{i}] = {x}");
166//! }
167//!
168//! // The `boxed_slice_into_iter` lint suggests this change for future compatibility:
169//! for item in boxed_slice.iter().enumerate() {
170//!     let (i, x): (usize, &i32) = item;
171//!     println!("boxed_slice[{i}] = {x}");
172//! }
173//!
174//! // You can explicitly iterate a boxed slice by value using `IntoIterator::into_iter`
175//! for item in IntoIterator::into_iter(boxed_slice).enumerate() {
176//!     let (i, x): (usize, i32) = item;
177//!     println!("boxed_slice[{i}] = {x}");
178//! }
179//! ```
180//!
181//! Similar to the array implementation, this may be modified in the future to remove this override,
182//! and it's best to avoid relying on this edition-dependent behavior if you wish to preserve
183//! compatibility with future versions of the compiler.
184//!
185//! [ucg#198]: https://github.com/rust-lang/unsafe-code-guidelines/issues/198
186//! [ucg#326]: https://github.com/rust-lang/unsafe-code-guidelines/issues/326
187//! [dereferencing]: core::ops::Deref
188//! [`Box::<T>::from_raw(value)`]: TESBox::from_raw
189//! [`Global`]: crate::alloc::Global
190//! [`Layout`]: crate::alloc::Layout
191//! [`Layout::for_value(&*value)`]: crate::alloc::Layout::for_value
192//! [valid]: ptr#safety
193#![allow(clippy::explicit_auto_deref)]
194#![allow(clippy::missing_const_for_fn)]
195#![allow(clippy::missing_errors_doc)]
196#![allow(clippy::option_if_let_else)]
197#![allow(clippy::ptr_as_ptr)]
198#![allow(clippy::use_self)]
199
200use core::borrow::{Borrow, BorrowMut};
201use core::cmp::Ordering;
202use core::error::Error;
203use core::hash::{Hash, Hasher};
204use core::mem::{self};
205use core::ops::{Deref, DerefMut};
206use core::pin::Pin;
207use core::ptr::NonNull;
208use core::{fmt, ptr};
209use std::alloc::handle_alloc_error;
210
211use crate::re::MemoryManager::TESGlobalAlloc as Global;
212use core::alloc::Layout;
213use stdx::{
214    alloc::{AllocError, Allocator},
215    ptr::Unique,
216};
217
218// The declaration of the `Box` struct must be kept in sync with the
219// compiler or ICEs will happen.
220
221/// Heap memory allocation smart pointer that `MemoryManager` `malloc` and `free` trigger by default.
222///
223/// The allocator side is always of type zero size and represents `owned *mut ptr`. (i.e. size is type ptr)
224// #[repr(transparent)] // FIXME: maybe need this.
225///
226/// # Examples
227///
228/// ```
229/// # use commonlibsse_ng::re::TESBox::TESBox;
230/// let five = TESBox::new(5);
231/// ```
232pub struct TESBox<T: ?Sized, A: Allocator = Global>(Unique<T>, A);
233const _: () = assert!(core::mem::size_of::<TESBox<()>>() == core::mem::size_of::<usize>());
234
235// #[repr(transparent)]
236// pub struct TESBox<T: ?Sized, A: Allocator = Global>(Unique<T>, core::marker::PhantomData<A>);
237// const _: () = assert!(core::mem::size_of::<TESBox<()>>() == core::mem::size_of::<usize>());
238
239impl<T> TESBox<T> {
240    /// Allocates memory on the heap and then places `x` into it.
241    ///
242    /// This doesn't actually allocate if `T` is zero-sized.
243    ///
244    /// # Examples
245    ///
246    /// ```
247    /// # use commonlibsse_ng::re::TESBox::TESBox;
248    /// let five = TESBox::new(5);
249    /// ```
250    #[inline(always)]
251    #[must_use]
252    #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
253    pub fn new(x: T) -> Self {
254        Self::new_in(x, Global)
255    }
256
257    /// Constructs a new box with uninitialized contents.
258    ///
259    /// # Examples
260    ///
261    /// ```
262    /// # use commonlibsse_ng::re::TESBox::TESBox;
263    /// let mut five = TESBox::<u32>::new_uninit();
264    /// // Deferred initialization:
265    /// five.write(5);
266    /// let five = unsafe { five.assume_init() };
267    ///
268    /// assert_eq!(*five, 5)
269    /// ```
270    #[must_use]
271    #[inline]
272    pub fn new_uninit() -> TESBox<mem::MaybeUninit<T>> {
273        Self::new_uninit_in(Global)
274    }
275
276    /// Allocates memory on the heap then places `x` into it,
277    /// returning an error if the allocation fails
278    ///
279    /// This doesn't actually allocate if `T` is zero-sized.
280    ///
281    /// # Examples
282    ///
283    /// ```
284    /// # use commonlibsse_ng::re::TESBox::TESBox;
285    ///
286    /// let five = TESBox::try_new(5)?;
287    /// # Ok::<(), stdx::alloc::AllocError>(())
288    /// ```
289    #[inline]
290    pub fn try_new(x: T) -> Result<Self, AllocError> {
291        Self::try_new_in(x, Global)
292    }
293}
294
295impl<T, A: Allocator> TESBox<T, A> {
296    /// Allocates memory in the given allocator then places `x` into it.
297    ///
298    /// This doesn't actually allocate if `T` is zero-sized.
299    ///
300    /// # Examples
301    ///
302    /// ```
303    /// # use commonlibsse_ng::re::TESBox::TESBox;
304    ///
305    /// use stdx::alloc::Global;
306    ///
307    /// let five = TESBox::new_in(5, Global);
308    /// ```
309    #[must_use]
310    #[inline]
311    pub fn new_in(x: T, alloc: A) -> Self
312    where
313        A: Allocator,
314    {
315        let mut boxed = Self::new_uninit_in(alloc);
316        boxed.write(x);
317        unsafe { boxed.assume_init() }
318    }
319
320    /// Allocates memory in the given allocator then places `x` into it,
321    /// returning an error if the allocation fails
322    ///
323    /// This doesn't actually allocate if `T` is zero-sized.
324    ///
325    /// # Examples
326    ///
327    /// ```
328    /// # use commonlibsse_ng::re::TESBox::TESBox;
329    ///
330    /// use stdx::alloc::Global;
331    ///
332    /// let five = TESBox::try_new_in(5, Global)?;
333    /// # Ok::<(), stdx::alloc::AllocError>(())
334    /// ```
335    #[inline]
336    pub fn try_new_in(x: T, alloc: A) -> Result<Self, AllocError>
337    where
338        A: Allocator,
339    {
340        let mut boxed = Self::try_new_uninit_in(alloc)?;
341        boxed.write(x);
342        unsafe { Ok(boxed.assume_init()) }
343    }
344
345    /// Constructs a new box with uninitialized contents in the provided allocator.
346    ///
347    /// # Examples
348    ///
349    /// ```
350    /// # use commonlibsse_ng::re::TESBox::TESBox;
351    ///
352    /// use stdx::alloc::Global;
353    ///
354    /// let mut five = TESBox::<u32, _>::new_uninit_in(Global);
355    /// // Deferred initialization:
356    /// five.write(5);
357    /// let five = unsafe { five.assume_init() };
358    ///
359    /// assert_eq!(*five, 5)
360    /// ```
361    #[must_use]
362    pub fn new_uninit_in(alloc: A) -> TESBox<mem::MaybeUninit<T>, A>
363    where
364        A: Allocator,
365    {
366        let layout = Layout::new::<mem::MaybeUninit<T>>();
367        // NOTE: Prefer match over unwrap_or_else since closure sometimes not inline-able.
368        // That would make code size bigger.
369        match Self::try_new_uninit_in(alloc) {
370            Ok(m) => m,
371            Err(_) => handle_alloc_error(layout),
372        }
373    }
374
375    /// Constructs a new box with uninitialized contents in the provided allocator,
376    /// returning an error if the allocation fails
377    ///
378    /// # Examples
379    ///
380    /// ```
381    /// # use commonlibsse_ng::re::TESBox::TESBox;
382    ///
383    /// use stdx::alloc::Global;
384    ///
385    /// let mut five = TESBox::<u32, _>::try_new_uninit_in(Global)?;
386    /// // Deferred initialization:
387    /// five.write(5);
388    /// let five = unsafe { five.assume_init() };
389    ///
390    /// assert_eq!(*five, 5);
391    /// # Ok::<(), stdx::alloc::AllocError>(())
392    /// ```
393    pub fn try_new_uninit_in(alloc: A) -> Result<TESBox<mem::MaybeUninit<T>, A>, AllocError>
394    where
395        A: Allocator,
396    {
397        let ptr = if core::mem::size_of::<T>() == 0 {
398            NonNull::dangling()
399        } else {
400            let layout = Layout::new::<mem::MaybeUninit<T>>();
401            alloc.allocate(layout)?.cast()
402        };
403        unsafe { Ok(TESBox::from_raw_in(ptr.as_ptr(), alloc)) }
404    }
405}
406
407impl<T> TESBox<[T]> {
408    /// Converts the boxed slice into a boxed array.
409    ///
410    /// This operation does not reallocate; the underlying array of the slice is simply reinterpreted as an array type.
411    ///
412    /// If `N` is not exactly equal to the length of `self`, then this method returns `None`.
413    #[inline]
414    #[must_use]
415    pub fn into_array<const N: usize>(self) -> Option<TESBox<[T; N]>> {
416        if self.len() == N {
417            let ptr = Self::into_raw(self).cast::<[T; N]>();
418
419            // SAFETY: The underlying array of a slice has the exact same layout as an actual array `[T; N]` if `N` is equal to the slice's length.
420            let me = unsafe { TESBox::from_raw(ptr) };
421            Some(me)
422        } else {
423            None
424        }
425    }
426}
427
428impl<T, A: Allocator> TESBox<mem::MaybeUninit<T>, A> {
429    /// Converts to `Box<T, A>`.
430    ///
431    /// # Safety
432    ///
433    /// As with [`MaybeUninit::assume_init`],
434    /// it is up to the caller to guarantee that the value
435    /// really is in an initialized state.
436    /// Calling this when the content is not yet fully initialized
437    /// causes immediate undefined behavior.
438    ///
439    /// [`MaybeUninit::assume_init`]: mem::MaybeUninit::assume_init
440    ///
441    /// # Examples
442    ///
443    /// ```
444    /// # use commonlibsse_ng::re::TESBox::TESBox;
445    /// let mut five = TESBox::<u32>::new_uninit();
446    /// // Deferred initialization:
447    /// five.write(5);
448    /// let five: TESBox<u32> = unsafe { five.assume_init() };
449    ///
450    /// assert_eq!(*five, 5)
451    /// ```
452    #[inline]
453    pub unsafe fn assume_init(self) -> TESBox<T, A> {
454        let (raw, alloc) = TESBox::into_raw_with_allocator(self);
455        unsafe { TESBox::from_raw_in(raw as *mut T, alloc) }
456    }
457
458    /// Writes the value and converts to `Box<T, A>`.
459    ///
460    /// This method converts the box similarly to [`Box::assume_init`] but
461    /// writes `value` into it before conversion thus guaranteeing safety.
462    /// In some scenarios use of this method may improve performance because
463    /// the compiler may be able to optimize copying from stack.
464    ///
465    /// # Examples
466    ///
467    /// ```
468    /// # use commonlibsse_ng::re::TESBox::TESBox;
469    ///
470    /// let big_box = TESBox::<[usize; 1024]>::new_uninit();
471    ///
472    /// let mut array = [0; 1024];
473    /// for (i, place) in array.iter_mut().enumerate() {
474    ///     *place = i;
475    /// }
476    ///
477    /// // The optimizer may be able to elide this copy, so previous code writes
478    /// // to heap directly.
479    /// let big_box = TESBox::write(big_box, array);
480    ///
481    /// for (i, x) in big_box.iter().enumerate() {
482    ///     assert_eq!(*x, i);
483    /// }
484    /// ```
485    #[inline]
486    pub fn write(mut boxed: Self, value: T) -> TESBox<T, A> {
487        unsafe {
488            (*boxed).write(value);
489            boxed.assume_init()
490        }
491    }
492}
493
494impl<T: ?Sized> TESBox<T> {
495    /// Constructs a box from a raw pointer.
496    ///
497    /// After calling this function, the raw pointer is owned by the
498    /// resulting `Box`. Specifically, the `Box` destructor will call
499    /// the destructor of `T` and free the allocated memory. For this
500    /// to be safe, the memory must have been allocated in accordance
501    /// with the [memory layout] used by `Box` .
502    ///
503    /// # Safety
504    ///
505    /// This function is unsafe because improper use may lead to
506    /// memory problems. For example, a double-free may occur if the
507    /// function is called twice on the same raw pointer.
508    ///
509    /// The raw pointer must point to a block of memory allocated by the global allocator.
510    ///
511    /// The safety conditions are described in the [memory layout] section.
512    ///
513    /// # Examples
514    ///
515    /// Recreate a `Box` which was previously converted to a raw pointer
516    /// using [`Box::into_raw`]:
517    /// ```
518    /// # use commonlibsse_ng::re::TESBox::TESBox;
519    /// let x = TESBox::new(5);
520    /// let ptr = TESBox::into_raw(x);
521    /// let x = unsafe { TESBox::from_raw(ptr) };
522    /// ```
523    /// Manually create a `Box` from scratch by using the global allocator:
524    /// ```
525    /// use std::alloc::{alloc, Layout};
526    /// use stdx::alloc::{Allocator, Global};
527    /// use commonlibsse_ng::re::TESBox::TESBox;
528    ///
529    /// unsafe {
530    ///     let ptr = alloc(Layout::new::<i32>()) as *mut i32;
531    ///     // In general .write is required to avoid attempting to destruct
532    ///     // the (uninitialized) previous contents of `ptr`, though for this
533    ///     // simple example `*ptr = 5` would have worked as well.
534    ///     ptr.write(5);
535    ///     let x = TESBox::from_raw(ptr);
536    /// }
537    /// ```
538    ///
539    /// [memory layout]: self#memory-layout
540    /// [`Layout`]: crate::Layout
541    #[inline]
542    #[must_use = "call `drop(Box::from_raw(ptr))` if you intend to drop the `Box`"]
543    pub const unsafe fn from_raw(raw: *mut T) -> Self {
544        unsafe { Self::from_raw_in(raw, Global) }
545    }
546
547    /// Constructs a box from a `NonNull` pointer.
548    ///
549    /// After calling this function, the `NonNull` pointer is owned by
550    /// the resulting `Box`. Specifically, the `Box` destructor will call
551    /// the destructor of `T` and free the allocated memory. For this
552    /// to be safe, the memory must have been allocated in accordance
553    /// with the [memory layout] used by `Box` .
554    ///
555    /// # Safety
556    ///
557    /// This function is unsafe because improper use may lead to
558    /// memory problems. For example, a double-free may occur if the
559    /// function is called twice on the same `NonNull` pointer.
560    ///
561    /// The non-null pointer must point to a block of memory allocated by the global allocator.
562    ///
563    /// The safety conditions are described in the [memory layout] section.
564    ///
565    /// # Examples
566    ///
567    /// Recreate a `Box` which was previously converted to a `NonNull`
568    /// pointer using [`Box::into_non_null`]:
569    /// ```
570    /// # use stdx::alloc::{Allocator, Global};
571    /// # use std::alloc::Layout;
572    /// # use commonlibsse_ng::re::TESBox::TESBox;
573    ///
574    /// let x = TESBox::new(5);
575    /// let non_null = TESBox::into_non_null(x);
576    /// let x = unsafe { TESBox::from_non_null(non_null) };
577    /// ```
578    /// Manually create a `Box` from scratch by using the global allocator:
579    /// ```
580    /// use stdx::alloc::{Allocator, Global};
581    /// use std::alloc::{alloc, Layout};
582    /// use std::ptr::NonNull;
583    /// use commonlibsse_ng::re::TESBox::TESBox;
584    ///
585    /// unsafe {
586    ///     let non_null = NonNull::new(alloc(Layout::new::<i32>()).cast::<i32>())
587    ///         .expect("allocation failed");
588    ///     // In general .write is required to avoid attempting to destruct
589    ///     // the (uninitialized) previous contents of `non_null`.
590    ///     non_null.write(5);
591    ///     let x = TESBox::from_non_null(non_null);
592    /// }
593    /// ```
594    ///
595    /// [memory layout]: self#memory-layout
596    /// [`Layout`]: crate::Layout
597    #[inline]
598    #[must_use = "call `drop(Box::from_non_null(ptr))` if you intend to drop the `Box`"]
599    pub unsafe fn from_non_null(ptr: NonNull<T>) -> Self {
600        unsafe { Self::from_raw(ptr.as_ptr()) }
601    }
602}
603
604impl<T: ?Sized, A: Allocator> TESBox<T, A> {
605    /// Constructs a box from a raw pointer in the given allocator.
606    ///
607    /// After calling this function, the raw pointer is owned by the
608    /// resulting `Box`. Specifically, the `Box` destructor will call
609    /// the destructor of `T` and free the allocated memory. For this
610    /// to be safe, the memory must have been allocated in accordance
611    /// with the [memory layout] used by `Box` .
612    ///
613    /// # Safety
614    ///
615    /// This function is unsafe because improper use may lead to
616    /// memory problems. For example, a double-free may occur if the
617    /// function is called twice on the same raw pointer.
618    ///
619    /// The raw pointer must point to a block of memory allocated by `alloc`.
620    ///
621    /// # Examples
622    ///
623    /// Recreate a `Box` which was previously converted to a raw pointer
624    /// using [`Box::into_raw_with_allocator`]:
625    /// ```
626    ///
627    /// # use commonlibsse_ng::re::TESBox::TESBox;
628    /// use stdx::alloc::Global;
629    ///
630    /// let x = TESBox::new_in(5, Global);
631    /// let (ptr, alloc) = TESBox::into_raw_with_allocator(x);
632    /// let x = unsafe { TESBox::from_raw_in(ptr, alloc) };
633    /// ```
634    /// Manually create a `Box` from scratch by using the system allocator:
635    /// ```
636    ///
637    /// // use std::alloc::Layout;
638    /// // use stdx::alloc::{Allocator, Global};
639    /// // use commonlibsse_ng::re::TESBox::TESBox;
640    ///
641    /// // unsafe {
642    /// //     let ptr = Global.allocate(Layout::new::<i32>())?.as_mut_ptr() as *mut i32;
643    /// //     // In general .write is required to avoid attempting to destruct
644    /// //     // the (uninitialized) previous contents of `ptr`, though for this
645    /// //     // simple example `*ptr = 5` would have worked as well.
646    /// //     ptr.write(5);
647    /// //     let x = TESBox::from_raw_in(ptr, Global);
648    /// // }
649    /// // # Ok::<(), stdx::alloc::AllocError>(())
650    /// ```
651    ///
652    /// [memory layout]: self#memory-layout
653    /// [`Layout`]: crate::Layout
654    #[inline]
655    pub const unsafe fn from_raw_in(raw: *mut T, alloc: A) -> Self {
656        TESBox(unsafe { Unique::new_unchecked(raw) }, alloc)
657    }
658
659    /// Constructs a box from a `NonNull` pointer in the given allocator.
660    ///
661    /// After calling this function, the `NonNull` pointer is owned by
662    /// the resulting `Box`. Specifically, the `Box` destructor will call
663    /// the destructor of `T` and free the allocated memory. For this
664    /// to be safe, the memory must have been allocated in accordance
665    /// with the [memory layout] used by `Box` .
666    ///
667    /// # Safety
668    ///
669    /// This function is unsafe because improper use may lead to
670    /// memory problems. For example, a double-free may occur if the
671    /// function is called twice on the same raw pointer.
672    ///
673    /// The non-null pointer must point to a block of memory allocated by `alloc`.
674    ///
675    /// # Examples
676    ///
677    /// Recreate a `Box` which was previously converted to a `NonNull` pointer
678    /// using [`Box::into_non_null_with_allocator`]:
679    /// ```
680    ///
681    /// use stdx::alloc::Global;
682    /// use commonlibsse_ng::re::TESBox::TESBox;
683    ///
684    /// let x = TESBox::new_in(5, Global);
685    /// let (non_null, alloc) = TESBox::into_non_null_with_allocator(x);
686    /// let x = unsafe { TESBox::from_non_null_in(non_null, alloc) };
687    /// ```
688    /// Manually create a `Box` from scratch by using the system allocator:
689    /// ```
690    /// use std::alloc::Layout;
691    /// use stdx::alloc::{Allocator, Global};
692    /// use commonlibsse_ng::re::TESBox::TESBox;
693    ///
694    /// unsafe {
695    ///     let non_null = Global.allocate(Layout::new::<i32>())?.cast::<i32>();
696    ///     // In general .write is required to avoid attempting to destruct
697    ///     // the (uninitialized) previous contents of `non_null`.
698    ///     non_null.write(5);
699    ///     let x = TESBox::from_non_null_in(non_null, Global);
700    /// }
701    /// # Ok::<(), stdx::alloc::AllocError>(())
702    /// ```
703    ///
704    /// [memory layout]: self#memory-layout
705    /// [`Layout`]: crate::Layout
706    #[inline]
707    pub const unsafe fn from_non_null_in(raw: NonNull<T>, alloc: A) -> Self {
708        // SAFETY: guaranteed by the caller.
709        unsafe { TESBox::from_raw_in(raw.as_ptr(), alloc) }
710    }
711
712    /// Consumes the `Box`, returning a wrapped raw pointer.
713    ///
714    /// The pointer will be properly aligned and non-null.
715    ///
716    /// After calling this function, the caller is responsible for the
717    /// memory previously managed by the `Box`. In particular, the
718    /// caller should properly destroy `T` and release the memory, taking
719    /// into account the [memory layout] used by `Box`. The easiest way to
720    /// do this is to convert the raw pointer back into a `Box` with the
721    /// [`Box::from_raw`] function, allowing the `Box` destructor to perform
722    /// the cleanup.
723    ///
724    /// Note: this is an associated function, which means that you have
725    /// to call it as `Box::into_raw(b)` instead of `b.into_raw()`. This
726    /// is so that there is no conflict with a method on the inner type.
727    ///
728    /// # Examples
729    /// Converting the raw pointer back into a `Box` with [`Box::from_raw`]
730    /// for automatic cleanup:
731    /// ```
732    /// # use commonlibsse_ng::re::TESBox::TESBox;
733    /// let x = TESBox::new(String::from("Hello"));
734    /// let ptr = TESBox::into_raw(x);
735    /// let x = unsafe { TESBox::from_raw(ptr) };
736    /// ```
737    /// Manual cleanup by explicitly running the destructor and deallocating
738    /// the memory:
739    /// ```
740    /// use std::alloc::{dealloc, Layout};
741    /// use std::ptr;
742    /// # use commonlibsse_ng::re::TESBox::TESBox;
743    ///
744    /// let x = TESBox::new(String::from("Hello"));
745    /// let ptr = TESBox::into_raw(x);
746    /// unsafe {
747    ///     ptr::drop_in_place(ptr);
748    ///     dealloc(ptr as *mut u8, Layout::new::<String>());
749    /// }
750    /// ```
751    /// Note: This is equivalent to the following:
752    /// ```
753    /// # use commonlibsse_ng::re::TESBox::TESBox;
754    /// let x = TESBox::new(String::from("Hello"));
755    /// let ptr = TESBox::into_raw(x);
756    /// unsafe {
757    ///     drop(TESBox::from_raw(ptr));
758    /// }
759    /// ```
760    ///
761    /// [memory layout]: self#memory-layout
762    #[must_use = "losing the pointer will leak memory"]
763    #[inline]
764    pub fn into_raw(b: Self) -> *mut T {
765        // Make sure Miri realizes that we transition from a noalias pointer to a raw pointer here.
766        &raw mut *Self::into_raw_with_allocator(b).0
767    }
768
769    /// Consumes the `Box`, returning a wrapped `NonNull` pointer.
770    ///
771    /// The pointer will be properly aligned.
772    ///
773    /// After calling this function, the caller is responsible for the
774    /// memory previously managed by the `Box`. In particular, the
775    /// caller should properly destroy `T` and release the memory, taking
776    /// into account the [memory layout] used by `Box`. The easiest way to
777    /// do this is to convert the `NonNull` pointer back into a `Box` with the
778    /// [`Box::from_non_null`] function, allowing the `Box` destructor to
779    /// perform the cleanup.
780    ///
781    /// Note: this is an associated function, which means that you have
782    /// to call it as `Box::into_non_null(b)` instead of `b.into_non_null()`.
783    /// This is so that there is no conflict with a method on the inner type.
784    ///
785    /// # Examples
786    /// Converting the `NonNull` pointer back into a `Box` with [`Box::from_non_null`]
787    /// for automatic cleanup:
788    /// ```
789    /// use commonlibsse_ng::re::TESBox::TESBox;
790    ///
791    /// let x = TESBox::new(String::from("Hello"));
792    /// let non_null = TESBox::into_non_null(x);
793    /// let x = unsafe { TESBox::from_non_null(non_null) };
794    /// ```
795    /// Manual cleanup by explicitly running the destructor and deallocating
796    /// the memory:
797    /// ```
798    ///
799    /// use std::alloc::{dealloc, Layout};
800    /// use commonlibsse_ng::re::TESBox::TESBox;
801    ///
802    /// let x = TESBox::new(String::from("Hello"));
803    /// let non_null = TESBox::into_non_null(x);
804    /// unsafe {
805    ///     non_null.drop_in_place();
806    ///     dealloc(non_null.as_ptr().cast::<u8>(), Layout::new::<String>());
807    /// }
808    /// ```
809    /// Note: This is equivalent to the following:
810    /// ```
811    /// use commonlibsse_ng::re::TESBox::TESBox;
812    ///
813    /// let x = TESBox::new(String::from("Hello"));
814    /// let non_null = TESBox::into_non_null(x);
815    /// unsafe {
816    ///     drop(TESBox::from_non_null(non_null));
817    /// }
818    /// ```
819    ///
820    /// [memory layout]: self#memory-layout
821    #[must_use = "losing the pointer will leak memory"]
822    #[inline]
823    pub fn into_non_null(b: Self) -> NonNull<T> {
824        // SAFETY: `Box` is guaranteed to be non-null.
825        unsafe { NonNull::new_unchecked(Self::into_raw(b)) }
826    }
827
828    /// Consumes the `Box`, returning a wrapped raw pointer and the allocator.
829    ///
830    /// The pointer will be properly aligned and non-null.
831    ///
832    /// After calling this function, the caller is responsible for the
833    /// memory previously managed by the `Box`. In particular, the
834    /// caller should properly destroy `T` and release the memory, taking
835    /// into account the [memory layout] used by `Box`. The easiest way to
836    /// do this is to convert the raw pointer back into a `Box` with the
837    /// [`Box::from_raw_in`] function, allowing the `Box` destructor to perform
838    /// the cleanup.
839    ///
840    /// Note: this is an associated function, which means that you have
841    /// to call it as `Box::into_raw_with_allocator(b)` instead of `b.into_raw_with_allocator()`. This
842    /// is so that there is no conflict with a method on the inner type.
843    ///
844    /// # Examples
845    /// Converting the raw pointer back into a `Box` with [`Box::from_raw_in`]
846    /// for automatic cleanup:
847    /// ```
848    ///
849    /// use stdx::alloc::Global;
850    /// use commonlibsse_ng::re::TESBox::TESBox;
851    ///
852    /// let x = TESBox::new_in(String::from("Hello"), Global);
853    /// let (ptr, alloc) = TESBox::into_raw_with_allocator(x);
854    /// let x = unsafe { TESBox::from_raw_in(ptr, alloc) };
855    /// ```
856    /// Manual cleanup by explicitly running the destructor and deallocating
857    /// the memory:
858    /// ```
859    ///
860    /// use std::alloc::Layout;
861    /// use std::ptr::{self, NonNull};
862    /// use stdx::alloc::{Allocator, Global};
863    /// use commonlibsse_ng::re::TESBox::TESBox;
864    ///
865    /// let x = TESBox::new_in(String::from("Hello"), Global);
866    /// let (ptr, alloc) = TESBox::into_raw_with_allocator(x);
867    /// unsafe {
868    ///     ptr::drop_in_place(ptr);
869    ///     let non_null = NonNull::new_unchecked(ptr);
870    ///     alloc.deallocate(non_null.cast(), Layout::new::<String>());
871    /// }
872    /// ```
873    ///
874    /// [memory layout]: self#memory-layout
875    #[must_use = "losing the pointer will leak memory"]
876    #[inline]
877    pub fn into_raw_with_allocator(b: Self) -> (*mut T, A) {
878        let mut b = mem::ManuallyDrop::new(b);
879        // We carefully get the raw pointer out in a way that Miri's aliasing model understands what
880        // is happening: using the primitive "deref" of `Box`. In case `A` is *not* `Global`, we
881        // want *no* aliasing requirements here!
882        // In case `A` *is* `Global`, this does not quite have the right behavior; `into_raw`
883        // works around that.
884        let ptr = &raw mut **b;
885        let alloc = unsafe { ptr::read(&b.1) };
886        (ptr, alloc)
887    }
888
889    /// Consumes the `TESBox`, returning a wrapped `NonNull` pointer and the allocator.
890    ///
891    /// The pointer will be properly aligned.
892    ///
893    /// After calling this function, the caller is responsible for the
894    /// memory previously managed by the `Box`. In particular, the
895    /// caller should properly destroy `T` and release the memory, taking
896    /// into account the [memory layout] used by `TESBox`. The easiest way to
897    /// do this is to convert the `NonNull` pointer back into a `Box` with the
898    /// [`TESBox::from_non_null_in`] function, allowing the `Box` destructor to
899    /// perform the cleanup.
900    ///
901    /// Note: this is an associated function, which means that you have
902    /// to call it as `Box::into_non_null_with_allocator(b)` instead of
903    /// `b.into_non_null_with_allocator()`. This is so that there is no
904    /// conflict with a method on the inner type.
905    ///
906    /// # Examples
907    /// Converting the `NonNull` pointer back into a `Box` with
908    /// [`Box::from_non_null_in`] for automatic cleanup:
909    /// ```
910    ///
911    /// # use commonlibsse_ng::re::TESBox::TESBox;
912    /// use stdx::alloc::Global;
913    ///
914    /// let x = TESBox::new_in(String::from("Hello"), Global);
915    /// let (non_null, alloc) = TESBox::into_non_null_with_allocator(x);
916    /// let x = unsafe { TESBox::from_non_null_in(non_null, alloc) };
917    /// ```
918    /// Manual cleanup by explicitly running the destructor and deallocating
919    /// the memory:
920    /// ```
921    ///
922    /// use stdx::alloc::{Allocator, Global};
923    /// use std::alloc::Layout;
924    /// use commonlibsse_ng::re::TESBox::TESBox;
925    ///
926    /// let x = TESBox::new_in(String::from("Hello"), Global);
927    /// let (non_null, alloc) = TESBox::into_non_null_with_allocator(x);
928    /// unsafe {
929    ///     non_null.drop_in_place();
930    ///     alloc.deallocate(non_null.cast::<u8>(), Layout::new::<String>());
931    /// }
932    /// ```
933    ///
934    /// [memory layout]: self#memory-layout
935    #[must_use = "losing the pointer will leak memory"]
936    #[inline]
937    pub fn into_non_null_with_allocator(b: Self) -> (NonNull<T>, A) {
938        let (ptr, alloc) = TESBox::into_raw_with_allocator(b);
939        // SAFETY: `Box` is guaranteed to be non-null.
940        unsafe { (NonNull::new_unchecked(ptr), alloc) }
941    }
942
943    /// Returns a raw mutable pointer to the `Box`'s contents.
944    ///
945    /// The caller must ensure that the `Box` outlives the pointer this
946    /// function returns, or else it will end up dangling.
947    ///
948    /// This method guarantees that for the purpose of the aliasing model, this method
949    /// does not materialize a reference to the underlying memory, and thus the returned pointer
950    /// will remain valid when mixed with other calls to [`as_ptr`] and [`as_mut_ptr`].
951    /// Note that calling other methods that materialize references to the memory
952    /// may still invalidate this pointer.
953    /// See the example below for how this guarantee can be used.
954    ///
955    /// # Examples
956    ///
957    /// Due to the aliasing guarantee, the following code is legal:
958    ///
959    /// ```rust
960    /// use commonlibsse_ng::re::TESBox::TESBox;
961    ///
962    /// unsafe {
963    ///     let mut b = TESBox::new(0);
964    ///     let ptr1 = TESBox::as_mut_ptr(&mut b);
965    ///     ptr1.write(1);
966    ///     let ptr2 = TESBox::as_mut_ptr(&mut b);
967    ///     ptr2.write(2);
968    ///     // Notably, the write to `ptr2` did *not* invalidate `ptr1`:
969    ///     ptr1.write(3);
970    /// }
971    /// ```
972    ///
973    /// [`as_mut_ptr`]: Self::as_mut_ptr
974    /// [`as_ptr`]: Self::as_ptr
975    #[inline]
976    pub fn as_mut_ptr(b: &mut Self) -> *mut T {
977        // This is a primitive deref, not going through `DerefMut`, and therefore not materializing
978        // any references.
979        &raw mut **b
980    }
981
982    /// Returns a raw pointer to the `Box`'s contents.
983    ///
984    /// The caller must ensure that the `Box` outlives the pointer this
985    /// function returns, or else it will end up dangling.
986    ///
987    /// The caller must also ensure that the memory the pointer (non-transitively) points to
988    /// is never written to (except inside an `UnsafeCell`) using this pointer or any pointer
989    /// derived from it. If you need to mutate the contents of the `Box`, use [`as_mut_ptr`].
990    ///
991    /// This method guarantees that for the purpose of the aliasing model, this method
992    /// does not materialize a reference to the underlying memory, and thus the returned pointer
993    /// will remain valid when mixed with other calls to [`as_ptr`] and [`as_mut_ptr`].
994    /// Note that calling other methods that materialize mutable references to the memory,
995    /// as well as writing to this memory, may still invalidate this pointer.
996    /// See the example below for how this guarantee can be used.
997    ///
998    /// # Examples
999    ///
1000    /// Due to the aliasing guarantee, the following code is legal:
1001    ///
1002    /// ```rust
1003    /// # use commonlibsse_ng::re::TESBox::TESBox;
1004    ///
1005    /// unsafe {
1006    ///     let mut v = TESBox::new(0);
1007    ///     let ptr1 = TESBox::as_ptr(&v);
1008    ///     let ptr2 = TESBox::as_mut_ptr(&mut v);
1009    ///     let _val = ptr2.read();
1010    ///     // No write to this memory has happened yet, so `ptr1` is still valid.
1011    ///     let _val = ptr1.read();
1012    ///     // However, once we do a write...
1013    ///     ptr2.write(1);
1014    ///     // ... `ptr1` is no longer valid.
1015    ///     // This would be UB: let _val = ptr1.read();
1016    /// }
1017    /// ```
1018    ///
1019    /// [`as_mut_ptr`]: Self::as_mut_ptr
1020    /// [`as_ptr`]: Self::as_ptr
1021    #[inline]
1022    pub fn as_ptr(b: &Self) -> *const T {
1023        // This is a primitive deref, not going through `DerefMut`, and therefore not materializing
1024        // any references.
1025        &raw const **b
1026    }
1027
1028    /// Returns a reference to the underlying allocator.
1029    ///
1030    /// Note: this is an associated function, which means that you have
1031    /// to call it as `Box::allocator(&b)` instead of `b.allocator()`. This
1032    /// is so that there is no conflict with a method on the inner type.
1033    #[inline]
1034    pub const fn allocator(b: &Self) -> &A {
1035        &b.1
1036    }
1037
1038    /// Consumes and leaks the `Box`, returning a mutable reference,
1039    /// `&'a mut T`.
1040    ///
1041    /// Note that the type `T` must outlive the chosen lifetime `'a`. If the type
1042    /// has only static references, or none at all, then this may be chosen to be
1043    /// `'static`.
1044    ///
1045    /// This function is mainly useful for data that lives for the remainder of
1046    /// the program's life. Dropping the returned reference will cause a memory
1047    /// leak. If this is not acceptable, the reference should first be wrapped
1048    /// with the [`Box::from_raw`] function producing a `Box`. This `Box` can
1049    /// then be dropped which will properly destroy `T` and release the
1050    /// allocated memory.
1051    ///
1052    /// Note: this is an associated function, which means that you have
1053    /// to call it as `Box::leak(b)` instead of `b.leak()`. This
1054    /// is so that there is no conflict with a method on the inner type.
1055    ///
1056    /// # Examples
1057    ///
1058    /// Simple usage:
1059    ///
1060    /// ```
1061    /// # use commonlibsse_ng::re::TESBox::TESBox;
1062    /// let x = TESBox::new(41);
1063    /// let static_ref: &'static mut usize = TESBox::leak(x);
1064    /// *static_ref += 1;
1065    /// assert_eq!(*static_ref, 42);
1066    /// # // FIXME(https://github.com/rust-lang/miri/issues/3670):
1067    /// # // use -Zmiri-disable-leak-check instead of unleaking in tests meant to leak.
1068    /// # drop(unsafe { TESBox::from_raw(static_ref) });
1069    /// ```
1070    ///
1071    /// Unsized data:
1072    ///
1073    /// ```
1074    /// # use commonlibsse_ng::re::TESBox::TESBox;
1075    /// // let x = vec![1, 2, 3].into_boxed_slice();
1076    /// // let static_ref = TESBox::leak(x);
1077    /// // static_ref[0] = 4;
1078    /// // assert_eq!(*static_ref, [4, 2, 3]);
1079    /// # // FIXME(https://github.com/rust-lang/miri/issues/3670):
1080    /// # // use -Zmiri-disable-leak-check instead of unleaking in tests meant to leak.
1081    /// // # drop(unsafe { TESBox::from_raw(static_ref) });
1082    /// ```
1083    #[inline]
1084    pub fn leak<'a>(b: Self) -> &'a mut T
1085    where
1086        A: 'a,
1087    {
1088        unsafe { &mut *TESBox::into_raw(b) }
1089    }
1090
1091    /// Converts a `TESBox<T>` into a `Pin<TESBox<T>>`. If `T` does not implement [`Unpin`], then
1092    /// `*boxed` will be pinned in memory and unable to be moved.
1093    ///
1094    /// This conversion does not allocate on the heap and happens in place.
1095    ///
1096    /// This is also available via [`From`].
1097    ///
1098    /// Constructing and pinning a `TESBox` with <code>TESBox::into_pin([TESBox::new]\(x))</code>
1099    /// can also be written more concisely using <code>[TESBox::pin]\(x)</code>.
1100    /// This `into_pin` method is useful if you already have a `TESBox<T>`, or you are
1101    /// constructing a (pinned) `TESBox` in a different way than with [`TESBox::new`].
1102    ///
1103    /// # Notes
1104    ///
1105    /// It's not recommended that crates add an impl like `From<TESBox<T>> for Pin<T>`,
1106    /// as it'll introduce an ambiguity when calling `Pin::from`.
1107    /// A demonstration of such a poor impl is shown below.
1108    ///
1109    /// ```compile_fail
1110    /// # use std::pin::Pin;
1111    /// # use commonlibsse_ng::re::TESBox::TESBox;
1112    /// struct Foo; // A type defined in this crate.
1113    /// impl From<TESBox<()>> for Pin<Foo> {
1114    ///     fn from(_: TESBox<()>) -> Pin<Foo> {
1115    ///         Pin::new(Foo)
1116    ///     }
1117    /// }
1118    ///
1119    /// let foo = TESBox::new(());
1120    /// let bar = Pin::from(foo);
1121    /// ```
1122    pub const fn into_pin(boxed: Self) -> Pin<Self>
1123    where
1124        A: 'static,
1125    {
1126        // It's not possible to move or replace the insides of a `Pin<TESBox<T>>`
1127        // when `T: !Unpin`, so it's safe to pin it directly without any
1128        // additional requirements.
1129        unsafe { Pin::new_unchecked(boxed) }
1130    }
1131}
1132
1133impl<T: ?Sized, A: Allocator> Drop for TESBox<T, A> {
1134    #[inline]
1135    fn drop(&mut self) {
1136        // the T in the Box is dropped by the compiler before the destructor is run
1137
1138        let ptr = self.0;
1139
1140        unsafe {
1141            let layout = Layout::for_value::<T>(&**self);
1142            if layout.size() != 0 {
1143                self.1.deallocate(ptr.as_non_null_ptr().cast(), layout);
1144            }
1145        }
1146    }
1147}
1148
1149impl<T: Default> Default for TESBox<T> {
1150    /// Creates a `TESBox<T>`, with the `Default` value for T.
1151    #[inline]
1152    fn default() -> Self {
1153        TESBox::write(TESBox::new_uninit(), T::default())
1154    }
1155}
1156
1157impl<T> Default for TESBox<[T]> {
1158    #[inline]
1159    fn default() -> Self {
1160        // SAFETY: [T; 0] is a valid allocation
1161        let layout = Layout::array::<T>(0).unwrap();
1162        let Ok(ptr) = Global::allocate(&Global, layout) else {
1163            panic!("TESBox: allocation failed for empty slice");
1164        };
1165
1166        let slice = unsafe { core::slice::from_raw_parts_mut(ptr.cast().as_ptr(), 0) };
1167        let slice = unsafe { NonNull::new_unchecked(slice as *mut [T]) };
1168        unsafe { Self::from_raw_in(slice.as_ptr(), Global) }
1169    }
1170}
1171
1172impl<T: Clone, A: Allocator + Clone> Clone for TESBox<T, A> {
1173    /// Returns a new box with a `clone()` of this box's contents.
1174    ///
1175    /// # Examples
1176    ///
1177    /// ```
1178    /// # use commonlibsse_ng::re::TESBox::TESBox;
1179    /// let x = TESBox::new(5);
1180    /// let y = x.clone();
1181    ///
1182    /// // The value is the same
1183    /// assert_eq!(x, y);
1184    ///
1185    /// // But they are unique objects
1186    /// assert_ne!(&*x as *const i32, &*y as *const i32);
1187    /// ```
1188    #[inline]
1189    fn clone(&self) -> Self {
1190        let cloned = (**self).clone();
1191        TESBox::new_in(cloned, self.1.clone())
1192    }
1193
1194    /// Copies `source`'s contents into `self` without creating a new allocation.
1195    ///
1196    /// # Examples
1197    ///
1198    /// ```
1199    /// # use commonlibsse_ng::re::TESBox::TESBox;
1200    /// let x = TESBox::new(5);
1201    /// let mut y = TESBox::new(10);
1202    /// let yp: *const i32 = &*y;
1203    ///
1204    /// y.clone_from(&x);
1205    ///
1206    /// // The value is the same
1207    /// assert_eq!(x, y);
1208    ///
1209    /// // And no allocation occurred
1210    /// assert_eq!(yp, &*y);
1211    /// ```
1212    #[inline]
1213    fn clone_from(&mut self, source: &Self) {
1214        (**self).clone_from(&(**source));
1215    }
1216}
1217
1218impl<T: Clone, A: Allocator + Clone> Clone for TESBox<[T], A> {
1219    fn clone(&self) -> Self {
1220        let mut vec: Vec<T> = self.iter().cloned().collect();
1221
1222        // -- from_vec_in --
1223        let len = vec.len();
1224        let ptr = vec.as_mut_ptr();
1225        // SAFETY: This was created from a Vec<T, A>
1226        let slice = unsafe { core::slice::from_raw_parts_mut(ptr, len) };
1227        let slice = unsafe { NonNull::new_unchecked(slice as *mut [T]) };
1228
1229        // Prevent Vec from dropping
1230        let _ = mem::ManuallyDrop::new(vec);
1231
1232        Self(unsafe { Unique::new_unchecked(slice.as_ptr()) }, self.1.clone())
1233    }
1234
1235    /// Copies `source`'s contents into `self` without creating a new allocation,
1236    /// so long as the two are of the same length.
1237    ///
1238    /// # Examples
1239    ///
1240    /// ```
1241    /// # use commonlibsse_ng::re::TESBox::TESBox;
1242    /// let x = TESBox::new([5, 6, 7]);
1243    /// let mut y = TESBox::new([8, 9, 10]);
1244    /// let yp: *const [i32] = &*y;
1245    ///
1246    /// y.clone_from(&x);
1247    ///
1248    /// // The value is the same
1249    /// assert_eq!(x, y);
1250    ///
1251    /// // And no allocation occurred
1252    /// assert_eq!(yp, &*y);
1253    /// ```
1254    fn clone_from(&mut self, source: &Self) {
1255        if self.len() == source.len() {
1256            self.clone_from_slice(source);
1257        } else {
1258            *self = source.clone();
1259        }
1260    }
1261}
1262
1263impl<T: ?Sized + PartialEq, A: Allocator> PartialEq for TESBox<T, A> {
1264    #[inline]
1265    fn eq(&self, other: &Self) -> bool {
1266        PartialEq::eq(&**self, &**other)
1267    }
1268    #[inline]
1269    #[allow(clippy::partialeq_ne_impl)]
1270    fn ne(&self, other: &Self) -> bool {
1271        PartialEq::ne(&**self, &**other)
1272    }
1273}
1274
1275impl<T: ?Sized + PartialOrd, A: Allocator> PartialOrd for TESBox<T, A> {
1276    #[inline]
1277    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
1278        PartialOrd::partial_cmp(&**self, &**other)
1279    }
1280    #[inline]
1281    fn lt(&self, other: &Self) -> bool {
1282        PartialOrd::lt(&**self, &**other)
1283    }
1284    #[inline]
1285    fn le(&self, other: &Self) -> bool {
1286        PartialOrd::le(&**self, &**other)
1287    }
1288    #[inline]
1289    fn ge(&self, other: &Self) -> bool {
1290        PartialOrd::ge(&**self, &**other)
1291    }
1292    #[inline]
1293    fn gt(&self, other: &Self) -> bool {
1294        PartialOrd::gt(&**self, &**other)
1295    }
1296}
1297
1298impl<T: ?Sized + Ord, A: Allocator> Ord for TESBox<T, A> {
1299    #[inline]
1300    fn cmp(&self, other: &Self) -> Ordering {
1301        Ord::cmp(&**self, &**other)
1302    }
1303}
1304
1305impl<T: ?Sized + Eq, A: Allocator> Eq for TESBox<T, A> {}
1306
1307impl<T: ?Sized + Hash, A: Allocator> Hash for TESBox<T, A> {
1308    fn hash<H: Hasher>(&self, state: &mut H) {
1309        (**self).hash(state);
1310    }
1311}
1312
1313impl<T: ?Sized + Hasher, A: Allocator> Hasher for TESBox<T, A> {
1314    fn finish(&self) -> u64 {
1315        (**self).finish()
1316    }
1317    fn write(&mut self, bytes: &[u8]) {
1318        (**self).write(bytes);
1319    }
1320    fn write_u8(&mut self, i: u8) {
1321        (**self).write_u8(i);
1322    }
1323    fn write_u16(&mut self, i: u16) {
1324        (**self).write_u16(i);
1325    }
1326    fn write_u32(&mut self, i: u32) {
1327        (**self).write_u32(i);
1328    }
1329    fn write_u64(&mut self, i: u64) {
1330        (**self).write_u64(i);
1331    }
1332    fn write_u128(&mut self, i: u128) {
1333        (**self).write_u128(i);
1334    }
1335    fn write_usize(&mut self, i: usize) {
1336        (**self).write_usize(i);
1337    }
1338    fn write_i8(&mut self, i: i8) {
1339        (**self).write_i8(i);
1340    }
1341    fn write_i16(&mut self, i: i16) {
1342        (**self).write_i16(i);
1343    }
1344    fn write_i32(&mut self, i: i32) {
1345        (**self).write_i32(i);
1346    }
1347    fn write_i64(&mut self, i: i64) {
1348        (**self).write_i64(i);
1349    }
1350    fn write_i128(&mut self, i: i128) {
1351        (**self).write_i128(i);
1352    }
1353    fn write_isize(&mut self, i: isize) {
1354        (**self).write_isize(i);
1355    }
1356}
1357
1358impl<T: fmt::Display + ?Sized, A: Allocator> fmt::Display for TESBox<T, A> {
1359    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1360        fmt::Display::fmt(&**self, f)
1361    }
1362}
1363
1364impl<T: fmt::Debug + ?Sized, A: Allocator> fmt::Debug for TESBox<T, A> {
1365    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1366        fmt::Debug::fmt(&**self, f)
1367    }
1368}
1369
1370impl<T: ?Sized, A: Allocator> fmt::Pointer for TESBox<T, A> {
1371    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1372        // It's not possible to extract the inner Uniq directly from the Box,
1373        // instead we cast it to a *const which aliases the Unique
1374        let ptr: *const T = &**self;
1375        fmt::Pointer::fmt(&ptr, f)
1376    }
1377}
1378
1379impl<T: ?Sized, A: Allocator> Deref for TESBox<T, A> {
1380    type Target = T;
1381
1382    fn deref(&self) -> &T {
1383        unsafe { self.0.as_ref() }
1384    }
1385}
1386
1387impl<T: ?Sized, A: Allocator> DerefMut for TESBox<T, A> {
1388    fn deref_mut(&mut self) -> &mut T {
1389        unsafe { self.0.as_mut() }
1390    }
1391}
1392
1393impl<T: ?Sized, A: Allocator> Borrow<T> for TESBox<T, A> {
1394    fn borrow(&self) -> &T {
1395        &**self
1396    }
1397}
1398
1399impl<T: ?Sized, A: Allocator> BorrowMut<T> for TESBox<T, A> {
1400    fn borrow_mut(&mut self) -> &mut T {
1401        &mut **self
1402    }
1403}
1404
1405impl<T: ?Sized, A: Allocator> AsRef<T> for TESBox<T, A> {
1406    fn as_ref(&self) -> &T {
1407        &**self
1408    }
1409}
1410
1411impl<T: ?Sized, A: Allocator> AsMut<T> for TESBox<T, A> {
1412    fn as_mut(&mut self) -> &mut T {
1413        &mut **self
1414    }
1415}
1416
1417impl<E: Error> Error for TESBox<E> {
1418    #[allow(deprecated, deprecated_in_future)]
1419    fn description(&self) -> &str {
1420        Error::description(&**self)
1421    }
1422
1423    #[allow(deprecated)]
1424    fn cause(&self) -> Option<&dyn Error> {
1425        Error::cause(&**self)
1426    }
1427
1428    fn source(&self) -> Option<&(dyn Error + 'static)> {
1429        Error::source(&**self)
1430    }
1431}