use std::{
borrow::Borrow,
convert::TryFrom,
fmt::{Debug, Display},
hash::Hash,
ops::{Deref, RangeBounds},
str::Utf8Error,
};
use bytes::Bytes;
use crate::TextMut;
#[derive(Default, Clone)]
pub struct Text(Bytes);
impl Text {
pub fn new() -> Self {
Self(Bytes::new())
}
pub fn from_utf8(b: Bytes) -> Result<Self, Utf8Error> {
let _ = std::str::from_utf8(b.as_ref())?;
Ok(Self(b))
}
#[inline]
pub const unsafe fn from_utf8_unchecked(b: Bytes) -> Self {
Self(b)
}
pub fn copy_from(s: impl AsRef<str>) -> Self {
Self(Bytes::copy_from_slice(s.as_ref().as_bytes()))
}
pub const fn from_static(s: &'static str) -> Self {
Self(Bytes::from_static(s.as_bytes()))
}
pub fn len(&self) -> usize {
self.0.len()
}
pub fn is_empty(&self) -> bool {
self.0.is_empty()
}
pub const fn as_bytes(&self) -> &Bytes {
&self.0
}
pub fn into_bytes(self) -> Bytes {
self.0
}
pub fn get(&self, r: impl RangeBounds<usize>) -> Option<Text> {
let start = match r.start_bound() {
std::ops::Bound::Included(&i) => i,
std::ops::Bound::Excluded(&i) => i.checked_add(1)?,
std::ops::Bound::Unbounded => 0,
};
let end = match r.end_bound() {
std::ops::Bound::Included(&i) => i.checked_add(1)?,
std::ops::Bound::Excluded(&i) => i,
std::ops::Bound::Unbounded => self.len(),
};
soft_assert::soft_assert!(self.is_char_boundary(start) && self.is_char_boundary(end));
Some(Self(self.0.slice(start..end)))
}
pub fn split_at(mut self, index: usize) -> Result<(Self, Self), Self> {
soft_assert::soft_assert!(self.is_char_boundary(index), Err(self));
let right = self.0.split_off(index);
Ok((Self(self.0), Self(right)))
}
pub fn split_off(&mut self, index: usize) -> Option<Self> {
soft_assert::soft_assert!(self.is_char_boundary(index));
let right = self.0.split_off(index);
Some(Self(right))
}
pub fn split_to(&mut self, index: usize) -> Option<Self> {
soft_assert::soft_assert!(self.is_char_boundary(index));
let right = self.0.split_to(index);
Some(Self(right))
}
fn as_str(&self) -> &str {
unsafe { std::str::from_utf8_unchecked(self.0.as_ref()) }
}
}
impl AsRef<str> for Text {
fn as_ref(&self) -> &str {
self.as_str()
}
}
impl Borrow<str> for Text {
fn borrow(&self) -> &str {
self.as_str()
}
}
impl Deref for Text {
type Target = str;
fn deref(&self) -> &Self::Target {
self.as_str()
}
}
impl From<&'static str> for Text {
fn from(s: &'static str) -> Self {
Self::from_static(s)
}
}
impl From<String> for Text {
fn from(s: String) -> Self {
Self(Bytes::from(s.into_bytes()))
}
}
impl TryFrom<Bytes> for Text {
type Error = Utf8Error;
fn try_from(b: Bytes) -> Result<Self, Self::Error> {
Self::from_utf8(b)
}
}
impl From<Text> for Bytes {
fn from(t: Text) -> Self {
t.into_bytes()
}
}
impl Display for Text {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
Display::fmt(self.as_str(), f)
}
}
impl Debug for Text {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
Debug::fmt(self.as_str(), f)
}
}
impl PartialEq for Text {
fn eq(&self, other: &Self) -> bool {
(&**self).eq(&**other)
}
}
impl Eq for Text {}
impl PartialEq<&Text> for Text {
fn eq(&self, other: &&Text) -> bool {
(&**self).eq(&***other)
}
}
impl PartialEq<&mut Text> for Text {
fn eq(&self, other: &&mut Text) -> bool {
(&**self).eq(&***other)
}
}
impl PartialOrd for Text {
fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
Some(self.cmp(other))
}
}
impl Ord for Text {
fn cmp(&self, other: &Self) -> std::cmp::Ordering {
(&**self).cmp(&**other)
}
}
impl PartialEq<str> for Text {
fn eq(&self, other: &str) -> bool {
(&**self).eq(other)
}
}
impl PartialEq<&str> for Text {
fn eq(&self, other: &&str) -> bool {
(&**self).eq(*other)
}
}
impl PartialEq<&mut str> for Text {
fn eq(&self, other: &&mut str) -> bool {
(&**self).eq(*other)
}
}
impl PartialOrd<str> for Text {
fn partial_cmp(&self, other: &str) -> Option<std::cmp::Ordering> {
(&**self).partial_cmp(other)
}
}
impl PartialOrd<&str> for Text {
fn partial_cmp(&self, other: &&str) -> Option<std::cmp::Ordering> {
(&**self).partial_cmp(*other)
}
}
impl PartialOrd<&mut str> for Text {
fn partial_cmp(&self, other: &&mut str) -> Option<std::cmp::Ordering> {
(&**self).partial_cmp(*other)
}
}
impl PartialEq<String> for Text {
fn eq(&self, other: &String) -> bool {
(&**self).eq(other)
}
}
impl PartialEq<&String> for Text {
fn eq(&self, other: &&String) -> bool {
(&**self).eq(*other)
}
}
impl PartialEq<&mut String> for Text {
fn eq(&self, other: &&mut String) -> bool {
(&**self).eq(*other)
}
}
impl PartialOrd<String> for Text {
fn partial_cmp(&self, other: &String) -> Option<std::cmp::Ordering> {
(&**self).partial_cmp(&**other)
}
}
impl PartialOrd<&String> for Text {
fn partial_cmp(&self, other: &&String) -> Option<std::cmp::Ordering> {
(&**self).partial_cmp(&***other)
}
}
impl PartialOrd<&mut String> for Text {
fn partial_cmp(&self, other: &&mut String) -> Option<std::cmp::Ordering> {
(&**self).partial_cmp(&***other)
}
}
impl PartialEq<TextMut> for Text {
fn eq(&self, other: &TextMut) -> bool {
(&**self).eq(&**other)
}
}
impl PartialEq<&TextMut> for Text {
fn eq(&self, other: &&TextMut) -> bool {
(&**self).eq(&***other)
}
}
impl PartialEq<&mut TextMut> for Text {
fn eq(&self, other: &&mut TextMut) -> bool {
(&**self).eq(&***other)
}
}
impl PartialOrd<TextMut> for Text {
fn partial_cmp(&self, other: &TextMut) -> Option<std::cmp::Ordering> {
(&**self).partial_cmp(&**other)
}
}
impl PartialOrd<&TextMut> for Text {
fn partial_cmp(&self, other: &&TextMut) -> Option<std::cmp::Ordering> {
(&**self).partial_cmp(&***other)
}
}
impl PartialOrd<&mut TextMut> for Text {
fn partial_cmp(&self, other: &&mut TextMut) -> Option<std::cmp::Ordering> {
(&**self).partial_cmp(&***other)
}
}
impl Hash for Text {
fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
(&**self).hash(state);
}
}