use bytes::{Bytes, BytesMut};
pub unsafe trait IoBuf {
fn stable_ptr(&self) -> *const u8;
fn bytes_init(&self) -> usize;
fn bytes_total(&self) -> usize;
fn slice(self, range: impl std::ops::RangeBounds<usize>) -> Slice<Self>
where
Self: Sized,
{
let begin = match range.start_bound() {
std::ops::Bound::Included(&n) => n,
std::ops::Bound::Unbounded => 0,
_ => unreachable!(),
};
let end = match range.end_bound() {
std::ops::Bound::Excluded(&n) => n,
std::ops::Bound::Included(&n) => n + 1,
std::ops::Bound::Unbounded => self.bytes_total(),
};
assert!(begin <= end && end <= self.bytes_total());
Slice::new(self, begin, end)
}
}
pub unsafe trait IoBufMut: IoBuf {
fn stable_mut_ptr(&mut self) -> *mut u8;
unsafe fn set_init(&mut self, pos: usize);
fn clear(&mut self) {
unsafe { self.set_init(0) };
}
}
#[derive(Debug)]
pub struct Slice<B> {
buf: B,
begin: usize,
end: usize,
}
impl<B: IoBuf> Slice<B> {
pub fn new(buf: B, begin: usize, end: usize) -> Self {
assert!(begin <= end && end <= buf.bytes_total());
Self { buf, begin, end }
}
pub fn into_inner(self) -> B {
self.buf
}
pub fn len(&self) -> usize {
self.bytes_init()
}
pub fn is_empty(&self) -> bool {
self.bytes_init() == 0
}
}
unsafe impl<B: IoBuf> IoBuf for Slice<B> {
fn stable_ptr(&self) -> *const u8 {
unsafe { self.buf.stable_ptr().add(self.begin) }
}
fn bytes_init(&self) -> usize {
self.buf
.bytes_init()
.saturating_sub(self.begin)
.min(self.end - self.begin)
}
fn bytes_total(&self) -> usize {
self.end - self.begin
}
}
unsafe impl<B: IoBufMut> IoBufMut for Slice<B> {
fn stable_mut_ptr(&mut self) -> *mut u8 {
unsafe { self.buf.stable_mut_ptr().add(self.begin) }
}
unsafe fn set_init(&mut self, pos: usize) {
unsafe { self.buf.set_init(self.begin + pos) };
}
}
impl<B: IoBuf> AsRef<[u8]> for Slice<B> {
fn as_ref(&self) -> &[u8] {
let ptr = self.stable_ptr();
let len = self.bytes_init();
unsafe { std::slice::from_raw_parts(ptr, len) }
}
}
pub enum MaybeRegistered<R, F> {
Registered(R),
Fallback(F),
}
unsafe impl<R: IoBuf, F: IoBuf> IoBuf for MaybeRegistered<R, F> {
fn stable_ptr(&self) -> *const u8 {
match self {
Self::Registered(r) => r.stable_ptr(),
Self::Fallback(f) => f.stable_ptr(),
}
}
fn bytes_init(&self) -> usize {
match self {
Self::Registered(r) => r.bytes_init(),
Self::Fallback(f) => f.bytes_init(),
}
}
fn bytes_total(&self) -> usize {
match self {
Self::Registered(r) => r.bytes_total(),
Self::Fallback(f) => f.bytes_total(),
}
}
}
unsafe impl<R: IoBufMut, F: IoBufMut> IoBufMut for MaybeRegistered<R, F> {
fn stable_mut_ptr(&mut self) -> *mut u8 {
match self {
Self::Registered(r) => r.stable_mut_ptr(),
Self::Fallback(f) => f.stable_mut_ptr(),
}
}
unsafe fn set_init(&mut self, pos: usize) {
unsafe {
match self {
Self::Registered(r) => r.set_init(pos),
Self::Fallback(f) => f.set_init(pos),
}
}
}
}
unsafe impl<const N: usize> IoBuf for [u8; N] {
fn stable_ptr(&self) -> *const u8 {
self.as_ptr()
}
fn bytes_init(&self) -> usize {
N
}
fn bytes_total(&self) -> usize {
N
}
}
unsafe impl<const N: usize> IoBufMut for [u8; N] {
fn stable_mut_ptr(&mut self) -> *mut u8 {
self.as_mut_ptr()
}
unsafe fn set_init(&mut self, _pos: usize) {} }
unsafe impl IoBuf for &'static [u8] {
fn stable_ptr(&self) -> *const u8 {
self.as_ptr()
}
fn bytes_init(&self) -> usize {
self.len()
}
fn bytes_total(&self) -> usize {
self.len()
}
}
unsafe impl IoBuf for Bytes {
fn stable_ptr(&self) -> *const u8 {
self.as_ptr()
}
fn bytes_init(&self) -> usize {
self.len()
}
fn bytes_total(&self) -> usize {
self.len()
}
}
unsafe impl IoBuf for BytesMut {
fn stable_ptr(&self) -> *const u8 {
self.as_ptr()
}
fn bytes_init(&self) -> usize {
self.len()
}
fn bytes_total(&self) -> usize {
self.capacity()
}
}
unsafe impl IoBufMut for BytesMut {
fn stable_mut_ptr(&mut self) -> *mut u8 {
self.as_mut_ptr()
}
unsafe fn set_init(&mut self, pos: usize) {
unsafe { self.set_len(pos) };
}
}
unsafe impl IoBuf for Vec<u8> {
fn stable_ptr(&self) -> *const u8 {
self.as_ptr()
}
fn bytes_init(&self) -> usize {
self.len()
}
fn bytes_total(&self) -> usize {
self.capacity()
}
}
unsafe impl IoBufMut for Vec<u8> {
fn stable_mut_ptr(&mut self) -> *mut u8 {
self.as_mut_ptr()
}
unsafe fn set_init(&mut self, pos: usize) {
unsafe { self.set_len(pos) };
}
}