use std::cmp::min;
use std::io::IoSliceMut;
use std::mem::MaybeUninit;
use std::ops::{Deref, DerefMut};
use std::{fmt, slice};
pub trait Bytes {
fn as_bytes(&mut self) -> &mut [MaybeUninit<u8>];
fn spare_capacity(&self) -> usize;
fn has_spare_capacity(&self) -> bool {
self.spare_capacity() == 0
}
unsafe fn update_length(&mut self, n: usize);
fn limit(self, limit: usize) -> LimitedBytes<Self>
where
Self: Sized,
{
LimitedBytes { buf: self, limit }
}
}
impl<B> Bytes for &mut B
where
B: Bytes + ?Sized,
{
fn as_bytes(&mut self) -> &mut [MaybeUninit<u8>] {
(&mut **self).as_bytes()
}
fn spare_capacity(&self) -> usize {
(&**self).spare_capacity()
}
fn has_spare_capacity(&self) -> bool {
(&**self).has_spare_capacity()
}
unsafe fn update_length(&mut self, n: usize) {
(&mut **self).update_length(n)
}
}
impl Bytes for Vec<u8> {
fn as_bytes(&mut self) -> &mut [MaybeUninit<u8>] {
self.spare_capacity_mut()
}
fn spare_capacity(&self) -> usize {
self.capacity() - self.len()
}
fn has_spare_capacity(&self) -> bool {
self.capacity() != self.len()
}
unsafe fn update_length(&mut self, n: usize) {
let new = self.len() + n;
debug_assert!(self.capacity() >= new);
self.set_len(new);
}
}
#[repr(transparent)]
pub struct MaybeUninitSlice<'a>(socket2::MaybeUninitSlice<'a>);
impl<'a> fmt::Debug for MaybeUninitSlice<'a> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
self.0.fmt(f)
}
}
impl<'a> MaybeUninitSlice<'a> {
pub fn new(buf: &'a mut [MaybeUninit<u8>]) -> MaybeUninitSlice<'a> {
MaybeUninitSlice(socket2::MaybeUninitSlice::new(buf))
}
pub fn from_vec(buf: &'a mut Vec<u8>) -> MaybeUninitSlice<'a> {
MaybeUninitSlice(socket2::MaybeUninitSlice::new(buf.as_bytes()))
}
fn limit(&mut self, limit: usize) {
let len = self.len();
assert!(len >= limit);
self.0 = unsafe {
socket2::MaybeUninitSlice::new(slice::from_raw_parts_mut(self.0.as_mut_ptr(), limit))
};
}
#[allow(clippy::wrong_self_convention)]
pub(crate) fn as_socket2<'b>(
bufs: &'b mut [MaybeUninitSlice<'a>],
) -> &'b mut [socket2::MaybeUninitSlice<'a>] {
unsafe { &mut *(bufs as *mut _ as *mut _) }
}
#[allow(clippy::wrong_self_convention)]
pub(crate) unsafe fn as_io<'b>(
bufs: &'b mut [MaybeUninitSlice<'a>],
) -> &'b mut [IoSliceMut<'a>] {
&mut *(bufs as *mut _ as *mut _)
}
}
impl<'a> Deref for MaybeUninitSlice<'a> {
type Target = [MaybeUninit<u8>];
fn deref(&self) -> &[MaybeUninit<u8>] {
&*self.0
}
}
impl<'a> DerefMut for MaybeUninitSlice<'a> {
fn deref_mut(&mut self) -> &mut [MaybeUninit<u8>] {
&mut *self.0
}
}
pub trait BytesVectored {
type Bufs<'b>: AsMut<[MaybeUninitSlice<'b>]>
where
Self: 'b;
fn as_bufs<'b>(&'b mut self) -> Self::Bufs<'b>;
fn spare_capacity(&self) -> usize;
fn has_spare_capacity(&self) -> bool {
self.spare_capacity() == 0
}
unsafe fn update_lengths(&mut self, n: usize);
fn limit(self, limit: usize) -> LimitedBytes<Self>
where
Self: Sized,
{
LimitedBytes { buf: self, limit }
}
}
impl<B> BytesVectored for &mut B
where
B: BytesVectored + ?Sized,
{
type Bufs<'b> = B::Bufs<'b> where Self: 'b;
fn as_bufs<'b>(&'b mut self) -> Self::Bufs<'b> {
(&mut **self).as_bufs()
}
fn spare_capacity(&self) -> usize {
(&**self).spare_capacity()
}
fn has_spare_capacity(&self) -> bool {
(&**self).has_spare_capacity()
}
unsafe fn update_lengths(&mut self, n: usize) {
(&mut **self).update_lengths(n)
}
}
impl<B, const N: usize> BytesVectored for [B; N]
where
B: Bytes,
{
type Bufs<'b> = [MaybeUninitSlice<'b>; N] where Self: 'b;
fn as_bufs<'b>(&'b mut self) -> Self::Bufs<'b> {
let mut bufs = MaybeUninit::uninit_array::<N>();
for (i, buf) in self.iter_mut().enumerate() {
let _ = bufs[i].write(MaybeUninitSlice::new(buf.as_bytes()));
}
unsafe { MaybeUninit::array_assume_init(bufs) }
}
fn spare_capacity(&self) -> usize {
self.iter().map(Bytes::spare_capacity).sum()
}
fn has_spare_capacity(&self) -> bool {
self.iter().any(Bytes::has_spare_capacity)
}
unsafe fn update_lengths(&mut self, n: usize) {
let mut left = n;
for buf in self.iter_mut() {
let n = min(left, buf.spare_capacity());
buf.update_length(n);
left -= n;
if left == 0 {
return;
}
}
}
}
macro_rules! impl_vectored_bytes_tuple {
( $N: tt : $( $t: ident $idx: tt ),+ ) => {
impl<$( $t ),+> BytesVectored for ( $( $t ),+ )
where $( $t: Bytes ),+
{
type Bufs<'b> = [MaybeUninitSlice<'b>; $N] where Self: 'b;
fn as_bufs<'b>(&'b mut self) -> Self::Bufs<'b> {
let mut bufs = MaybeUninit::uninit_array::<$N>();
$(
let _ = bufs[$idx].write(MaybeUninitSlice::new(self.$idx.as_bytes()));
)+
unsafe { MaybeUninit::array_assume_init(bufs) }
}
fn spare_capacity(&self) -> usize {
$( self.$idx.spare_capacity() + )+ 0
}
fn has_spare_capacity(&self) -> bool {
$( self.$idx.has_spare_capacity() || )+ false
}
unsafe fn update_lengths(&mut self, n: usize) {
let mut left = n;
$(
let n = min(left, self.$idx.spare_capacity());
self.$idx.update_length(n);
left -= n;
if left == 0 {
return;
}
)+
}
}
};
}
impl_vectored_bytes_tuple! { 12: B0 0, B1 1, B2 2, B3 3, B4 4, B5 5, B6 6, B7 7, B8 8, B9 9, B10 10, B11 11 }
impl_vectored_bytes_tuple! { 11: B0 0, B1 1, B2 2, B3 3, B4 4, B5 5, B6 6, B7 7, B8 8, B9 9, B10 10 }
impl_vectored_bytes_tuple! { 10: B0 0, B1 1, B2 2, B3 3, B4 4, B5 5, B6 6, B7 7, B8 8, B9 9 }
impl_vectored_bytes_tuple! { 9: B0 0, B1 1, B2 2, B3 3, B4 4, B5 5, B6 6, B7 7, B8 8 }
impl_vectored_bytes_tuple! { 8: B0 0, B1 1, B2 2, B3 3, B4 4, B5 5, B6 6, B7 7 }
impl_vectored_bytes_tuple! { 7: B0 0, B1 1, B2 2, B3 3, B4 4, B5 5, B6 6 }
impl_vectored_bytes_tuple! { 6: B0 0, B1 1, B2 2, B3 3, B4 4, B5 5 }
impl_vectored_bytes_tuple! { 5: B0 0, B1 1, B2 2, B3 3, B4 4 }
impl_vectored_bytes_tuple! { 4: B0 0, B1 1, B2 2, B3 3 }
impl_vectored_bytes_tuple! { 3: B0 0, B1 1, B2 2 }
impl_vectored_bytes_tuple! { 2: B0 0, B1 1 }
#[derive(Debug)]
pub struct LimitedBytes<B> {
buf: B,
limit: usize,
}
impl<B> LimitedBytes<B> {
pub fn into_inner(self) -> B {
self.buf
}
}
impl<B> Bytes for LimitedBytes<B>
where
B: Bytes,
{
fn as_bytes(&mut self) -> &mut [MaybeUninit<u8>] {
let bytes = self.buf.as_bytes();
if bytes.len() > self.limit {
&mut bytes[..self.limit]
} else {
bytes
}
}
fn spare_capacity(&self) -> usize {
min(self.buf.spare_capacity(), self.limit)
}
fn has_spare_capacity(&self) -> bool {
self.spare_capacity() > 0
}
unsafe fn update_length(&mut self, n: usize) {
self.buf.update_length(n);
self.limit -= n;
}
}
impl<B> BytesVectored for LimitedBytes<B>
where
B: BytesVectored,
{
type Bufs<'b> = B::Bufs<'b> where Self: 'b;
fn as_bufs<'b>(&'b mut self) -> Self::Bufs<'b> {
let mut bufs = self.buf.as_bufs();
let mut left = self.limit;
let mut iter = bufs.as_mut().iter_mut();
while let Some(buf) = iter.next() {
let len = buf.len();
if left > len {
left -= len;
} else {
buf.limit(left);
for buf in iter {
*buf = MaybeUninitSlice::new(&mut []);
}
break;
}
}
bufs
}
fn spare_capacity(&self) -> usize {
if self.limit == 0 {
0
} else {
min(self.buf.spare_capacity(), self.limit)
}
}
fn has_spare_capacity(&self) -> bool {
self.limit != 0 && self.buf.has_spare_capacity()
}
unsafe fn update_lengths(&mut self, n: usize) {
self.buf.update_lengths(n);
self.limit -= n;
}
}