use std::borrow::Cow;
use std::fs::File;
use std::io;
use std::ops::Deref;
use std::path::Path;
use memmap::Mmap;
use owning_ref::OwningHandle;
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>, io::Error> {
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>, io::Error> {
let file = File::open(path)?;
let inner = match unsafe { Mmap::map(&file) } {
Ok(mmap) => ByteViewInner::Mmap(mmap),
Err(err) => {
if err.kind() == io::ErrorKind::InvalidInput {
ByteViewInner::Buf(Cow::Borrowed(b""))
} else {
return Err(err);
}
}
};
Ok(ByteView { inner })
}
#[inline(always)]
fn buffer(&self) -> &[u8] {
match self.inner {
ByteViewInner::Buf(ref buf) => buf,
ByteViewInner::Mmap(ref mmap) => mmap.deref(),
}
}
}
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, E>(view: ByteView<'bytes>, f: F) -> Result<ByteViewHandle<'bytes, T>, E>
where
F: FnOnce(&'bytes [u8]) -> Result<T, E>,
{
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, E>(buffer: &'bytes [u8], f: F) -> Result<ByteViewHandle<'bytes, T>, E>
where
F: FnOnce(&'bytes [u8]) -> Result<T, E>,
{
ByteViewHandle::from_byteview(ByteView::from_slice(buffer), f)
}
pub fn from_vec<F, E>(vec: Vec<u8>, f: F) -> Result<ByteViewHandle<'static, T>, E>
where
F: FnOnce(&'static [u8]) -> Result<T, E>,
{
ByteViewHandle::from_byteview(ByteView::from_vec(vec), f)
}
pub fn from_reader<F, R, E>(reader: R, f: F) -> Result<ByteViewHandle<'static, T>, E>
where
F: FnOnce(&'static [u8]) -> Result<T, E>,
E: From<io::Error>,
R: io::Read,
{
ByteViewHandle::from_byteview(ByteView::from_reader(reader)?, f)
}
pub fn from_path<F, P, E>(path: P, f: F) -> Result<ByteViewHandle<'static, T>, E>
where
F: FnOnce(&'static [u8]) -> Result<T, E>,
E: From<io::Error>,
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
}
}