use crate::{
error::{TextosError as Error, TextosResult as Result},
macros::impl_sized_alias,
unicode::{
char::*,
egc::Egcs,
string::{StaticNonNulString, Strings},
},
};
#[cfg(feature = "alloc")]
use alloc::{ffi::CString, str::Chars};
use core::fmt;
use devela::codegen::paste;
#[derive(Clone, PartialEq, Eq, Hash, PartialOrd, Ord)]
#[repr(transparent)]
pub struct StaticNonNulEgc<const CAP: usize>(StaticNonNulString<CAP>);
impl_sized_alias![
NonNulEgc, StaticNonNulEgc,
"<abbr title='Extended Grapheme Cluster'>EGC</abbr>, with fixed capacity of ",
", no nul chars.":
"An" 8, 1 "";
"A" 16, 2 "s";
"A" 24, 3 "s";
"A" 32, 4 "s";
"A" 40, 5 "s";
"A" 48, 6 "s";
"A" 56, 7 "s";
"A" 64, 8 "s";
"A" 128, 16 "s"
];
impl<const CAP: usize> StaticNonNulEgc<CAP> {
#[inline]
pub const fn new() -> Self {
Self(StaticNonNulString::new())
}
#[inline]
#[must_use]
pub const fn from_char7(c: Char7) -> Self {
Self(StaticNonNulString::from_char7(c))
}
#[inline]
#[must_use]
pub const fn from_char8(c: Char8) -> Self {
Self(StaticNonNulString::from_char8(c))
}
#[inline]
#[must_use]
pub const fn from_char16(c: Char16) -> Self {
Self(StaticNonNulString::from_char16(c))
}
#[inline]
#[must_use]
pub const fn from_char24(c: Char24) -> Self {
Self(StaticNonNulString::from_char24(c))
}
#[inline]
#[must_use]
pub const fn from_char32(c: Char32) -> Self {
Self(StaticNonNulString::from_char32(c))
}
#[inline]
#[must_use]
pub const fn from_char(c: char) -> Self {
Self::from_char32(Char32(c))
}
pub fn len(&self) -> usize {
self.0.len()
}
pub fn is_empty(&self) -> bool {
self.0.len() == 0
}
#[inline]
pub const fn capacity() -> usize {
CAP
}
#[inline]
pub fn remaining_capacity(&self) -> usize {
CAP - self.len()
}
#[inline]
pub fn is_full(&self) -> bool {
self.len() == CAP
}
#[inline]
pub fn clear(&mut self) {
self.0.clear();
}
#[inline]
pub fn as_bytes(&self) -> &[u8] {
self.0.as_bytes()
}
#[inline]
#[cfg(feature = "unsafe")]
#[cfg_attr(feature = "nightly", doc(cfg(feature = "unsafe")))]
pub unsafe fn as_bytes_mut(&mut self) -> &mut [u8] {
self.0.as_bytes_mut()
}
#[inline]
pub fn as_array(&self) -> [u8; CAP] {
self.0.as_array()
}
#[inline]
pub fn into_array(self) -> [u8; CAP] {
self.0.into_array()
}
#[inline]
pub fn as_str(&self) -> &str {
self.0.as_str()
}
#[cfg(feature = "unsafe")]
#[cfg_attr(feature = "nightly", doc(cfg(feature = "unsafe")))]
pub unsafe fn as_str_mut(&mut self) -> &mut str {
self.0.as_str_mut()
}
#[cfg(feature = "alloc")]
#[cfg_attr(feature = "nightly", doc(cfg(feature = "alloc")))]
pub fn chars(&self) -> Chars {
self.0.chars()
}
#[inline]
#[cfg(feature = "alloc")]
#[cfg_attr(feature = "nightly", doc(cfg(feature = "alloc")))]
pub fn to_cstring(&self) -> CString {
self.0.to_cstring()
}
}
impl<const CAP: usize> Strings for StaticNonNulEgc<CAP> {}
impl<const CAP: usize> Egcs for StaticNonNulEgc<CAP> {}
mod core_impls {
use super::*;
impl<const CAP: usize> Default for StaticNonNulEgc<CAP> {
#[inline]
fn default() -> Self {
Self::new()
}
}
impl<const CAP: usize> fmt::Display for StaticNonNulEgc<CAP> {
#[inline]
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{}", self.0)
}
}
impl<const CAP: usize> fmt::Debug for StaticNonNulEgc<CAP> {
#[inline]
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{:?}", self.0)
}
}
}
macro_rules! impl_from_char {
( $char:ty => $for_name:ident: $( $for_bit:expr ),+ ) => {
$( impl_from_char![@$char => $for_name: $for_bit]; )+
};
( @$char:ty => $for_name:ident: $for_bit:expr ) => { paste! {
impl From<$char> for [< $for_name $for_bit >] {
fn from(c: $char) -> [< $for_name $for_bit >] {
let mut s = Self::new();
let _ = s.0.push(c.into());
s
}
}
}};
( try $char:ty => $for_name:ident: $( $for_bit:expr ),+ ) => {
$( impl_from_char![@try $char => $for_name: $for_bit]; )+
};
( @try $char:ty => $for_name:ident: $for_bit:expr ) => { paste! {
impl TryFrom<$char> for [< $for_name $for_bit >] {
type Error = Error;
fn try_from(c: $char) -> Result<[< $for_name $for_bit >]> {
let mut s = Self::new();
s.0.try_push(c.into())?;
Ok(s)
}
}
}};
}
impl_from_char![Char7 => NonNulEgc: 8, 16, 24, 32, 40, 48, 56, 64, 128];
impl_from_char![Char8 => NonNulEgc: 16, 24, 32, 40, 48, 56, 64, 128];
impl_from_char![try Char8 => NonNulEgc: 8];
impl_from_char![Char16 => NonNulEgc: 24, 32, 40, 48, 56, 64, 128];
impl_from_char![try Char16 => NonNulEgc: 8, 16];
impl_from_char![Char24 => NonNulEgc: 32, 40, 48, 56, 64, 128];
impl_from_char![try Char24 => NonNulEgc: 8, 16, 24];
impl_from_char![Char32 => NonNulEgc: 32, 40, 48, 56, 64, 128];
impl_from_char![try Char32 => NonNulEgc: 8, 16, 24];
impl_from_char![char => NonNulEgc: 32, 40, 48, 56, 64, 128];
impl_from_char![try char => NonNulEgc: 8, 16, 24];