use core::{
hash::{Hash, Hasher},
marker::PhantomData,
ops::RangeBounds,
};
use bytes::{Buf, Bytes};
use std::{borrow::Cow, boxed::Box, string::String, sync::Arc, vec::Vec};
use crate::{
BytesMut, OutOfBounds, RangeOutOfBounds,
buffer::{Buffer, INLINE_CAP},
};
use super::strategy::ImmutableStorage;
mod cmp;
mod fmt;
mod from;
mod iter;
mod ops;
#[cfg(feature = "arbitrary")]
mod arbitrary;
#[cfg(feature = "borsh")]
mod borsh;
#[cfg(feature = "quickcheck")]
mod quickcheck;
#[cfg(feature = "serde")]
mod serde;
#[repr(transparent)]
pub struct RawBytes<S> {
pub(crate) repr: Repr,
_strategy: PhantomData<S>,
}
impl<S> Clone for RawBytes<S> {
#[cfg_attr(not(coverage), inline(always))]
fn clone(&self) -> Self {
match &self.repr {
Repr::Inline(_) => unsafe { core::ptr::read(self as *const RawBytes<S>) },
Repr::Heap(bytes) => Self {
repr: Repr::Heap(bytes.clone()),
_strategy: PhantomData,
},
}
}
}
impl<S> RawBytes<S> {
#[inline]
pub const fn new() -> Self {
Self::inline(Buffer::new())
}
#[inline]
pub const fn new_inline(bytes: &[u8]) -> Self {
let blen = bytes.len();
assert!(blen <= INLINE_CAP);
Self::inline(unsafe { Buffer::copy_from_slice(bytes) })
}
#[inline]
pub const fn from_static(bytes: &'static [u8]) -> Self {
if bytes.len() <= INLINE_CAP {
return Self::new_inline(bytes);
}
Self::heap(Bytes::from_static(bytes))
}
#[cfg_attr(not(coverage), inline(always))]
pub const fn is_inline(&self) -> bool {
matches!(self.repr, Repr::Inline(..))
}
#[cfg_attr(not(coverage), inline(always))]
pub const fn is_heap(&self) -> bool {
matches!(self.repr, Repr::Heap(..))
}
#[inline]
pub fn unwrap_inline(self) -> Buffer {
match self.repr {
Repr::Inline(b) => b,
Repr::Heap(_) => panic!("called `Bytes::unwrap_inline()` on a heap allocated buffer"),
}
}
#[inline]
pub fn try_unwrap_inline(self) -> Result<Buffer, Bytes> {
match self.repr {
Repr::Inline(b) => Ok(b),
Repr::Heap(b) => Err(b),
}
}
#[inline]
pub fn unwrap_heap(self) -> Bytes {
match self.repr {
Repr::Inline(_) => panic!("called `Bytes::unwrap_heap()` on an inline buffer"),
Repr::Heap(b) => b,
}
}
#[inline]
pub fn try_unwrap_heap(self) -> Result<Bytes, Buffer> {
match self.repr {
Repr::Inline(b) => Err(b),
Repr::Heap(b) => Ok(b),
}
}
}
impl<S> RawBytes<S>
where
Self: ImmutableStorage,
{
#[inline]
pub fn slice(&self, range: impl RangeBounds<usize>) -> Self {
ImmutableStorage::slice(self, range)
}
pub fn try_slice(&self, range: impl RangeBounds<usize>) -> Result<Self, RangeOutOfBounds> {
ImmutableStorage::try_slice(self, range)
}
#[must_use = "consider RawBytes::truncate if you don't need the other half"]
pub fn split_off(&mut self, at: usize) -> Self {
ImmutableStorage::split_off(self, at)
}
#[cfg_attr(not(coverage), inline(always))]
pub fn try_split_off(&mut self, at: usize) -> Result<Self, OutOfBounds> {
let len = self.len();
if at > len {
return Err(OutOfBounds::new(at, len));
}
Ok(self.split_off(at))
}
#[must_use = "consider RawBytes::advance if you don't need the other half"]
pub fn split_to(&mut self, at: usize) -> Self {
ImmutableStorage::split_to(self, at)
}
#[cfg_attr(not(coverage), inline(always))]
pub fn try_split_to(&mut self, at: usize) -> Result<Self, OutOfBounds> {
let len = self.len();
if at > len {
return Err(OutOfBounds::new(at, len));
}
Ok(self.split_to(at))
}
#[cfg_attr(not(coverage), inline(always))]
pub fn truncate(&mut self, new_len: usize) {
ImmutableStorage::truncate(self, new_len);
}
#[cfg_attr(not(coverage), inline(always))]
pub fn clear(&mut self) {
ImmutableStorage::clear(self)
}
#[cfg_attr(not(coverage), inline(always))]
pub fn try_advance(&mut self, cnt: usize) -> Result<(), OutOfBounds> {
let len = self.len();
if cnt > len {
return Err(OutOfBounds::new(cnt, len));
}
ImmutableStorage::advance(self, cnt);
Ok(())
}
}
impl<S> RawBytes<S> {
#[cfg_attr(not(coverage), inline(always))]
const fn new_in(repr: Repr) -> Self {
Self {
repr,
_strategy: PhantomData,
}
}
#[cfg_attr(not(coverage), inline(always))]
pub(crate) const fn inline(storage: Buffer) -> Self {
Self::new_in(Repr::inline(storage))
}
#[cfg_attr(not(coverage), inline(always))]
pub(crate) const fn heap(bytes: Bytes) -> Self {
Self::new_in(Repr::Heap(bytes))
}
#[cfg_attr(not(coverage), inline(always))]
pub fn is_unique(&self) -> bool {
self.repr.is_unique()
}
#[cfg_attr(not(coverage), inline(always))]
pub const fn len(&self) -> usize {
self.repr.len()
}
#[cfg_attr(not(coverage), inline(always))]
pub const fn is_empty(&self) -> bool {
self.repr.is_empty()
}
#[inline]
pub fn copy_from_slice(bytes: impl AsRef<[u8]>) -> Self {
Self::new_in(Repr::new(bytes.as_ref()))
}
#[cfg_attr(not(coverage), inline(always))]
pub fn as_slice(&self) -> &[u8] {
self.repr.as_slice()
}
pub fn try_into_mut(self) -> Result<BytesMut, Bytes> {
match self.repr {
Repr::Inline(storage) => Ok(BytesMut::from_inline(storage)),
Repr::Heap(bytes) => bytes.try_into_mut().map(BytesMut::from_bytes_mut),
}
}
#[inline]
pub fn into_vec(self) -> Vec<u8> {
self.repr.into_vec()
}
#[inline]
pub fn into_bytes(self) -> Bytes {
self.repr.into_bytes()
}
#[inline]
pub fn into_arc(self) -> Arc<[u8]> {
self.repr.into_arc()
}
#[inline]
pub fn to_vec(&self) -> Vec<u8> {
self.as_slice().to_vec()
}
#[inline]
pub fn to_boxed_slice(&self) -> Box<[u8]> {
self.as_slice().into()
}
}
impl<S> Default for RawBytes<S> {
#[cfg_attr(not(coverage), inline(always))]
fn default() -> Self {
Self::new()
}
}
impl<S> Buf for RawBytes<S>
where
Self: ImmutableStorage,
{
#[inline]
fn remaining(&self) -> usize {
self.len()
}
#[inline]
fn chunk(&self) -> &[u8] {
self.as_slice()
}
#[cfg_attr(not(coverage), inline(always))]
fn advance(&mut self, cnt: usize) {
ImmutableStorage::advance(self, cnt);
}
#[cfg_attr(not(coverage), inline(always))]
fn copy_to_bytes(&mut self, len: usize) -> Bytes {
ImmutableStorage::copy_to_bytes(self, len)
}
crate::macros::forward_buf! { repr {
i16,
i32,
i64,
i128,
u16,
u32,
u64,
u128,
f32,
f64,
}}
}
#[derive(Clone, Debug)]
pub(crate) enum Repr {
Inline(Buffer),
Heap(Bytes),
}
impl Repr {
#[cfg_attr(not(coverage), inline(always))]
pub(crate) const fn inline(storage: Buffer) -> Self {
Self::Inline(storage)
}
#[inline]
fn new(bytes: &[u8]) -> Self {
if let Some(inline) = Self::new_on_stack(bytes) {
inline
} else {
Self::Heap(Bytes::copy_from_slice(bytes))
}
}
#[inline]
fn from_vec(vec: Vec<u8>) -> Self {
if let Some(inline) = Self::new_on_stack(&vec) {
inline
} else {
Self::Heap(Bytes::from(vec))
}
}
#[inline]
fn from_box(vec: Box<[u8]>) -> Self {
if let Some(inline) = Self::new_on_stack(&vec) {
inline
} else {
Self::Heap(Bytes::from(vec))
}
}
#[inline]
fn from_arc(vec: Arc<[u8]>) -> Self {
if let Some(inline) = Self::new_on_stack(&vec) {
inline
} else {
Self::Heap(Bytes::copy_from_slice(vec.as_ref()))
}
}
#[inline]
const fn new_on_stack(bytes: &[u8]) -> Option<Self> {
if bytes.len() <= INLINE_CAP {
Some(Self::Inline(unsafe { Buffer::copy_from_slice(bytes) }))
} else {
None
}
}
#[cfg_attr(not(coverage), inline(always))]
const fn len(&self) -> usize {
match self {
Self::Inline(storage) => storage.remaining(),
Self::Heap(bytes) => bytes.len(),
}
}
#[cfg_attr(not(coverage), inline(always))]
const fn is_empty(&self) -> bool {
match self {
Self::Inline(storage) => storage.remaining() == 0,
Self::Heap(bytes) => bytes.is_empty(),
}
}
#[cfg_attr(not(coverage), inline(always))]
fn is_unique(&self) -> bool {
match self {
Self::Inline { .. } => false,
Self::Heap(bytes) => bytes.is_unique(),
}
}
#[cfg_attr(not(coverage), inline(always))]
fn as_slice(&self) -> &[u8] {
match self {
Self::Inline(storage) => storage.as_slice(),
Self::Heap(bytes) => bytes.as_ref(),
}
}
#[inline]
fn ptr_eq(&self, other: &Self) -> bool {
match (self, other) {
(Self::Inline { .. }, Self::Inline { .. }) => false,
(Self::Heap(a), Self::Heap(b)) => a.len() == b.len() && a.as_ptr() == b.as_ptr(),
_ => false,
}
}
#[inline]
fn into_vec(self) -> Vec<u8> {
match self {
Self::Inline(storage) => storage.to_vec(),
Self::Heap(bytes) => bytes.into(),
}
}
#[inline]
fn into_bytes(self) -> Bytes {
match self {
Self::Inline(storage) => Bytes::copy_from_slice(storage.as_slice()),
Self::Heap(bytes) => bytes,
}
}
#[inline]
fn into_arc(self) -> Arc<[u8]> {
match self {
Self::Inline(storage) => Arc::from(storage.as_slice()),
Self::Heap(bytes) => Arc::from(Vec::<u8>::from(bytes)),
}
}
}