pub trait RevWriter {
type RawBuf;
type TightBuf;
type Mark: Copy;
fn with_capacity(cap: usize) -> Self;
fn empty() -> Self;
fn mark(&self) -> Self::Mark;
fn written_since(&self, mark: Self::Mark) -> usize;
fn as_written_slice(&self) -> &[u8];
fn len(&self) -> usize;
fn is_empty(&self) -> bool;
fn put_u8(&mut self, b: u8);
fn put_slice(&mut self, s: &[u8]);
fn put_varint(&mut self, v: u64);
#[inline]
fn put_fixed32(&mut self, v: u32) {
self.put_slice(&v.to_le_bytes());
}
#[inline]
fn put_fixed64(&mut self, v: u64) {
self.put_slice(&v.to_le_bytes());
}
fn finish_raw(self) -> Self::RawBuf;
fn finish_tight(self) -> Self::TightBuf;
}
pub struct RevVec {
buf: Vec<u8>,
pos: usize, }
impl RevVec {
const MIN_GROW: usize = 64;
#[inline]
const fn cap(&self) -> usize {
self.buf.capacity()
}
#[inline]
fn ensure_space(&mut self, need: usize) {
if self.pos >= need {
return;
}
let old_cap = self.cap();
let used = old_cap - self.pos;
let mut new_cap = (old_cap * 2).next_power_of_two().max(Self::MIN_GROW);
while new_cap < used + need {
new_cap *= 2;
}
let mut new_buf: Vec<u8> = Vec::with_capacity(new_cap);
let new_cap = new_buf.capacity();
unsafe { new_buf.set_len(new_cap) };
unsafe {
core::ptr::copy_nonoverlapping(self.buf.as_ptr().add(self.pos), new_buf.as_mut_ptr().add(new_cap - used), used);
}
self.buf = new_buf;
self.pos = new_cap - used;
}
}
impl RevWriter for RevVec {
type TightBuf = Vec<u8>;
type RawBuf = Vec<u8>;
type Mark = usize;
#[inline]
fn with_capacity(cap: usize) -> Self {
let mut buf = Vec::with_capacity(cap);
let cap = buf.capacity();
unsafe { buf.set_len(cap) }; Self { buf, pos: cap }
}
#[inline]
fn empty() -> Self {
Self { buf: Vec::new(), pos: 0 }
}
#[inline]
fn mark(&self) -> Self::Mark {
self.cap() - self.pos
}
#[inline]
fn len(&self) -> usize {
self.cap() - self.pos
}
#[inline]
fn is_empty(&self) -> bool {
self.len() == 0
}
#[inline]
fn written_since(&self, mark: Self::Mark) -> usize {
(self.cap() - self.pos) - mark
}
#[inline]
fn put_u8(&mut self, b: u8) {
self.ensure_space(1);
self.pos -= 1;
unsafe {
*self.buf.as_mut_ptr().add(self.pos) = b;
}
}
#[inline]
fn put_slice(&mut self, s: &[u8]) {
let n = s.len();
if n == 0 {
return;
}
self.ensure_space(n);
self.pos -= n;
unsafe {
core::ptr::copy_nonoverlapping(s.as_ptr(), self.buf.as_mut_ptr().add(self.pos), n);
}
}
#[inline]
fn put_varint(&mut self, mut v: u64) {
let mut tmp = [0u8; 10];
let mut i = 0usize;
loop {
let byte = (v as u8) & 0x7f;
v >>= 7;
if v == 0 {
tmp[i] = byte;
i += 1;
break;
}
tmp[i] = byte | 0x80;
i += 1;
}
self.put_slice(&tmp[..i]);
}
#[inline]
fn finish_raw(self) -> Self::RawBuf {
self.buf
}
#[inline]
fn as_written_slice(&self) -> &[u8] {
let cap = self.cap();
unsafe { core::slice::from_raw_parts(self.buf.as_ptr().add(self.pos), cap - self.pos) }
}
#[inline]
fn finish_tight(mut self) -> Self::TightBuf {
let cap = self.cap();
let pos = self.pos;
let len = cap - pos;
if len == 0 {
unsafe { self.buf.set_len(0) };
return self.buf;
}
if pos != 0 {
unsafe {
core::ptr::copy(self.buf.as_ptr().add(pos), self.buf.as_mut_ptr(), len);
}
}
unsafe { self.buf.set_len(len) };
self.buf
}
}