// Licensed under the Apache-2.0 license
// SPDX-License-Identifier: Apache-2.0

//! Input/Output traits and utilities.

#![no_std]

use util_error::{ErrorCode, ErrorModule};

/// The generic IO error module.
pub const IO_GENERIC: ErrorModule = ErrorModule::new(0x494F); // ascii: IO
/// The read operation is out of bounds.
pub const IO_GENERIC_READ_OUT_OF_BOUNDS: ErrorCode =
    IO_GENERIC.from_pw(1, pw_status::Error::OutOfRange);

/// Trait for random access read operations.
pub trait RandomRead {
    type Error;
    /// Reads data from the source into the destination buffer.
    ///
    /// # Arguments
    /// * `start_addr`: The offset from which to start reading.
    /// * `dst`: The buffer to read data into.
    fn read(&mut self, start_addr: usize, dst: &mut [u8]) -> Result<(), Self::Error>;

    /// Returns the total size of the readable data in bytes.
    fn size(&mut self) -> Result<usize, Self::Error>;
}

impl RandomRead for &[u8] {
    type Error = ErrorCode;
    fn read(&mut self, start_addr: usize, dst: &mut [u8]) -> Result<(), Self::Error> {
        // Explicit wrapping add. Overflows are expected to
        // be detected in the indexing operation
        let end_addr = start_addr.wrapping_add(dst.len());
        let src = self
            .get(start_addr..end_addr)
            .ok_or(IO_GENERIC_READ_OUT_OF_BOUNDS)?;
        dst.copy_from_slice(src);
        Ok(())
    }
    fn size(&mut self) -> Result<usize, Self::Error> {
        Ok(self.len())
    }
}

#[cfg(test)]
mod test {
    use super::*;

    #[test]
    fn should_read() {
        let mut src: &[u8] = &[1, 2, 3, 4, 5, 6, 7, 8, 9];
        let mut dst: [u8; 3] = [0; 3];
        assert!(src.read(6, &mut dst).is_ok());
        assert_eq!(&dst, &[7, 8, 9]);
        assert_eq!(RandomRead::size(&mut src).unwrap(), 9);
    }

    #[test]
    fn should_fail() {
        let mut src: &[u8] = &[1, 2, 3, 4, 5, 6, 7, 8, 9];
        let mut dst: [u8; 3] = [0; 3];
        assert!(src.read(7, &mut dst).is_err());
    }

    #[test]
    fn invalid_start_address_should_not_panic() {
        let mut src: &[u8] = &[1, 2, 3, 4, 5, 6, 7, 8];
        let mut dst: [u8; 4] = [0; 4];
        // Set `start_addr` so that adding `dst.len()` causes it to
        // wrap around and become smaller than `src.len()`
        let start_addr: usize = usize::MAX - (dst.len() - 1);
        // Should not panic
        let result = src.read(start_addr, &mut dst);
        assert!(result.is_err());
    }
}
