use crate::{
CharIter, GraphemeMachine, GraphemeScanner, MismatchedCapacity, StringNonul, char7, char8,
char16, charu, doclink, unwrap,
};
#[doc = crate::_tags!(text)]
#[doc = concat!["An ", crate::_ABBR_EGC!(), " backed by a [`StringNonul`]."]]
#[doc = crate::_doc_location!("text/grapheme")]
#[must_use]
#[repr(transparent)]
#[derive(Clone, Eq, PartialOrd, Ord)]
pub struct GraphemeNonul<const CAP: usize>(pub(crate) StringNonul<CAP>);
#[rustfmt::skip]
impl<const CAP: usize> GraphemeNonul<CAP> {
#[inline(always)]
pub const fn new() -> Self {
Self(StringNonul::new())
}
pub const fn new_checked() -> Result<Self, MismatchedCapacity> {
Ok(Self(unwrap![ok? StringNonul::new_checked()]))
}
pub const fn from_str(string: &str) -> Result<Self, MismatchedCapacity> {
let mut machine = GraphemeMachine::new();
let mut scanner = GraphemeScanner::<charu>::new(&mut machine, string);
if let Some(g) = scanner.next_grapheme_nonul::<CAP>() {
Ok(g)
} else {
Ok(Self::new())
}
}
pub const fn from_char7(c: char7) -> Result<Self, MismatchedCapacity> {
Ok(Self(unwrap![ok? StringNonul::from_char7(c)]))
}
pub const fn from_char8(c: char8) -> Result<Self, MismatchedCapacity> {
Ok(Self(unwrap![ok? StringNonul::from_char8(c)]))
}
pub const fn from_char16(c: char16) -> Result<Self, MismatchedCapacity> {
Ok(Self(unwrap![ok? StringNonul::from_char16(c)]))
}
#[doc = doclink!(devela "[`is_nul()`]" "text/trait.UnicodeScalar.html#method.is_nul")]
#[doc = doclink!(devela "[`len_utf8()`]" "text/trait.UnicodeScalar.html#method.len_utf8")]
pub const fn from_char(c: char) -> Result<Self, MismatchedCapacity> {
Ok(Self(unwrap![ok? StringNonul::from_char(c)]))
}
pub const fn from_charu(c: charu) -> Result<Self, MismatchedCapacity> {
Ok(Self(unwrap![ok? StringNonul::from_charu(c)]))
}
pub const fn from_charu_unchecked(c: charu) -> Self {
Self(StringNonul::from_charu_unchecked(c))
}
#[must_use] #[inline(always)]
pub const fn len(&self) -> usize { self.0.len() }
#[must_use] #[inline(always)]
pub const fn is_empty(&self) -> bool { self.0.len() == 0 }
#[must_use] #[inline(always)]
pub const fn capacity() -> usize { CAP }
#[must_use] #[inline(always)]
pub const fn remaining_capacity(&self) -> usize { CAP - self.len() }
#[must_use] #[inline(always)]
pub const fn is_full(&self) -> bool { self.len() == CAP }
#[inline(always)]
pub const fn clear(&mut self) { self.0.clear(); }
#[inline(always)]
pub const fn eq(self, other: &Self) -> bool { self.0.eq(&other.0) }
#[must_use] #[inline(always)]
pub const fn as_bytes(&self) -> &[u8] { self.0.as_bytes() }
#[must_use] #[inline(always)]
#[cfg(all(not(feature = "safe_text"), feature = "unsafe_str"))]
#[cfg_attr(nightly_doc, doc(cfg(feature = "unsafe_str")))]
pub const unsafe fn as_bytes_mut(&mut self) -> &mut [u8] {
unsafe { self.0.as_bytes_mut() }
}
#[must_use] #[inline(always)]
pub const fn as_array(&self) -> &[u8; CAP] { self.0.as_array() }
#[must_use] #[inline(always)]
pub const fn into_array(self) -> [u8; CAP] { self.0.into_array() }
#[must_use] #[inline(always)]
pub const fn as_str(&self) -> &str { self.0.as_str() }
#[inline(always)]
pub const fn as_string_nonul(&self) -> &StringNonul::<CAP> { &self.0 }
#[inline(always)]
pub const fn into_string_nonul(self) -> StringNonul::<CAP> { self.0 }
#[must_use] #[inline(always)]
#[cfg(all(not(feature = "safe_text"), feature = "unsafe_str"))]
#[cfg_attr(nightly_doc, doc(cfg(feature = "unsafe_str")))]
pub const unsafe fn as_mut_str(&mut self) -> &mut str {
unsafe { self.0.as_mut_str() }
}
#[inline(always)]
pub const fn chars(&self) -> CharIter<'_, &str> { self.0.chars() }
}
#[rustfmt::skip]
mod trait_impls {
use crate::{
ConstInit, Debug, Display, Formatter, FmtResult, GraphemeNonul, Hash, Hasher,
StringNonul,
};
impl<const CAP: usize> Default for GraphemeNonul<CAP> {
#[inline(always)]
fn default() -> Self { Self::new() }
}
impl<const CAP: usize> ConstInit for GraphemeNonul<CAP> {
const INIT: Self = Self::new();
}
impl<const CAP: usize> PartialEq for GraphemeNonul<CAP> {
fn eq(&self, other: &Self) -> bool { self.0.eq(&other.0) }
}
impl<const CAP: usize> PartialEq<StringNonul<CAP>> for GraphemeNonul<CAP> {
fn eq(&self, other: &StringNonul<CAP>) -> bool { self.0.eq(other) }
}
impl<const CAP: usize> PartialEq<GraphemeNonul<CAP>> for StringNonul<CAP> {
fn eq(&self, other: &GraphemeNonul<CAP>) -> bool { self.eq(&other.0) }
}
impl<const CAP: usize> Hash for GraphemeNonul<CAP> {
fn hash<H: Hasher>(&self, state: &mut H) { self.0.hash(state); }
}
impl<const CAP: usize> Display for GraphemeNonul<CAP> {
fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult<()> { write!(f, "{}", self.0) }
}
impl<const CAP: usize> Debug for GraphemeNonul<CAP> {
fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult<()> { write!(f, "{:?}", self.0) }
}
}