use std::{
fmt,
io::IoSlice,
mem,
ops::{Bound, Deref, DerefMut, RangeBounds},
};
mod array;
mod vec;
pub use array::WriteVectoredArrayBuffer;
pub use vec::WriteVectoredVecBuffer;
pub(crate) static EMPTY_SLICE: &[u8] = &[];
pub struct VectoredSlice<'a> {
slices: &'a mut [IoSlice<'static>],
total_size: usize,
}
impl<'a> fmt::Debug for VectoredSlice<'a> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("VectoredSlice")
.field("slices", &self.deref())
.field("total_size", &self.total_size)
.finish()
}
}
impl<'a> Deref for VectoredSlice<'a> {
type Target = [IoSlice<'a>];
fn deref(&self) -> &Self::Target {
&self.slices[1..self.slices.len() - 1]
}
}
impl<'a> DerefMut for VectoredSlice<'a> {
fn deref_mut(&mut self) -> &mut Self::Target {
let slices_len = self.slices.len();
unsafe { mem::transmute(&mut self.slices[1..slices_len - 1]) }
}
}
impl<'a> VectoredSlice<'a> {
pub(crate) unsafe fn new(slices: &'a mut [IoSlice<'static>], total_size: usize) -> Self {
Self { slices, total_size }
}
pub fn total_size(&self) -> usize {
self.total_size
}
pub fn frame(
&mut self,
range: impl RangeBounds<usize>,
header: Option<&'a [u8]>,
trailer: Option<&'a [u8]>,
) -> VectoredFrame<'a> {
let mut start = match range.start_bound() {
Bound::Included(&n) => n,
Bound::Excluded(&n) => n + 1,
Bound::Unbounded => 0,
};
let mut end = match range.end_bound() {
Bound::Included(&n) => n + 2,
Bound::Excluded(&n) => n + 1,
Bound::Unbounded => self.slices.len(),
};
let header = if let Some(header) = header {
Some(mem::replace(&mut self.slices[start], unsafe {
mem::transmute::<IoSlice, IoSlice>(IoSlice::new(header))
}))
} else {
start += 1;
None
};
let trailer = if let Some(trailer) = trailer {
Some(mem::replace(&mut self.slices[end - 1], unsafe {
mem::transmute::<IoSlice, IoSlice>(IoSlice::new(trailer))
}))
} else {
end -= 1;
None
};
VectoredFrame {
slices: unsafe {
mem::transmute::<&mut [IoSlice], &mut [IoSlice]>(&mut self.slices[start..end])
},
header,
trailer,
}
}
}
pub struct VectoredFrame<'a> {
slices: &'a mut [IoSlice<'a>],
header: Option<IoSlice<'static>>,
trailer: Option<IoSlice<'static>>,
}
impl fmt::Debug for VectoredFrame<'_> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_tuple("VectoredFrame").field(&self.slices).finish()
}
}
impl<'a> Deref for VectoredFrame<'a> {
type Target = [IoSlice<'a>];
fn deref(&self) -> &Self::Target {
self.slices
}
}
impl<'a> DerefMut for VectoredFrame<'a> {
fn deref_mut(&mut self) -> &mut Self::Target {
self.slices
}
}
impl<'a> Drop for VectoredFrame<'a> {
fn drop(&mut self) {
if let Some(header) = self.header {
self.slices[0] = header;
}
if let Some(trailer) = self.trailer {
self.slices[self.slices.len() - 1] = trailer;
}
}
}