1use core::{fmt, mem};
2
3#[derive(Copy, Clone, PartialEq, Eq)]
5#[repr(transparent)]
6pub(crate) struct Tag(pub(super) u8);
7impl Tag {
8 pub(crate) const EMPTY: Tag = Tag(0b1111_1111);
10
11 pub(crate) const DELETED: Tag = Tag(0b1000_0000);
13
14 #[inline]
16 pub(crate) const fn is_full(self) -> bool {
17 self.0 & 0x80 == 0
18 }
19
20 #[inline]
22 pub(crate) const fn is_special(self) -> bool {
23 self.0 & 0x80 != 0
24 }
25
26 #[inline]
28 pub(crate) const fn special_is_empty(self) -> bool {
29 debug_assert!(self.is_special());
30 self.0 & 0x01 != 0
31 }
32
33 #[inline]
35 pub(crate) const fn full(hash: u64) -> Tag {
36 const MIN_HASH_LEN: usize = if mem::size_of::<usize>() < mem::size_of::<u64>() {
38 mem::size_of::<usize>()
39 } else {
40 mem::size_of::<u64>()
41 };
42
43 let top7 = hash >> (MIN_HASH_LEN * 8 - 7);
48 Tag((top7 & 0x7f) as u8) }
50}
51impl fmt::Debug for Tag {
52 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
53 if self.is_special() {
54 if self.special_is_empty() {
55 f.pad("EMPTY")
56 } else {
57 f.pad("DELETED")
58 }
59 } else {
60 f.debug_tuple("full").field(&(self.0 & 0x7F)).finish()
61 }
62 }
63}
64
65pub(crate) trait TagSliceExt {
67 fn fill_tag(&mut self, tag: Tag);
69
70 #[inline]
72 fn fill_empty(&mut self) {
73 self.fill_tag(Tag::EMPTY);
74 }
75}
76impl TagSliceExt for [mem::MaybeUninit<Tag>] {
77 #[inline]
78 fn fill_tag(&mut self, tag: Tag) {
79 unsafe { self.as_mut_ptr().write_bytes(tag.0, self.len()) }
81 }
82}