use std::ops::{Deref, DerefMut};
pub type BufResult<T, B> = (std::io::Result<T>, B);
pub unsafe trait IoBufMut: Unpin + 'static {
fn stable_ptr_mut(&mut self) -> *mut u8;
fn bytes_total(&self) -> usize;
unsafe fn set_init(&mut self, n: usize);
}
pub unsafe trait IoBuf: Unpin + 'static {
fn stable_ptr(&self) -> *const u8;
fn bytes_init(&self) -> usize;
}
unsafe impl IoBufMut for Vec<u8> {
fn stable_ptr_mut(&mut self) -> *mut u8 {
self.as_mut_ptr()
}
fn bytes_total(&self) -> usize {
self.capacity()
}
unsafe fn set_init(&mut self, n: usize) {
unsafe { self.set_len(n) }
}
}
unsafe impl IoBuf for Vec<u8> {
fn stable_ptr(&self) -> *const u8 {
self.as_ptr()
}
fn bytes_init(&self) -> usize {
self.len()
}
}
pub struct Slice<B> {
buf: B,
begin: usize,
end: usize,
}
impl<B: IoBufMut> Slice<B> {
pub fn new(buf: B, begin: usize, end: usize) -> Self {
assert!(begin <= end);
Self { buf, begin, end }
}
pub fn into_inner(self) -> B {
self.buf
}
pub fn begin(&self) -> usize {
self.begin
}
pub fn end(&self) -> usize {
self.end
}
}
impl<B: IoBuf + IoBufMut> Deref for Slice<B> {
type Target = [u8];
fn deref(&self) -> &[u8] {
unsafe {
std::slice::from_raw_parts(self.buf.stable_ptr().add(self.begin), self.end - self.begin)
}
}
}
impl<B: IoBuf + IoBufMut> DerefMut for Slice<B> {
fn deref_mut(&mut self) -> &mut [u8] {
unsafe {
std::slice::from_raw_parts_mut(
self.buf.stable_ptr_mut().add(self.begin),
self.end - self.begin,
)
}
}
}
unsafe impl<B: IoBufMut> IoBufMut for Slice<B> {
fn stable_ptr_mut(&mut self) -> *mut u8 {
unsafe { self.buf.stable_ptr_mut().add(self.begin) }
}
fn bytes_total(&self) -> usize {
self.end - self.begin
}
unsafe fn set_init(&mut self, n: usize) {
unsafe { self.buf.set_init(self.begin + n) }
}
}
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.end - self.begin
}
}
pub trait IoBufMutExt: IoBufMut + Sized {
fn slice(self, range: impl std::ops::RangeBounds<usize>) -> Slice<Self> {
use std::ops::Bound::*;
let begin = match range.start_bound() {
Included(&n) => n,
Excluded(&n) => n + 1,
Unbounded => 0,
};
let end = match range.end_bound() {
Included(&n) => n + 1,
Excluded(&n) => n,
Unbounded => self.bytes_total(),
};
Slice::new(self, begin, end)
}
}
impl<B: IoBufMut> IoBufMutExt for B {}