binvec/lib.rs
1pub mod error;
2
3mod iter;
4pub use iter::*;
5
6
7/// A fixed-length array type that stores `0` or `1`.
8/// It uses up to 8 times less memory compared to a [`bool`] array.
9///
10/// ---
11/// # Note
12/// The [`bool`] type uses 1 byte (8 bits). Therefore, storing 100 [`bool`]s requires 100 bytes (800 bits).
13/// In general situations, this is not a big problem,
14/// but when the array length exceeds thousands or in embedded environments with limited memory capacity,
15/// this memory usage cannot be ignored.
16///
17/// To use minimal memory, calculate the minimum byte array size `N` needed to store `L` bits. The formula is as follows:
18/// ```text
19/// N = (L + 7) / 8
20/// ```
21///
22/// For example, to store 10 bits, 2 bytes are used. In this case, the remaining 6 bits are unused.
23/// ```text
24/// |----- byte0 -----|----- byte1 -----|
25/// | 0 0 0 0 0 0 0 0 | 0 0 0 0 0 0 0 0 |
26/// ^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^
27/// 10 bits used Not used
28/// ```
29///
30/// ---
31/// # Generics
32/// - `L`: The number of bits to store.
33/// - `N`: The minimum byte array length required to store `L`.
34///
35/// ---
36/// # Examples
37/// ```
38/// use binvec::*;
39///
40/// // A binvec storing 12 bits initialized to 0
41/// let mut binvec = binvec!(12, false);
42/// ```
43///
44#[derive(Debug, Clone, PartialEq, Eq)]
45pub struct Binvec<const L: usize, const N: usize> {
46 inner: [u8; N],
47}
48
49
50// impl
51impl<const L: usize, const N: usize> Binvec<L, N> {
52 /// Creates a new [`Binvec`].
53 ///
54 /// **It is not recommended to use this function. Please use [`binvec!`] macro instead.**
55 ///
56 /// ---
57 /// # Arguments
58 /// - `initial_value`: The initial value to initialize the array.
59 ///
60 /// ---
61 /// # Returns
62 /// An `L` length [`Binvec`] initialized with `initial_value`.
63 ///
64 /// ---
65 /// # Examples
66 /// ```
67 /// use binvec::Binvec;
68 ///
69 /// let binvec = Binvec::<12, 2>::new(false);
70 /// ```
71 ///
72 #[deprecated(note = "Use the `binvec!` macro instead.")]
73 #[doc(hidden)]
74 pub const fn new(initial_value: bool) -> Self {
75 let mut new: Binvec<L, N> = Self { inner: [0x00; N] };
76 new.fill(initial_value);
77 new
78 }
79
80 /// Returns the length in bits of the [`Binvec`].
81 ///
82 /// ---
83 /// # Returns
84 /// The number of bits stored in the [`Binvec`].
85 ///
86 /// ---
87 /// # Examples
88 /// ```
89 /// use binvec::*;
90 ///
91 /// let binvec = binvec!(12, false);
92 /// assert_eq!(binvec.len(), 12);
93 /// ```
94 ///
95 #[inline(always)]
96 pub const fn len(&self) -> usize {
97 L
98 }
99
100 /// Returns the bit value at the given index without performing bounds checking.
101 ///
102 /// ---
103 /// # Safety
104 /// Calling this method with an out-of-bounds index is undefined behavior.
105 ///
106 /// ---
107 /// # Arguments
108 /// - `index`: The bit index to retrieve.
109 ///
110 /// ---
111 /// # Returns
112 /// - `true` if the bit at `index` is 1.
113 /// - `false` if the bit at `index` is 0.
114 ///
115 /// ---
116 /// # Examples
117 /// ```
118 /// use binvec::*;
119 ///
120 /// let binvec = binvec!(12, true);
121 /// let bit = unsafe { binvec.get_unchecked(5) };
122 /// assert_eq!(bit, true);
123 /// ```
124 ///
125 pub const unsafe fn get_unchecked(&self, index: usize) -> bool {
126 let byte_index: usize = index >> 3; // same as `index / 8`
127 let bit_offset: usize = index & 0b111; // same as `index % 8`
128 let byte: u8 = self.inner[byte_index];
129 ((byte >> bit_offset) & 1) != 0
130 }
131
132 /// Returns the bit value at the given index with bounds checking.
133 ///
134 /// ---
135 /// # Arguments
136 /// - `index`: The bit index to retrieve.
137 ///
138 /// ---
139 /// # Returns
140 /// - `Some(true)` if the bit at `index` is 1.
141 /// - `Some(false)` if the bit at `index` is 0.
142 /// - `None` if `index` is out of bounds.
143 ///
144 /// # Examples
145 /// ```
146 /// use binvec::*;
147 ///
148 /// let binvec = binvec!(12, true);
149 /// assert_eq!(binvec.get(5), Some(true));
150 /// assert_eq!(binvec.get(20), None);
151 /// ```
152 ///
153 #[inline]
154 pub fn get(&self, index: usize) -> Option<bool> {
155 if index < L {
156 Some(unsafe { self.get_unchecked(index) })
157 } else {
158 None
159 }
160 }
161
162 /// Sets the bit value at the given index without performing bounds checking.
163 ///
164 /// ---
165 /// # Safety
166 /// Calling this method with an out-of-bounds index is undefined behavior.
167 ///
168 /// ---
169 /// # Arguments
170 /// - `index`: The bit index to set.
171 /// - `value`: The bit value to set (`true` for 1, `false` for 0).
172 ///
173 /// ---
174 /// # Examples
175 /// ```
176 /// use binvec::*;
177 ///
178 /// let mut binvec = binvec!(12, false);
179 /// unsafe { binvec.set_unchecked(3, true); }
180 /// assert_eq!(binvec.get(3), Some(true));
181 /// ```
182 ///
183 pub unsafe fn set_unchecked(&mut self, index: usize, value: bool) {
184 let byte_index: usize = index >> 3; // same as `index / 8`
185 let bit_offset: usize = index & 0b111; // same as `index % 8`
186 let mask: u8 = 1 << bit_offset;
187 let byte: &mut u8 = &mut self.inner[byte_index];
188 if value == true {
189 *byte |= mask;
190 } else {
191 *byte &= !mask;
192 }
193 }
194
195 /// Sets the bit value at the given index with bounds checking.
196 ///
197 /// ---
198 /// # Arguments
199 /// - `index`: The bit index to set.
200 /// - `value`: The bit value to set (`true` for 1, `false` for 0).
201 ///
202 /// ---
203 /// # Returns
204 /// - `Ok(())` if the bit was successfully set.
205 /// - `Err(())` if the index is out of bounds.
206 ///
207 /// ---
208 /// # Examples
209 /// ```
210 /// use binvec::*;
211 ///
212 /// let mut binvec = binvec!(12, false);
213 /// assert_eq!(binvec.set(5, true), Ok(()));
214 /// assert_eq!(binvec.get(5), Some(true));
215 ///
216 /// assert_eq!(binvec.set(20, true), Err(error::IndexOutOfBounds));
217 /// ```
218 ///
219 #[inline]
220 pub fn set(&mut self, index: usize, value: bool) -> Result<(), error::IndexOutOfBounds> {
221 if index < L {
222 unsafe { self.set_unchecked(index, value); }
223 Ok(())
224 } else {
225 Err(error::IndexOutOfBounds)
226 }
227 }
228
229 /// Fills the entire [`Binvec`] with the specified bit value.
230 ///
231 /// This method sets all bits in the [`Binvec`] to either `true` (1) or `false` (0).
232 /// For bits beyond the length `L` in the last byte, those bits are cleared to zero.
233 ///
234 /// ---
235 /// # Arguments
236 /// - `value`: The bit value to fill the [`Binvec`] with (`true` for 1, `false` for 0).
237 ///
238 /// ---
239 /// # Examples
240 /// ```
241 /// use binvec::*;
242 ///
243 /// let mut binvec = binvec!(12, false);
244 /// binvec.fill(true);
245 /// assert_eq!(binvec.is_all_one(), true);
246 /// ```
247 ///
248 pub const fn fill(&mut self, value: bool) {
249 let byte: u8 = if value == true { 0xFF } else { 0x00 };
250 let mut inner: [u8; N] = [byte; N];
251 if L > 0
252 && L % 8 != 0 {
253 let last_bits: usize = L % 8;
254 let mask: u8 = (1u8 << last_bits) - 1;
255 inner[N - 1] &= mask;
256 }
257 self.inner = inner;
258 }
259
260 /// Counts the number of bits set to `1` in the [`Binvec`].
261 ///
262 /// ---
263 /// # Returns
264 /// The total count of bits that are set to `1`.
265 ///
266 /// ---
267 /// # Examples
268 /// ```
269 /// use binvec::*;
270 ///
271 /// let binvec = binvec!(12, true);
272 /// assert_eq!(binvec.count_ones(), 12);
273 ///
274 /// let mut binvec = binvec!(12, false);
275 /// binvec.set(3, true).unwrap();
276 /// assert_eq!(binvec.count_ones(), 1);
277 /// ```
278 ///
279 pub const fn count_ones(&self) -> usize {
280 let mut count: usize = 0;
281 let mut i: usize = 0;
282 while i < N {
283 count += self.inner[i].count_ones() as usize;
284 i += 1;
285 }
286 count // unused value is always filled with 0
287 }
288
289 /// Counts the number of bits set to `0` in the [`Binvec`].
290 ///
291 /// ---
292 /// # Returns
293 /// The total count of bits that are set to `0`.
294 ///
295 /// ---
296 /// # Examples
297 /// ```
298 /// use binvec::*;
299 ///
300 /// let binvec = binvec!(12, false);
301 /// assert_eq!(binvec.count_zeros(), 12);
302 ///
303 /// let mut binvec = binvec!(12, true);
304 /// binvec.set(3, false).unwrap();
305 /// assert_eq!(binvec.count_zeros(), 1);
306 /// ```
307 ///
308 pub const fn count_zeros(&self) -> usize {
309 let mut count: usize = 0;
310 let mut i: usize = 0;
311 while i < N {
312 count += self.inner[i].count_zeros() as usize;
313 i += 1;
314 }
315 count - ((N * 8) - L) // unused value is always filled with 0
316 }
317
318 /// Checks if all bits in the [`Binvec`] are set to `1`.
319 ///
320 /// ---
321 /// # Returns
322 /// `true` if all bits that are using is `1`, otherwise `false`.
323 ///
324 /// ---
325 /// # Examples
326 /// ```
327 /// use binvec::*;
328 ///
329 /// let binvec = binvec!(12, true);
330 /// assert_eq!(binvec.is_all_one(), true);
331 ///
332 /// let mut binvec = binvec!(12, false);
333 /// assert_eq!(binvec.is_all_one(), false);
334 /// binvec.fill(true);
335 /// assert_eq!(binvec.is_all_one(), true);
336 /// ```
337 ///
338 #[inline(always)]
339 pub const fn is_all_one(&self) -> bool {
340 self.count_ones() == L
341 }
342
343 /// Checks if all bits in the [`Binvec`] are set to `0`.
344 ///
345 /// ---
346 /// # Returns
347 /// `true` if all bits that are using is `0`, otherwise `false`.
348 ///
349 /// ---
350 /// # Examples
351 /// ```
352 /// use binvec::*;
353 ///
354 /// let binvec = binvec!(12, false);
355 /// assert_eq!(binvec.is_all_zero(), true);
356 ///
357 /// let mut binvec = binvec!(12, true);
358 /// assert_eq!(binvec.is_all_zero(), false);
359 /// binvec.fill(false);
360 /// assert_eq!(binvec.is_all_zero(), true);
361 /// ```
362 ///
363 #[inline(always)]
364 pub const fn is_all_zero(&self) -> bool {
365 self.count_zeros() == L
366 }
367
368 /// Returns an iterator over the bits of the [`Binvec`].
369 ///
370 /// ---
371 /// # Returns
372 /// A [`BinvecIter`] that yields each bit as a `bool`.
373 ///
374 /// ---
375 /// # Examples
376 /// ```
377 /// use binvec::*;
378 ///
379 /// let binvec = binvec!(12, true);
380 /// for bit in binvec.iter() {
381 /// assert_eq!(bit, true);
382 /// }
383 /// ```
384 ///
385 #[inline(always)]
386 pub fn iter(&self) -> BinvecIter<'_, L, N> {
387 BinvecIter::new(self)
388 }
389}
390
391
392// impl IntoIterator
393impl<'a, const L: usize, const N: usize> IntoIterator for &'a Binvec<L, N> {
394 type Item = bool;
395 type IntoIter = BinvecIter<'a, L, N>;
396
397 fn into_iter(self) -> Self::IntoIter {
398 self.iter()
399 }
400}
401
402
403/// Creates a new [`Binvec`].
404///
405/// ---
406/// # Arguments
407/// - `len`: Number of bits to store
408/// - `initial_value`: Initial value of the array
409///
410/// ---
411/// # Returns
412/// An `len` length [`Binvec`] initialized with `initial_value`.
413///
414/// ---
415/// # Examples
416/// ```
417/// use binvec::*;
418///
419/// let binvec = binvec!(12, false);
420/// ```
421///
422#[macro_export]
423macro_rules! binvec {
424 ($len:expr, $initial_value:expr) => {{
425 const L: usize = $len;
426 const N: usize = (L + 7) >> 3; // same as (L + 7) / 8
427 #[allow(deprecated)]
428 Binvec::<L, N>::new($initial_value)
429 }};
430}
431
432
433// impl Display
434impl<const L: usize, const N: usize> core::fmt::Display for Binvec<L, N> {
435 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
436 write!(f, "[")?;
437 let mut iter: BinvecIter<'_, L, N> = self.iter();
438 if let Some(first) = iter.next() {
439 write!(f, "{}", if first { "1" } else { "0" })?;
440 for bit in iter {
441 write!(f, ", {}", if bit { "1" } else { "0" })?;
442 }
443 }
444 write!(f, "]")
445 }
446}