use bytes::Buf;
use bytes::BytesMut;
use serde_v8::JsBuffer;
use serde_v8::V8Slice;
use std::ops::Deref;
use std::ops::DerefMut;
#[derive(Debug)]
pub struct BufView {
inner: BufViewInner,
cursor: usize,
}
#[derive(Debug)]
enum BufViewInner {
Empty,
Bytes(bytes::Bytes),
JsBuffer(V8Slice<u8>),
}
impl BufView {
const fn from_inner(inner: BufViewInner) -> Self {
Self { inner, cursor: 0 }
}
pub const 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::JsBuffer(js_buf) => js_buf.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 truncate(&mut self, size: usize) {
match &mut self.inner {
BufViewInner::Empty => {}
BufViewInner::Bytes(bytes) => bytes.truncate(size + self.cursor),
BufViewInner::JsBuffer(buffer) => buffer.truncate(size + self.cursor),
}
}
pub fn split_off(&mut self, at: usize) -> Self {
let at = at + self.cursor;
assert!(at <= self.len());
let other = match &mut self.inner {
BufViewInner::Empty => BufViewInner::Empty,
BufViewInner::Bytes(bytes) => BufViewInner::Bytes(bytes.split_off(at)),
BufViewInner::JsBuffer(buffer) => {
BufViewInner::JsBuffer(buffer.split_off(at))
}
};
Self {
inner: other,
cursor: 0,
}
}
pub fn split_to(&mut self, at: usize) -> Self {
assert!(at <= self.len());
let at = at + self.cursor;
let other = match &mut self.inner {
BufViewInner::Empty => BufViewInner::Empty,
BufViewInner::Bytes(bytes) => BufViewInner::Bytes(bytes.split_to(at)),
BufViewInner::JsBuffer(buffer) => {
BufViewInner::JsBuffer(buffer.split_to(at))
}
};
let cursor = std::mem::take(&mut self.cursor);
Self {
inner: other,
cursor,
}
}
}
impl Buf for BufView {
fn remaining(&self) -> usize {
self.len()
}
fn chunk(&self) -> &[u8] {
self.deref()
}
fn advance(&mut self, cnt: usize) {
self.advance_cursor(cnt)
}
}
impl Deref for BufView {
type Target = [u8];
fn deref(&self) -> &[u8] {
let buf = match &self.inner {
BufViewInner::Empty => &[],
BufViewInner::Bytes(bytes) => bytes.deref(),
BufViewInner::JsBuffer(js_buf) => js_buf.deref(),
};
&buf[self.cursor..]
}
}
impl AsRef<[u8]> for BufView {
fn as_ref(&self) -> &[u8] {
self.deref()
}
}
impl From<JsBuffer> for BufView {
fn from(buf: JsBuffer) -> Self {
Self::from_inner(BufViewInner::JsBuffer(buf.into_parts()))
}
}
impl From<Vec<u8>> for BufView {
fn from(vec: Vec<u8>) -> Self {
Self::from_inner(BufViewInner::Bytes(vec.into()))
}
}
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::JsBuffer(js_buf) => js_buf.into(),
}
}
}
pub struct BufMutViewWhole {
inner: BufMutViewInner,
cursor: usize,
}
#[derive(Debug)]
pub struct BufMutView {
inner: BufMutViewInner,
cursor: usize,
}
#[derive(Debug)]
enum BufMutViewInner {
JsBuffer(V8Slice<u8>),
Bytes(BytesMut),
}
impl Default for BufMutView {
fn default() -> Self {
BufMutView {
inner: BufMutViewInner::Bytes(BytesMut::default()),
cursor: 0,
}
}
}
impl BufMutView {
fn from_inner(inner: BufMutViewInner) -> Self {
Self { inner, cursor: 0 }
}
pub fn new(len: usize) -> Self {
let bytes = BytesMut::zeroed(len);
Self::from_inner(BufMutViewInner::Bytes(bytes))
}
pub fn len(&self) -> usize {
match &self.inner {
BufMutViewInner::JsBuffer(js_buf) => js_buf.len() - self.cursor,
BufMutViewInner::Bytes(bytes) => bytes.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::JsBuffer(js_buf) => BufViewInner::JsBuffer(js_buf),
BufMutViewInner::Bytes(bytes) => BufViewInner::Bytes(bytes.into()),
};
BufView {
inner,
cursor: self.cursor,
}
}
pub fn maybe_unwrap_bytes(self) -> Result<BytesMut, Self> {
match self.inner {
BufMutViewInner::JsBuffer(_) => Err(self),
BufMutViewInner::Bytes(bytes) => Ok(bytes),
}
}
#[must_use = "The result of this method should be tested"]
#[deprecated = "API will be replaced in the future"]
#[doc(hidden)]
pub fn maybe_resize(
&mut self,
target_size: usize,
maximum_increment: usize,
) -> Option<usize> {
if let BufMutViewInner::Bytes(bytes) = &mut self.inner {
use std::cmp::Ordering::*;
let len = bytes.len();
let target_size = target_size + self.cursor;
match target_size.cmp(&len) {
Greater => {
bytes.resize(std::cmp::min(target_size, len + maximum_increment), 0);
}
Less => {
bytes.truncate(target_size);
}
Equal => {}
}
Some(bytes.len())
} else {
None
}
}
#[must_use = "The result of this method should be tested"]
#[deprecated = "API will be replaced in the future"]
#[doc(hidden)]
pub fn maybe_grow(&mut self, target_size: usize) -> Option<usize> {
if let BufMutViewInner::Bytes(bytes) = &mut self.inner {
let len = bytes.len();
let target_size = target_size + self.cursor;
if target_size > len {
bytes.resize(target_size, 0);
}
Some(bytes.len())
} else {
None
}
}
pub fn truncate(&mut self, size: usize) {
match &mut self.inner {
BufMutViewInner::Bytes(bytes) => bytes.truncate(size + self.cursor),
BufMutViewInner::JsBuffer(buffer) => buffer.truncate(size + self.cursor),
}
self.cursor = std::cmp::min(self.cursor, self.len());
}
pub fn split_off(&mut self, at: usize) -> Self {
let at = at + self.cursor;
assert!(at <= self.len());
let other = match &mut self.inner {
BufMutViewInner::Bytes(bytes) => {
BufMutViewInner::Bytes(bytes.split_off(at))
}
BufMutViewInner::JsBuffer(buffer) => {
BufMutViewInner::JsBuffer(buffer.split_off(at))
}
};
Self {
inner: other,
cursor: 0,
}
}
pub fn split_to(&mut self, at: usize) -> Self {
assert!(at <= self.len());
let at = at + self.cursor;
let other = match &mut self.inner {
BufMutViewInner::Bytes(bytes) => {
BufMutViewInner::Bytes(bytes.split_to(at))
}
BufMutViewInner::JsBuffer(buffer) => {
BufMutViewInner::JsBuffer(buffer.split_to(at))
}
};
let cursor = std::mem::take(&mut self.cursor);
Self {
inner: other,
cursor,
}
}
}
impl Buf for BufMutView {
fn remaining(&self) -> usize {
self.len()
}
fn chunk(&self) -> &[u8] {
self.deref()
}
fn advance(&mut self, cnt: usize) {
self.advance_cursor(cnt)
}
}
impl Deref for BufMutView {
type Target = [u8];
fn deref(&self) -> &[u8] {
let buf = match &self.inner {
BufMutViewInner::JsBuffer(js_buf) => js_buf.deref(),
BufMutViewInner::Bytes(vec) => vec.deref(),
};
&buf[self.cursor..]
}
}
impl DerefMut for BufMutView {
fn deref_mut(&mut self) -> &mut [u8] {
let buf = match &mut self.inner {
BufMutViewInner::JsBuffer(js_buf) => js_buf.deref_mut(),
BufMutViewInner::Bytes(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<JsBuffer> for BufMutView {
fn from(buf: JsBuffer) -> Self {
Self::from_inner(BufMutViewInner::JsBuffer(buf.into_parts()))
}
}
impl From<BytesMut> for BufMutView {
fn from(buf: BytesMut) -> Self {
Self::from_inner(BufMutViewInner::Bytes(buf))
}
}
impl BufMutViewWhole {
fn from_inner(inner: BufMutViewInner) -> Self {
Self { inner, cursor: 0 }
}
pub fn new(len: usize) -> Self {
let bytes = BytesMut::zeroed(len);
Self::from_inner(BufMutViewInner::Bytes(bytes))
}
pub fn len(&self) -> usize {
match &self.inner {
BufMutViewInner::JsBuffer(js_buf) => js_buf.len() - self.cursor,
BufMutViewInner::Bytes(bytes) => bytes.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::JsBuffer(js_buf) => BufViewInner::JsBuffer(js_buf),
BufMutViewInner::Bytes(bytes) => BufViewInner::Bytes(bytes.into()),
};
BufView {
inner,
cursor: self.cursor,
}
}
pub fn maybe_unwrap_bytes(self) -> Result<BytesMut, Self> {
match self.inner {
BufMutViewInner::JsBuffer(_) => Err(self),
BufMutViewInner::Bytes(bytes) => Ok(bytes),
}
}
pub fn truncate(&mut self, size: usize) {
match &mut self.inner {
BufMutViewInner::Bytes(bytes) => bytes.truncate(size + self.cursor),
BufMutViewInner::JsBuffer(buffer) => buffer.truncate(size + self.cursor),
}
self.cursor = std::cmp::min(self.cursor, self.len());
}
}
impl Buf for BufMutViewWhole {
fn remaining(&self) -> usize {
self.len()
}
fn chunk(&self) -> &[u8] {
self.deref()
}
fn advance(&mut self, cnt: usize) {
self.advance_cursor(cnt)
}
}
impl Deref for BufMutViewWhole {
type Target = [u8];
fn deref(&self) -> &[u8] {
let buf = match &self.inner {
BufMutViewInner::JsBuffer(js_buf) => js_buf.deref(),
BufMutViewInner::Bytes(vec) => vec.deref(),
};
&buf[self.cursor..]
}
}
impl DerefMut for BufMutViewWhole {
fn deref_mut(&mut self) -> &mut [u8] {
let buf = match &mut self.inner {
BufMutViewInner::JsBuffer(js_buf) => js_buf.deref_mut(),
BufMutViewInner::Bytes(vec) => vec.deref_mut(),
};
&mut buf[self.cursor..]
}
}
impl From<JsBuffer> for BufMutViewWhole {
fn from(buf: JsBuffer) -> Self {
Self::from_inner(BufMutViewInner::JsBuffer(buf.into_parts()))
}
}
impl From<BytesMut> for BufMutViewWhole {
fn from(buf: BytesMut) -> Self {
Self::from_inner(BufMutViewInner::Bytes(buf))
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
pub fn bufview_read_and_truncate() {
let mut buf = BufView::from(vec![1, 2, 3, 4]);
assert_eq!(4, buf.len());
assert_eq!(0, buf.cursor);
assert_eq!(1, buf.get_u8());
assert_eq!(3, buf.len());
buf.truncate(2);
assert_eq!(2, buf.len());
assert_eq!(2, buf.get_u8());
assert_eq!(1, buf.len());
buf.reset_cursor();
assert_eq!(3, buf.len());
}
#[test]
pub fn bufview_split() {
let mut buf = BufView::from(Vec::from_iter(0..100));
assert_eq!(100, buf.len());
buf.advance_cursor(25);
assert_eq!(75, buf.len());
let mut other = buf.split_off(10);
assert_eq!(25, buf.cursor);
assert_eq!(10, buf.len());
assert_eq!(65, other.len());
let other2 = other.split_to(20);
assert_eq!(20, other2.len());
assert_eq!(45, other.len());
assert_eq!(100, buf.cursor + buf.len() + other.len() + other2.len());
buf.reset_cursor();
assert_eq!(100, buf.cursor + buf.len() + other.len() + other2.len());
}
#[test]
pub fn bufmutview_read_and_truncate() {
let mut buf = BufMutView::from(BytesMut::from([1, 2, 3, 4].as_slice()));
assert_eq!(4, buf.len());
assert_eq!(0, buf.cursor);
assert_eq!(1, buf.get_u8());
assert_eq!(3, buf.len());
buf.truncate(2);
assert_eq!(2, buf.len());
assert_eq!(2, buf.get_u8());
assert_eq!(1, buf.len());
buf.reset_cursor();
assert_eq!(3, buf.len());
}
#[test]
pub fn bufmutview_split() {
let mut buf =
BufMutView::from(BytesMut::from(Vec::from_iter(0..100).as_slice()));
assert_eq!(100, buf.len());
buf.advance_cursor(25);
assert_eq!(75, buf.len());
let mut other = buf.split_off(10);
assert_eq!(25, buf.cursor);
assert_eq!(10, buf.len());
assert_eq!(65, other.len());
let other2 = other.split_to(20);
assert_eq!(20, other2.len());
assert_eq!(45, other.len());
assert_eq!(100, buf.cursor + buf.len() + other.len() + other2.len());
buf.reset_cursor();
assert_eq!(100, buf.cursor + buf.len() + other.len() + other2.len());
}
#[test]
#[allow(deprecated)]
fn bufmutview_resize() {
let new =
|| BufMutView::from(BytesMut::from(Vec::from_iter(0..100).as_slice()));
let mut buf = new();
assert_eq!(100, buf.len());
buf.maybe_resize(200, 10).unwrap();
assert_eq!(110, buf.len());
let mut buf = new();
assert_eq!(100, buf.len());
buf.maybe_resize(200, 100).unwrap();
assert_eq!(200, buf.len());
let mut buf = new();
assert_eq!(100, buf.len());
buf.maybe_resize(200, 1000).unwrap();
assert_eq!(200, buf.len());
let mut buf = new();
buf.advance_cursor(50);
assert_eq!(50, buf.len());
buf.maybe_resize(100, 100).unwrap();
assert_eq!(100, buf.len());
buf.reset_cursor();
assert_eq!(150, buf.len());
}
#[test]
#[allow(deprecated)]
fn bufmutview_grow() {
let new =
|| BufMutView::from(BytesMut::from(Vec::from_iter(0..100).as_slice()));
let mut buf = new();
assert_eq!(100, buf.len());
buf.maybe_grow(200).unwrap();
assert_eq!(200, buf.len());
let mut buf = new();
buf.advance_cursor(50);
assert_eq!(50, buf.len());
buf.maybe_grow(100).unwrap();
assert_eq!(100, buf.len());
buf.reset_cursor();
assert_eq!(150, buf.len());
}
}