use std::borrow::Cow;
use std::cmp::min;
use std::mem::MaybeUninit;
use std::sync::Arc;
use std::{fmt, slice};
pub unsafe trait BufMut: 'static {
unsafe fn parts_mut(&mut self) -> (*mut u8, u32);
unsafe fn set_init(&mut self, n: usize);
fn spare_capacity(&self) -> u32;
fn has_spare_capacity(&self) -> bool {
self.spare_capacity() != 0
}
#[doc(hidden)]
#[allow(private_interfaces)]
fn parts(&mut self) -> BufMutParts {
let (ptr, len) = unsafe { self.parts_mut() };
BufMutParts::Buf { ptr, len }
}
#[doc(hidden)]
#[allow(private_interfaces)]
#[cfg(any(target_os = "android", target_os = "linux"))]
unsafe fn buffer_init(&mut self, id: BufId, n: u32) {
_ = id;
_ = n;
unreachable!()
}
fn extend_from_slice(&mut self, bytes: &[u8]) -> usize {
let (ptr, capacity) = unsafe { self.parts_mut() };
let written = unsafe { copy_bytes(ptr, capacity as usize, bytes) };
unsafe { self.set_init(written) };
written
}
#[doc(hidden)]
#[cfg(any(
target_os = "dragonfly",
target_os = "freebsd",
target_os = "ios",
target_os = "macos",
target_os = "netbsd",
target_os = "openbsd",
target_os = "tvos",
target_os = "visionos",
target_os = "watchos",
))]
fn release(&mut self) {
}
}
unsafe fn copy_bytes(dst: *mut u8, dst_len: usize, src: &[u8]) -> usize {
let len = min(src.len(), dst_len);
unsafe { dst.copy_from_nonoverlapping(src.as_ptr(), len) };
len
}
pub(crate) enum BufMutParts {
Buf { ptr: *mut u8, len: u32 },
Pool(crate::sys::io::PoolBufParts),
}
#[derive(Copy, Clone, Debug)]
#[cfg(any(target_os = "android", target_os = "linux"))]
pub struct BufId(pub(crate) u16);
unsafe impl BufMut for Vec<u8> {
unsafe fn parts_mut(&mut self) -> (*mut u8, u32) {
let slice = self.spare_capacity_mut();
(slice.as_mut_ptr().cast(), slice.len() as u32)
}
unsafe fn set_init(&mut self, n: usize) {
unsafe { self.set_len(self.len() + n) };
}
fn spare_capacity(&self) -> u32 {
(self.capacity() - self.len()) as u32
}
fn has_spare_capacity(&self) -> bool {
self.capacity() > self.len()
}
}
pub unsafe trait BufMutSlice<const N: usize>: 'static {
unsafe fn as_iovecs_mut(&mut self) -> [IoMutSlice; N];
unsafe fn set_init(&mut self, n: usize);
fn extend_from_slice(&mut self, bytes: &[u8]) -> usize {
let mut left = bytes;
for mut iovec in unsafe { self.as_iovecs_mut() } {
let (ptr, capacity) = unsafe { iovec.0.parts_mut() };
let n = unsafe { copy_bytes(ptr, capacity, left) };
left = &left[n..];
if left.is_empty() {
break;
}
}
let written = bytes.len() - left.len();
unsafe { self.set_init(written) };
written
}
}
pub struct IoMutSlice(crate::sys::io::IoMutSlice);
impl IoMutSlice {
pub(crate) unsafe fn new<B: BufMut>(buf: &mut B) -> IoMutSlice {
IoMutSlice(crate::sys::io::IoMutSlice::new(buf))
}
#[doc(hidden)] #[allow(clippy::len_without_is_empty)]
pub const fn len(&self) -> usize {
self.0.len()
}
#[doc(hidden)] pub unsafe fn set_len(&mut self, new_len: usize) {
self.0.set_len(new_len);
}
pub(crate) unsafe fn ptr(&self) -> *const u8 {
self.0.ptr()
}
}
impl fmt::Debug for IoMutSlice {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
self.0.fmt(f)
}
}
unsafe impl<B: BufMut, const N: usize> BufMutSlice<N> for [B; N] {
unsafe fn as_iovecs_mut(&mut self) -> [IoMutSlice; N] {
let mut iovecs = [const { MaybeUninit::uninit() }; N];
for (buf, iovec) in self.iter_mut().zip(iovecs.iter_mut()) {
iovec.write(unsafe { IoMutSlice::new(buf) });
}
unsafe { std::mem::transmute_copy(&std::mem::ManuallyDrop::new(iovecs)) }
}
unsafe fn set_init(&mut self, n: usize) {
let mut left = n;
for buf in self {
let (_, len) = unsafe { buf.parts_mut() };
let len = len as usize;
if len < left {
unsafe { buf.set_init(len) };
left -= len;
} else {
unsafe { buf.set_init(left) };
return;
}
}
unreachable!(
"called BufMutSlice::set_init({n}), with buffers totaling in {} in size",
n - left
);
}
}
pub unsafe trait Buf: 'static {
unsafe fn parts(&self) -> (*const u8, u32);
fn len(&self) -> usize {
unsafe { self.parts() }.1 as usize
}
fn is_empty(&self) -> bool {
self.len() == 0
}
fn as_slice(&self) -> &[u8] {
unsafe {
let (ptr, len) = self.parts();
slice::from_raw_parts(ptr, len as usize)
}
}
}
unsafe impl Buf for Vec<u8> {
unsafe fn parts(&self) -> (*const u8, u32) {
let slice = self.as_slice();
(slice.as_ptr().cast(), slice.len() as u32)
}
fn len(&self) -> usize {
Vec::len(self)
}
fn is_empty(&self) -> bool {
Vec::is_empty(self)
}
fn as_slice(&self) -> &[u8] {
self
}
}
unsafe impl Buf for Box<[u8]> {
unsafe fn parts(&self) -> (*const u8, u32) {
(self.as_ptr().cast(), self.len() as u32)
}
fn len(&self) -> usize {
<[u8]>::len(self)
}
fn is_empty(&self) -> bool {
<[u8]>::is_empty(self)
}
fn as_slice(&self) -> &[u8] {
self
}
}
unsafe impl Buf for String {
unsafe fn parts(&self) -> (*const u8, u32) {
let slice = self.as_bytes();
(slice.as_ptr().cast(), slice.len() as u32)
}
fn len(&self) -> usize {
String::len(self)
}
fn is_empty(&self) -> bool {
String::is_empty(self)
}
fn as_slice(&self) -> &[u8] {
self.as_bytes()
}
}
unsafe impl Buf for Box<str> {
unsafe fn parts(&self) -> (*const u8, u32) {
let bytes = self.as_bytes();
(bytes.as_ptr().cast(), bytes.len() as u32)
}
fn len(&self) -> usize {
str::len(self)
}
fn is_empty(&self) -> bool {
str::is_empty(self)
}
fn as_slice(&self) -> &[u8] {
self.as_bytes()
}
}
unsafe impl Buf for &'static [u8] {
unsafe fn parts(&self) -> (*const u8, u32) {
(self.as_ptr(), self.len() as u32)
}
fn len(&self) -> usize {
<[u8]>::len(self)
}
fn is_empty(&self) -> bool {
<[u8]>::is_empty(self)
}
fn as_slice(&self) -> &[u8] {
self
}
}
unsafe impl Buf for &'static str {
unsafe fn parts(&self) -> (*const u8, u32) {
(self.as_bytes().as_ptr(), self.len() as u32)
}
fn len(&self) -> usize {
str::len(self)
}
fn is_empty(&self) -> bool {
str::is_empty(self)
}
fn as_slice(&self) -> &[u8] {
self.as_bytes()
}
}
unsafe impl Buf for Cow<'static, [u8]> {
unsafe fn parts(&self) -> (*const u8, u32) {
(self.as_ptr(), self.len() as u32)
}
fn len(&self) -> usize {
<[u8]>::len(self)
}
fn is_empty(&self) -> bool {
<[u8]>::is_empty(self)
}
fn as_slice(&self) -> &[u8] {
self
}
}
unsafe impl Buf for Cow<'static, str> {
unsafe fn parts(&self) -> (*const u8, u32) {
(self.as_bytes().as_ptr(), self.len() as u32)
}
fn len(&self) -> usize {
str::len(self)
}
fn is_empty(&self) -> bool {
str::is_empty(self)
}
fn as_slice(&self) -> &[u8] {
self.as_bytes()
}
}
unsafe impl Buf for Arc<[u8]> {
unsafe fn parts(&self) -> (*const u8, u32) {
(self.as_ptr().cast(), self.len() as u32)
}
fn len(&self) -> usize {
<[u8]>::len(self)
}
fn is_empty(&self) -> bool {
<[u8]>::is_empty(self)
}
fn as_slice(&self) -> &[u8] {
self
}
}
unsafe impl Buf for Arc<str> {
unsafe fn parts(&self) -> (*const u8, u32) {
let bytes = self.as_bytes();
(bytes.as_ptr().cast(), bytes.len() as u32)
}
fn len(&self) -> usize {
str::len(self)
}
fn is_empty(&self) -> bool {
str::is_empty(self)
}
fn as_slice(&self) -> &[u8] {
self.as_bytes()
}
}
pub unsafe trait BufSlice<const N: usize>: 'static {
unsafe fn as_iovecs(&self) -> [IoSlice; N];
fn total_len(&self) -> usize {
unsafe { self.as_iovecs().iter().map(IoSlice::len).sum() }
}
}
pub struct IoSlice(crate::sys::io::IoSlice);
impl IoSlice {
#[doc(hidden)] pub unsafe fn new<B: Buf>(buf: &B) -> IoSlice {
IoSlice(crate::sys::io::IoSlice::new(buf))
}
pub(crate) const fn len(&self) -> usize {
self.0.len()
}
pub(crate) unsafe fn set_len(&mut self, new_len: usize) {
self.0.set_len(new_len);
}
pub(crate) unsafe fn skip(&mut self, n: usize) {
self.0.skip(n);
}
pub(crate) unsafe fn ptr(&self) -> *const u8 {
self.0.ptr()
}
}
impl fmt::Debug for IoSlice {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
self.0.fmt(f)
}
}
unsafe impl<B: Buf, const N: usize> BufSlice<N> for [B; N] {
unsafe fn as_iovecs(&self) -> [IoSlice; N] {
let mut iovecs = [const { MaybeUninit::uninit() }; N];
for (buf, iovec) in self.iter().zip(iovecs.iter_mut()) {
iovec.write(unsafe { IoSlice::new(buf) });
}
unsafe { std::mem::transmute_copy(&std::mem::ManuallyDrop::new(iovecs)) }
}
fn total_len(&self) -> usize {
self.iter().map(Buf::len).sum()
}
}
macro_rules! buf_slice_for_tuple {
(
// Number of values.
$N: expr,
// Generic parameter name and tuple index.
$( $generic: ident . $index: tt ),+
) => {
unsafe impl<$( $generic: BufMut ),+> BufMutSlice<$N> for ($( $generic ),+) {
unsafe fn as_iovecs_mut(&mut self) -> [IoMutSlice; $N] {
[
$({ unsafe { IoMutSlice::new(&mut self.$index) } }),+
]
}
unsafe fn set_init(&mut self, n: usize) {
let mut left = n;
$({
let (_, len) = unsafe { self.$index.parts_mut() };
let len = len as usize;
if len < left {
unsafe { self.$index.set_init(len) };
left -= len;
} else {
unsafe { self.$index.set_init(left) };
return;
}
})+
unreachable!(
"called BufMutSlice::set_init({n}), with buffers totaling in {} in size",
n - left
);
}
}
unsafe impl<$( $generic: Buf ),+> BufSlice<$N> for ($( $generic ),+) {
unsafe fn as_iovecs(&self) -> [IoSlice; $N] {
[
$({
unsafe { IoSlice::new(&self.$index) }
}),+
]
}
fn total_len(&self) -> usize {
0
$( + self.$index.len() )+
}
}
};
}
buf_slice_for_tuple!(2, A.0, B.1);
buf_slice_for_tuple!(3, A.0, B.1, C.2);
buf_slice_for_tuple!(4, A.0, B.1, C.2, D.3);
buf_slice_for_tuple!(5, A.0, B.1, C.2, D.3, E.4);
buf_slice_for_tuple!(6, A.0, B.1, C.2, D.3, E.4, F.5);
buf_slice_for_tuple!(7, A.0, B.1, C.2, D.3, E.4, F.5, G.6);
buf_slice_for_tuple!(8, A.0, B.1, C.2, D.3, E.4, F.5, G.6, I.7);
#[derive(Copy, Clone, Debug)]
pub struct StaticBuf(&'static [u8]);
impl From<&'static [u8]> for StaticBuf {
fn from(buf: &'static [u8]) -> StaticBuf {
StaticBuf(buf)
}
}
impl From<&'static str> for StaticBuf {
fn from(buf: &'static str) -> StaticBuf {
StaticBuf(buf.as_bytes())
}
}
unsafe impl Buf for StaticBuf {
unsafe fn parts(&self) -> (*const u8, u32) {
unsafe { self.0.parts() }
}
fn len(&self) -> usize {
self.0.len()
}
fn is_empty(&self) -> bool {
self.0.is_empty()
}
fn as_slice(&self) -> &[u8] {
Buf::as_slice(&self.0)
}
}