1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
use core::{
    ops::{Deref, DerefMut},
    ptr::addr_of,
};

use crate::{BitBlock, BitSlice, LE};

#[cfg(feature = "alloc")]
use alloc::fmt::Debug;

#[cfg_attr(feature = "std", derive(Hash))]
#[derive(Clone)]
#[repr(transparent)]
/// A bitmap that is internally represented as `[B; BLOCKS]`.
pub struct BitMap<B: BitBlock, const BLOCKS: usize>(pub [B; BLOCKS]);

#[cfg(feature = "alloc")]
impl<B: BitBlock, const BLOCKS: usize> Debug for BitMap<B, BLOCKS> {
    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
        let slice: &BitSlice<B> = self.as_ref();

        slice.fmt(f)
    }
}

impl<B: BitBlock, const BLOCKS: usize> BitMap<LE<B>, BLOCKS>
where
    LE<B>: BitBlock,
{
    /// Convenience function for creating little endian bitmaps. This is planned to become `const` when the needed rust features are stabilized. \
    /// For now, something like `BitBlock::from_raw([LE(0b00100111), LE(0b01100011)])` may be used instead.
    pub fn from_raw_le(raw: [B; BLOCKS]) -> Self {
        Self::from_raw(unsafe { *addr_of!(raw).cast::<[LE<B>; BLOCKS]>() })
    }
}

impl<B: BitBlock, const BLOCKS: usize> BitMap<B, BLOCKS> {
    /// Creates a zero-initialized bitmap
    pub const fn new() -> Self {
        Self([B::ZERO; BLOCKS])
    }

    /// Same as `raw.into()` but usable in const contexts;
    pub const fn from_raw(raw: [B; BLOCKS]) -> Self {
        Self(raw)
    }
}

impl<B: BitBlock, const BLOCKS: usize> Default for BitMap<B, BLOCKS> {
    fn default() -> Self {
        Self::new()
    }
}

impl<B: BitBlock, const BLOCKS: usize> From<[B; BLOCKS]> for BitMap<B, BLOCKS> {
    fn from(value: [B; BLOCKS]) -> Self {
        Self::from_raw(value)
    }
}

impl<B: BitBlock, const BLOCKS: usize> From<BitMap<B, BLOCKS>> for [B; BLOCKS] {
    fn from(value: BitMap<B, BLOCKS>) -> Self {
        // transmute doesn't work because, as of now, rustc doesn't know that [B; BLOCKS] is the same size as BitMap<B, BLOCKS>
        unsafe { *(addr_of!(value).cast::<[B; BLOCKS]>()) }
    }
}

impl<B: BitBlock, const BLOCKS: usize> AsRef<[B]> for BitMap<B, BLOCKS> {
    fn as_ref(&self) -> &[B] {
        self.0.as_ref()
    }
}

impl<B: BitBlock, const BLOCKS: usize> AsMut<[B]> for BitMap<B, BLOCKS> {
    fn as_mut(&mut self) -> &mut [B] {
        self.0.as_mut()
    }
}

impl<B: BitBlock, const BLOCKS: usize> AsRef<[B; BLOCKS]> for BitMap<B, BLOCKS> {
    fn as_ref(&self) -> &[B; BLOCKS] {
        &self.0
    }
}

impl<B: BitBlock, const BLOCKS: usize> AsMut<[B; BLOCKS]> for BitMap<B, BLOCKS> {
    fn as_mut(&mut self) -> &mut [B; BLOCKS] {
        &mut self.0
    }
}

impl<B: BitBlock, const BLOCKS: usize> AsRef<BitSlice<B>> for BitMap<B, BLOCKS> {
    fn as_ref(&self) -> &BitSlice<B> {
        let slice: &[B] = self.as_ref();

        slice.as_ref()
    }
}

impl<B: BitBlock, const BLOCKS: usize> AsMut<BitSlice<B>> for BitMap<B, BLOCKS> {
    fn as_mut(&mut self) -> &mut BitSlice<B> {
        let slice: &mut [B] = self.as_mut();

        slice.as_mut()
    }
}

impl<B: BitBlock, const BLOCKS: usize> Deref for BitMap<B, BLOCKS> {
    type Target = BitSlice<B>;

    fn deref(&self) -> &Self::Target {
        self.as_ref()
    }
}

impl<B: BitBlock, const BLOCKS: usize> DerefMut for BitMap<B, BLOCKS> {
    fn deref_mut(&mut self) -> &mut Self::Target {
        self.as_mut()
    }
}