1use std::{
2 cmp::Ordering,
3 collections::{HashMap},
4 sync::{Arc, Weak, Mutex},
5 ops::{
6 Range,
7 RangeFull,
8 RangeInclusive,
9 RangeFrom,
10 RangeTo,
11 RangeToInclusive, Add,
12 }, fmt::{Debug, Display},
13};
14use once_cell::sync::Lazy;
15use super::character_validation::is_whitespace;
16
17pub type SvStringMap<V> = std::collections::BTreeMap<SvString, V>;
18pub type SvStringSet = std::collections::BTreeSet<SvString>;
19
20static INTERN_LIMIT: i32 = 512;
21
22static INTERNED: Lazy<Mutex<HashMap<i32, Vec<Weak<StringRepr0>>>>> = Lazy::new(|| {
23 Mutex::new(HashMap::new())
24});
25
26fn intern(s: Arc<StringRepr0>) -> Arc<StringRepr0> {
27 if s.m_len > INTERN_LIMIT {
28 return s.clone();
29 }
30 let p1 = &mut *INTERNED.lock().unwrap();
31 let mut p2 = p1.get_mut(&s.m_len);
32 let v = vec![];
33 if p2.is_none() {
34 p1.insert(s.m_len, v);
35 p2 = p1.get_mut(&s.m_len);
36 }
37 let p2 = p2.unwrap();
38 for s2 in p2.iter() {
39 let s2 = s2.upgrade().unwrap();
40 if s == s2 {
41 return s2.clone();
42 }
43 }
44 p2.push(Arc::downgrade(&s));
45 s.clone()
46}
47
48#[derive(Clone, Ord)]
52pub struct SvString {
53 m_repr: Arc<StringRepr0>,
54}
55
56impl Eq for SvString {
57}
58
59#[derive(Clone)]
60struct StringRepr0 {
61 m_len: i32,
62 m_repr: StringRepr1,
63}
64
65impl Ord for StringRepr0 {
66 fn cmp(&self, other: &Self) -> Ordering {
67 self.partial_cmp(other).unwrap_or(Ordering::Equal)
68 }
69}
70
71impl Eq for StringRepr0 {
72}
73
74impl Drop for StringRepr0 {
75 fn drop(&mut self) {
76 if self.m_len > INTERN_LIMIT {
77 return;
78 }
79 let p1 = &mut *INTERNED.lock().unwrap();
80 let p2 = p1.get_mut(&self.m_len);
81 if p2.is_none() {
82 return;
83 }
84 let p2 = p2.unwrap();
85 let mut i: usize = 0;
86 let mut f: Vec<usize> = vec![];
87 for s2 in p2.iter() {
88 if s2.upgrade().is_none() {
89 f.push(i);
90 }
91 i += 1;
92 }
93 for &i in f.iter().rev() {
94 p2.remove(i);
95 }
96 if p2.len() == 0 {
97 p1.remove(&self.m_len);
98 }
99 }
100}
101
102#[derive(Clone)]
103enum StringRepr1 {
104 Reference(Arc<StringRepr2>),
105 Slice(Slice),
106}
107
108impl StringRepr1 {
109 fn char_at(&self, index: usize) -> char {
110 match self {
111 StringRepr1::Reference(r) => r.char_at(index),
112 StringRepr1::Slice(s) => s.container.char_at(s.start + index),
113 }
114 }
115}
116
117#[derive(Clone)]
118struct Slice {
119 container: Arc<StringRepr2>,
120 start: usize,
121 end: usize,
122}
123
124impl PartialEq for Slice {
125 fn eq(&self, other: &Self) -> bool {
126 if (self.end - self.start) != (other.end - other.start) {
127 return false;
128 }
129 let mut l_i = self.start;
130 let mut r_i = other.start;
131 match self.container.as_ref() {
132 StringRepr2::Latin1(l) => {
133 match other.container.as_ref() {
134 StringRepr2::Latin1(r) => {
135 while l_i < self.end {
136 if l[l_i] != r[r_i] {
137 return false;
138 }
139 l_i += 1;
140 r_i += 1;
141 }
142 true
143 },
144 StringRepr2::Ucs2(r) => {
145 while l_i < self.end {
146 if (l[l_i] as u16) != r[r_i] {
147 return false;
148 }
149 l_i += 1;
150 r_i += 1;
151 }
152 true
153 },
154 StringRepr2::Ucs4(r) => {
155 while l_i < self.end {
156 if (l[l_i] as u32) != r[r_i] {
157 return false;
158 }
159 l_i += 1;
160 r_i += 1;
161 }
162 true
163 },
164 }
165 },
166 StringRepr2::Ucs2(l) => {
167 match other.container.as_ref() {
168 StringRepr2::Latin1(r) => {
169 while l_i < self.end {
170 if l[l_i] != (r[r_i] as u16) {
171 return false;
172 }
173 l_i += 1;
174 r_i += 1;
175 }
176 true
177 },
178 StringRepr2::Ucs2(r) => {
179 while l_i < self.end {
180 if l[l_i] != r[r_i] {
181 return false;
182 }
183 l_i += 1;
184 r_i += 1;
185 }
186 true
187 },
188 StringRepr2::Ucs4(r) => {
189 while l_i < self.end {
190 if (l[l_i] as u32) != r[r_i] {
191 return false;
192 }
193 l_i += 1;
194 r_i += 1;
195 }
196 true
197 },
198 }
199 },
200 StringRepr2::Ucs4(l) => {
201 match other.container.as_ref() {
202 StringRepr2::Latin1(r) => {
203 while l_i < self.end {
204 if l[l_i] != (r[r_i] as u32) {
205 return false;
206 }
207 l_i += 1;
208 r_i += 1;
209 }
210 true
211 },
212 StringRepr2::Ucs2(r) => {
213 while l_i < self.end {
214 if l[l_i] != (r[r_i] as u32) {
215 return false;
216 }
217 l_i += 1;
218 r_i += 1;
219 }
220 true
221 },
222 StringRepr2::Ucs4(r) => {
223 while l_i < self.end {
224 if l[l_i] != r[r_i] {
225 return false;
226 }
227 l_i += 1;
228 r_i += 1;
229 }
230 true
231 },
232 }
233 },
234 }
235 }
236}
237
238#[derive(Clone)]
239enum StringRepr2 {
240 Latin1(Vec<u8>),
241 Ucs2(Vec<u16>),
242 Ucs4(Vec<u32>),
243}
244
245impl StringRepr2 {
246 fn len(&self) -> usize {
247 match self {
248 StringRepr2::Latin1(v) => v.len(),
249 StringRepr2::Ucs2(v) => v.len(),
250 StringRepr2::Ucs4(v) => v.len(),
251 }
252 }
253
254 fn char_at(&self, index: usize) -> char {
255 match self {
256 StringRepr2::Latin1(v) => v[index] as char,
257 StringRepr2::Ucs2(v) => char::from_u32(v[index] as u32).unwrap_or('\x00'),
258 StringRepr2::Ucs4(v) => char::from_u32(v[index]).unwrap_or('\x00'),
259 }
260 }
261}
262
263impl PartialEq for StringRepr2 {
264 fn eq(&self, other: &Self) -> bool {
265 match self {
266 StringRepr2::Latin1(l) => {
267 match other {
268 StringRepr2::Latin1(r) => {
269 l.eq(r)
270 },
271 StringRepr2::Ucs2(r) => {
272 l.iter().map(|&e| e as u16).collect::<Vec<u16>>().eq(r)
273 },
274 StringRepr2::Ucs4(r) => {
275 l.iter().map(|&e| e as u32).collect::<Vec<u32>>().eq(r)
276 },
277 }
278 },
279 StringRepr2::Ucs2(l) => {
280 match other {
281 StringRepr2::Latin1(r) => {
282 r.iter().map(|&e| e as u16).collect::<Vec<u16>>().eq(l)
283 },
284 StringRepr2::Ucs2(r) => {
285 l.eq(r)
286 },
287 StringRepr2::Ucs4(r) => {
288 l.iter().map(|&e| e as u32).collect::<Vec<u32>>().eq(r)
289 },
290 }
291 },
292 StringRepr2::Ucs4(l) => {
293 match other {
294 StringRepr2::Latin1(r) => {
295 r.iter().map(|&e| e as u32).collect::<Vec<u32>>().eq(l)
296 },
297 StringRepr2::Ucs2(r) => {
298 r.iter().map(|&e| e as u32).collect::<Vec<u32>>().eq(l)
299 },
300 StringRepr2::Ucs4(r) => {
301 l.eq(r)
302 },
303 }
304 },
305 }
306 }
307}
308
309impl PartialEq for SvString {
310 fn eq(&self, other: &Self) -> bool {
311 self.m_repr == other.m_repr
312 }
313}
314
315impl PartialEq for StringRepr0 {
316 fn eq(&self, other: &Self) -> bool {
317 match &self.m_repr {
318 StringRepr1::Reference(l) => {
319 match &other.m_repr {
320 StringRepr1::Reference(r) => {
321 Arc::ptr_eq(l, r) || l == r
322 },
323 StringRepr1::Slice(r) => {
324 are_reference_and_slice_eq(l, r)
325 },
326 }
327 },
328 StringRepr1::Slice(l) => {
329 match &other.m_repr {
330 StringRepr1::Reference(r) => {
331 are_reference_and_slice_eq(r, l)
332 },
333 StringRepr1::Slice(r) => {
334 l == r
335 },
336 }
337 },
338 }
339 }
340}
341
342fn are_reference_and_slice_eq(l: &Arc<StringRepr2>, r: &Slice) -> bool {
343 let l_l = l.len();
344 if l_l != (r.end - r.start) {
345 return false;
346 }
347 let mut l_i = 0;
348 let mut r_i = r.start;
349 match l.as_ref() {
350 StringRepr2::Latin1(l) => {
351 match r.container.as_ref() {
352 StringRepr2::Latin1(r) => {
353 while l_i < l_l {
354 if l[l_i] != r[r_i] {
355 return false;
356 }
357 l_i += 1;
358 r_i += 1;
359 }
360 true
361 },
362 StringRepr2::Ucs2(r) => {
363 while l_i < l_l {
364 if (l[l_i] as u16) != r[r_i] {
365 return false;
366 }
367 l_i += 1;
368 r_i += 1;
369 }
370 true
371 },
372 StringRepr2::Ucs4(r) => {
373 while l_i < l_l {
374 if (l[l_i] as u32) != r[r_i] {
375 return false;
376 }
377 l_i += 1;
378 r_i += 1;
379 }
380 true
381 },
382 }
383 },
384 StringRepr2::Ucs2(l) => {
385 match r.container.as_ref() {
386 StringRepr2::Latin1(r) => {
387 while l_i < l_l {
388 if l[l_i] != (r[r_i] as u16) {
389 return false;
390 }
391 l_i += 1;
392 r_i += 1;
393 }
394 true
395 },
396 StringRepr2::Ucs2(r) => {
397 while l_i < l_l {
398 if l[l_i] != r[r_i] {
399 return false;
400 }
401 l_i += 1;
402 r_i += 1;
403 }
404 true
405 },
406 StringRepr2::Ucs4(r) => {
407 while l_i < l_l {
408 if (l[l_i] as u32) != r[r_i] {
409 return false;
410 }
411 l_i += 1;
412 r_i += 1;
413 }
414 true
415 },
416 }
417 },
418 StringRepr2::Ucs4(l) => {
419 match r.container.as_ref() {
420 StringRepr2::Latin1(r) => {
421 while l_i < l_l {
422 if l[l_i] != (r[r_i] as u32) {
423 return false;
424 }
425 l_i += 1;
426 r_i += 1;
427 }
428 true
429 },
430 StringRepr2::Ucs2(r) => {
431 while l_i < l_l {
432 if l[l_i] != (r[r_i] as u32) {
433 return false;
434 }
435 l_i += 1;
436 r_i += 1;
437 }
438 true
439 },
440 StringRepr2::Ucs4(r) => {
441 while l_i < l_l {
442 if l[l_i] != r[r_i] {
443 return false;
444 }
445 l_i += 1;
446 r_i += 1;
447 }
448 true
449 },
450 }
451 },
452 }
453}
454
455impl PartialOrd for SvString {
456 fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
457 self.m_repr.partial_cmp(&other.m_repr)
458 }
459}
460
461impl PartialOrd for StringRepr0 {
462 fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
463 let mut l: Option<&StringRepr2> = None;
464 let mut l_i: usize = 0;
465 let mut l_l: usize = 0;
466 let mut r: Option<&StringRepr2> = None;
467 let mut r_i: usize = 0;
468 let mut r_l: usize = 0;
469 match &self.m_repr {
470 StringRepr1::Reference(v) => {
471 l_l = v.len();
472 l = Some(v.as_ref());
473 },
474 StringRepr1::Slice(s) => {
475 l = Some(s.container.as_ref());
476 l_i = s.start;
477 l_l = s.end;
478 },
479 }
480 match &other.m_repr {
481 StringRepr1::Reference(v) => {
482 r_l = v.len();
483 r = Some(v.as_ref());
484 },
485 StringRepr1::Slice(s) => {
486 r = Some(s.container.as_ref());
487 r_i = s.start;
488 r_l = s.end;
489 },
490 }
491 let l = l.unwrap();
492 let r = r.unwrap();
493 loop {
494 if l_i >= l_l {
495 return Some(Ordering::Less);
496 }
497 if r_i >= r_l {
498 return Some(Ordering::Greater);
499 }
500 let l_char = l.char_at(l_i);
501 let r_char = r.char_at(r_i);
502 if l_char < r_char {
503 return Some(Ordering::Less);
504 }
505 if l_char > r_char {
506 return Some(Ordering::Greater);
507 }
508 l_i += 1;
509 r_i += 1;
510 }
511 #[allow(unreachable_code)]
512 Some(Ordering::Equal)
513 }
514}
515
516impl From<char> for SvString {
517 fn from(value: char) -> Self {
518 SvString::from(value.to_string())
519 }
520}
521
522impl From<String> for SvString {
523 fn from(value: String) -> Self {
524 SvString::from(value.as_ref())
525 }
526}
527
528impl From<&str> for SvString {
529 fn from(value: &str) -> Self {
530 let mut r: Vec<char> = vec![];
531 let mut max_ordinal: char = '\x00';
533 for c in value.chars() {
534 r.push(c);
535 max_ordinal = char::max(c, max_ordinal);
536 }
537 SvString {
538 m_repr: intern(Arc::new(if max_ordinal < '\u{100}' {
539 StringRepr0 {
540 m_len: r.len() as i32,
541 m_repr: StringRepr1::Reference(
542 Arc::new(StringRepr2::Latin1(r.iter().map(|&c| c as u8).collect()))
543 ),
544 }
545 } else if max_ordinal < '\u{10000}' {
546 StringRepr0 {
547 m_len: r.len() as i32,
548 m_repr: StringRepr1::Reference(
549 Arc::new(StringRepr2::Ucs2(r.iter().map(|&c| c as u16).collect()))
550 ),
551 }
552 } else {
553 StringRepr0 {
554 m_len: r.len() as i32,
555 m_repr: StringRepr1::Reference(
556 Arc::new(StringRepr2::Ucs4(r.iter().map(|&c| c as u32).collect()))
557 ),
558 }
559 })),
560 }
561 }
562}
563
564impl From<Vec<char>> for SvString {
565 fn from(r: Vec<char>) -> Self {
566 let mut max_ordinal: char = '\x00';
568 for &c in r.iter() {
569 max_ordinal = char::max(c, max_ordinal);
570 }
571 SvString {
572 m_repr: intern(Arc::new(if max_ordinal < '\u{100}' {
573 StringRepr0 {
574 m_len: r.len() as i32,
575 m_repr: StringRepr1::Reference(
576 Arc::new(StringRepr2::Latin1(r.iter().map(|&c| c as u8).collect()))
577 ),
578 }
579 } else if max_ordinal < '\u{10000}' {
580 StringRepr0 {
581 m_len: r.len() as i32,
582 m_repr: StringRepr1::Reference(
583 Arc::new(StringRepr2::Ucs2(r.iter().map(|&c| c as u16).collect()))
584 ),
585 }
586 } else {
587 StringRepr0 {
588 m_len: r.len() as i32,
589 m_repr: StringRepr1::Reference(
590 Arc::new(StringRepr2::Ucs4(r.iter().map(|&c| c as u32).collect()))
591 ),
592 }
593 })),
594 }
595 }
596}
597
598impl SvString {
599 pub fn empty() -> Self {
601 Self {
602 m_repr: intern(Arc::new(StringRepr0 {
603 m_len: 0,
604 m_repr: StringRepr1::Reference(Arc::new(StringRepr2::Latin1(vec![]))),
605 })),
606 }
607 }
608
609 pub fn len(&self) -> i32 {
611 self.m_repr.m_len
612 }
613
614 pub fn to_standard_string(&self) -> String {
616 self.chars().collect()
617 }
618
619 pub fn char_at(&self, index: i32) -> char {
622 if index >= 0 && index < self.m_repr.m_len { self.m_repr.m_repr.char_at(index as usize) } else { '\x00' }
623 }
624
625 pub fn chars(&self) -> impl Iterator<Item = char> + '_ {
627 match &&self.m_repr.m_repr {
628 StringRepr1::Reference(r) => {
629 CharIterator {
630 container: r.as_ref(),
631 index: 0,
632 lim: r.len(),
633 }
634 },
635 StringRepr1::Slice(s) => {
636 CharIterator {
637 container: s.container.as_ref(),
638 index: s.start,
639 lim: s.end,
640 }
641 },
642 }
643 }
644
645 pub fn concat(&self, other: impl AnySvStringType) -> SvString {
647 let other = other.convert();
648 let mut r: Vec<char> = vec![];
649 let mut max_ordinal: char = '\x00';
651 for ch in self.chars() {
652 r.push(ch);
653 max_ordinal = char::max(ch, max_ordinal);
654 }
655 for ch in other.chars() {
656 r.push(ch);
657 max_ordinal = char::max(ch, max_ordinal);
658 }
659 SvString {
660 m_repr: intern(Arc::new(if max_ordinal < '\u{100}' {
661 StringRepr0 {
662 m_len: r.len() as i32,
663 m_repr: StringRepr1::Reference(
664 Arc::new(StringRepr2::Latin1(r.iter().map(|&c| c as u8).collect()))
665 ),
666 }
667 } else if max_ordinal < '\u{10000}' {
668 StringRepr0 {
669 m_len: r.len() as i32,
670 m_repr: StringRepr1::Reference(
671 Arc::new(StringRepr2::Ucs2(r.iter().map(|&c| c as u16).collect()))
672 ),
673 }
674 } else {
675 StringRepr0 {
676 m_len: r.len() as i32,
677 m_repr: StringRepr1::Reference(
678 Arc::new(StringRepr2::Ucs4(r.iter().map(|&c| c as u32).collect()))
679 ),
680 }
681 })),
682 }
683 }
684
685 pub fn contains(&self, other: impl AnySvStringType) -> bool {
687 self.index_of(other) != -1
688 }
689
690 pub fn starts_with(&self, other: impl AnySvStringType) -> bool {
692 let other = other.convert();
693 for i in 0..other.len() {
694 if i >= self.len() || self.char_at(i) != other.char_at(i) {
695 return false;
696 }
697 }
698 true
699 }
700
701 pub fn ends_with(&self, other: impl AnySvStringType) -> bool {
703 let other = other.convert();
704 let mut i = other.len() - 1;
705 let mut j = self.len() - 1;
706 while i >= 0 {
707 if j < 0 || self.char_at(j) != other.char_at(i) {
708 return false;
709 }
710 i -= 1;
711 j -= 1;
712 }
713 true
714 }
715
716 pub fn index_of(&self, other: impl AnySvStringType) -> i32 {
719 let other = other.convert();
720 let mut remaining = other.chars();
721 let mut i: i32 = 0;
722 let mut j: i32 = -1;
723 for ch in self.chars() {
724 if j == -1 {
725 j = i;
726 }
727 let remaining_ch = remaining.next();
728 if remaining_ch.is_none() {
729 break;
730 }
731 if ch != remaining_ch.unwrap() {
732 remaining = other.chars();
733 j = -1;
734 }
735 i += 1;
736 }
737 if remaining.next().is_none() { j } else { -1 }
738 }
739
740 pub fn last_index_of(&self, other: impl AnySvStringType) -> i32 {
743 let other = other.convert();
744 if other.m_repr.m_len == 0 {
745 return self.m_repr.m_len;
746 }
747 let mut remaining = other.chars();
748 let mut i: i32 = 0;
749 let mut j: i32 = -1;
750 let mut r: Vec<i32> = vec![];
751 for ch in self.chars() {
752 if j == -1 {
753 j = i;
754 }
755 let remaining_ch = remaining.next();
756 if remaining_ch.is_none() {
757 r.push(j);
758 remaining = other.chars();
759 j = -1;
760 }
761 if ch != remaining_ch.unwrap() {
762 remaining = other.chars();
763 j = -1;
764 }
765 i += 1;
766 }
767 if r.len() > 0 { r[r.len() - 1] } else { -1 }
768 }
769
770 pub fn is_empty(&self) -> bool {
772 self.m_repr.m_len == 0
773 }
774
775 pub fn repeat(&self, n: i32) -> SvString {
777 if n < 1 {
778 return SvString::empty();
779 }
780 let v = self.chars().collect::<Vec<char>>();
781 let mut r: Vec<char> = vec![];
782 let mut max_ordinal: char = '\x00';
784 for _ in 0..n {
785 for &ch in v.iter() {
786 r.push(ch);
787 max_ordinal = char::max(ch, max_ordinal);
788 }
789 }
790 SvString {
791 m_repr: intern(Arc::new(if max_ordinal < '\u{100}' {
792 StringRepr0 {
793 m_len: r.len() as i32,
794 m_repr: StringRepr1::Reference(
795 Arc::new(StringRepr2::Latin1(r.iter().map(|&c| c as u8).collect()))
796 ),
797 }
798 } else if max_ordinal < '\u{10000}' {
799 StringRepr0 {
800 m_len: r.len() as i32,
801 m_repr: StringRepr1::Reference(
802 Arc::new(StringRepr2::Ucs2(r.iter().map(|&c| c as u16).collect()))
803 ),
804 }
805 } else {
806 StringRepr0 {
807 m_len: r.len() as i32,
808 m_repr: StringRepr1::Reference(
809 Arc::new(StringRepr2::Ucs4(r.iter().map(|&c| c as u32).collect()))
810 ),
811 }
812 })),
813 }
814 }
815
816 pub fn to_lowercase(&self) -> SvString {
818 SvString::from(self.to_standard_string().to_lowercase())
819 }
820
821 pub fn to_uppercase(&self) -> SvString {
823 SvString::from(self.to_standard_string().to_uppercase())
824 }
825
826 pub fn substr(&self, index: impl SvSubstringIndex) -> SvString {
828 self.covered_substring(index.from_index(), index.to_index())
829 }
830
831 pub fn substr_with_length(&self, mut from: i32, mut len: i32) -> SvString {
833 from = i32::max(0, from);
834 from = i32::min(from, self.m_repr.m_len);
835 len = i32::max(0, len);
836 if from + len >= self.m_repr.m_len {
837 self.substr(from..)
838 } else {
839 self.substr(from..(from + len))
840 }
841 }
842
843 fn covered_substring(&self, mut from: i32, mut to: i32) -> SvString {
844 from = i32::max(0, from);
845 from = i32::min(from, self.m_repr.m_len);
846 to = i32::max(0, to);
847 to = i32::min(to, self.m_repr.m_len);
848 if to < from {
849 let k = from;
850 from = to;
851 to = k;
852 }
853 match &self.m_repr.m_repr {
854 StringRepr1::Reference(r) => {
855 SvString {
856 m_repr: intern(Arc::new(StringRepr0 {
857 m_len: to - from,
858 m_repr: StringRepr1::Slice(Slice {
859 container: r.clone(),
860 start: from as usize,
861 end: to as usize,
862 }),
863 }))
864 }
865 },
866 StringRepr1::Slice(slice) => {
867 SvString {
868 m_repr: intern(Arc::new(StringRepr0 {
869 m_len: to - from,
870 m_repr: StringRepr1::Slice(Slice {
871 container: slice.container.clone(),
872 start: slice.start + (from as usize),
873 end: slice.start + (to as usize),
874 }),
875 }))
876 }
877 },
878 }
879 }
880
881 pub fn trim(&self) -> SvString {
883 let mut i: i32 = 0;
884 while is_whitespace(self.char_at(i)) {
885 i += 1;
886 }
887 let mut j: i32 = self.len();
888 while is_whitespace(self.char_at(j - 1)) {
889 j -= 1;
890 }
891 self.substr(i..j)
892 }
893
894 pub fn trim_left(&self) -> SvString {
896 let mut i: i32 = 0;
897 while is_whitespace(self.char_at(i)) {
898 i += 1;
899 }
900 self.substr(i..)
901 }
902
903 pub fn trim_right(&self) -> SvString {
905 let mut i: i32 = self.len();
906 while is_whitespace(self.char_at(i - 1)) {
907 i -= 1;
908 }
909 self.substr(..i)
910 }
911
912 pub fn join(vector: Vec<SvString>, sep: impl AnySvStringType) -> SvString {
914 let sep = sep.convert();
915 let mut r: Vec<char> = vec![];
916 let mut max_ordinal: char = '\x00';
917 let mut add_sep = false;
918 for s in vector {
919 if add_sep {
920 for ch in sep.chars() {
921 r.push(ch);
922 max_ordinal = char::max(ch, max_ordinal);
923 }
924 }
925 for ch in s.chars() {
926 r.push(ch);
927 max_ordinal = char::max(ch, max_ordinal);
928 }
929 add_sep = true;
930 }
931 SvString {
932 m_repr: intern(Arc::new(if max_ordinal < '\u{100}' {
933 StringRepr0 {
934 m_len: r.len() as i32,
935 m_repr: StringRepr1::Reference(
936 Arc::new(StringRepr2::Latin1(r.iter().map(|&c| c as u8).collect()))
937 ),
938 }
939 } else if max_ordinal < '\u{10000}' {
940 StringRepr0 {
941 m_len: r.len() as i32,
942 m_repr: StringRepr1::Reference(
943 Arc::new(StringRepr2::Ucs2(r.iter().map(|&c| c as u16).collect()))
944 ),
945 }
946 } else {
947 StringRepr0 {
948 m_len: r.len() as i32,
949 m_repr: StringRepr1::Reference(
950 Arc::new(StringRepr2::Ucs4(r.iter().map(|&c| c as u32).collect()))
951 ),
952 }
953 })),
954 }
955 }
956}
957
958struct CharIterator<'a> {
959 container: &'a StringRepr2,
960 index: usize,
961 lim: usize,
962}
963
964impl<'a> Iterator for CharIterator<'a> {
965 type Item = char;
966 fn next(&mut self) -> Option<Self::Item> {
967 if self.index >= self.lim {
968 return None;
969 }
970 let r = self.container.char_at(self.index);
971 self.index += 1;
972 Some(r)
973 }
974}
975
976pub trait AnySvStringType {
979 fn convert(&self) -> SvString;
980}
981
982impl AnySvStringType for SvString {
983 fn convert(&self) -> SvString {
984 self.clone()
985 }
986}
987
988impl<'a> AnySvStringType for &'a str {
989 fn convert(&self) -> SvString {
990 SvString::from(*self)
991 }
992}
993
994impl<'a> AnySvStringType for char {
995 fn convert(&self) -> SvString {
996 SvString::from(*self)
997 }
998}
999
1000pub trait SvSubstringIndex {
1002 fn from_index(&self) -> i32;
1003 fn to_index(&self) -> i32;
1004}
1005
1006impl SvSubstringIndex for Range<i32> {
1007 fn from_index(&self) -> i32 {
1008 self.start
1009 }
1010 fn to_index(&self) -> i32 {
1011 self.end
1012 }
1013}
1014
1015impl SvSubstringIndex for RangeFrom<i32> {
1016 fn from_index(&self) -> i32 {
1017 self.start
1018 }
1019 fn to_index(&self) -> i32 {
1020 i32::MAX
1021 }
1022}
1023
1024impl SvSubstringIndex for RangeFull {
1025 fn from_index(&self) -> i32 {
1026 0
1027 }
1028 fn to_index(&self) -> i32 {
1029 i32::MAX
1030 }
1031}
1032
1033impl SvSubstringIndex for RangeInclusive<i32> {
1034 fn from_index(&self) -> i32 {
1035 *self.start()
1036 }
1037 fn to_index(&self) -> i32 {
1038 self.end() + 1
1039 }
1040}
1041
1042impl SvSubstringIndex for RangeTo<i32> {
1043 fn from_index(&self) -> i32 {
1044 0
1045 }
1046 fn to_index(&self) -> i32 {
1047 self.end
1048 }
1049}
1050
1051impl SvSubstringIndex for RangeToInclusive<i32> {
1052 fn from_index(&self) -> i32 {
1053 0
1054 }
1055 fn to_index(&self) -> i32 {
1056 self.end + 1
1057 }
1058}
1059
1060impl Debug for SvString {
1061 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1062 write!(f, "{}", self.to_standard_string())
1063 }
1064}
1065
1066impl Display for SvString {
1067 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1068 write!(f, "{}", self.to_standard_string())
1069 }
1070}
1071
1072impl Add for SvString {
1073 type Output = SvString;
1074 fn add(self, rhs: Self) -> Self::Output {
1075 self.concat(rhs)
1076 }
1077}