byte-array-ops 0.4.0

A no_std-compatible library for security-by-default byte array operations. Includes automatic memory zeroization, constant-time utilities, multiple input formats (hex, binary, UTF-8), bitwise operations, and comprehensive type conversions with minimal dependencies.
Documentation
//! Iterator implementations for ByteArray
//!
//! Provides controlled iteration over byte references

use super::model::ByteArray;

// TODO document this in my md notes

/// Iterator over immutable references to bytes in a [`ByteArray`].
///
/// Created by `ByteArray::iter()` or via `IntoIterator` for `&ByteArray`.
pub struct ByteArrayIter<'a> {
    inner: core::slice::Iter<'a, u8>,
}

/// Iterator over mutable references to bytes in a [`ByteArray`].
///
/// Created by `ByteArray::iter_mut()` or via `IntoIterator` for `&mut ByteArray`.
pub struct ByteArrayIterMut<'a> {
    inner: core::slice::IterMut<'a, u8>,
}

impl<'a> Iterator for ByteArrayIter<'a> {
    type Item = &'a u8;

    fn next(&mut self) -> Option<Self::Item> {
        self.inner.next()
    }
}

impl<'a> Iterator for ByteArrayIterMut<'a> {
    type Item = &'a mut u8;

    fn next(&mut self) -> Option<Self::Item> {
        self.inner.next()
    }
}

impl<'a> ExactSizeIterator for ByteArrayIter<'a> {
    fn len(&self) -> usize {
        self.inner.len()
    }
}

impl<'a> ExactSizeIterator for ByteArrayIterMut<'a> {
    fn len(&self) -> usize {
        self.inner.len()
    }
}

impl<'a> IntoIterator for &'a ByteArray {
    type Item = &'a u8;
    type IntoIter = ByteArrayIter<'a>;

    fn into_iter(self) -> Self::IntoIter {
        ByteArrayIter {
            inner: self.bytes.iter(),
        }
    }
}

impl<'a> IntoIterator for &'a mut ByteArray {
    type Item = &'a mut u8;
    type IntoIter = ByteArrayIterMut<'a>;

    fn into_iter(self) -> Self::IntoIter {
        ByteArrayIterMut {
            inner: self.bytes.iter_mut(),
        }
    }
}
impl ByteArray {
    /// Returns an iterator over the bytes.
    ///
    /// # Example
    /// ```
    /// use byte_array_ops::ByteArray;
    ///
    /// let arr: ByteArray = "0xdeadbeef".parse().unwrap();
    /// let mut iter = arr.iter();
    /// assert_eq!(iter.next(), Some(&0xde));
    /// assert_eq!(iter.next(),Some(&0xad));
    /// assert_eq!(iter.next(),Some(&0xbe));
    /// assert_eq!(iter.next(),Some(&0xef));
    /// assert_eq!(iter.next(),None);
    ///
    /// ```
    pub fn iter(&'_ self) -> ByteArrayIter<'_> {
        ByteArrayIter {
            inner: self.bytes.iter(),
        }
    }

    /// Returns an iterator that allows modifying each byte.
    ///
    /// # Example
    /// ```
    /// use byte_array_ops::ByteArray;
    ///
    /// let mut arr: ByteArray = "0xff00ff".parse().unwrap();
    /// let mut iter_mut = arr.iter_mut();
    /// iter_mut.next();
    /// let mut byte = iter_mut.next().unwrap();
    /// *byte = 0xee;
    /// assert_eq!(arr.as_bytes(),[0x0ff,0xee,0xff]);
    ///
    /// ```
    pub fn iter_mut(&'_ mut self) -> ByteArrayIterMut<'_> {
        ByteArrayIterMut {
            inner: self.bytes.iter_mut(),
        }
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use alloc::vec::Vec;

    #[test]
    fn test_iter_empty() {
        let arr = ByteArray::default();

        let mut iter = arr.iter();
        assert_eq!(iter.next(), None);
        assert_eq!(iter.next(), None);
    }

    #[test]
    fn test_iter_single_byte() {
        let arr: ByteArray = "0xff".parse().unwrap();

        let mut iter = arr.iter();
        assert_eq!(iter.next(), Some(&0xff));
        assert_eq!(iter.next(), None);
    }

    #[test]
    fn test_iter_exhaustion() {
        let arr: ByteArray = "0xaabbcc".parse().unwrap();

        let mut iter = arr.iter();
        assert_eq!(iter.next(), Some(&0xaa));
        assert_eq!(iter.next(), Some(&0xbb));
        assert_eq!(iter.next(), Some(&0xcc));
        assert_eq!(iter.next(), None);
        assert_eq!(iter.next(), None);
    }

    #[test]
    fn test_multiple_iterators() {
        let arr: ByteArray = "0xaabb".parse().unwrap();

        let mut iter1 = arr.iter();
        let mut iter2 = arr.iter();

        assert_eq!(iter1.next(), Some(&0xaa));
        assert_eq!(iter2.next(), Some(&0xaa));
        assert_eq!(iter1.next(), Some(&0xbb));
    }

    #[test]
    fn test_partial_iteration() {
        let arr: ByteArray = "0xaabbccdd".parse().unwrap();

        let mut iter = arr.iter();
        assert_eq!(iter.next(), Some(&0xaa));
        assert_eq!(iter.next(), Some(&0xbb));
        // Drop iterator without consuming all elements
    }

    #[test]
    fn test_for_loop() {
        let arr: ByteArray = "0x010203".parse().unwrap();

        let mut sum = 0u32;
        for byte in &arr {
            sum += *byte as u32;
        }
        assert_eq!(sum, 1 + 2 + 3);
    }

    #[test]
    fn test_iter_mut_modification() {
        let mut arr: ByteArray = "0x000000".parse().unwrap();

        for byte in arr.iter_mut() {
            *byte = 0xff;
        }

        assert_eq!(arr.as_bytes(), &[0xff, 0xff, 0xff]);
    }

    #[test]
    fn test_iter_after_mutation() {
        let mut arr: ByteArray = "0xaa".parse().unwrap();
        arr[0] = 0xbb;

        let mut iter = arr.iter();
        assert_eq!(iter.next(), Some(&0xbb));
    }

    #[test]
    fn test_collect() {
        let arr: ByteArray = "0xaabbcc".parse().unwrap();

        let collected: Vec<u8> = arr.iter().copied().collect();
        let expected = Vec::from([0xaa, 0xbb, 0xcc]);
        assert_eq!(collected, expected);
    }

    #[test]
    fn test_iterator_methods() {
        let arr: ByteArray = "0x010203".parse().unwrap();

        assert_eq!(arr.iter().count(), 3);
        assert!(arr.iter().any(|&b| b == 0x02));
        assert!(arr.iter().all(|&b| b > 0));
        assert_eq!(arr.iter().find(|&&b| b == 0x03), Some(&0x03));
    }

    #[test]
    fn test_large_array() {
        let arr = ByteArray::init_value(0xff, 10000);
        assert_eq!(arr.iter().count(), 10000);
    }

    #[test]
    fn test_borrow_then_iterate() {
        let arr: ByteArray = "0xaa".parse().unwrap();
        let _slice = arr.as_bytes();

        let mut iter = arr.iter();
        assert_eq!(iter.next(), Some(&0xaa));
    }

    #[test]
    fn test_exact_size_iterator() {
        let arr: ByteArray = "0xaabbccdd".parse().unwrap();

        let iter = arr.iter();
        assert_eq!(iter.len(), 4);

        let mut iter = arr.iter();
        iter.next();
        assert_eq!(iter.len(), 3);

        iter.next();
        assert_eq!(iter.len(), 2);
    }

    #[test]
    fn test_exact_size_iterator_mut() {
        let mut arr: ByteArray = "0xaabbcc".parse().unwrap();

        let iter = arr.iter_mut();
        assert_eq!(iter.len(), 3);

        let mut iter = arr.iter_mut();
        iter.next();
        assert_eq!(iter.len(), 2);
    }

    #[test]
    fn test_exact_size_empty() {
        let arr = ByteArray::default();

        let iter = arr.iter();
        assert_eq!(iter.len(), 0);
    }

    #[test]
    fn test_iter_mut_for_loop() {
        let mut arr: ByteArray = "0x010203".parse().unwrap();

        for byte in &mut arr {
            *byte = byte.wrapping_add(1);
        }

        assert_eq!(arr.as_bytes(), &[0x02, 0x03, 0x04]);
    }
}