use std::fs::File;
use std::io::Error;
use std::io::ErrorKind;
use std::io::Result;
use crate::VolatileSlice;
pub trait FileSync {
fn fsync(&self) -> Result<()>;
fn fdatasync(&self) -> Result<()>;
}
impl FileSync for File {
fn fsync(&self) -> Result<()> {
self.sync_all()
}
fn fdatasync(&self) -> Result<()> {
self.sync_data()
}
}
pub trait FileSetLen {
fn set_len(&self, _len: u64) -> Result<()>;
}
impl FileSetLen for File {
fn set_len(&self, len: u64) -> Result<()> {
File::set_len(self, len)
}
}
pub trait FileAllocate {
fn allocate(&self, offset: u64, len: u64) -> Result<()>;
}
pub trait FileGetLen {
fn get_len(&self) -> Result<u64>;
}
impl FileGetLen for File {
fn get_len(&self) -> Result<u64> {
Ok(self.metadata()?.len())
}
}
pub trait FileReadWriteVolatile {
fn read_volatile(&mut self, slice: VolatileSlice) -> Result<usize>;
fn read_vectored_volatile(&mut self, bufs: &[VolatileSlice]) -> Result<usize> {
bufs.iter()
.find(|b| b.size() > 0)
.map(|&b| self.read_volatile(b))
.unwrap_or(Ok(0))
}
fn read_exact_volatile(&mut self, mut slice: VolatileSlice) -> Result<()> {
while slice.size() > 0 {
let bytes_read = self.read_volatile(slice)?;
if bytes_read == 0 {
return Err(Error::from(ErrorKind::UnexpectedEof));
}
slice = slice.offset(bytes_read).unwrap();
}
Ok(())
}
fn write_volatile(&mut self, slice: VolatileSlice) -> Result<usize>;
fn write_vectored_volatile(&mut self, bufs: &[VolatileSlice]) -> Result<usize> {
bufs.iter()
.find(|b| b.size() > 0)
.map(|&b| self.write_volatile(b))
.unwrap_or(Ok(0))
}
fn write_all_volatile(&mut self, mut slice: VolatileSlice) -> Result<()> {
while slice.size() > 0 {
let bytes_written = self.write_volatile(slice)?;
if bytes_written == 0 {
return Err(Error::from(ErrorKind::WriteZero));
}
slice = slice.offset(bytes_written).unwrap();
}
Ok(())
}
}
impl<'a, T: FileReadWriteVolatile + ?Sized> FileReadWriteVolatile for &'a mut T {
fn read_volatile(&mut self, slice: VolatileSlice) -> Result<usize> {
(**self).read_volatile(slice)
}
fn read_vectored_volatile(&mut self, bufs: &[VolatileSlice]) -> Result<usize> {
(**self).read_vectored_volatile(bufs)
}
fn read_exact_volatile(&mut self, slice: VolatileSlice) -> Result<()> {
(**self).read_exact_volatile(slice)
}
fn write_volatile(&mut self, slice: VolatileSlice) -> Result<usize> {
(**self).write_volatile(slice)
}
fn write_vectored_volatile(&mut self, bufs: &[VolatileSlice]) -> Result<usize> {
(**self).write_vectored_volatile(bufs)
}
fn write_all_volatile(&mut self, slice: VolatileSlice) -> Result<()> {
(**self).write_all_volatile(slice)
}
}
pub trait FileReadWriteAtVolatile {
fn read_at_volatile(&self, slice: VolatileSlice, offset: u64) -> Result<usize>;
fn read_vectored_at_volatile(&self, bufs: &[VolatileSlice], offset: u64) -> Result<usize> {
if let Some(&slice) = bufs.first() {
self.read_at_volatile(slice, offset)
} else {
Ok(0)
}
}
fn read_exact_at_volatile(&self, mut slice: VolatileSlice, mut offset: u64) -> Result<()> {
while slice.size() > 0 {
match self.read_at_volatile(slice, offset) {
Ok(0) => return Err(Error::from(ErrorKind::UnexpectedEof)),
Ok(n) => {
slice = slice.offset(n).unwrap();
offset = offset.checked_add(n as u64).unwrap();
}
Err(ref e) if e.kind() == ErrorKind::Interrupted => {}
Err(e) => return Err(e),
}
}
Ok(())
}
fn write_at_volatile(&self, slice: VolatileSlice, offset: u64) -> Result<usize>;
fn write_vectored_at_volatile(&self, bufs: &[VolatileSlice], offset: u64) -> Result<usize> {
if let Some(&slice) = bufs.first() {
self.write_at_volatile(slice, offset)
} else {
Ok(0)
}
}
fn write_all_at_volatile(&self, mut slice: VolatileSlice, mut offset: u64) -> Result<()> {
while slice.size() > 0 {
match self.write_at_volatile(slice, offset) {
Ok(0) => return Err(Error::from(ErrorKind::WriteZero)),
Ok(n) => {
slice = slice.offset(n).unwrap();
offset = offset.checked_add(n as u64).unwrap();
}
Err(ref e) if e.kind() == ErrorKind::Interrupted => {}
Err(e) => return Err(e),
}
}
Ok(())
}
}
impl<'a, T: FileReadWriteAtVolatile + ?Sized> FileReadWriteAtVolatile for &'a mut T {
fn read_at_volatile(&self, slice: VolatileSlice, offset: u64) -> Result<usize> {
(**self).read_at_volatile(slice, offset)
}
fn read_vectored_at_volatile(&self, bufs: &[VolatileSlice], offset: u64) -> Result<usize> {
(**self).read_vectored_at_volatile(bufs, offset)
}
fn read_exact_at_volatile(&self, slice: VolatileSlice, offset: u64) -> Result<()> {
(**self).read_exact_at_volatile(slice, offset)
}
fn write_at_volatile(&self, slice: VolatileSlice, offset: u64) -> Result<usize> {
(**self).write_at_volatile(slice, offset)
}
fn write_vectored_at_volatile(&self, bufs: &[VolatileSlice], offset: u64) -> Result<usize> {
(**self).write_vectored_at_volatile(bufs, offset)
}
fn write_all_at_volatile(&self, slice: VolatileSlice, offset: u64) -> Result<()> {
(**self).write_all_at_volatile(slice, offset)
}
}
impl<'a, T: FileReadWriteAtVolatile + ?Sized> FileReadWriteAtVolatile for &'a T {
fn read_at_volatile(&self, slice: VolatileSlice, offset: u64) -> Result<usize> {
(**self).read_at_volatile(slice, offset)
}
fn read_vectored_at_volatile(&self, bufs: &[VolatileSlice], offset: u64) -> Result<usize> {
(**self).read_vectored_at_volatile(bufs, offset)
}
fn read_exact_at_volatile(&self, slice: VolatileSlice, offset: u64) -> Result<()> {
(**self).read_exact_at_volatile(slice, offset)
}
fn write_at_volatile(&self, slice: VolatileSlice, offset: u64) -> Result<usize> {
(**self).write_at_volatile(slice, offset)
}
fn write_vectored_at_volatile(&self, bufs: &[VolatileSlice], offset: u64) -> Result<usize> {
(**self).write_vectored_at_volatile(bufs, offset)
}
fn write_all_at_volatile(&self, slice: VolatileSlice, offset: u64) -> Result<()> {
(**self).write_all_at_volatile(slice, offset)
}
}
#[cfg(test)]
mod tests {
use std::io::Read;
use std::io::Seek;
use std::io::SeekFrom;
use std::io::Write;
use tempfile::tempfile;
use super::*;
#[test]
fn read_file() -> Result<()> {
let mut f = tempfile()?;
f.write_all(b"AAAAAAAAAAbbbbbbbbbbAAAAA")
.expect("Failed to write bytes");
f.seek(SeekFrom::Start(0))?;
let mut omem = [0u8; 30];
let om = &mut omem[..];
let buf = VolatileSlice::new(om);
f.read_volatile(buf).expect("read_volatile failed.");
f.seek(SeekFrom::Start(0))?;
let mut mem = [0u8; 30];
let (m1, rest) = mem.split_at_mut(10);
let (m2, m3) = rest.split_at_mut(10);
let buf1 = VolatileSlice::new(m1);
let buf2 = VolatileSlice::new(m2);
let buf3 = VolatileSlice::new(m3);
let bufs = [buf1, buf2, buf3];
f.read_vectored_volatile(&bufs)
.expect("read_vectored_volatile failed.");
assert_eq!(&mem[..], b"AAAAAAAAAAbbbbbbbbbbAAAAA\0\0\0\0\0");
Ok(())
}
#[test]
fn write_file() -> Result<()> {
let mut f = tempfile()?;
let mut omem = [0u8; 25];
let om = &mut omem[..];
let buf = VolatileSlice::new(om);
buf.write_bytes(65);
f.write_volatile(buf).expect("write_volatile failed.");
f.seek(SeekFrom::Start(0))?;
let mut filebuf = [0u8; 25];
f.read_exact(&mut filebuf).expect("Failed to read filebuf");
assert_eq!(&filebuf, b"AAAAAAAAAAAAAAAAAAAAAAAAA");
Ok(())
}
#[test]
fn write_vectored_file() -> Result<()> {
let mut f = tempfile()?;
let mut mem = [0u8; 30];
let (m1, rest) = mem.split_at_mut(10);
let (m2, m3) = rest.split_at_mut(10);
let buf1 = VolatileSlice::new(m1);
let buf2 = VolatileSlice::new(m2);
let buf3 = VolatileSlice::new(m3);
buf1.write_bytes(65);
buf2.write_bytes(98);
buf3.write_bytes(65);
let bufs = [buf1, buf2, buf3];
f.write_vectored_volatile(&bufs)
.expect("write_vectored_volatile failed.");
f.seek(SeekFrom::Start(0))?;
let mut filebuf = [0u8; 30];
f.read_exact(&mut filebuf).expect("Failed to read filebuf.");
assert_eq!(&filebuf, b"AAAAAAAAAAbbbbbbbbbbAAAAAAAAAA");
Ok(())
}
#[test]
fn read_at_file() -> Result<()> {
let mut f = tempfile()?;
f.write_all(b"AAAAAAAAAAbbbbbbbbbbAAAAA")
.expect("Failed to write bytes.");
let mut omem = [0u8; 20];
let om = &mut omem[..];
let buf = VolatileSlice::new(om);
f.read_at_volatile(buf, 10)
.expect("read_at_volatile failed.");
assert_eq!(om, b"bbbbbbbbbbAAAAA\0\0\0\0\0");
let mut mem = [0u8; 20];
let (m1, m2) = mem.split_at_mut(10);
let buf1 = VolatileSlice::new(m1);
let buf2 = VolatileSlice::new(m2);
let bufs = [buf1, buf2];
f.read_vectored_at_volatile(&bufs, 10)
.expect("read_vectored_at_volatile failed.");
assert_eq!(&mem[..], b"bbbbbbbbbbAAAAA\0\0\0\0\0");
Ok(())
}
#[test]
fn write_at_file() -> Result<()> {
let mut f = tempfile()?;
f.write_all(b"ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ")
.expect("Failed to write bytes");
let mut omem = [0u8; 15];
let om = &mut omem[..];
let buf = VolatileSlice::new(om);
buf.write_bytes(65);
f.write_at_volatile(buf, 10)
.expect("write_at_volatile failed.");
f.seek(SeekFrom::Start(0))?;
let mut filebuf = [0u8; 30];
f.read_exact(&mut filebuf).expect("Failed to read filebuf.");
assert_eq!(&filebuf, b"ZZZZZZZZZZAAAAAAAAAAAAAAAZZZZZ");
Ok(())
}
#[test]
fn write_vectored_at_file() -> Result<()> {
let mut f = tempfile()?;
f.write_all(b"ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ")
.expect("Failed to write bytes");
let mut mem = [0u8; 30];
let (m1, m2) = mem.split_at_mut(10);
let buf1 = VolatileSlice::new(m1);
let buf2 = VolatileSlice::new(m2);
buf1.write_bytes(65);
buf2.write_bytes(98);
let bufs = [buf1, buf2];
f.write_vectored_at_volatile(&bufs, 10)
.expect("write_vectored_at_volatile failed.");
f.seek(SeekFrom::Start(0))?;
let mut filebuf = [0u8; 30];
f.read_exact(&mut filebuf).expect("Failed to read filebuf.");
assert_eq!(&filebuf, b"ZZZZZZZZZZAAAAAAAAAAbbbbbbbbbb");
Ok(())
}
}