use std::fs::File;
use std::cmp;
use std::io::{Empty, Error, ErrorKind, Read, Repeat, Result, Seek, SeekFrom, Sink, Write};
pub trait ReadAt {
fn read_at(&mut self, pos: u64, buf: &mut [u8]) -> Result<usize>;
fn read_exact_at(&mut self, mut pos: u64, mut buf: &mut [u8]) -> Result<()> {
while !buf.is_empty() {
match self.read_at(pos, buf) {
Ok(0) => break,
Ok(n) => {
let tmp = buf;
buf = &mut tmp[n..];
pos += n as u64;
}
Err(ref e) if e.kind() == ErrorKind::Interrupted => {}
Err(e) => return Err(e),
}
}
if !buf.is_empty() {
Err(Error::new(ErrorKind::UnexpectedEof, "failed to fill whole buffer"))
} else {
Ok(())
}
}
}
pub trait WriteAt {
fn write_at(&mut self, pos: u64, buf: &[u8]) -> Result<usize>;
fn flush(&mut self) -> Result<()>;
fn write_all_at(&mut self, mut pos: u64, mut buf: &[u8]) -> Result<()> {
while !buf.is_empty() {
match self.write_at(pos, buf) {
Ok(0) => {
return Err(Error::new(ErrorKind::WriteZero, "failed to write whole buffer"));
}
Ok(n) => {
buf = &buf[n..];
pos += n as u64;
}
Err(ref e) if e.kind() == ErrorKind::Interrupted => {}
Err(e) => return Err(e),
}
}
Ok(())
}
}
impl<'a, R: ReadAt> ReadAt for &'a mut R {
#[inline]
fn read_at(&mut self, pos: u64, buf: &mut [u8]) -> Result<usize> {
(**self).read_at(pos, buf)
}
#[inline]
fn read_exact_at(&mut self, pos: u64, buf: &mut [u8]) -> Result<()> {
(**self).read_exact_at(pos, buf)
}
}
impl<'a, W: WriteAt> WriteAt for &'a mut W {
#[inline]
fn write_at(&mut self, pos: u64, buf: &[u8]) -> Result<usize> {
(**self).write_at(pos, buf)
}
#[inline]
fn write_all_at(&mut self, pos: u64, buf: &[u8]) -> Result<()> {
(**self).write_all_at(pos, buf)
}
#[inline]
fn flush(&mut self) -> Result<()> {
(**self).flush()
}
}
impl<'a> ReadAt for &'a [u8] {
fn read_at(&mut self, pos: u64, buf: &mut [u8]) -> Result<usize> {
if pos >= self.len() as u64 {
return Ok(0);
}
let i = pos as usize;
buf.copy_from_slice(&self[i..]);
Ok(cmp::min(self.len() - i, buf.len()))
}
fn read_exact_at(&mut self, pos: u64, buf: &mut [u8]) -> Result<()> {
if try!(self.read_at(pos, buf)) < buf.len() {
Err(Error::new(ErrorKind::UnexpectedEof, "failed to write whole buffer"))
} else {
Ok(())
}
}
}
impl ReadAt for Vec<u8> {
#[inline]
fn read_at(&mut self, pos: u64, buf: &mut [u8]) -> Result<usize> {
(&self[..]).read_at(pos, buf)
}
#[inline]
fn read_exact_at(&mut self, pos: u64, buf: &mut [u8]) -> Result<()> {
(&self[..]).read_exact_at(pos, buf)
}
}
impl ReadAt for Box<[u8]> {
#[inline]
fn read_at(&mut self, pos: u64, buf: &mut [u8]) -> Result<usize> {
(&self[..]).read_at(pos, buf)
}
#[inline]
fn read_exact_at(&mut self, pos: u64, buf: &mut [u8]) -> Result<()> {
(&self[..]).read_exact_at(pos, buf)
}
}
impl ReadAt for File {
#[inline]
fn read_at(&mut self, pos: u64, buf: &mut [u8]) -> Result<usize> {
AssertThreadSafe(self).read_at(pos, buf)
}
#[inline]
fn read_exact_at(&mut self, pos: u64, buf: &mut [u8]) -> Result<()> {
AssertThreadSafe(self).read_exact_at(pos, buf)
}
}
impl ReadAt for Empty {
#[inline]
fn read_at(&mut self, _pos: u64, _buf: &mut [u8]) -> Result<usize> {
Ok(0)
}
}
impl ReadAt for Repeat {
#[inline]
fn read_at(&mut self, _pos: u64, buf: &mut [u8]) -> Result<usize> {
self.read(buf)
}
}
impl WriteAt for [u8] {
fn write_at(&mut self, pos: u64, buf: &[u8]) -> Result<usize> {
if pos >= self.len() as u64 {
return Ok(0);
}
let i = pos as usize;
self[i..].copy_from_slice(buf);
Ok(cmp::min(self.len() - i, buf.len()))
}
#[inline]
fn flush(&mut self) -> Result<()> {
Ok(())
}
fn write_all_at(&mut self, pos: u64, buf: &[u8]) -> Result<()> {
if try!(self.write_at(pos, buf)) < buf.len() {
Err(Error::new(ErrorKind::UnexpectedEof, "failed to write whole buffer"))
} else {
Ok(())
}
}
}
impl WriteAt for Vec<u8> {
fn write_at(&mut self, pos: u64, buf: &[u8]) -> Result<usize> {
if pos >= usize::max_value() as u64 {
return Ok(0);
}
let i = pos as usize;
if i >= self.len() {
let needed = self.len() - i;
self.reserve(needed);
}
self[i..].copy_from_slice(buf);
Ok(cmp::min(self.len() - i, buf.len()))
}
#[inline]
fn flush(&mut self) -> Result<()> {
Ok(())
}
fn write_all_at(&mut self, pos: u64, buf: &[u8]) -> Result<()> {
if try!(self.write_at(pos, buf)) < buf.len() {
Err(Error::new(ErrorKind::UnexpectedEof, "failed to write whole buffer"))
} else {
Ok(())
}
}
}
impl WriteAt for Box<[u8]> {
#[inline]
fn write_at(&mut self, pos: u64, buf: &[u8]) -> Result<usize> {
(&mut self[..]).write_at(pos, buf)
}
#[inline]
fn write_all_at(&mut self, pos: u64, buf: &[u8]) -> Result<()> {
(&mut self[..]).write_all_at(pos, buf)
}
#[inline]
fn flush(&mut self) -> Result<()> {
Ok(())
}
}
impl WriteAt for File {
#[inline]
fn write_at(&mut self, pos: u64, buf: &[u8]) -> Result<usize> {
AssertThreadSafe(self).write_at(pos, buf)
}
#[inline]
fn flush(&mut self) -> Result<()> {
AssertThreadSafe(self).flush()
}
#[inline]
fn write_all_at(&mut self, pos: u64, buf: &[u8]) -> Result<()> {
AssertThreadSafe(self).write_all_at(pos, buf)
}
}
impl WriteAt for Sink {
#[inline]
fn write_at(&mut self, _pos: u64, buf: &[u8]) -> Result<usize> {
Ok(buf.len())
}
#[inline]
fn flush(&mut self) -> Result<()> {
Ok(())
}
}
#[derive(Clone, Debug)]
pub struct AssertThreadSafe<T>(pub T);
impl<T> ReadAt for AssertThreadSafe<T>
where T: Read + Seek
{
#[inline]
fn read_at(&mut self, pos: u64, buf: &mut [u8]) -> Result<usize> {
try!(self.0.seek(SeekFrom::Start(pos)));
self.0.read(buf)
}
#[inline]
fn read_exact_at(&mut self, pos: u64, buf: &mut [u8]) -> Result<()> {
try!(self.0.seek(SeekFrom::Start(pos)));
self.0.read_exact(buf)
}
}
impl<T> WriteAt for AssertThreadSafe<T>
where T: Write + Seek
{
#[inline]
fn write_at(&mut self, pos: u64, buf: &[u8]) -> Result<usize> {
try!(self.0.seek(SeekFrom::Start(pos)));
self.0.write(buf)
}
#[inline]
fn flush(&mut self) -> Result<()> {
self.0.flush()
}
#[inline]
fn write_all_at(&mut self, pos: u64, buf: &[u8]) -> Result<()> {
try!(self.0.seek(SeekFrom::Start(pos)));
self.0.write_all(buf)
}
}