use std::io;
#[cfg(feature = "mmap")]
pub mod mmap;
#[cfg(feature = "mmap")]
pub use mmap::MmapImage;
pub trait RandomAccess {
fn len(&self) -> u64;
fn is_empty(&self) -> bool {
self.len() == 0
}
fn read_at(&self, offset: u64, len: usize) -> io::Result<&[u8]>;
}
pub trait RandomAccessMut {
fn len(&self) -> u64;
fn is_empty(&self) -> bool {
self.len() == 0
}
fn read_at_mut(&mut self, offset: u64, len: usize) -> io::Result<&[u8]>;
}
#[cfg(test)]
mod tests {
use super::*;
struct InMemory<'a>(&'a [u8]);
impl<'a> RandomAccess for InMemory<'a> {
fn len(&self) -> u64 {
self.0.len() as u64
}
fn read_at(&self, offset: u64, len: usize) -> io::Result<&[u8]> {
let off = offset as usize;
let end = off
.checked_add(len)
.ok_or_else(|| io::Error::new(io::ErrorKind::UnexpectedEof, "offset overflow"))?;
self.0
.get(off..end)
.ok_or_else(|| io::Error::new(io::ErrorKind::UnexpectedEof, "read past image end"))
}
}
#[test]
fn in_memory_round_trip() {
let buf = b"abcdefgh";
let img = InMemory(buf);
assert_eq!(img.len(), 8);
assert!(!img.is_empty());
assert_eq!(img.read_at(0, 4).unwrap(), b"abcd");
assert_eq!(img.read_at(4, 4).unwrap(), b"efgh");
}
#[test]
fn in_memory_eof() {
let img = InMemory(b"abc");
assert_eq!(
img.read_at(0, 4).unwrap_err().kind(),
io::ErrorKind::UnexpectedEof
);
}
#[test]
fn in_memory_offset_overflow() {
let img = InMemory(b"abc");
let err = img.read_at(u64::MAX, 1).unwrap_err();
assert_eq!(err.kind(), io::ErrorKind::UnexpectedEof);
}
struct InMemoryMut<'a>(&'a [u8]);
impl<'a> RandomAccessMut for InMemoryMut<'a> {
fn len(&self) -> u64 {
self.0.len() as u64
}
fn read_at_mut(&mut self, offset: u64, len: usize) -> io::Result<&[u8]> {
let off = offset as usize;
self.0
.get(off..off + len)
.ok_or_else(|| io::Error::new(io::ErrorKind::UnexpectedEof, "eof"))
}
}
#[test]
fn random_access_mut_default_is_empty() {
let empty = InMemoryMut(b"");
assert!(empty.is_empty(), "empty slice → is_empty() should be true");
let mut nonempty = InMemoryMut(b"xy");
assert!(
!nonempty.is_empty(),
"non-empty slice → is_empty() should be false"
);
assert_eq!(nonempty.read_at_mut(0, 2).unwrap(), b"xy");
}
}