use std::io;
use std::path::Path;
use std::borrow::Cow;
use std::ops::Deref;
use memmap::{Mmap, Protection};
use owning_ref::OwningHandle;
use errors::Result;
enum ByteViewInner<'bytes> {
Buf(Cow<'bytes, [u8]>),
Mmap(Mmap),
}
pub struct ByteView<'bytes> {
inner: ByteViewInner<'bytes>,
}
impl<'bytes> ByteView<'bytes> {
fn from_cow(cow: Cow<'bytes, [u8]>) -> ByteView<'bytes> {
ByteView {
inner: ByteViewInner::Buf(cow),
}
}
pub fn from_slice(buffer: &'bytes [u8]) -> ByteView<'bytes> {
ByteView::from_cow(Cow::Borrowed(buffer))
}
pub fn from_vec(buffer: Vec<u8>) -> ByteView<'static> {
ByteView::from_cow(Cow::Owned(buffer))
}
pub fn from_reader<R: io::Read>(mut reader: R) -> Result<ByteView<'static>> {
let mut buffer = vec![];
reader.read_to_end(&mut buffer)?;
Ok(ByteView::from_vec(buffer))
}
pub fn from_path<P: AsRef<Path>>(path: P) -> Result<ByteView<'static>> {
let inner = match Mmap::open_path(path, Protection::Read) {
Ok(mmap) => ByteViewInner::Mmap(mmap),
Err(err) => {
if err.kind() == io::ErrorKind::InvalidInput {
ByteViewInner::Buf(Cow::Borrowed(b""))
} else {
return Err(err.into());
}
}
};
Ok(ByteView { inner: inner })
}
#[inline(always)]
fn buffer(&self) -> &[u8] {
match self.inner {
ByteViewInner::Buf(ref buf) => buf,
ByteViewInner::Mmap(ref mmap) => unsafe {
mmap.as_slice()
},
}
}
}
impl<'bytes> Deref for ByteView<'bytes> {
type Target = [u8];
fn deref(&self) -> &[u8] {
self.buffer()
}
}
impl<'bytes> AsRef<[u8]> for ByteView<'bytes> {
fn as_ref(&self) -> &[u8] {
self.buffer()
}
}
pub struct ByteViewHandle<'bytes, T> {
inner: OwningHandle<Box<ByteView<'bytes>>, Box<(&'bytes [u8], T)>>,
}
impl<'bytes, T> ByteViewHandle<'bytes, T> {
pub fn from_byteview<F>(view: ByteView<'bytes>, f: F) -> Result<ByteViewHandle<'bytes, T>>
where
F: FnOnce(&'bytes [u8]) -> Result<T>,
{
Ok(ByteViewHandle {
inner: OwningHandle::try_new(Box::new(view), |bv| -> Result<_> {
let bytes: &[u8] = unsafe { &*bv };
Ok(Box::new((bytes, f(bytes)?)))
})?,
})
}
pub fn from_slice<F>(buffer: &'bytes [u8], f: F) -> Result<ByteViewHandle<'bytes, T>>
where
F: FnOnce(&'bytes [u8]) -> Result<T>,
{
ByteViewHandle::from_byteview(ByteView::from_slice(buffer), f)
}
pub fn from_vec<F>(vec: Vec<u8>, f: F) -> Result<ByteViewHandle<'static, T>>
where
F: FnOnce(&'static [u8]) -> Result<T>,
{
ByteViewHandle::from_byteview(ByteView::from_vec(vec), f)
}
pub fn from_reader<F, R>(reader: R, f: F) -> Result<ByteViewHandle<'static, T>>
where
F: FnOnce(&'static [u8]) -> Result<T>,
R: io::Read,
{
ByteViewHandle::from_byteview(ByteView::from_reader(reader)?, f)
}
pub fn from_path<F, P>(path: P, f: F) -> Result<ByteViewHandle<'static, T>>
where
F: FnOnce(&'static [u8]) -> Result<T>,
P: AsRef<Path>,
{
ByteViewHandle::from_byteview(ByteView::from_path(path)?, f)
}
pub fn get_bytes<'b>(this: &'b ByteViewHandle<'bytes, T>) -> &'b [u8] {
this.inner.0
}
}
impl<'bytes, T> Deref for ByteViewHandle<'bytes, T> {
type Target = T;
fn deref(&self) -> &T {
&self.inner.1
}
}
impl<'bytes, T> AsRef<T> for ByteViewHandle<'bytes, T> {
fn as_ref(&self) -> &T {
&self.inner.1
}
}