Skip to main content

mnemosyne_heap/branded_vec/
traits.rs

1use crate::BrandedVec;
2use crate::heap::BlockFreeGuard;
3use core::ops::{Deref, DerefMut};
4use mnemosyne_core::AllocPolicy;
5use mnemosyne_local::LocalAllocatorSelector;
6use mnemosyne_local::internal::HasSegmentPool;
7
8impl<'brand, 'heap, T, P: AllocPolicy, B: HasSegmentPool + LocalAllocatorSelector<B>> Deref
9    for BrandedVec<'brand, 'heap, T, P, B>
10{
11    type Target = [T];
12    #[inline(always)]
13    fn deref(&self) -> &Self::Target {
14        self.as_slice()
15    }
16}
17
18impl<'brand, 'heap, T, P: AllocPolicy, B: HasSegmentPool + LocalAllocatorSelector<B>> DerefMut
19    for BrandedVec<'brand, 'heap, T, P, B>
20{
21    #[inline(always)]
22    fn deref_mut(&mut self) -> &mut Self::Target {
23        self.as_mut_slice()
24    }
25}
26
27impl<'brand, 'heap, T, P: AllocPolicy, B: HasSegmentPool + LocalAllocatorSelector<B>> Drop
28    for BrandedVec<'brand, 'heap, T, P, B>
29{
30    #[inline]
31    fn drop(&mut self) {
32        // The guard rather than a trailing free is what keeps the block from
33        // leaking when an element's destructor panics: slice drop glue still
34        // drops the remaining elements, but the unwind would carry straight past
35        // a trailing call. `Vec` frees on both paths, and so must this.
36        if self.cap > 0 || (core::mem::size_of::<T>() == 0 && self.len > 0) {
37            // SAFETY: the condition restricts this to vectors that own resources
38            // — a live non-ZST block (`self.cap > 0`), or ZST elements whose
39            // `Drop` must still run (`len > 0`). `as_mut_slice` yields the
40            // initialized prefix `[0, self.len)` as a unique `&mut [T]` (this is
41            // `&mut self`), so `drop_in_place` drops each element exactly once.
42            // For non-ZST `T`, `self.ptr` is the live block from `self.heap`, so
43            // the guard holds exactly what its contract wants and returns it
44            // once; the ZST branch has no block (its pointer is the dangling
45            // sentinel, never allocated). `drop` runs at most once per value, so
46            // nothing is freed twice.
47            unsafe {
48                if core::mem::size_of::<T>() == 0 {
49                    core::ptr::drop_in_place(self.as_mut_slice());
50                } else {
51                    let _free = BlockFreeGuard::new(self.heap, self.ptr.as_ptr() as *mut u8);
52                    core::ptr::drop_in_place(self.as_mut_slice());
53                }
54            }
55        }
56    }
57}
58
59impl<
60    'brand,
61    'heap,
62    T: core::fmt::Debug,
63    P: AllocPolicy,
64    B: HasSegmentPool + LocalAllocatorSelector<B>,
65> core::fmt::Debug for BrandedVec<'brand, 'heap, T, P, B>
66{
67    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
68        core::fmt::Debug::fmt(self.as_slice(), f)
69    }
70}
71
72impl<'brand, 'heap, T: PartialEq, P: AllocPolicy, B: HasSegmentPool + LocalAllocatorSelector<B>>
73    PartialEq for BrandedVec<'brand, 'heap, T, P, B>
74{
75    #[inline]
76    fn eq(&self, other: &Self) -> bool {
77        self.as_slice() == other.as_slice()
78    }
79}
80impl<'brand, 'heap, T: Eq, P: AllocPolicy, B: HasSegmentPool + LocalAllocatorSelector<B>> Eq
81    for BrandedVec<'brand, 'heap, T, P, B>
82{
83}
84
85impl<'brand, 'heap, T: PartialOrd, P: AllocPolicy, B: HasSegmentPool + LocalAllocatorSelector<B>>
86    PartialOrd for BrandedVec<'brand, 'heap, T, P, B>
87{
88    #[inline]
89    fn partial_cmp(&self, other: &Self) -> Option<core::cmp::Ordering> {
90        self.as_slice().partial_cmp(other.as_slice())
91    }
92}
93impl<'brand, 'heap, T: Ord, P: AllocPolicy, B: HasSegmentPool + LocalAllocatorSelector<B>> Ord
94    for BrandedVec<'brand, 'heap, T, P, B>
95{
96    #[inline]
97    fn cmp(&self, other: &Self) -> core::cmp::Ordering {
98        self.as_slice().cmp(other.as_slice())
99    }
100}
101impl<
102    'brand,
103    'heap,
104    T: core::hash::Hash,
105    P: AllocPolicy,
106    B: HasSegmentPool + LocalAllocatorSelector<B>,
107> core::hash::Hash for BrandedVec<'brand, 'heap, T, P, B>
108{
109    #[inline]
110    fn hash<H: core::hash::Hasher>(&self, state: &mut H) {
111        self.as_slice().hash(state);
112    }
113}