brainfoamkit_lib/iterable_nybble.rs
1// SPDX-FileCopyrightText: 2023 - 2024 Ali Sajid Imami
2//
3// SPDX-License-Identifier: Apache-2.0
4// SPDX-License-Identifier: MIT
5
6use crate::{
7 Bit,
8 Nybble,
9};
10
11/// An iterator over a nybble
12///
13/// This struct is a wrapper struct to generate an iterator
14/// for `Nybble`. This allows us to map and/or loop over all the `Bit`s
15/// in the `Nybble`.
16///
17/// This iterator iterates from the Least Significant Bit (LSB) to the
18/// Most Significant Bit (MSB). This means that the first `Bit` returned
19/// is the last `Bit` in the `Nybble` and the last `Bit` returned is the
20/// first `Bit` in the `Nybble`.
21///
22/// # Examples
23///
24/// ```
25/// use brainfoamkit_lib::{
26/// Bit,
27/// IterableNybble,
28/// Nybble,
29/// };
30///
31/// let nybble = Nybble::from(0b1010); // Dec: 10; Hex: 0xA; Oct: 0o12
32/// let mut iter = IterableNybble::new(&nybble);
33///
34/// assert_eq!(iter.next(), Some(Bit::zero()));
35/// assert_eq!(iter.next(), Some(Bit::one()));
36/// assert_eq!(iter.next(), Some(Bit::zero()));
37/// assert_eq!(iter.next(), Some(Bit::one()));
38/// assert_eq!(iter.next(), None);
39/// ```
40///
41/// # See Also
42///
43/// * [`Nybble`](crate::Nybble)
44/// * [`Bit`](crate::Bit)
45/// * [`Byte`](crate::Byte)
46/// * [`IterableByte`](crate::IterableByte)
47pub struct IterableNybble<'a> {
48 nybble: &'a Nybble,
49 current_index: u8,
50}
51
52impl<'a> IterableNybble<'a> {
53 /// Create a new `IterableNybble` from a reference to a `Nybble`
54 ///
55 /// # Arguments
56 ///
57 /// * `nybble` - A reference to a `Nybble` to iterate over
58 ///
59 /// # Returns
60 ///
61 /// A new `IterableNybble` that can be used to iterate over the `Nybble`
62 ///
63 /// # Examples
64 ///
65 /// ```
66 /// use brainfoamkit_lib::{
67 /// IterableNybble,
68 /// Nybble,
69 /// };
70 ///
71 /// let nybble = Nybble::from(0b1010); // Dec: 10; Hex: 0xA; Oct: 0o12
72 /// let mut iter = IterableNybble::new(&nybble);
73 ///
74 /// for bit in iter {
75 /// println!("{}", bit);
76 /// }
77 /// ```
78 #[must_use]
79 pub const fn new(nybble: &'a Nybble) -> Self {
80 Self {
81 nybble,
82 current_index: 0,
83 }
84 }
85}
86
87impl<'a> Iterator for IterableNybble<'a> {
88 /// The type of the element the iterator returns
89 type Item = Bit;
90
91 /// Advance the iterator and return the next element
92 ///
93 /// # Returns
94 ///
95 /// The next element in the iterator
96 ///
97 /// # Examples
98 ///
99 /// ```
100 /// use brainfoamkit_lib::{
101 /// Bit,
102 /// IterableNybble,
103 /// Nybble,
104 /// };
105 ///
106 /// let nybble = Nybble::from(0b1010); // Dec: 10; Hex: 0xA; Oct: 0o12
107 ///
108 /// let mut iter = IterableNybble::new(&nybble);
109 ///
110 /// assert_eq!(iter.next(), Some(Bit::zero()));
111 /// assert_eq!(iter.next(), Some(Bit::one()));
112 /// assert_eq!(iter.next(), Some(Bit::zero()));
113 /// assert_eq!(iter.next(), Some(Bit::one()));
114 /// assert_eq!(iter.next(), None);
115 /// ```
116 fn next(&mut self) -> Option<Self::Item> {
117 let current_index = self.current_index;
118 let next_index = current_index + 1;
119
120 if next_index > 4 {
121 self.current_index = 0;
122 None
123 } else {
124 self.current_index = next_index;
125 Some(self.nybble.get_bit(current_index))
126 }
127 }
128}
129
130#[cfg(test)]
131mod tests {
132 use super::*;
133 use crate::Bit;
134
135 #[test]
136 fn test_iterable_nybble() {
137 let nybble = Nybble::from(0b1010); // Dec: 10; Hex: 0xA; Oct: 0o12
138 let mut iter = nybble.iter();
139
140 assert_eq!(iter.next(), Some(Bit::zero()));
141 assert_eq!(iter.next(), Some(Bit::one()));
142 assert_eq!(iter.next(), Some(Bit::zero()));
143 assert_eq!(iter.next(), Some(Bit::one()));
144 assert_eq!(iter.next(), None);
145 }
146}