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<'a> {
Buf(Cow<'a, [u8]>),
Mmap(Mmap),
}
pub struct ByteView<'a> {
inner: ByteViewInner<'a>,
}
impl<'a> ByteView<'a> {
fn from_cow(cow: Cow<'a, [u8]>) -> ByteView<'a> {
ByteView {
inner: ByteViewInner::Buf(cow)
}
}
pub fn from_slice(buffer: &'a [u8]) -> ByteView<'a> {
ByteView::from_cow(Cow::Borrowed(buffer))
}
pub fn from_vec(buffer: Vec<u8>) -> ByteView<'static> {
ByteView::from_cow(Cow::Owned(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<'a> Deref for ByteView<'a> {
type Target = [u8];
fn deref(&self) -> &[u8] {
self.buffer()
}
}
impl<'a> AsRef<[u8]> for ByteView<'a> {
fn as_ref(&self) -> &[u8] {
self.buffer()
}
}
pub struct ByteViewHandle<'a, T> {
inner: OwningHandle<Box<ByteView<'a>>, Box<(&'a [u8], T)>>,
}
impl<'a, T> ByteViewHandle<'a, T> {
pub fn from_byteview<F>(view: ByteView<'a>, f: F) -> Result<ByteViewHandle<'a, T>>
where F: FnOnce(&'a [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: &'a [u8], f: F) -> Result<ByteViewHandle<'a, T>>
where F: FnOnce(&'a [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_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<'a, T>) -> &'b [u8] {
this.inner.0
}
}
impl<'a, T> Deref for ByteViewHandle<'a, T> {
type Target = T;
fn deref(&self) -> &T {
&self.inner.1
}
}
impl<'a, T> AsRef<T> for ByteViewHandle<'a, T> {
fn as_ref(&self) -> &T {
&self.inner.1
}
}