use core::{borrow::Borrow, ops::RangeBounds, str};
use super::{
bytes::{RawBytes, strategy::ImmutableStorage},
error::*,
utf8_buf::Utf8Buf,
};
mod cmp;
mod fmt;
mod from;
mod ops;
#[cfg(feature = "arbitrary")]
mod arbitrary;
#[cfg(feature = "borsh")]
mod borsh;
#[cfg(feature = "quickcheck")]
mod quickcheck;
#[cfg(feature = "serde")]
mod serde;
#[cfg(feature = "pyo3")]
mod python;
#[cfg(feature = "pyo3")]
pub use python::PyCompactUtf8Bytes;
#[cfg(feature = "pyo3")]
pub use python::PySharedUtf8Bytes;
#[cfg(feature = "wasm")]
mod wasm;
pub struct Utf8Bytes<S> {
pub(crate) inner: RawBytes<S>,
}
impl<S> Clone for Utf8Bytes<S> {
#[inline]
fn clone(&self) -> Self {
Self {
inner: self.inner.clone(),
}
}
}
impl<S> Default for Utf8Bytes<S>
where
RawBytes<S>: ImmutableStorage,
{
fn default() -> Self {
Self::new()
}
}
impl<S> Utf8Bytes<S>
where
RawBytes<S>: ImmutableStorage,
{
pub const fn new() -> Self {
Self {
inner: RawBytes::new(),
}
}
pub const fn from_static(s: &'static str) -> Self {
Self {
inner: RawBytes::from_static(s.as_bytes()),
}
}
pub const fn as_inner(&self) -> &RawBytes<S> {
&self.inner
}
pub fn into_inner(self) -> RawBytes<S> {
self.inner
}
#[inline]
pub fn as_str(&self) -> &str {
unsafe { str::from_utf8_unchecked(self.inner.as_ref()) }
}
#[inline]
pub fn len(&self) -> usize {
self.inner.len()
}
#[inline]
pub fn is_empty(&self) -> bool {
self.inner.is_empty()
}
#[inline]
pub fn is_inline(&self) -> bool {
self.inner.is_inline()
}
#[inline]
pub fn is_heap(&self) -> bool {
self.inner.is_heap()
}
pub fn split_to(&mut self, at: usize) -> Self {
self.try_split_to(at).expect("split_to failed")
}
pub fn try_split_to(&mut self, at: usize) -> Result<Self, Utf8Error> {
<Self as Utf8Buf>::try_split_to(self, at)
}
pub fn split_off(&mut self, at: usize) -> Self {
self.try_split_off(at).expect("split_off failed")
}
pub fn try_split_off(&mut self, at: usize) -> Result<Self, Utf8Error> {
<Self as Utf8Buf>::try_split_off(self, at)
}
pub fn slice(&self, range: impl RangeBounds<usize>) -> Self {
self.try_slice(range).expect("slice failed")
}
pub fn try_slice(&self, range: impl RangeBounds<usize>) -> Result<Self, Utf8Error> {
<Self as Utf8Buf>::try_slice(self, range)
}
}
impl<S> AsRef<str> for Utf8Bytes<S>
where
RawBytes<S>: ImmutableStorage,
{
fn as_ref(&self) -> &str {
self.as_str()
}
}
impl<S> AsRef<[u8]> for Utf8Bytes<S>
where
RawBytes<S>: ImmutableStorage,
{
fn as_ref(&self) -> &[u8] {
self.as_str().as_bytes()
}
}
impl<S> Borrow<str> for Utf8Bytes<S>
where
RawBytes<S>: ImmutableStorage,
{
fn borrow(&self) -> &str {
self.as_str()
}
}
impl<S> core::ops::Deref for Utf8Bytes<S>
where
RawBytes<S>: ImmutableStorage,
{
type Target = str;
fn deref(&self) -> &Self::Target {
self.as_str()
}
}
impl<S> Utf8Buf for Utf8Bytes<S>
where
RawBytes<S>: ImmutableStorage,
{
fn try_split_to(&mut self, at: usize) -> Result<Self, Utf8Error> {
self.validate_char_boundary(at)?;
Ok(Self {
inner: self.inner.try_split_to(at).expect("already checked bounds"),
})
}
fn try_split_off(&mut self, at: usize) -> Result<Self, Utf8Error> {
self.validate_char_boundary(at)?;
Ok(Self {
inner: self
.inner
.try_split_off(at)
.expect("already checked bounds"),
})
}
fn try_slice(&self, range: impl RangeBounds<usize>) -> Result<Self, Utf8Error> {
let (start, end) = self.range_bounds_to_start_end(range)?;
Ok(Self {
inner: self
.inner
.try_slice(start..end)
.expect("already checked bounds"),
})
}
}