mod iter;
pub use self::iter::{IntoIter, Iter};
#[cfg(test)]
mod tests;
use crate::{owned_slice::OwnedSlice, util::range, IndexOutOfBounds, RangeOfSubset, SharedStr};
use std::{
borrow::{Borrow, Cow},
fmt::{self, Debug},
ops::{Deref, Range, RangeBounds},
sync::Arc,
};
#[derive(Clone)]
pub struct SharedBytes(pub(crate) Flavour);
#[derive(Clone)]
pub(crate) enum Flavour {
Static(&'static [u8]),
ArcVecSlice(OwnedSlice<Arc<Vec<u8>>, [u8]>),
ArcStringSlice(OwnedSlice<Arc<String>, [u8]>),
}
impl SharedBytes {
#[inline]
pub const fn new() -> Self {
Self(Flavour::Static(b""))
}
#[inline]
pub const fn from_static(x: &'static [u8]) -> Self {
Self(Flavour::Static(x))
}
#[inline]
pub fn from_vec(x: Vec<u8>) -> Self {
Self::from_arc_vec(Arc::new(x))
}
#[inline]
pub fn from_arc_vec(x: Arc<Vec<u8>>) -> Self {
Self(Flavour::ArcVecSlice(OwnedSlice::new(x).unwrap()))
}
#[inline]
pub fn from_arc_string(x: Arc<String>) -> Self {
Self(Flavour::ArcStringSlice(OwnedSlice::new(x).unwrap()))
}
pub fn into_vec(self) -> Vec<u8> {
self.into_static_cow().into_owned()
}
fn into_static_cow(self) -> Cow<'static, [u8]> {
match self.0 {
Flavour::Static(x) => Cow::Borrowed(x),
Flavour::ArcVecSlice(x) => Cow::Owned(x.into_unwrapped(Into::into, ToOwned::to_owned)),
Flavour::ArcStringSlice(x) => {
Cow::Owned(x.into_unwrapped(Into::into, ToOwned::to_owned))
}
}
}
#[inline]
pub fn as_slice(&self) -> &[u8] {
match &self.0 {
Flavour::Static(x) => x,
Flavour::ArcVecSlice(x) => x,
Flavour::ArcStringSlice(x) => x,
}
}
pub fn as_static(&self) -> Option<&'static [u8]> {
match &self.0 {
Flavour::Static(x) => Some(x),
_ => None,
}
}
pub fn len(&self) -> usize {
self.as_slice().len()
}
pub fn is_empty(&self) -> bool {
self.as_slice().is_empty()
}
pub fn clear(&mut self) {
*self = Self::new()
}
pub fn truncate(&mut self, at: usize) {
self.try_slice_mut(..at)
.unwrap_or_else(|_| panic!("truncate index '{at}' should be <= len '{}'", self.len()))
}
#[must_use = "consider fn truncate if you don't need the other half"]
pub fn split_off(&mut self, at: usize) -> Self {
self.try_split_off(at)
.unwrap_or_else(|| panic!("split index '{at}' should be <= len '{}'", self.len()))
}
fn try_split_off(&mut self, at: usize) -> Option<Self> {
self.as_slice().get(at)?; let mut split = self.clone();
split.slice_mut(at..);
self.slice_mut(..at);
Some(split)
}
pub fn range_of_subset(&self, subset: &[u8]) -> Range<usize> {
RangeOfSubset::range_of_subset(self.as_slice(), subset)
}
pub fn slice_cloned<R: RangeBounds<usize>>(&self, r: R) -> Self {
self.non_generic_slice_cloned(self.slice_range_from_bounds(r))
}
fn non_generic_slice_cloned(&self, range: Range<usize>) -> Self {
self.non_generic_try_slice_cloned(range.clone())
.unwrap_or_else(|_| self.out_of_bounds_panic(range))
}
pub fn try_slice_cloned<R: RangeBounds<usize>>(&self, r: R) -> Result<Self, IndexOutOfBounds> {
self.non_generic_try_slice_cloned(self.slice_range_from_bounds(r))
}
fn non_generic_try_slice_cloned(&self, range: Range<usize>) -> Result<Self, IndexOutOfBounds> {
if self.as_slice().get(range.clone()).is_none() {
return Err(IndexOutOfBounds::new());
}
Ok(self.clone().slice_into(range))
}
pub fn slice_into<R: RangeBounds<usize>>(self, r: R) -> Self {
let range = self.slice_range_from_bounds(r);
self.non_generic_slice_into(range)
}
fn non_generic_slice_into(self, range: Range<usize>) -> Self {
self.non_generic_try_slice_into(range.clone())
.unwrap_or_else(|this| this.out_of_bounds_panic(range))
}
pub fn try_slice_into<R: RangeBounds<usize>>(self, r: R) -> Result<Self, Self> {
let range = self.slice_range_from_bounds(r);
self.non_generic_try_slice_into(range)
}
fn non_generic_try_slice_into(mut self, range: Range<usize>) -> Result<Self, Self> {
match self.internal_try_slice_mut(range) {
Ok(()) => Ok(self),
Err(()) => Err(self),
}
}
pub fn slice_mut<R: RangeBounds<usize>>(&mut self, r: R) {
self.non_generic_slice_mut(self.slice_range_from_bounds(r))
}
fn non_generic_slice_mut(&mut self, range: Range<usize>) {
self.internal_try_slice_mut(range.clone())
.unwrap_or_else(|()| self.out_of_bounds_panic(range))
}
pub fn try_slice_mut<R: RangeBounds<usize>>(&mut self, r: R) -> Result<(), IndexOutOfBounds> {
self.non_generic_try_slice_mut(self.slice_range_from_bounds(r))
}
fn non_generic_try_slice_mut(&mut self, range: Range<usize>) -> Result<(), IndexOutOfBounds> {
self.internal_try_slice_mut(range)
.map_err(|()| IndexOutOfBounds::new())
}
fn slice_range_from_bounds<R: RangeBounds<usize>>(&self, r: R) -> Range<usize> {
range::from_slice_bounds(r, || self.len())
}
fn out_of_bounds_panic<R: RangeBounds<usize> + Debug, T>(&self, range: R) -> T {
let length = self.len();
panic!("slice range {range:?} is out of bounds for length {length}")
}
#[must_use = "`internal_try_slice_mut` may fail to mutate `self`"]
fn internal_try_slice_mut(&mut self, range: Range<usize>) -> Result<(), ()> {
match &mut self.0 {
Flavour::Static(old) => match old.get(range) {
None => Err(()),
Some(new) => {
*old = new;
Ok(())
}
},
Flavour::ArcVecSlice(x) => x.try_slice_mut(range),
Flavour::ArcStringSlice(x) => x.try_slice_mut(range),
}
}
pub fn iter(&self) -> Iter {
Iter::new(self.as_slice())
}
}
impl AsRef<[u8]> for SharedBytes {
#[inline]
fn as_ref(&self) -> &[u8] {
self.as_slice()
}
}
impl Borrow<[u8]> for SharedBytes {
#[inline]
fn borrow(&self) -> &[u8] {
self.as_slice()
}
}
impl Debug for SharedBytes {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
Debug::fmt(self.as_slice(), f)
}
}
impl Default for SharedBytes {
#[inline]
fn default() -> Self {
Self::new()
}
}
impl Deref for SharedBytes {
type Target = [u8];
#[inline]
fn deref(&self) -> &Self::Target {
self.as_slice()
}
}
impl Eq for SharedBytes {}
impl PartialEq for SharedBytes {
#[inline]
fn eq(&self, other: &Self) -> bool {
self.as_slice() == other.as_slice()
}
}
impl<Other: ?Sized> PartialEq<&Other> for SharedBytes
where
Self: PartialEq<Other>,
{
#[inline]
fn eq(&self, other: &&Other) -> bool {
self == *other
}
}
impl PartialEq<[u8]> for SharedBytes {
#[inline]
fn eq(&self, other: &[u8]) -> bool {
self.as_slice() == other
}
}
impl<const N: usize> PartialEq<[u8; N]> for SharedBytes {
#[inline]
fn eq(&self, other: &[u8; N]) -> bool {
self.as_slice() == other.as_slice()
}
}
impl PartialEq<Vec<u8>> for SharedBytes {
#[inline]
fn eq(&self, other: &Vec<u8>) -> bool {
self.as_slice() == other.as_slice()
}
}
impl PartialEq<str> for SharedBytes {
#[inline]
fn eq(&self, other: &str) -> bool {
self.as_slice() == other.as_bytes()
}
}
impl PartialEq<String> for SharedBytes {
#[inline]
fn eq(&self, other: &String) -> bool {
self.as_slice() == other.as_bytes()
}
}
impl std::hash::Hash for SharedBytes {
fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
self.as_slice().hash(state)
}
}
impl From<&'static [u8]> for SharedBytes {
#[inline]
fn from(x: &'static [u8]) -> Self {
Self::from_static(x)
}
}
impl From<Vec<u8>> for SharedBytes {
#[inline]
fn from(x: Vec<u8>) -> Self {
Self::from_vec(x)
}
}
impl From<Arc<Vec<u8>>> for SharedBytes {
#[inline]
fn from(x: Arc<Vec<u8>>) -> Self {
Self::from_arc_vec(x)
}
}
impl From<SharedStr> for SharedBytes {
fn from(x: SharedStr) -> Self {
use crate::shared_str::Flavour::*;
Self(match x.0 {
Static(x) => Flavour::Static(x.as_bytes()),
ArcVecSlice(x) => Flavour::ArcVecSlice(x.try_map_output().unwrap()),
ArcStringSlice(x) => Flavour::ArcStringSlice(x.try_map_output().unwrap()),
})
}
}
impl From<&'static str> for SharedBytes {
#[inline]
fn from(x: &'static str) -> Self {
Self::from_static(x.as_bytes())
}
}
impl From<String> for SharedBytes {
#[inline]
fn from(x: String) -> Self {
Self::from_vec(x.into_bytes())
}
}
impl From<Arc<String>> for SharedBytes {
#[inline]
fn from(x: Arc<String>) -> Self {
Self::from_arc_string(x)
}
}
impl From<SharedBytes> for Vec<u8> {
fn from(x: SharedBytes) -> Self {
x.into_vec()
}
}
impl FromIterator<u8> for SharedBytes {
#[inline]
fn from_iter<T: IntoIterator<Item = u8>>(iter: T) -> Self {
Self::from_vec(iter.into_iter().collect())
}
}
impl<'a> IntoIterator for &'a SharedBytes {
type Item = u8;
type IntoIter = Iter<'a>;
fn into_iter(self) -> Self::IntoIter {
self.iter()
}
}
impl IntoIterator for SharedBytes {
type Item = u8;
type IntoIter = IntoIter;
fn into_iter(self) -> IntoIter {
IntoIter(self)
}
}