textos/unicode/egc/
u8string.rs1use crate::{
11 error::{TextosError as Error, TextosResult as Result},
12 macros::impl_sized_alias,
13 unicode::{
14 char::*,
15 egc::Egcs,
16 string::{StaticU8String, Strings},
17 },
18};
19#[cfg(feature = "alloc")]
20use alloc::{ffi::CString, str::Chars};
21use core::fmt;
22use devela::codegen::paste;
23#[derive(Clone, PartialEq, Eq, Hash)]
30#[repr(transparent)]
31pub struct StaticU8Egc<const CAP: usize>(StaticU8String<CAP>);
32
33impl_sized_alias![
34 Egc, StaticU8Egc,
35 "<abbr title='Extended Grapheme Cluster'>EGC</abbr>, with fixed capacity of ",
36 ".":
37 "A" 16, 1 "";
38 "A" 24, 2 "s";
39 "A" 32, 3 "s";
40 "A" 40, 4 "s";
41 "A" 48, 5 "s";
42 "A" 56, 6 "s";
43 "A" 64, 7 "s";
44 "A" 128, 15 "s"
45];
46
47impl<const CAP: usize> StaticU8Egc<CAP> {
48 #[inline]
53 #[must_use]
54 pub const fn new() -> Self {
55 Self(StaticU8String::new())
56 }
57
58 #[inline]
65 #[must_use]
66 pub const fn from_char7(c: Char7) -> Self {
67 Self(StaticU8String::from_char7(c))
68 }
69
70 #[inline]
77 #[must_use]
78 pub const fn from_char8(c: Char8) -> Self {
79 Self(StaticU8String::from_char8(c))
80 }
81
82 #[inline]
89 #[must_use]
90 pub const fn from_char16(c: Char16) -> Self {
91 Self(StaticU8String::from_char16(c))
92 }
93
94 #[inline]
101 #[must_use]
102 pub const fn from_char24(c: Char24) -> Self {
103 Self(StaticU8String::from_char24(c))
104 }
105
106 #[inline]
113 #[must_use]
114 pub const fn from_char32(c: Char32) -> Self {
115 Self(StaticU8String::from_char32(c))
116 }
117
118 #[inline]
125 #[must_use]
126 pub const fn from_char(c: char) -> Self {
127 Self::from_char32(Char32(c))
128 }
129
130 pub const fn len(&self) -> usize {
134 self.0.len()
135 }
136
137 pub const fn is_empty(&self) -> bool {
139 self.0.len() == 0
140 }
141
142 #[inline]
144 pub const fn capacity() -> usize {
145 CAP
146 }
147
148 #[inline]
150 pub const fn remaining_capacity(&self) -> usize {
151 CAP - self.len()
152 }
153
154 #[inline]
156 pub const fn is_full(&self) -> bool {
157 self.len() == CAP
158 }
159
160 #[inline]
162 pub fn clear(&mut self) {
163 self.0.clear();
164 }
165
166 #[inline]
170 pub fn as_bytes(&self) -> &[u8] {
171 self.0.as_bytes()
172 }
173
174 #[inline]
176 #[cfg(feature = "unsafe")]
177 #[cfg_attr(feature = "nightly", doc(cfg(feature = "unsafe")))]
178 pub unsafe fn as_bytes_mut(&mut self) -> &mut [u8] {
179 self.0.as_bytes_mut()
180 }
181
182 #[inline]
186 pub const fn as_array(&self) -> [u8; CAP] {
187 self.0.as_array()
188 }
189
190 #[inline]
194 pub const fn into_array(self) -> [u8; CAP] {
195 self.0.into_array()
196 }
197
198 #[inline]
200 pub fn as_str(&self) -> &str {
201 self.0.as_str()
202 }
203
204 #[cfg(feature = "unsafe")]
206 #[cfg_attr(feature = "nightly", doc(cfg(feature = "unsafe")))]
207 pub unsafe fn as_str_mut(&mut self) -> &mut str {
208 self.0.as_str_mut()
209 }
210
211 #[cfg(feature = "alloc")]
213 #[cfg_attr(feature = "nightly", doc(cfg(feature = "alloc")))]
214 pub fn chars(&self) -> Chars {
215 self.0.chars()
216 }
217
218 #[inline]
220 #[cfg(feature = "alloc")]
221 #[cfg_attr(feature = "nightly", doc(cfg(feature = "alloc")))]
222 pub fn to_cstring(&self) -> CString {
223 self.0.to_cstring()
224 }
225}
226
227impl<const CAP: usize> Strings for StaticU8Egc<CAP> {}
230impl<const CAP: usize> Egcs for StaticU8Egc<CAP> {}
231
232mod core_impls {
233 use super::*;
234
235 impl<const CAP: usize> Default for StaticU8Egc<CAP> {
236 #[inline]
238 fn default() -> Self {
239 Self::new()
240 }
241 }
242
243 impl<const CAP: usize> fmt::Display for StaticU8Egc<CAP> {
244 #[inline]
245 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
246 write!(f, "{}", self.0)
247 }
248 }
249 impl<const CAP: usize> fmt::Debug for StaticU8Egc<CAP> {
250 #[inline]
251 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
252 write!(f, "{:?}", self.0)
253 }
254 }
255
256 }
272
273macro_rules! impl_from_char {
274 ( $char:ty => $for_name:ident: $( $for_bit:expr ),+ ) => {
278 $( impl_from_char![@$char => $for_name: $for_bit]; )+
279 };
280 ( @$char:ty => $for_name:ident: $for_bit:expr ) => { paste! {
281 impl From<$char> for [< $for_name $for_bit >] {
282 fn from(c: $char) -> [< $for_name $for_bit >] {
283 let mut s = Self::default();
284 let _ = s.0.push(c.into());
285 s
286 }
287 }
288 }};
289 ( try $char:ty => $for_name:ident: $( $for_bit:expr ),+ ) => {
290 $( impl_from_char![@try $char => $for_name: $for_bit]; )+
291 };
292 ( @try $char:ty => $for_name:ident: $for_bit:expr ) => { paste! {
293 impl TryFrom<$char> for [< $for_name $for_bit >] {
294 type Error = Error;
295 fn try_from(c: $char) -> Result<[< $for_name $for_bit >]> {
296 let mut s = Self::default();
297 s.0.try_push(c.into())?;
298 Ok(s)
299 }
300 }
301 }};
302}
303impl_from_char![Char7 => Egc: 16, 24, 32, 40, 48, 56, 64, 128];
304impl_from_char![Char8 => Egc: 24, 32, 40, 48, 56, 64, 128];
305impl_from_char![try Char8 => Egc: 16];
306impl_from_char![Char16 => Egc: 32, 40, 48, 56, 64, 128];
307impl_from_char![try Char16 => Egc: 16, 24];
308impl_from_char![Char24 => Egc: 40, 48, 56, 64, 128];
309impl_from_char![try Char24 => Egc: 16, 24, 32];
310impl_from_char![Char32 => Egc: 40, 48, 56, 64, 128];
311impl_from_char![try Char32 => Egc: 16, 24, 32];
312impl_from_char![char => Egc: 40, 48, 56, 64, 128];
313impl_from_char![try char => Egc: 16, 24, 32];