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
121
122
123
124
125
126
127
128
use crate::{
    ptr,
    NonNull,
    alloc,
    RawBitVec, 
    BitProto, 
    MemUtil,
};

pub struct RawBitVecIter {
    pub(crate) ptr: NonNull<usize>,
    pub(crate) true_cap: usize,
    pub(crate) start: usize,
    pub(crate) end_excluded: usize,
}

impl RawBitVecIter {
    #[inline]
    pub unsafe fn next(&mut self, proto: BitProto) -> Option<usize> {
        match self.start == self.end_excluded {
            true => None,
            false => Some(self.next_unchecked(proto))
        }
    }

    #[inline]
    pub unsafe fn next_unchecked(&mut self, proto: BitProto) -> usize {
        let idx_proxy = BitProto::idx_proxy(proto, self.start);
        let mut block_ptr = self.ptr.as_ptr().add(idx_proxy.real_idx);
        let mut block_bits = ptr::read(block_ptr);
        let mut val = (block_bits & idx_proxy.first_mask) >> idx_proxy.first_offset;
        if idx_proxy.second_mask != 0 {
            block_ptr = block_ptr.add(1);
            block_bits = ptr::read(block_ptr);
            val = val | ((block_bits & idx_proxy.second_mask) << idx_proxy.second_offset);
        }
        self.start += 1;
        val
    }

    #[inline]
    pub unsafe fn next_back(&mut self, proto: BitProto) -> Option<usize> {
        match self.start == self.end_excluded {
            true => None,
            false => Some(self.next_back_unchecked(proto))
        }
    }

    pub unsafe fn next_back_unchecked(&mut self, proto: BitProto) -> usize {
        self.end_excluded -= 1;
        let idx_proxy = BitProto::idx_proxy(proto, self.end_excluded);
        let mut block_ptr = self.ptr.as_ptr().add(idx_proxy.real_idx);
        let mut block_bits = ptr::read(block_ptr);
        let mut val = (block_bits & idx_proxy.first_mask) >> idx_proxy.first_offset;
        if idx_proxy.second_mask != 0 {
            block_ptr = block_ptr.add(1);
            block_bits = ptr::read(block_ptr);
            val = val | ((block_bits & idx_proxy.second_mask) << idx_proxy.second_offset);
        }
        val
    }

    #[inline(always)]
    pub fn len(&self) -> usize {
        self.end_excluded - self.start
    }
}

impl Drop for RawBitVecIter  {
    #[inline(always)]
    fn drop(&mut self) {
        if self.true_cap > 0 {
            unsafe {alloc::dealloc(self.ptr.as_ptr().cast(), MemUtil::usize_array_layout(self.true_cap))};
        }
    }
}

pub struct RawBitVecDrain<'vec> {
    pub(crate) vec: &'vec mut RawBitVec,
    pub(crate) start: usize,
    pub(crate) end_excluded: usize,
}

impl<'vec> RawBitVecDrain<'vec> {
    #[inline]
    pub unsafe fn next(&mut self, proto: BitProto) -> Option<usize> {
        match self.start == self.end_excluded {
            true => None,
            false => Some(self.next_unchecked(proto))
        }
    }

    #[inline]
    pub unsafe fn next_unchecked(&mut self, proto: BitProto) -> usize {
        let idx_proxy = BitProto::idx_proxy(proto, self.start);
        let val = self.vec.replace_val_with_idx_proxy(idx_proxy, 0);
        self.start += 1;
        val
    }

    #[inline]
    pub unsafe fn next_back(&mut self, proto: BitProto) -> Option<usize> {
        match self.start == self.end_excluded {
            true => None,
            false => Some(self.next_back_unchecked(proto))
        }
    }

    #[inline]
    pub unsafe fn next_back_unchecked(&mut self, proto: BitProto) -> usize {
        self.end_excluded -= 1;
        let idx_proxy = BitProto::idx_proxy(proto, self.end_excluded);
        let val = self.vec.replace_val_with_idx_proxy(idx_proxy, 0);
        val
    }

    #[inline(always)]
    pub fn len(&self) -> usize {
        self.end_excluded - self.start
    }
}

impl<'vec> Drop for RawBitVecDrain<'vec>  {
    #[inline(always)]
    fn drop(&mut self) {
        self.vec.len = 0;
    }
}