#![warn(missing_docs)]
mod adapter;
mod file;
pub use adapter::Adapter;
pub use file::{RandomAccessFile, SyncFile};
use std::{cmp::min, convert::TryInto, io};
pub trait ReadAt {
fn read_at(&self, buf: &mut [u8], offset: u64) -> io::Result<usize>;
fn read_exact_at(&self, mut buf: &mut [u8], mut offset: u64) -> io::Result<()> {
while !buf.is_empty() {
match self.read_at(buf, offset) {
Ok(0) => break,
Ok(n) => {
buf = &mut buf[n..];
offset += n as u64;
}
Err(ref e) if e.kind() == io::ErrorKind::Interrupted => {}
Err(e) => return Err(e),
}
}
if buf.is_empty() {
Ok(())
} else {
Err(fill_buffer_error())
}
}
fn read_vectored_at(&self, bufs: &mut [io::IoSliceMut<'_>], offset: u64) -> io::Result<usize> {
let buf = bufs
.iter_mut()
.find(|b| !b.is_empty())
.map_or(&mut [][..], |b| &mut **b);
self.read_at(buf, offset)
}
}
impl ReadAt for [u8] {
#[inline]
fn read_at(&self, buf: &mut [u8], offset: u64) -> io::Result<usize> {
let read = (|| {
let offset = offset.try_into().ok()?;
let this = self.get(offset..)?;
let len = min(this.len(), buf.len());
buf[..len].copy_from_slice(&this[..len]);
Some(len)
})();
Ok(read.unwrap_or(0))
}
#[inline]
fn read_exact_at(&self, buf: &mut [u8], offset: u64) -> io::Result<()> {
(|| {
let offset = offset.try_into().ok()?;
let this = self.get(offset..)?;
let len = buf.len();
(this.len() >= len).then(|| buf.copy_from_slice(&this[..len]))
})()
.ok_or_else(fill_buffer_error)
}
}
impl<const N: usize> ReadAt for [u8; N] {
#[inline]
fn read_at(&self, buf: &mut [u8], offset: u64) -> io::Result<usize> {
self.as_ref().read_at(buf, offset)
}
#[inline]
fn read_exact_at(&self, buf: &mut [u8], offset: u64) -> io::Result<()> {
self.as_ref().read_exact_at(buf, offset)
}
#[inline]
fn read_vectored_at(&self, bufs: &mut [io::IoSliceMut<'_>], offset: u64) -> io::Result<usize> {
self.as_ref().read_vectored_at(bufs, offset)
}
}
impl ReadAt for Vec<u8> {
#[inline]
fn read_at(&self, buf: &mut [u8], offset: u64) -> io::Result<usize> {
(**self).read_at(buf, offset)
}
#[inline]
fn read_exact_at(&self, buf: &mut [u8], offset: u64) -> io::Result<()> {
(**self).read_exact_at(buf, offset)
}
#[inline]
fn read_vectored_at(&self, bufs: &mut [io::IoSliceMut<'_>], offset: u64) -> io::Result<usize> {
(**self).read_vectored_at(bufs, offset)
}
}
impl ReadAt for std::borrow::Cow<'_, [u8]> {
#[inline]
fn read_at(&self, buf: &mut [u8], offset: u64) -> io::Result<usize> {
(**self).read_at(buf, offset)
}
#[inline]
fn read_exact_at(&self, buf: &mut [u8], offset: u64) -> io::Result<()> {
(**self).read_exact_at(buf, offset)
}
#[inline]
fn read_vectored_at(&self, bufs: &mut [io::IoSliceMut<'_>], offset: u64) -> io::Result<usize> {
(**self).read_vectored_at(bufs, offset)
}
}
impl<R> ReadAt for &R
where
R: ReadAt + ?Sized,
{
#[inline]
fn read_at(&self, buf: &mut [u8], offset: u64) -> io::Result<usize> {
(**self).read_at(buf, offset)
}
#[inline]
fn read_exact_at(&self, buf: &mut [u8], offset: u64) -> io::Result<()> {
(**self).read_exact_at(buf, offset)
}
#[inline]
fn read_vectored_at(&self, bufs: &mut [io::IoSliceMut<'_>], offset: u64) -> io::Result<usize> {
(**self).read_vectored_at(bufs, offset)
}
}
impl<R> ReadAt for Box<R>
where
R: ReadAt + ?Sized,
{
#[inline]
fn read_at(&self, buf: &mut [u8], offset: u64) -> io::Result<usize> {
(**self).read_at(buf, offset)
}
#[inline]
fn read_exact_at(&self, buf: &mut [u8], offset: u64) -> io::Result<()> {
(**self).read_exact_at(buf, offset)
}
#[inline]
fn read_vectored_at(&self, bufs: &mut [io::IoSliceMut<'_>], offset: u64) -> io::Result<usize> {
(**self).read_vectored_at(bufs, offset)
}
}
impl<R> ReadAt for std::sync::Arc<R>
where
R: ReadAt + ?Sized,
{
#[inline]
fn read_at(&self, buf: &mut [u8], offset: u64) -> io::Result<usize> {
(**self).read_at(buf, offset)
}
#[inline]
fn read_exact_at(&self, buf: &mut [u8], offset: u64) -> io::Result<()> {
(**self).read_exact_at(buf, offset)
}
#[inline]
fn read_vectored_at(&self, bufs: &mut [io::IoSliceMut<'_>], offset: u64) -> io::Result<usize> {
(**self).read_vectored_at(bufs, offset)
}
}
impl<R> ReadAt for std::rc::Rc<R>
where
R: ReadAt + ?Sized,
{
#[inline]
fn read_at(&self, buf: &mut [u8], offset: u64) -> io::Result<usize> {
(**self).read_at(buf, offset)
}
#[inline]
fn read_exact_at(&self, buf: &mut [u8], offset: u64) -> io::Result<()> {
(**self).read_exact_at(buf, offset)
}
#[inline]
fn read_vectored_at(&self, bufs: &mut [io::IoSliceMut<'_>], offset: u64) -> io::Result<usize> {
(**self).read_vectored_at(bufs, offset)
}
}
impl<T> ReadAt for io::Cursor<T>
where
T: AsRef<[u8]>,
{
#[inline]
fn read_at(&self, buf: &mut [u8], offset: u64) -> io::Result<usize> {
self.get_ref().as_ref().read_at(buf, offset)
}
#[inline]
fn read_exact_at(&self, buf: &mut [u8], offset: u64) -> io::Result<()> {
self.get_ref().as_ref().read_exact_at(buf, offset)
}
#[inline]
fn read_vectored_at(&self, bufs: &mut [io::IoSliceMut<'_>], offset: u64) -> io::Result<usize> {
self.get_ref().as_ref().read_vectored_at(bufs, offset)
}
}
impl ReadAt for io::Empty {
#[inline]
fn read_at(&self, _buf: &mut [u8], _offset: u64) -> io::Result<usize> {
Ok(0)
}
#[inline]
fn read_exact_at(&self, buf: &mut [u8], _offset: u64) -> io::Result<()> {
if buf.is_empty() {
Ok(())
} else {
Err(fill_buffer_error())
}
}
#[inline]
fn read_vectored_at(&self, _: &mut [io::IoSliceMut<'_>], _: u64) -> io::Result<usize> {
Ok(0)
}
}
pub trait WriteAt {
fn write_at(&self, buf: &[u8], offset: u64) -> io::Result<usize>;
fn write_all_at(&self, mut buf: &[u8], mut offset: u64) -> io::Result<()> {
while !buf.is_empty() {
match self.write_at(buf, offset) {
Ok(0) => {
return Err(write_buffer_error());
}
Ok(n) => {
buf = &buf[n..];
offset += n as u64;
}
Err(ref e) if e.kind() == io::ErrorKind::Interrupted => {}
Err(e) => return Err(e),
}
}
Ok(())
}
fn write_vectored_at(&self, bufs: &[io::IoSlice<'_>], offset: u64) -> io::Result<usize> {
let buf = bufs
.iter()
.find(|b| !b.is_empty())
.map_or(&[][..], |b| &**b);
self.write_at(buf, offset)
}
#[inline]
fn flush(&self) -> io::Result<()> {
Ok(())
}
}
impl<W> WriteAt for &W
where
W: WriteAt + ?Sized,
{
#[inline]
fn write_at(&self, buf: &[u8], offset: u64) -> io::Result<usize> {
(**self).write_at(buf, offset)
}
#[inline]
fn write_all_at(&self, buf: &[u8], offset: u64) -> io::Result<()> {
(**self).write_all_at(buf, offset)
}
#[inline]
fn write_vectored_at(&self, bufs: &[io::IoSlice<'_>], offset: u64) -> io::Result<usize> {
(**self).write_vectored_at(bufs, offset)
}
#[inline]
fn flush(&self) -> io::Result<()> {
(**self).flush()
}
}
impl<W> WriteAt for Box<W>
where
W: WriteAt + ?Sized,
{
#[inline]
fn write_at(&self, buf: &[u8], offset: u64) -> io::Result<usize> {
(**self).write_at(buf, offset)
}
#[inline]
fn write_all_at(&self, buf: &[u8], offset: u64) -> io::Result<()> {
(**self).write_all_at(buf, offset)
}
#[inline]
fn write_vectored_at(&self, bufs: &[io::IoSlice<'_>], offset: u64) -> io::Result<usize> {
(**self).write_vectored_at(bufs, offset)
}
#[inline]
fn flush(&self) -> io::Result<()> {
(**self).flush()
}
}
impl<W> WriteAt for std::sync::Arc<W>
where
W: WriteAt + ?Sized,
{
#[inline]
fn write_at(&self, buf: &[u8], offset: u64) -> io::Result<usize> {
(**self).write_at(buf, offset)
}
#[inline]
fn write_all_at(&self, buf: &[u8], offset: u64) -> io::Result<()> {
(**self).write_all_at(buf, offset)
}
#[inline]
fn write_vectored_at(&self, bufs: &[io::IoSlice<'_>], offset: u64) -> io::Result<usize> {
(**self).write_vectored_at(bufs, offset)
}
#[inline]
fn flush(&self) -> io::Result<()> {
(**self).flush()
}
}
impl<W> WriteAt for std::rc::Rc<W>
where
W: WriteAt + ?Sized,
{
#[inline]
fn write_at(&self, buf: &[u8], offset: u64) -> io::Result<usize> {
(**self).write_at(buf, offset)
}
#[inline]
fn write_all_at(&self, buf: &[u8], offset: u64) -> io::Result<()> {
(**self).write_all_at(buf, offset)
}
#[inline]
fn write_vectored_at(&self, bufs: &[io::IoSlice<'_>], offset: u64) -> io::Result<usize> {
(**self).write_vectored_at(bufs, offset)
}
#[inline]
fn flush(&self) -> io::Result<()> {
(**self).flush()
}
}
impl WriteAt for io::Sink {
#[inline]
fn write_at(&self, buf: &[u8], _offset: u64) -> io::Result<usize> {
Ok(buf.len())
}
#[inline]
fn write_all_at(&self, _buf: &[u8], _offset: u64) -> io::Result<()> {
Ok(())
}
#[inline]
fn write_vectored_at(&self, bufs: &[io::IoSlice<'_>], _offset: u64) -> io::Result<usize> {
Ok(bufs.iter().map(|b| b.len()).sum())
}
}
#[cold]
fn fill_buffer_error() -> io::Error {
io::Error::new(io::ErrorKind::UnexpectedEof, "failed to fill whole buffer")
}
#[cold]
fn write_buffer_error() -> io::Error {
io::Error::new(io::ErrorKind::WriteZero, "failed to write whole buffer")
}
#[cfg(test)]
mod tests {
use super::*;
use std::io::prelude::*;
#[test]
fn smoke_test() {
let mut f = SyncFile::open("LICENSE-APACHE").unwrap();
let mut buf = [0; 9];
f.read_exact(&mut buf).unwrap();
assert_eq!(&buf, b"Copyright");
assert_eq!(f.stream_position().unwrap(), 9);
assert_eq!(f.seek(io::SeekFrom::Current(-2)).unwrap(), 7);
f.read_exact(&mut buf[..2]).unwrap();
assert_eq!(&buf[..2], b"ht");
assert!(f.seek(io::SeekFrom::Current(-10)).is_err());
}
}