use core::slice;
use std::ptr::NonNull;
use std::{fmt::Debug, fmt::Formatter};
use crate::alloc;
use crate::alloc::Deallocation;
pub struct Bytes {
ptr: NonNull<u8>,
len: usize,
deallocation: Deallocation,
}
impl Bytes {
#[inline]
pub(crate) unsafe fn new(
ptr: std::ptr::NonNull<u8>,
len: usize,
deallocation: Deallocation,
) -> Bytes {
Bytes {
ptr,
len,
deallocation,
}
}
fn as_slice(&self) -> &[u8] {
self
}
#[inline]
pub fn len(&self) -> usize {
self.len
}
#[inline]
pub fn is_empty(&self) -> bool {
self.len == 0
}
#[inline]
pub fn ptr(&self) -> NonNull<u8> {
self.ptr
}
pub fn capacity(&self) -> usize {
match self.deallocation {
Deallocation::Arrow(capacity) => capacity,
Deallocation::Custom(_) => 0,
}
}
}
impl Drop for Bytes {
#[inline]
fn drop(&mut self) {
match &self.deallocation {
Deallocation::Arrow(capacity) => {
unsafe { alloc::free_aligned::<u8>(self.ptr, *capacity) };
}
Deallocation::Custom(_allocation) => (),
}
}
}
impl std::ops::Deref for Bytes {
type Target = [u8];
fn deref(&self) -> &[u8] {
unsafe { slice::from_raw_parts(self.ptr.as_ptr(), self.len) }
}
}
impl PartialEq for Bytes {
fn eq(&self, other: &Bytes) -> bool {
self.as_slice() == other.as_slice()
}
}
impl Debug for Bytes {
fn fmt(&self, f: &mut Formatter) -> std::fmt::Result {
write!(f, "Bytes {{ ptr: {:?}, len: {}, data: ", self.ptr, self.len,)?;
f.debug_list().entries(self.iter()).finish()?;
write!(f, " }}")
}
}