fixedstr/
tiny_internal.rs1#![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 if chars[0] == 0 {
83 chars[0] = blen as u8;
84 }
85 tstr { chrs: chars }
86 } pub fn create(s: &str) -> tstr<N> {
90 let mut chars = [0u8; N];
91 let bytes = s.as_bytes();
92 let blen = bytes.len();
93 let limit = min(N - 1, blen);
94 chars[1..limit + 1].copy_from_slice(&bytes[..limit]);
95 chars[0] = limit as u8;
96 if chars[0] == 0 {
97 chars[0] = blen as u8;
98 }
99 tstr { chrs: chars }
100 } pub fn try_make(s: &str) -> Result<tstr<N>, &str> {
105 if s.len() > N - 1 {
106 Err(s)
107 } else {
108 Ok(tstr::make(s))
109 }
110 }
111
112pub const fn const_make(s:&str) -> tstr<N> {
117 let mut t = tstr::<N>::new();
118 let mut len = s.len();
119 if len>N-1 { len = N-1; } t.chrs[0] = len as u8;
121 let bytes = s.as_bytes();
122 let mut i = 0;
123 while i<len {
124 t.chrs[i+1] = bytes[i];
125 i += 1;
126 }
127 t
128 }pub const fn const_try_make(s:&str) -> Option<tstr<N>> {
132 if s.len()+1>N {None}
133 else { Some(tstr::const_make(s)) }
134 }
135
136 #[inline]
139 pub const fn new() -> tstr<N> {
140 tstr {
141 chrs : [0;N]
142 }
143 }
144
145 #[inline]
148 pub const fn len(&self) -> usize {
149 self.chrs[0] as usize
150 }
151
152 pub fn charlen(&self) -> usize {
155 self.to_str().chars().count()
156 }
157
158 #[inline]
160 pub fn capacity(&self) -> usize {
161 N - 1
162 }
163
164 #[cfg(not(feature = "no-alloc"))]
166 pub fn to_string(&self) -> alloc::string::String {
167 alloc::string::String::from(self.as_str())
168 }
169
170 pub fn as_bytes(&self) -> &[u8] {
172 &self.chrs[1..self.len() + 1]
173 }
174
175 pub fn to_str(&self) -> &str {
177 unsafe { core::str::from_utf8_unchecked(&self.chrs[1..self.len() + 1]) }
178 }
179 pub fn as_str(&self) -> &str {
181 core::str::from_utf8(&self.chrs[1..self.len() + 1]).unwrap()
182 }
183
184 pub fn set(&mut self, i: usize, c: char) -> bool {
189 let ref mut cbuf = [0u8; 4];
190 c.encode_utf8(cbuf);
191 let clen = c.len_utf8();
192 if let Some((bi, rc)) = self.to_str().char_indices().nth(i) {
193 if clen == rc.len_utf8() {
194 self.chrs[bi + 1..bi + clen + 1].copy_from_slice(&cbuf[..clen]);
195 return true;
197 }
198 }
199 return false;
200 } pub fn push<'t>(&mut self, s: &'t str) -> &'t str {
206 self.push_str(s)
231 } pub fn push_str<'t>(&mut self, src: &'t str) -> &'t str {
235 let srclen = src.len();
237 let slen = self.len();
238 let bytes = &src.as_bytes();
239 let length = core::cmp::min(slen + srclen, N - 1);
240 let remain = if N - 1 >= (slen + srclen) {
241 0
242 } else {
243 (srclen + slen) - N + 1
244 };
245 let mut i = 0;
246 while i < srclen && i + slen + 1 < N {
247 self.chrs[slen + i + 1] = bytes[i];
248 i += 1;
249 } self.chrs[0] += i as u8;
251 &src[srclen - remain..]
252 } pub fn push_char(&mut self, c: char) -> bool {
257 let clen = c.len_utf8();
258 let slen = self.len();
259 if slen + clen >= N {
260 return false;
261 }
262 let mut buf = [0u8; 4]; c.encode_utf8(&mut buf);
264 for i in 0..clen {
265 self.chrs[slen + i + 1] = buf[i];
266 }
267 self.chrs[0] = (slen + clen) as u8;
268 true
269 } pub fn pop_char(&mut self) -> Option<char> {
273 if self.len() == 0 {
274 return None;
275 }
276 let (ci, lastchar) = self.char_indices().last().unwrap();
277 self.chrs[0] = ci as u8;
278 Some(lastchar)
279 } pub fn nth(&self, n: usize) -> Option<char> {
283 self.to_str().chars().nth(n)
284 }
285
286 pub fn nth_bytechar(&self, n: usize) -> char {
292 self.chrs[n + 1] as char
293 }
294
295 pub fn nth_ascii(&self, n: usize) -> char {
297 self.chrs[n + 1] as char
298 }
299
300 pub fn is_ascii(&self) -> bool {
302 self.to_str().is_ascii()
303 }
304
305 pub fn truncate(&mut self, n: usize) {
310 if let Some((bi, c)) = self.to_str().char_indices().nth(n) {
311 self.chrs[0] = bi as u8;
312 }
313 }
314
315 pub fn truncate_bytes(&mut self, n: usize) {
318 if (n < self.chrs[0] as usize) {
319 assert!(self.is_char_boundary(n));
320 self.chrs[0] = n as u8;
321 }
322 }
323
324 pub fn right_ascii_trim(&mut self) {
328 let mut n = self.chrs[0] as usize;
329 while n > 0 && (self.chrs[n] as char).is_ascii_whitespace() {
330 n -= 1;
332 }
333 assert!(self.is_char_boundary(n));
334 self.chrs[0] = n as u8;
335 } pub fn clear(&mut self) {
339 self.chrs[0] = 0;
340 }
341
342 pub fn make_ascii_lowercase(&mut self) {
345 assert!(self.is_ascii());
346 let end = (self.chrs[0] as usize) + 1;
347 for b in &mut self.chrs[1..end] {
348 if *b >= 65 && *b <= 90 {
349 *b |= 32;
350 }
351 }
352 } pub fn make_ascii_uppercase(&mut self) {
357 assert!(self.is_ascii());
358 let end = (self.chrs[0] as usize) + 1;
359 for b in &mut self.chrs[1..end] {
360 if *b >= 97 && *b <= 122 {
361 *b -= 32;
362 }
363 }
364 }
365
366 pub fn to_ascii_upper(&self) -> Self {
370 let mut cp = self.clone();
371 cp.make_ascii_uppercase();
372 cp
373 }
374
375 pub fn to_ascii_lower(&self) -> Self {
379 let mut cp = *self;
380 cp.make_ascii_lowercase();
381 cp
382 }
383
384 pub fn case_insensitive_eq<TA>(&self, other: TA) -> bool
387 where
388 TA: AsRef<str>,
389 {
390 if self.len() != other.as_ref().len() {
391 return false;
392 }
393 let obytes = other.as_ref().as_bytes();
394 for i in 0..self.len() {
395 let mut c = self.chrs[i + 1];
396 if (c > 64 && c < 91) {
397 c = c | 32;
398 } let mut d = obytes[i];
400 if (d > 64 && d < 91) {
401 d = d | 32;
402 } if c != d {
404 return false;
405 }
406 } true
408 } pub fn from_utf16(v: &[u16]) -> Result<Self, Self> {
414 let mut s = Self::new();
415 for c in char::decode_utf16(v.iter().cloned()) {
416 if let Ok(c1) = c {
417 if !s.push_char(c1) {
418 return Err(s);
419 }
420 } else {
421 return Err(s);
422 }
423 }
424 Ok(s)
425 } } impl<const N: usize> core::ops::Deref for tstr<N> {
430 type Target = str;
431 fn deref(&self) -> &Self::Target {
432 self.to_str()
433 }
434}
435
436impl<const N: usize> core::convert::AsRef<str> for tstr<N> {
437 fn as_ref(&self) -> &str {
438 self.to_str()
439 }
440}
441impl<const N: usize> core::convert::AsMut<str> for tstr<N> {
442 fn as_mut(&mut self) -> &mut str {
443 let blen = self.len() + 1;
444 unsafe { core::str::from_utf8_unchecked_mut(&mut self.chrs[1..blen]) }
445 }
446}
447impl<T: AsRef<str> + ?Sized, const N: usize> core::convert::From<&T> for tstr<N> {
448 fn from(s: &T) -> tstr<N> {
449 tstr::make(s.as_ref())
450 }
451}
452impl<T: AsMut<str> + ?Sized, const N: usize> core::convert::From<&mut T> for tstr<N> {
453 fn from(s: &mut T) -> tstr<N> {
454 tstr::make(s.as_mut())
455 }
456}
457
458#[cfg(not(feature = "no-alloc"))]
459impl<const N: usize> core::convert::From<alloc::string::String> for tstr<N> {
460 fn from(s: alloc::string::String) -> tstr<N> {
461 tstr::<N>::make(&s[..])
462 }
463}
464
465#[cfg(feature = "std")]
466#[cfg(not(feature = "no-alloc"))]
467impl<const N: usize, const M: usize> std::convert::From<fstr<M>> for tstr<N> {
468 fn from(s: fstr<M>) -> tstr<N> {
469 tstr::<N>::make(s.to_str())
470 }
471}
472
473impl<const N: usize, const M: usize> core::convert::From<zstr<M>> for tstr<N> {
474 fn from(s: zstr<M>) -> tstr<N> {
475 tstr::<N>::make(s.to_str())
476 }
477}
478
479impl<const N: usize> core::cmp::PartialOrd for tstr<N> {
480 fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
481 Some(self.cmp(other))
482 }
483}
484
485impl<const N: usize> core::cmp::Ord for tstr<N> {
486 fn cmp(&self, other: &Self) -> Ordering {
487 self.chrs[1..self.len() + 1].cmp(&other.chrs[1..other.len() + 1])
488 }
489}
490
491impl<const M: usize> tstr<M> {
492 pub fn resize<const N: usize>(&self) -> tstr<N> {
501 let slen = self.len();
502 let length = if (slen < N - 1) { slen } else { N - 1 };
503 let mut chars = [0u8; N];
504 chars[1..length + 1].copy_from_slice(&self.chrs[1..length + 1]);
505 chars[0] = (length) as u8;
507 tstr { chrs: chars }
508 } pub fn reallocate<const N: usize>(&self) -> Option<tstr<N>> {
512 if self.len() < N {
513 Some(self.resize())
514 } else {
515 None
516 }
517 } } impl<const N: usize> core::fmt::Display for tstr<N> {
521 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
522 f.pad(self.to_str())
524 }
525}
526
527impl<const N: usize> PartialEq<&str> for tstr<N> {
528 fn eq(&self, other: &&str) -> bool {
529 self.to_str() == *other } }
532impl<const N: usize> PartialEq<&str> for &tstr<N> {
533 fn eq(&self, other: &&str) -> bool {
534 &self.to_str() == other
535 } }
537impl<'t, const N: usize> PartialEq<tstr<N>> for &'t str {
538 fn eq(&self, other: &tstr<N>) -> bool {
539 &other.to_str() == self
540 }
541}
542impl<'t, const N: usize> PartialEq<&tstr<N>> for &'t str {
543 fn eq(&self, other: &&tstr<N>) -> bool {
544 &other.to_str() == self
545 }
546}
547
548impl<const N: usize> Default for tstr<N> {
550 fn default() -> Self {
551 tstr::<N>::new()
552 }
553}
554#[cfg(feature = "std")]
555#[cfg(not(feature = "no-alloc"))]
556impl<const N: usize, const M: usize> PartialEq<tstr<N>> for fstr<M> {
557 fn eq(&self, other: &tstr<N>) -> bool {
558 other.to_str() == self.to_str()
559 }
560}
561#[cfg(feature = "std")]
562#[cfg(not(feature = "no-alloc"))]
563impl<const N: usize, const M: usize> PartialEq<fstr<N>> for tstr<M> {
564 fn eq(&self, other: &fstr<N>) -> bool {
565 other.to_str() == self.to_str()
566 }
567}
568
569impl<const N: usize, const M: usize> PartialEq<zstr<N>> for tstr<M> {
570 fn eq(&self, other: &zstr<N>) -> bool {
571 other.to_str() == self.to_str()
572 }
573}
574
575impl<const N: usize> core::fmt::Debug for tstr<N> {
576 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
577 f.pad(&self.to_str())
578 }
579} impl<const N: usize> tstr<N> {
595 pub fn substr(&self, start: usize, end: usize) -> tstr<N> {
598 let mut chars = [0u8; N];
599 let mut inds = self.char_indices();
600 let len = self.len();
601 if start >= len || end <= start {
602 return tstr { chrs: chars };
603 }
604 chars[0] = (end - start) as u8;
605 let (si, _) = inds.nth(start).unwrap();
606 let last = if (end >= len) {
607 len
608 } else {
609 match inds.nth(end - start - 1) {
610 Some((ei, _)) => ei,
611 None => len,
612 } }; chars[1..last - si + 1].copy_from_slice(&self.chrs[si + 1..last + 1]);
615 tstr { chrs: chars }
622 } }
624
625impl Add for str8 {
626 type Output = str16;
627 fn add(self, other: Self) -> Self::Output {
628 let mut cat: Self::Output = self.resize();
629 let slen = self.len();
630 let olen = other.len();
631 cat.chrs[slen + 1..slen + olen + 1].copy_from_slice(&other.chrs[1..olen + 1]);
632 cat.chrs[0] = (slen + olen) as u8;
633 cat
634 }
635} impl Add for str16 {
638 type Output = str32;
639 fn add(self, other: Self) -> Self::Output {
640 let mut cat: Self::Output = self.resize();
641 let slen = self.len();
642 let olen = other.len();
643 cat.chrs[slen + 1..slen + olen + 1].copy_from_slice(&other.chrs[1..olen + 1]);
644 cat.chrs[0] = (slen + olen) as u8;
645 cat
646 }
647} impl Add for str32 {
650 type Output = str64;
651 fn add(self, other: Self) -> Self::Output {
652 let mut cat: Self::Output = self.resize();
653 let slen = self.len();
654 let olen = other.len();
655 cat.chrs[slen + 1..slen + olen + 1].copy_from_slice(&other.chrs[1..olen + 1]);
656 cat.chrs[0] = (slen + olen) as u8;
657 cat
658 }
659} impl Add for str64 {
662 type Output = str128;
663 fn add(self, other: Self) -> Self::Output {
664 let mut cat: Self::Output = self.resize();
665 let slen = self.len();
666 let olen = other.len();
667 cat.chrs[slen + 1..slen + olen + 1].copy_from_slice(&other.chrs[1..olen + 1]);
668 cat.chrs[0] = (slen + olen) as u8;
669 cat
670 }
671} impl Add for str128 {
674 type Output = str256;
675 fn add(self, other: Self) -> Self::Output {
676 let mut cat: Self::Output = self.resize();
677 let slen = self.len();
678 let olen = other.len();
679 cat.chrs[slen + 1..slen + olen + 1].copy_from_slice(&other.chrs[1..olen + 1]);
680 cat.chrs[0] = (slen + olen) as u8;
681 cat
682 }
683} impl Add for str4 {
686 type Output = str8;
687 fn add(self, other: Self) -> Self::Output {
688 let mut cat: Self::Output = self.resize();
689 let slen = self.len();
690 let olen = other.len();
691 cat.chrs[slen + 1..slen + olen + 1].copy_from_slice(&other.chrs[1..olen + 1]);
692 cat.chrs[0] = (slen + olen) as u8;
693 cat
694 }
695} impl Add for str12 {
698 type Output = str24;
699 fn add(self, other: Self) -> Self::Output {
700 let mut cat: Self::Output = self.resize();
701 let slen = self.len();
702 let olen = other.len();
703 cat.chrs[slen + 1..slen + olen + 1].copy_from_slice(&other.chrs[1..olen + 1]);
704 cat.chrs[0] = (slen + olen) as u8;
705 cat
706 }
707} impl Add for str24 {
710 type Output = str48;
711 fn add(self, other: Self) -> Self::Output {
712 let mut cat: Self::Output = self.resize();
713 let slen = self.len();
714 let olen = other.len();
715 cat.chrs[slen + 1..slen + olen + 1].copy_from_slice(&other.chrs[1..olen + 1]);
716 cat.chrs[0] = (slen + olen) as u8;
717 cat
718 }
719} impl Add for str48 {
722 type Output = str96;
723 fn add(self, other: Self) -> Self::Output {
724 let mut cat: Self::Output = self.resize();
725 let slen = self.len();
726 let olen = other.len();
727 cat.chrs[slen + 1..slen + olen + 1].copy_from_slice(&other.chrs[1..olen + 1]);
728 cat.chrs[0] = (slen + olen) as u8;
729 cat
730 }
731} impl Add for str96 {
734 type Output = str192;
735 fn add(self, other: Self) -> Self::Output {
736 let mut cat: Self::Output = self.resize();
737 let slen = self.len();
738 let olen = other.len();
739 cat.chrs[slen + 1..slen + olen + 1].copy_from_slice(&other.chrs[1..olen + 1]);
740 cat.chrs[0] = (slen + olen) as u8;
741 cat
742 }
743} impl<const N: usize> Add<&str> for tstr<N> {
757 type Output = tstr<N>;
758 fn add(self, other: &str) -> tstr<N> {
759 let mut a2 = self;
760 a2.push(other);
761 a2
762 }
763} impl<const N: usize> Add<&tstr<N>> for &str {
766 type Output = tstr<N>;
767 fn add(self, other: &tstr<N>) -> tstr<N> {
768 let mut a2 = tstr::from(self);
769 a2.push(other);
770 a2
771 }
772} impl<const N: usize> Add<tstr<N>> for &str {
775 type Output = tstr<N>;
776 fn add(self, other: tstr<N>) -> tstr<N> {
777 let mut a2 = tstr::from(self);
778 a2.push(&other);
779 a2
780 }
781} impl<const N: usize> core::fmt::Write for tstr<N> {
794 fn write_str(&mut self, s: &str) -> core::fmt::Result {
795 if s.len() + self.len() > N - 1 {
796 return Err(core::fmt::Error::default());
797 }
798 self.push(s);
799 Ok(())
800 } } impl<const N: usize> core::hash::Hash for tstr<N> {
804 fn hash<H: core::hash::Hasher>(&self, state: &mut H) {
805 self.as_ref().hash(state);
806 }
807} impl<const N: usize> core::cmp::PartialEq for tstr<N> {
810 fn eq(&self, other: &Self) -> bool {
811 self.as_ref() == other.as_ref()
812 }
813}
814
815impl<const N: usize> core::str::FromStr for tstr<N> {
816 type Err = &'static str;
817 fn from_str(s: &str) -> Result<Self, Self::Err> {
818 if N < 257 && s.len() < N {
819 Ok(tstr::from(s))
820 } else {
821 Err("Parse Error: capacity exceeded")
822 }
823 }
824}
825
826