use super::{HashWork, Memory, MemoryError, OwnedVec, Work, allocator::ValidatedText};
use core::{
borrow::Borrow,
fmt,
hash::{Hash, Hasher},
ops::Deref,
str::Utf8Error,
};
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum TextErrorKind {
Resource(MemoryError),
Utf8(Utf8Error),
}
pub struct TextError<W: Work = Memory> {
kind: TextErrorKind,
bytes: OwnedVec<u8, W>,
}
impl<W: Work> TextError<W> {
#[must_use]
pub fn kind(&self) -> TextErrorKind {
self.kind
}
#[must_use]
pub fn into_bytes(self) -> OwnedVec<u8, W> {
self.bytes
}
}
impl<W: Work> fmt::Debug for TextError<W> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("TextError")
.field("kind", &self.kind)
.finish_non_exhaustive()
}
}
pub struct OwnedText<W: Work = Memory> {
text: ValidatedText<W>,
}
impl<W: Work> OwnedText<W> {
pub fn from_utf8(bytes: OwnedVec<u8, W>) -> Result<Self, TextError<W>> {
ValidatedText::from_utf8(bytes)
.map(|text| Self { text })
.map_err(|(kind, bytes)| TextError { kind, bytes })
}
pub fn try_from_str(text: &str, execution: &W) -> Result<Self, MemoryError> {
Ok(Self {
text: ValidatedText::from_str(text, execution)?,
})
}
pub fn try_push_str(&mut self, suffix: &str) -> Result<(), MemoryError> {
self.text.try_push_str(suffix)
}
pub fn try_reserve_exact(&mut self, additional: usize) -> Result<(), MemoryError> {
self.text.try_reserve_exact(additional)
}
#[must_use]
pub fn memory(&self) -> &Memory {
self.text.bytes().memory()
}
#[must_use]
pub fn len(&self) -> usize {
self.text.bytes().len()
}
#[must_use]
pub fn is_empty(&self) -> bool {
self.text.bytes().is_empty()
}
#[must_use]
pub fn capacity(&self) -> usize {
self.text.bytes().capacity()
}
#[must_use]
pub fn as_bytes(&self) -> &[u8] {
self.text.bytes()
}
#[must_use]
pub fn as_str(&self) -> &str {
self.text.as_str()
}
#[must_use]
pub fn into_owned(self) -> OwnedText {
OwnedText {
text: self.text.into_owned(),
}
}
#[must_use]
pub fn into_bytes(self) -> OwnedVec<u8, W> {
self.text.into_bytes()
}
}
impl<W: Work> fmt::Debug for OwnedText<W> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
self.as_str().fmt(f)
}
}
impl<W: Work> Deref for OwnedText<W> {
type Target = str;
fn deref(&self) -> &str {
self.as_str()
}
}
impl<W: Work> Borrow<str> for OwnedText<W> {
fn borrow(&self) -> &str {
self.as_str()
}
}
impl<W: Work> AsRef<str> for OwnedText<W> {
fn as_ref(&self) -> &str {
self.as_str()
}
}
impl<W: Work> fmt::Display for OwnedText<W> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.write_str(self.as_str())
}
}
impl<W: Work, V: Work> PartialEq<OwnedText<V>> for OwnedText<W> {
fn eq(&self, other: &OwnedText<V>) -> bool {
self.as_str() == other.as_str()
}
}
impl<W: Work> Eq for OwnedText<W> {}
impl<W: Work> Hash for OwnedText<W> {
fn hash<H: Hasher>(&self, state: &mut H) {
self.as_str().hash(state);
}
}
impl<W: Work> HashWork for OwnedText<W> {
fn hash_work(&self) -> Result<u64, MemoryError> {
(self.len() as u64)
.checked_add(1)
.ok_or(MemoryError::WorkExceeded)
}
}