Skip to main content

mnemosyne_arena/scratch/aligned_vec/
traits.rs

1//! The standard traits [`AlignedVec`] implements.
2//!
3//! Derives cannot produce these: the buffer is a raw owning pointer, so
4//! `Clone` reallocates and copies, `PartialEq` compares the initialized
5//! prefix, and `Debug` prints that prefix rather than the pointer.
6
7use super::AlignedVec;
8use super::ScratchElement;
9
10impl<T: ScratchElement> Drop for AlignedVec<T> {
11    fn drop(&mut self) {
12        if self.capacity > 0 {
13            let layout = Self::layout_for(self.capacity);
14            // SAFETY: `capacity > 0` means `self.ptr` came from `alloc`/`realloc`
15            // with `layout_for(self.capacity)`, and `capacity` tracks the most
16            // recent (re)allocation, so `layout` matches the live allocation's
17            // size and alignment exactly. `ScratchElement` types are non-`Drop`
18            // POD, so freeing the raw bytes leaks nothing.
19            unsafe {
20                alloc::alloc::dealloc(self.ptr as *mut u8, layout);
21            }
22        }
23    }
24}
25
26impl<T: ScratchElement + core::fmt::Debug> core::fmt::Debug for AlignedVec<T> {
27    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
28        f.debug_list().entries(self.as_slice().iter()).finish()
29    }
30}
31
32impl<T: ScratchElement> Clone for AlignedVec<T> {
33    fn clone(&self) -> Self {
34        let mut v = Self::with_capacity(self.len);
35        v.extend_from_slice(self.as_slice());
36        v
37    }
38}
39
40impl<T: ScratchElement> Default for AlignedVec<T> {
41    #[inline]
42    fn default() -> Self {
43        Self::dangling()
44    }
45}
46
47impl<T: ScratchElement + PartialEq> PartialEq for AlignedVec<T> {
48    fn eq(&self, other: &Self) -> bool {
49        self.as_slice() == other.as_slice()
50    }
51}
52
53impl<T: ScratchElement + PartialEq> PartialEq<[T]> for AlignedVec<T> {
54    fn eq(&self, other: &[T]) -> bool {
55        self.as_slice() == other
56    }
57}
58
59impl<T: ScratchElement + Eq> Eq for AlignedVec<T> {}
60
61impl<T: ScratchElement + PartialOrd> PartialOrd for AlignedVec<T> {
62    #[inline]
63    fn partial_cmp(&self, other: &Self) -> Option<core::cmp::Ordering> {
64        self.as_slice().partial_cmp(other.as_slice())
65    }
66}
67
68impl<T: ScratchElement + Ord> Ord for AlignedVec<T> {
69    #[inline]
70    fn cmp(&self, other: &Self) -> core::cmp::Ordering {
71        self.as_slice().cmp(other.as_slice())
72    }
73}
74
75impl<T: ScratchElement + core::hash::Hash> core::hash::Hash for AlignedVec<T> {
76    #[inline]
77    fn hash<H: core::hash::Hasher>(&self, state: &mut H) {
78        self.as_slice().hash(state);
79    }
80}
81
82// SAFETY: `AlignedVec` uniquely owns its heap buffer with no aliasing or shared
83// ownership, so moving it to another thread is sound whenever the element type
84// is itself `Send`.
85unsafe impl<T: ScratchElement + Send> Send for AlignedVec<T> {}
86
87// SAFETY: every shared path through `&AlignedVec<T>` — `as_slice`, `Deref` —
88// yields `&[T]` and nothing else, so a shared reference grants no way to reach
89// the owning `*mut T` mutably. Sharing one across threads is therefore exactly
90// as sound as sharing `&[T]`, which holds when `T: Sync`.
91unsafe impl<T: ScratchElement + Sync> Sync for AlignedVec<T> {}
92
93impl<T: ScratchElement> core::ops::Deref for AlignedVec<T> {
94    type Target = [T];
95    #[inline]
96    fn deref(&self) -> &[T] {
97        self.as_slice()
98    }
99}
100
101impl<T: ScratchElement> core::ops::DerefMut for AlignedVec<T> {
102    #[inline]
103    fn deref_mut(&mut self) -> &mut [T] {
104        self.as_mut_slice()
105    }
106}