use std::ops::Deref;
use std::ops::DerefMut;
use serde_v8::ZeroCopyBuf;
pub struct BufView {
inner: BufViewInner,
cursor: usize,
}
enum BufViewInner {
Empty,
Bytes(bytes::Bytes),
ZeroCopy(ZeroCopyBuf),
Vec(Vec<u8>),
}
impl BufView {
fn from_inner(inner: BufViewInner) -> Self {
Self { inner, cursor: 0 }
}
pub fn empty() -> Self {
Self::from_inner(BufViewInner::Empty)
}
pub fn len(&self) -> usize {
match &self.inner {
BufViewInner::Empty => 0,
BufViewInner::Bytes(bytes) => bytes.len() - self.cursor,
BufViewInner::ZeroCopy(zero_copy) => zero_copy.len() - self.cursor,
BufViewInner::Vec(vec) => vec.len() - self.cursor,
}
}
pub fn is_empty(&self) -> bool {
self.len() == 0
}
pub fn advance_cursor(&mut self, n: usize) {
assert!(self.len() >= n);
self.cursor += n;
}
pub fn reset_cursor(&mut self) -> usize {
let old = self.cursor;
self.cursor = 0;
old
}
}
impl Deref for BufView {
type Target = [u8];
fn deref(&self) -> &[u8] {
let buf = match &self.inner {
BufViewInner::Empty => &[],
BufViewInner::Bytes(bytes) => bytes.deref(),
BufViewInner::ZeroCopy(zero_copy) => zero_copy.deref(),
BufViewInner::Vec(vec) => vec.deref(),
};
&buf[self.cursor..]
}
}
impl AsRef<[u8]> for BufView {
fn as_ref(&self) -> &[u8] {
self.deref()
}
}
impl From<ZeroCopyBuf> for BufView {
fn from(buf: ZeroCopyBuf) -> Self {
Self::from_inner(BufViewInner::ZeroCopy(buf))
}
}
impl From<Vec<u8>> for BufView {
fn from(vec: Vec<u8>) -> Self {
Self::from_inner(BufViewInner::Vec(vec))
}
}
impl From<bytes::Bytes> for BufView {
fn from(buf: bytes::Bytes) -> Self {
Self::from_inner(BufViewInner::Bytes(buf))
}
}
impl From<BufView> for bytes::Bytes {
fn from(buf: BufView) -> Self {
match buf.inner {
BufViewInner::Empty => bytes::Bytes::new(),
BufViewInner::Bytes(bytes) => bytes,
BufViewInner::ZeroCopy(zero_copy) => zero_copy.into(),
BufViewInner::Vec(vec) => vec.into(),
}
}
}
pub struct BufMutView {
inner: BufMutViewInner,
cursor: usize,
}
enum BufMutViewInner {
ZeroCopy(ZeroCopyBuf),
Vec(Vec<u8>),
}
impl BufMutView {
fn from_inner(inner: BufMutViewInner) -> Self {
Self { inner, cursor: 0 }
}
pub fn new(len: usize) -> Self {
Self::from_inner(BufMutViewInner::Vec(vec![0; len]))
}
pub fn len(&self) -> usize {
match &self.inner {
BufMutViewInner::ZeroCopy(zero_copy) => zero_copy.len() - self.cursor,
BufMutViewInner::Vec(vec) => vec.len() - self.cursor,
}
}
pub fn is_empty(&self) -> bool {
self.len() == 0
}
pub fn advance_cursor(&mut self, n: usize) {
assert!(self.len() >= n);
self.cursor += n;
}
pub fn reset_cursor(&mut self) -> usize {
let old = self.cursor;
self.cursor = 0;
old
}
pub fn into_view(self) -> BufView {
let inner = match self.inner {
BufMutViewInner::ZeroCopy(zero_copy) => BufViewInner::ZeroCopy(zero_copy),
BufMutViewInner::Vec(vec) => BufViewInner::Vec(vec),
};
BufView {
inner,
cursor: self.cursor,
}
}
pub fn unwrap_vec(self) -> Vec<u8> {
match self.inner {
BufMutViewInner::ZeroCopy(_) => {
panic!("Cannot unwrap a ZeroCopyBuf backed BufMutView into a Vec");
}
BufMutViewInner::Vec(vec) => vec,
}
}
pub fn get_mut_vec(&mut self) -> &mut Vec<u8> {
match &mut self.inner {
BufMutViewInner::ZeroCopy(_) => {
panic!("Cannot unwrap a ZeroCopyBuf backed BufMutView into a Vec");
}
BufMutViewInner::Vec(vec) => vec,
}
}
}
impl Deref for BufMutView {
type Target = [u8];
fn deref(&self) -> &[u8] {
let buf = match &self.inner {
BufMutViewInner::ZeroCopy(zero_copy) => zero_copy.deref(),
BufMutViewInner::Vec(vec) => vec.deref(),
};
&buf[self.cursor..]
}
}
impl DerefMut for BufMutView {
fn deref_mut(&mut self) -> &mut [u8] {
let buf = match &mut self.inner {
BufMutViewInner::ZeroCopy(zero_copy) => zero_copy.deref_mut(),
BufMutViewInner::Vec(vec) => vec.deref_mut(),
};
&mut buf[self.cursor..]
}
}
impl AsRef<[u8]> for BufMutView {
fn as_ref(&self) -> &[u8] {
self.deref()
}
}
impl AsMut<[u8]> for BufMutView {
fn as_mut(&mut self) -> &mut [u8] {
self.deref_mut()
}
}
impl From<ZeroCopyBuf> for BufMutView {
fn from(buf: ZeroCopyBuf) -> Self {
Self::from_inner(BufMutViewInner::ZeroCopy(buf))
}
}
impl From<Vec<u8>> for BufMutView {
fn from(buf: Vec<u8>) -> Self {
Self::from_inner(BufMutViewInner::Vec(buf))
}
}
pub enum WriteOutcome {
Partial { nwritten: usize, view: BufView },
Full { nwritten: usize },
}
impl WriteOutcome {
pub fn nwritten(&self) -> usize {
match self {
WriteOutcome::Partial { nwritten, .. } => *nwritten,
WriteOutcome::Full { nwritten } => *nwritten,
}
}
}