1#![allow(unused_variables)]
13#![allow(non_snake_case)]
14#![allow(non_camel_case_types)]
15#![allow(unused_parens)]
16#![allow(unused_assignments)]
17#![allow(unused_mut)]
18#![allow(unused_imports)]
19#![allow(dead_code)]
20
21#[cfg(not(feature = "no-alloc"))]
22extern crate alloc;
23
24#[cfg(feature = "std")]
25#[cfg(not(feature = "no-alloc"))]
26extern crate std;
27
28#[cfg(feature = "std")]
29#[cfg(not(feature = "no-alloc"))]
30use crate::fstr;
31
32use crate::zstr;
33use crate::{str12, str128, str16, str192, str24, str256, str32, str4, str48, str64, str8, str96};
34use core::cmp::{min, Ordering};
35use core::ops::{Add, Index, IndexMut, Range, RangeFrom, RangeFull, RangeTo};
36use core::ops::{RangeInclusive, RangeToInclusive};
37
38#[derive(Copy, Clone, Eq)]
60pub struct tstr<const N: usize = 256> {
61 chrs: [u8; N],
62} impl<const N: usize> tstr<N> {
64 pub fn make(s: &str) -> tstr<N> {
69 let mut chars = [0u8; N];
70 let bytes = s.as_bytes(); let blen = bytes.len();
72 let limit = min(N - 1, blen);
73 chars[1..limit + 1].copy_from_slice(&bytes[..limit]);
74 chars[0] = limit as u8;
75 tstr { chrs: chars }
79 } pub fn create(s: &str) -> tstr<N> {
83 let mut chars = [0u8; N];
84 let bytes = s.as_bytes();
85 let blen = bytes.len();
86 let limit = min(N - 1, blen);
87 chars[1..limit + 1].copy_from_slice(&bytes[..limit]);
88 chars[0] = limit as u8;
89 tstr { chrs: chars }
93 } pub fn try_make(s: &str) -> Result<tstr<N>, &str> {
98 if s.len() + 1 > N {
99 Err(s)
100 } else {
101 Ok(tstr::make(s))
102 }
103 }
104
105 pub const fn const_make(s: &str) -> tstr<N> {
110 let mut t = tstr::<N>::new();
111 let mut len = s.len();
112 if len > N - 1 {
113 len = N - 1;
114 } t.chrs[0] = len as u8;
116 let bytes = s.as_bytes();
117 let mut i = 0;
118 while i < len {
119 t.chrs[i + 1] = bytes[i];
120 i += 1;
121 }
122 t
123 } pub const fn const_try_make(s: &str) -> Option<tstr<N>> {
130 if N == 0 || N > 256 || s.len() + 1 > N {
131 None
132 } else {
133 Some(tstr::const_make(s))
134 }
135 }
136
137 #[inline]
140 pub const fn new() -> tstr<N> {
141 tstr { chrs: [0; N] }
142 }
143
144 #[inline]
147 pub const fn len(&self) -> usize {
148 self.chrs[0] as usize
149 }
150
151 pub fn charlen(&self) -> usize {
154 self.to_str().chars().count()
155 }
156
157 #[inline]
159 pub const fn capacity(&self) -> usize {
160 N - 1
161 }
162
163 #[cfg(not(feature = "no-alloc"))]
165 pub fn to_string(&self) -> alloc::string::String {
166 alloc::string::String::from(self.to_str())
167 }
168
169 pub fn as_bytes(&self) -> &[u8] {
171 &self.chrs[1..self.len() + 1]
172 }
173
174 pub fn as_bytes_mut(&mut self) -> &mut [u8] {
176 let n = self.len() + 1;
177 &mut self.chrs[1..n]
178 }
179
180 pub fn to_str(&self) -> &str {
182 unsafe { core::str::from_utf8_unchecked(&self.chrs[1..self.len() + 1]) }
183 }
184 pub fn as_str(&self) -> &str {
186 core::str::from_utf8(&self.chrs[1..self.len() + 1]).unwrap()
187 }
188 pub fn as_str_safe(&self) -> Result<&str, core::str::Utf8Error> {
190 core::str::from_utf8(&self.chrs[1..self.len() + 1])
191 }
192
193 pub fn set(&mut self, i: usize, c: char) -> bool {
198 let ref mut cbuf = [0u8; 4];
199 c.encode_utf8(cbuf);
200 let clen = c.len_utf8();
201 if let Some((bi, rc)) = self.to_str().char_indices().nth(i) {
202 if clen == rc.len_utf8() {
203 self.chrs[bi + 1..bi + clen + 1].copy_from_slice(&cbuf[..clen]);
204 return true;
206 }
207 }
208 return false;
209 } pub fn push<'t>(&mut self, s: &'t str) -> &'t str {
216 self.push_str(s)
217 } pub fn push_str<'t>(&mut self, src: &'t str) -> &'t str {
221 let srclen = src.len();
223 let slen = self.len();
224 let bytes = &src.as_bytes();
225 let length = core::cmp::min(slen + srclen, N - 1);
226 let remain = if N - 1 >= (slen + srclen) {
227 0
228 } else {
229 (srclen + slen) - N + 1
230 };
231 let mut i = 0;
232 while i < srclen && i + slen + 1 < N {
233 self.chrs[slen + i + 1] = bytes[i];
234 i += 1;
235 } self.chrs[0] += i as u8;
237 &src[srclen - remain..]
238 } pub fn push_char(&mut self, c: char) -> bool {
243 let clen = c.len_utf8();
244 let slen = self.len();
245 if slen + clen >= N {
246 return false;
247 }
248 let mut buf = [0u8; 4]; c.encode_utf8(&mut buf);
250 for i in 0..clen {
251 self.chrs[slen + i + 1] = buf[i];
252 }
253 self.chrs[0] = (slen + clen) as u8;
254 true
255 } pub fn pop_char(&mut self) -> Option<char> {
259 if self.len() == 0 {
260 return None;
261 }
262 let (ci, lastchar) = self.char_indices().last().unwrap();
263 self.chrs[0] = ci as u8;
264 Some(lastchar)
265 } pub fn nth(&self, n: usize) -> Option<char> {
269 self.to_str().chars().nth(n)
270 }
271
272 pub const fn nth_bytechar(&self, n: usize) -> char {
278 self.chrs[n + 1] as char
279 }
280
281 pub const fn nth_ascii(&self, n: usize) -> char {
283 self.chrs[n + 1] as char
284 }
285
286 pub fn is_ascii(&self) -> bool {
288 self.to_str().is_ascii()
289 }
290
291 pub fn truncate(&mut self, n: usize) {
296 if let Some((bi, c)) = self.to_str().char_indices().nth(n) {
297 self.chrs[0] = bi as u8;
298 }
299 }
300
301 pub fn truncate_bytes(&mut self, n: usize) {
304 if (n < self.chrs[0] as usize) {
305 assert!(self.is_char_boundary(n));
306 self.chrs[0] = n as u8;
307 }
308 }
309
310 pub fn right_ascii_trim(&mut self) {
314 let mut n = self.chrs[0] as usize;
315 while n > 0 && (self.chrs[n] as char).is_ascii_whitespace() {
316 n -= 1;
318 }
319 assert!(self.is_char_boundary(n));
320 self.chrs[0] = n as u8;
321 } pub fn clear(&mut self) {
325 self.chrs[0] = 0;
326 }
327
328 pub fn make_ascii_lowercase(&mut self) {
331 assert!(self.is_ascii());
332 let end = (self.chrs[0] as usize) + 1;
333 for b in &mut self.chrs[1..end] {
334 if *b >= 65 && *b <= 90 {
335 *b |= 32;
336 }
337 }
338 } pub fn make_ascii_uppercase(&mut self) {
343 assert!(self.is_ascii());
344 let end = (self.chrs[0] as usize) + 1;
345 for b in &mut self.chrs[1..end] {
346 if *b >= 97 && *b <= 122 {
347 *b -= 32;
348 }
349 }
350 }
351
352 pub fn to_ascii_upper(&self) -> Self {
356 let mut cp = self.clone();
357 cp.make_ascii_uppercase();
358 cp
359 }
360
361 pub fn to_ascii_lower(&self) -> Self {
365 let mut cp = *self;
366 cp.make_ascii_lowercase();
367 cp
368 }
369
370 pub fn case_insensitive_eq<TA>(&self, other: TA) -> bool
373 where
374 TA: AsRef<str>,
375 {
376 if self.len() != other.as_ref().len() {
377 return false;
378 }
379 let obytes = other.as_ref().as_bytes();
380 for i in 0..self.len() {
381 let mut c = self.chrs[i + 1];
382 if (c > 64 && c < 91) {
383 c = c | 32;
384 } let mut d = obytes[i];
386 if (d > 64 && d < 91) {
387 d = d | 32;
388 } if c != d {
390 return false;
391 }
392 } true
394 } pub fn from_utf16(v: &[u16]) -> Result<Self, Self> {
400 let mut s = Self::new();
401 for c in char::decode_utf16(v.iter().cloned()) {
402 if let Ok(c1) = c {
403 if !s.push_char(c1) {
404 return Err(s);
405 }
406 } else {
407 return Err(s);
408 }
409 }
410 Ok(s)
411 } } impl<const N: usize> core::ops::Deref for tstr<N> {
431 type Target = str;
432 fn deref(&self) -> &Self::Target {
433 self.to_str()
434 }
435}
436
437impl<const N: usize> core::convert::AsRef<str> for tstr<N> {
438 fn as_ref(&self) -> &str {
439 self.to_str()
440 }
441}
442impl<const N: usize> core::convert::AsMut<str> for tstr<N> {
443 fn as_mut(&mut self) -> &mut str {
444 let blen = self.len() + 1;
445 unsafe { core::str::from_utf8_unchecked_mut(&mut self.chrs[1..blen]) }
446 }
447}
448impl<T: AsRef<str> + ?Sized, const N: usize> core::convert::From<&T> for tstr<N> {
449 fn from(s: &T) -> tstr<N> {
450 tstr::make(s.as_ref())
451 }
452}
453impl<T: AsMut<str> + ?Sized, const N: usize> core::convert::From<&mut T> for tstr<N> {
454 fn from(s: &mut T) -> tstr<N> {
455 tstr::make(s.as_mut())
456 }
457}
458
459#[cfg(not(feature = "no-alloc"))]
460impl<const N: usize> core::convert::From<alloc::string::String> for tstr<N> {
461 fn from(s: alloc::string::String) -> tstr<N> {
462 tstr::<N>::make(&s[..])
463 }
464}
465
466#[cfg(feature = "std")]
467#[cfg(not(feature = "no-alloc"))]
468impl<const N: usize, const M: usize> std::convert::From<fstr<M>> for tstr<N> {
469 fn from(s: fstr<M>) -> tstr<N> {
470 tstr::<N>::make(s.to_str())
471 }
472}
473
474impl<const N: usize, const M: usize> core::convert::From<zstr<M>> for tstr<N> {
475 fn from(s: zstr<M>) -> tstr<N> {
476 tstr::<N>::make(s.to_str())
477 }
478}
479
480impl<const N: usize> core::cmp::PartialOrd for tstr<N> {
481 fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
482 Some(self.cmp(other))
483 }
484}
485
486impl<const N: usize> core::cmp::Ord for tstr<N> {
487 fn cmp(&self, other: &Self) -> Ordering {
488 self.chrs[1..self.len() + 1].cmp(&other.chrs[1..other.len() + 1])
489 }
490}
491
492impl<const M: usize> tstr<M> {
493 pub fn resize<const N: usize>(&self) -> tstr<N> {
502 let slen = self.len();
503 let length = if (slen < N - 1) { slen } else { N - 1 };
504 let mut chars = [0u8; N];
505 chars[1..length + 1].copy_from_slice(&self.chrs[1..length + 1]);
506 chars[0] = (length) as u8;
508 tstr { chrs: chars }
509 } pub fn reallocate<const N: usize>(&self) -> Option<tstr<N>> {
513 if self.len() < N {
514 Some(self.resize())
515 } else {
516 None
517 }
518 } } impl<const N: usize> core::fmt::Display for tstr<N> {
522 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
523 f.pad(self.to_str())
525 }
526}
527
528impl<const N: usize> PartialEq<&str> for tstr<N> {
529 fn eq(&self, other: &&str) -> bool {
530 self.to_str() == *other } }
533impl<const N: usize> PartialEq<&str> for &tstr<N> {
534 fn eq(&self, other: &&str) -> bool {
535 &self.to_str() == other
536 } }
538impl<'t, const N: usize> PartialEq<tstr<N>> for &'t str {
539 fn eq(&self, other: &tstr<N>) -> bool {
540 &other.to_str() == self
541 }
542}
543impl<'t, const N: usize> PartialEq<&tstr<N>> for &'t str {
544 fn eq(&self, other: &&tstr<N>) -> bool {
545 &other.to_str() == self
546 }
547}
548
549impl<const N: usize> Default for tstr<N> {
551 fn default() -> Self {
552 tstr::<N>::new()
553 }
554}
555#[cfg(feature = "std")]
556#[cfg(not(feature = "no-alloc"))]
557impl<const N: usize, const M: usize> PartialEq<tstr<N>> for fstr<M> {
558 fn eq(&self, other: &tstr<N>) -> bool {
559 other.to_str() == self.to_str()
560 }
561}
562#[cfg(feature = "std")]
563#[cfg(not(feature = "no-alloc"))]
564impl<const N: usize, const M: usize> PartialEq<fstr<N>> for tstr<M> {
565 fn eq(&self, other: &fstr<N>) -> bool {
566 other.to_str() == self.to_str()
567 }
568}
569
570impl<const N: usize, const M: usize> PartialEq<zstr<N>> for tstr<M> {
571 fn eq(&self, other: &zstr<N>) -> bool {
572 other.to_str() == self.to_str()
573 }
574}
575
576impl<const N: usize> core::fmt::Debug for tstr<N> {
577 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
578 f.pad(&self.to_str())
579 }
580} impl<const N: usize> tstr<N> {
596 pub fn substr(&self, start: usize, end: usize) -> tstr<N> {
599 let mut chars = [0u8; N];
600 let mut inds = self.char_indices();
601 let len = self.len();
602 if start >= len || end <= start {
603 return tstr { chrs: chars };
604 }
605 chars[0] = (end - start) as u8;
606 let (si, _) = inds.nth(start).unwrap();
607 let last = if (end >= len) {
608 len
609 } else {
610 match inds.nth(end - start - 1) {
611 Some((ei, _)) => ei,
612 None => len,
613 } }; chars[1..last - si + 1].copy_from_slice(&self.chrs[si + 1..last + 1]);
616 tstr { chrs: chars }
623 } }
625
626impl Add for str8 {
627 type Output = str16;
628 fn add(self, other: Self) -> Self::Output {
629 let mut cat: Self::Output = self.resize();
630 let slen = self.len();
631 let olen = other.len();
632 cat.chrs[slen + 1..slen + olen + 1].copy_from_slice(&other.chrs[1..olen + 1]);
633 cat.chrs[0] = (slen + olen) as u8;
634 cat
635 }
636} impl Add for str16 {
639 type Output = str32;
640 fn add(self, other: Self) -> Self::Output {
641 let mut cat: Self::Output = self.resize();
642 let slen = self.len();
643 let olen = other.len();
644 cat.chrs[slen + 1..slen + olen + 1].copy_from_slice(&other.chrs[1..olen + 1]);
645 cat.chrs[0] = (slen + olen) as u8;
646 cat
647 }
648} impl Add for str32 {
651 type Output = str64;
652 fn add(self, other: Self) -> Self::Output {
653 let mut cat: Self::Output = self.resize();
654 let slen = self.len();
655 let olen = other.len();
656 cat.chrs[slen + 1..slen + olen + 1].copy_from_slice(&other.chrs[1..olen + 1]);
657 cat.chrs[0] = (slen + olen) as u8;
658 cat
659 }
660} impl Add for str64 {
663 type Output = str128;
664 fn add(self, other: Self) -> Self::Output {
665 let mut cat: Self::Output = self.resize();
666 let slen = self.len();
667 let olen = other.len();
668 cat.chrs[slen + 1..slen + olen + 1].copy_from_slice(&other.chrs[1..olen + 1]);
669 cat.chrs[0] = (slen + olen) as u8;
670 cat
671 }
672} impl Add for str128 {
675 type Output = str256;
676 fn add(self, other: Self) -> Self::Output {
677 let mut cat: Self::Output = self.resize();
678 let slen = self.len();
679 let olen = other.len();
680 cat.chrs[slen + 1..slen + olen + 1].copy_from_slice(&other.chrs[1..olen + 1]);
681 cat.chrs[0] = (slen + olen) as u8;
682 cat
683 }
684} impl Add for str4 {
687 type Output = str8;
688 fn add(self, other: Self) -> Self::Output {
689 let mut cat: Self::Output = self.resize();
690 let slen = self.len();
691 let olen = other.len();
692 cat.chrs[slen + 1..slen + olen + 1].copy_from_slice(&other.chrs[1..olen + 1]);
693 cat.chrs[0] = (slen + olen) as u8;
694 cat
695 }
696} impl Add for str12 {
699 type Output = str24;
700 fn add(self, other: Self) -> Self::Output {
701 let mut cat: Self::Output = self.resize();
702 let slen = self.len();
703 let olen = other.len();
704 cat.chrs[slen + 1..slen + olen + 1].copy_from_slice(&other.chrs[1..olen + 1]);
705 cat.chrs[0] = (slen + olen) as u8;
706 cat
707 }
708} impl Add for str24 {
711 type Output = str48;
712 fn add(self, other: Self) -> Self::Output {
713 let mut cat: Self::Output = self.resize();
714 let slen = self.len();
715 let olen = other.len();
716 cat.chrs[slen + 1..slen + olen + 1].copy_from_slice(&other.chrs[1..olen + 1]);
717 cat.chrs[0] = (slen + olen) as u8;
718 cat
719 }
720} impl Add for str48 {
723 type Output = str96;
724 fn add(self, other: Self) -> Self::Output {
725 let mut cat: Self::Output = self.resize();
726 let slen = self.len();
727 let olen = other.len();
728 cat.chrs[slen + 1..slen + olen + 1].copy_from_slice(&other.chrs[1..olen + 1]);
729 cat.chrs[0] = (slen + olen) as u8;
730 cat
731 }
732} impl Add for str96 {
735 type Output = str192;
736 fn add(self, other: Self) -> Self::Output {
737 let mut cat: Self::Output = self.resize();
738 let slen = self.len();
739 let olen = other.len();
740 cat.chrs[slen + 1..slen + olen + 1].copy_from_slice(&other.chrs[1..olen + 1]);
741 cat.chrs[0] = (slen + olen) as u8;
742 cat
743 }
744} impl<const N: usize> Add<&str> for tstr<N> {
758 type Output = tstr<N>;
759 fn add(self, other: &str) -> tstr<N> {
760 let mut a2 = self;
761 a2.push(other);
762 a2
763 }
764} impl<const N: usize> Add<&tstr<N>> for &str {
767 type Output = tstr<N>;
768 fn add(self, other: &tstr<N>) -> tstr<N> {
769 let mut a2 = tstr::from(self);
770 a2.push(other);
771 a2
772 }
773} impl<const N: usize> Add<tstr<N>> for &str {
776 type Output = tstr<N>;
777 fn add(self, other: tstr<N>) -> tstr<N> {
778 let mut a2 = tstr::from(self);
779 a2.push(&other);
780 a2
781 }
782} impl<const N: usize> core::fmt::Write for tstr<N> {
795 fn write_str(&mut self, s: &str) -> core::fmt::Result {
796 if s.len() + self.len() + 1 > N {
797 return Err(core::fmt::Error::default());
798 }
799 self.push(s);
800 Ok(())
801 } } impl<const N: usize> core::hash::Hash for tstr<N> {
805 fn hash<H: core::hash::Hasher>(&self, state: &mut H) {
806 self.as_ref().hash(state);
807 }
808} impl<const N: usize> core::cmp::PartialEq for tstr<N> {
811 fn eq(&self, other: &Self) -> bool {
812 self.as_ref() == other.as_ref()
813 }
814}
815
816impl<const N: usize> core::str::FromStr for tstr<N> {
817 type Err = &'static str;
818 fn from_str(s: &str) -> Result<Self, Self::Err> {
819 if N < 257 && s.len() < N {
820 Ok(tstr::from(s))
821 } else {
822 Err("Parse Error: capacity exceeded")
823 }
824 }
825}
826
827#[cfg(feature = "pub-tstr")]
836pub const fn tstr_limit(n: usize) -> usize {
837 if n == 0 {
838 1
839 } else if n > 256 {
840 256
841 } else {
842 n
843 }
844}