safebit 0.1.0

Safe and secure bit access into integer types
Documentation
//! `WordRead` definition and no_std implementations.

use crate::{
    error::CursorError,
    util::{Endianess, NativeEndian},
    word::Word,
};

/// The `WordRead` trait allows for reading words in a given endianess from a source.
///
/// Implementors of the `WordRead` trait are called "word readers". A type may implement `WordRead`
/// for multiple words and endianesses. Blanket implementations for types that implement
/// [std::io::Read] are provided.
pub trait WordRead<W, E, End>
where
    W: Word,
    End: Endianess,
{
    fn read(&mut self) -> Result<W, E>;
}

/// A cursor over a slice of words of a fixed type with native endianess.
///
/// # Examples
/// ```
/// use safebit::error::CursorError;
/// use safebit::word_read::Cursor;
/// use safebit::word_read::WordRead;
///
/// let data: [u16; 4] = [1, 2, 3, 4];
/// let mut cursor = Cursor::new(&data);
/// assert_eq!(cursor.read().unwrap(), 1);
/// assert_eq!(cursor.read().unwrap(), 2);
/// assert_eq!(cursor.read().unwrap(), 3);
/// assert_eq!(cursor.read().unwrap(), 4);
/// assert_eq!(cursor.read(), Err(CursorError::EndOfCursor));
/// ```
pub struct Cursor<'a, W>
where
    W: Word,
{
    data: &'a [W],
    pos: usize,
}

impl<'a, W> Cursor<'a, W>
where
    W: Word,
{
    pub fn new<D>(data: D) -> Self
    where
        &'a [W]: From<D>,
    {
        Self {
            data: data.into(),
            pos: 0,
        }
    }
}

impl<'a, W> WordRead<W, CursorError, NativeEndian> for Cursor<'a, W>
where
    W: Word,
{
    /// Read one [Word] from the cursor, returning [CursorError::EndOfCursor] if no words left.
    fn read(&mut self) -> Result<W, CursorError>
    where
        W: Word,
    {
        if self.pos < self.data.len() {
            let w = self.data[self.pos];
            self.pos += 1;
            Ok(w)
        } else {
            Err(CursorError::EndOfCursor)
        }
    }
}