use std::any::Any;
use std::ascii::escape_default;
use std::borrow::Borrow;
use std::cmp;
use std::fmt;
use std::hash;
use std::ops::Deref;
use std::slice::SliceIndex;
use std::sync::{Arc, Weak};
pub(crate) fn is_subslice(slice: &[u8], subslice: &[u8]) -> bool {
let slice_start = slice.as_ptr() as usize;
let slice_end = slice_start + slice.len();
let subslice_start = subslice.as_ptr() as usize;
let subslice_end = subslice_start + subslice.len();
subslice_start >= slice_start && subslice_end <= slice_end
}
pub unsafe trait ByteSource {
type Owner: ByteOwner;
fn as_bytes(&self) -> &[u8];
fn get_owner(self) -> Self::Owner;
}
pub trait ByteOwner: Any + Sync + Send {}
impl<T: ByteSource + Sync + Send + 'static> ByteOwner for T {}
pub struct Bytes {
data: *const [u8],
owner: Arc<dyn ByteOwner>,
}
#[derive(Clone, Debug)]
pub struct WeakBytes {
data: *const [u8],
owner: Weak<dyn ByteOwner>,
}
unsafe impl Send for Bytes {}
unsafe impl Sync for Bytes {}
impl Clone for Bytes {
fn clone(&self) -> Self {
Self {
data: self.data,
owner: self.owner.clone(),
}
}
}
impl Bytes {
#[inline]
pub(crate) fn data_ptr(&self) -> *const [u8] {
self.data
}
#[inline]
pub(crate) unsafe fn get_data(&self) -> &[u8] {
unsafe { &*self.data }
}
#[inline]
pub(crate) unsafe fn set_data(&mut self, data: &[u8]) {
self.data = data as *const [u8];
}
#[inline]
pub(crate) fn get_owner(&self) -> Arc<dyn ByteOwner> {
self.owner.clone()
}
#[inline]
pub(crate) fn take_owner(self) -> Arc<dyn ByteOwner> {
self.owner
}
#[inline]
pub fn empty() -> Self {
Self::from_source(&[0u8; 0][..])
}
pub unsafe fn from_raw_parts(data: &[u8], owner: Arc<dyn ByteOwner>) -> Self {
Self {
data: data as *const [u8],
owner,
}
}
pub fn from_source(source: impl ByteSource) -> Self {
let data = source.as_bytes() as *const [u8];
let owner = source.get_owner();
let owner = Arc::new(owner);
Self { data, owner }
}
pub fn from_owning_source_arc(arc: Arc<impl ByteSource + ByteOwner>) -> Self {
let data = arc.as_bytes() as *const [u8];
Self { data, owner: arc }
}
#[cfg(feature = "mmap")]
pub unsafe fn map_file<F>(file: F) -> std::io::Result<Self>
where
F: memmap2::MmapAsRawDesc,
{
let map = memmap2::MmapOptions::new().map(file)?;
Ok(Self::from_source(map))
}
#[cfg(feature = "mmap")]
pub unsafe fn map_file_region<F>(file: F, offset: u64, len: usize) -> std::io::Result<Self>
where
F: memmap2::MmapAsRawDesc,
{
let map = memmap2::MmapOptions::new()
.offset(offset)
.len(len)
.map(file)?;
Ok(Self::from_source(map))
}
#[inline]
pub(crate) fn as_slice(&self) -> &[u8] {
unsafe { &*self.data }
}
pub fn downcast_to_owner<T>(self) -> Result<Arc<T>, Bytes>
where
T: Send + Sync + 'static,
{
let owner_any: Arc<dyn Any + Send + Sync> = self.owner.clone();
match owner_any.downcast::<T>() {
Ok(owner) => Ok(owner),
Err(_) => Err(self),
}
}
pub fn try_unwrap_owner<T>(self) -> Result<T, Self>
where
T: ByteOwner + Send + Sync + 'static,
{
let Self { data, owner } = self;
let any: Arc<dyn Any + Send + Sync> = owner.clone();
let arc_t = match Arc::downcast::<T>(any) {
Ok(arc_t) => arc_t,
Err(_) => return Err(Self { data, owner }),
};
drop(owner);
match Arc::try_unwrap(arc_t) {
Ok(t) => Ok(t),
Err(arc_t) => {
let owner: Arc<dyn ByteOwner> = arc_t;
Err(Self { data, owner })
}
}
}
pub fn slice(&self, range: impl SliceIndex<[u8], Output = [u8]>) -> Self {
let sliced = &self.as_slice()[range];
Self {
data: sliced as *const [u8],
owner: self.owner.clone(),
}
}
pub fn slice_to_bytes(&self, slice: &[u8]) -> Option<Self> {
if is_subslice(self.as_slice(), slice) {
let owner = self.owner.clone();
Some(Self {
data: slice as *const [u8],
owner,
})
} else {
None
}
}
pub fn take_prefix(&mut self, len: usize) -> Option<Self> {
let slice = unsafe { &*self.data };
if len > slice.len() {
return None;
}
let (data, rest) = slice.split_at(len);
self.data = rest as *const [u8];
Some(Self {
data: data as *const [u8],
owner: self.owner.clone(),
})
}
pub fn take_suffix(&mut self, len: usize) -> Option<Self> {
let slice = unsafe { &*self.data };
if len > slice.len() {
return None;
}
let (rest, data) = slice.split_at(slice.len() - len);
self.data = rest as *const [u8];
Some(Self {
data: data as *const [u8],
owner: self.owner.clone(),
})
}
pub fn pop_front(&mut self) -> Option<u8> {
let slice = unsafe { &*self.data };
let (&b, rest) = slice.split_first()?;
self.data = rest as *const [u8];
Some(b)
}
pub fn pop_back(&mut self) -> Option<u8> {
let slice = unsafe { &*self.data };
let (last, rest) = slice.split_last()?;
self.data = rest as *const [u8];
Some(*last)
}
pub fn downgrade(&self) -> WeakBytes {
WeakBytes {
data: self.data,
owner: Arc::downgrade(&self.owner),
}
}
}
impl WeakBytes {
pub fn upgrade(&self) -> Option<Bytes> {
let arc = self.owner.upgrade()?;
Some(Bytes {
data: self.data,
owner: arc,
})
}
}
impl<T: ByteSource> From<T> for Bytes {
fn from(value: T) -> Self {
Self::from_source(value)
}
}
impl<T: ByteSource + ByteOwner> From<Arc<T>> for Bytes {
fn from(arc: Arc<T>) -> Self {
Self::from_owning_source_arc(arc)
}
}
#[cfg(feature = "bytes")]
impl From<Bytes> for bytes::Bytes {
fn from(bytes: Bytes) -> Self {
bytes::Bytes::from_owner(bytes)
}
}
impl Deref for Bytes {
type Target = [u8];
#[inline]
fn deref(&self) -> &Self::Target {
self.as_slice()
}
}
#[cfg(feature = "ownedbytes")]
unsafe impl ownedbytes::StableDeref for Bytes {}
impl Borrow<[u8]> for Bytes {
fn borrow(&self) -> &[u8] {
self
}
}
impl AsRef<[u8]> for Bytes {
#[inline]
fn as_ref(&self) -> &[u8] {
self
}
}
impl hash::Hash for Bytes {
fn hash<H: hash::Hasher>(&self, state: &mut H) {
self.as_slice().hash(state);
}
}
impl Default for Bytes {
fn default() -> Self {
Self::empty()
}
}
impl PartialEq for Bytes {
fn eq(&self, other: &Self) -> bool {
self.as_slice() == other.as_slice()
}
}
impl Eq for Bytes {}
impl PartialOrd for Bytes {
fn partial_cmp(&self, other: &Self) -> Option<cmp::Ordering> {
self.as_slice().partial_cmp(other.as_slice())
}
}
impl Ord for Bytes {
fn cmp(&self, other: &Bytes) -> cmp::Ordering {
self.as_slice().cmp(other.as_slice())
}
}
impl fmt::Debug for Bytes {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
f.write_str("b\"")?;
for &byte in self.as_slice() {
fmt::Display::fmt(&escape_default(byte), f)?;
}
f.write_str("\"")?;
Ok(())
}
}
#[cfg(feature = "bytes")]
impl bytes::Buf for Bytes {
#[inline]
fn remaining(&self) -> usize {
self.as_slice().len()
}
#[inline]
fn chunk(&self) -> &[u8] {
self.as_slice()
}
#[inline]
fn advance(&mut self, cnt: usize) {
let slice = unsafe { &*self.data };
if cnt > slice.len() {
panic!("advance out of bounds: {} > {}", cnt, slice.len());
}
self.data = &slice[cnt..] as *const [u8];
}
}
#[cfg(test)]
mod tests {
use super::Bytes;
#[test]
fn niche_optimisation() {
assert_eq!(size_of::<Bytes>(), size_of::<Option<Bytes>>());
}
}
#[cfg(kani)]
mod verification {
use super::*;
use kani::BoundedArbitrary;
#[kani::proof]
#[kani::unwind(16)]
pub fn check_take_prefix_ok() {
let data: Vec<u8> = Vec::bounded_any::<16>();
kani::assume(data.len() >= 5);
let mut bytes = Bytes::from_source(data.clone());
let original = bytes.clone();
let prefix = bytes.take_prefix(5).expect("prefix exists");
assert_eq!(prefix.as_ref(), &original.as_ref()[..5]);
assert_eq!(bytes.as_ref(), &original.as_ref()[5..]);
}
#[kani::proof]
#[kani::unwind(32)]
pub fn check_take_prefix_too_large() {
let data: Vec<u8> = Vec::bounded_any::<16>();
let mut bytes = Bytes::from_source(data.clone());
let copy = bytes.clone();
let res = bytes.take_prefix(32);
assert!(res.is_none());
assert_eq!(bytes.as_ref(), copy.as_ref());
}
#[kani::proof]
#[kani::unwind(16)]
pub fn check_take_suffix_ok() {
let data: Vec<u8> = Vec::bounded_any::<16>();
kani::assume(data.len() >= 4);
let mut bytes = Bytes::from_source(data.clone());
let original = bytes.clone();
let suffix = bytes.take_suffix(4).expect("suffix exists");
assert_eq!(suffix.as_ref(), &original.as_ref()[original.len() - 4..]);
assert_eq!(bytes.as_ref(), &original.as_ref()[..original.len() - 4]);
}
#[kani::proof]
#[kani::unwind(32)]
pub fn check_take_suffix_too_large() {
let data: Vec<u8> = Vec::bounded_any::<16>();
let mut bytes = Bytes::from_source(data.clone());
let copy = bytes.clone();
let res = bytes.take_suffix(64);
assert!(res.is_none());
assert_eq!(bytes.as_ref(), copy.as_ref());
}
#[kani::proof]
#[kani::unwind(16)]
pub fn check_pop_front_behaviour() {
let data: Vec<u8> = Vec::bounded_any::<16>();
let mut bytes = Bytes::from_source(data.clone());
let snapshot = bytes.clone();
if let Some((expected, remainder)) = data.split_first() {
let popped = bytes.pop_front().expect("non-empty slice");
assert_eq!(popped, *expected);
assert_eq!(bytes.as_ref(), remainder);
} else {
assert!(bytes.pop_front().is_none());
assert_eq!(bytes.as_ref(), snapshot.as_ref());
}
}
#[kani::proof]
#[kani::unwind(16)]
pub fn check_pop_back_behaviour() {
let data: Vec<u8> = Vec::bounded_any::<16>();
let mut bytes = Bytes::from_source(data.clone());
let snapshot = bytes.clone();
if let Some((expected, remainder)) = data.split_last() {
let popped = bytes.pop_back().expect("non-empty slice");
assert_eq!(popped, *expected);
assert_eq!(bytes.as_ref(), remainder);
} else {
assert!(bytes.pop_back().is_none());
assert_eq!(bytes.as_ref(), snapshot.as_ref());
}
}
#[kani::proof]
#[kani::unwind(16)]
pub fn check_slice_to_bytes_ok() {
let data: Vec<u8> = Vec::bounded_any::<16>();
kani::assume(data.len() >= 8);
let bytes = Bytes::from_source(data.clone());
let slice = &bytes.as_ref()[3..8];
let sub = bytes.slice_to_bytes(slice).expect("slice from same bytes");
assert_eq!(sub.as_ref(), slice);
}
#[kani::proof]
#[kani::unwind(16)]
pub fn check_slice_to_bytes_unrelated() {
let data: Vec<u8> = Vec::bounded_any::<16>();
let bytes = Bytes::from_source(data.clone());
let other: [u8; 4] = kani::any();
assert!(bytes.slice_to_bytes(&other).is_none());
}
#[kani::proof]
#[kani::unwind(16)]
pub fn check_try_unwrap_owner_unique() {
let data: Vec<u8> = Vec::bounded_any::<16>();
let bytes = Bytes::from_source(data.clone());
let recovered = bytes.try_unwrap_owner::<Vec<u8>>().expect("unwrap owner");
assert_eq!(recovered, data);
}
#[kani::proof]
#[kani::unwind(16)]
pub fn check_try_unwrap_owner_shared() {
let data: Vec<u8> = Vec::bounded_any::<16>();
let bytes = Bytes::from_source(data.clone());
let _clone = bytes.clone();
let result = bytes.try_unwrap_owner::<Vec<u8>>();
assert!(result.is_err());
}
#[kani::proof]
#[kani::unwind(16)]
pub fn check_try_unwrap_owner_wrong_type() {
let data: Vec<u8> = Vec::bounded_any::<16>();
let bytes = Bytes::from_source(data);
assert!(bytes.try_unwrap_owner::<String>().is_err());
}
#[kani::proof]
#[kani::unwind(16)]
pub fn check_weakbytes_upgrade_some() {
let data: Vec<u8> = Vec::bounded_any::<16>();
let bytes = Bytes::from_source(data.clone());
let weak = bytes.downgrade();
let upgraded = weak.upgrade().expect("upgrade");
assert_eq!(upgraded.as_ref(), data.as_slice());
}
#[kani::proof]
#[kani::unwind(16)]
pub fn check_weakbytes_upgrade_none() {
let data: Vec<u8> = Vec::bounded_any::<16>();
let bytes = Bytes::from_source(data);
let weak = bytes.downgrade();
drop(bytes);
assert!(weak.upgrade().is_none());
}
#[kani::proof]
#[kani::unwind(16)]
pub fn check_downcast_to_owner_preserves_data() {
let data: Vec<u8> = Vec::bounded_any::<16>();
kani::assume(data.len() <= 16);
let bytes = Bytes::from_source(data.clone());
let arc_vec = bytes
.clone()
.downcast_to_owner::<Vec<u8>>()
.expect("downcast to Vec<u8>");
assert_eq!(&*arc_vec, &data);
let result = bytes.downcast_to_owner::<String>();
let Err(returned) = result else {
panic!("downcast to String should fail");
};
assert_eq!(returned.as_ref(), data.as_slice());
}
#[kani::proof]
#[kani::unwind(16)]
pub fn check_is_subslice_accepts_ranges() {
let data: Vec<u8> = Vec::bounded_any::<16>();
let bytes = Bytes::from_source(data.clone());
let start: usize = kani::any();
let end: usize = kani::any();
kani::assume(start <= end);
kani::assume(end <= data.len());
let slice = &bytes.as_ref()[start..end];
assert!(is_subslice(bytes.as_ref(), slice));
}
#[kani::proof]
#[kani::unwind(16)]
pub fn check_is_subslice_rejects_disjoint_ranges() {
let data: Vec<u8> = Vec::bounded_any::<16>();
let other: Vec<u8> = Vec::bounded_any::<8>();
let base_len = data.len();
kani::assume(base_len > 0);
let base_ptr = data.as_ptr();
let other_len = other.len();
kani::assume(other_len > 0);
let other_ptr = other.as_ptr();
let base_start = base_ptr as usize;
let base_end = base_start + base_len;
let other_start = other_ptr as usize;
let other_end = other_start + other_len;
kani::assume(other_end <= base_start || other_start >= base_end);
let bytes = Bytes::from_source(data);
assert!(!is_subslice(bytes.as_ref(), other.as_slice()));
}
}