1
2pub mod iter;
52use iter::{Split, Lines};
53
54use std::{ops, str, cmp, fmt, hash, borrow};
55use ops::Bound;
56use std::rc::Rc;
57use std::sync::Arc;
58use std::string::FromUtf8Error;
59
60#[derive(Clone)]
81pub struct SharedGenString<R>
82where R: RefCounter {
83 start: usize,
85 len: usize,
86
87 bytes: R
89}
90
91pub type SharedString = SharedGenString<Rc<Box<[u8]>>>;
93pub type SharedSyncString = SharedGenString<Arc<Box<[u8]>>>;
95
96pub trait RefCounter: Clone + Sized + ops::Deref<Target = Box<[u8]>> + From<Box<[u8]>> {
103 fn try_unwrap(self) -> Result<Box<[u8]>, Self>;
104}
105
106impl RefCounter for Rc<Box<[u8]>> {
107 #[inline]
108 fn try_unwrap(self) -> Result<Box<[u8]>, Self> {
109 Rc::try_unwrap(self)
110 }
111}
112
113impl RefCounter for Arc<Box<[u8]>> {
114 #[inline]
115 fn try_unwrap(self) -> Result<Box<[u8]>, Self> {
116 Arc::try_unwrap(self)
117 }
118}
119
120impl<R> SharedGenString<R>
121where R: RefCounter {
122
123 #[inline]
125 pub fn new() -> Self {
126 "".into()
127 }
128
129 #[inline]
130 pub(crate) fn new_raw(start: usize, len: usize, bytes: R) -> Self {
131 Self { start, len, bytes }
132 }
133
134 #[inline]
147 pub fn from_utf8(vec: Vec<u8>) -> Result<Self, FromUtf8Error> {
148 String::from_utf8(vec).map(|s| s.into())
149 }
150
151 #[inline]
156 pub unsafe fn from_utf8_unchecked(vec: Vec<u8>) -> Self {
157 Self {
158 start: 0,
159 len: vec.len(),
160 bytes: vec.into_boxed_slice().into()
161 }
162 }
163
164 #[inline]
169 pub fn as_bytes(&self) -> &[u8] {
170 let end = self.start + self.len;
171 unsafe {
172 self.bytes.get_unchecked(self.start..end)
175 }
176 }
177
178 #[inline]
181 pub fn as_full_bytes(&self) -> &[u8] {
182 &self.bytes
183 }
184
185 #[inline]
196 pub fn as_str(&self) -> &str {
197 &self
198 }
199
200 #[inline]
214 pub fn as_full_str(&self) -> &str {
215 unsafe { str::from_utf8_unchecked(&self.bytes) }
216 }
217
218 #[inline]
231 pub fn len(&self) -> usize {
232 self.len
233 }
234
235 #[inline]
237 pub fn is_empty(&self) -> bool {
238 self.len == 0
239 }
240
241 #[inline]
245 fn validate_range<I>(&self, range: I) -> Option<(usize, usize)>
246 where I: ops::RangeBounds<usize> {
247
248 let len = self.len();
249
250 let start = match range.start_bound() {
251 Bound::Included(&i) => i,
252 Bound::Excluded(&i) => i + 1,
253 Bound::Unbounded => 0
254 };
255
256 let end = match range.end_bound() {
257 Bound::Included(&i) => i + 1,
258 Bound::Excluded(&i) => i,
259 Bound::Unbounded => len
260 };
261
262 if start > end || end > len {
263 None
264 } else {
265 Some((start, end))
266 }
267 }
268
269 #[inline]
293 pub fn get<I>(&self, range: I) -> Option<Self>
294 where I: ops::RangeBounds<usize> {
295 let (start, end) = self.validate_range(range)?;
296
297 if start == end {
298 return Some(Self::new())
299 }
300
301 let s = self.as_str();
303 if !(s.is_char_boundary(start) && s.is_char_boundary(end)) {
304 return None;
305 }
306
307 Some(Self {
308 start: self.start + start,
309 len: end - start,
310 bytes: self.bytes.clone()
311 })
312 }
313
314 #[inline]
343 pub fn idx<I>(&self, range: I) -> Self
344 where I: ops::RangeBounds<usize> {
345 let (start, end) = self.validate_range(range).expect("invalid range");
346
347 Self {
348 start: self.start + start,
349 len: end - start,
350 bytes: self.bytes.clone()
351 }
352 }
353
354 #[inline]
359 pub fn into_bytes(self) -> Vec<u8> {
360 match self.bytes.try_unwrap().map(|b| b.into_vec()) {
361 Ok(mut bytes) if self.start == 0 => {
363 bytes.truncate(self.len);
364 bytes
365 },
366 Ok(bytes) => unsafe {
369 let range = self.start..(self.start + self.len);
370 bytes.get_unchecked(range).to_vec()
371 },
372 Err(slice) => unsafe {
375 let range = self.start..(self.start + self.len);
376 slice.get_unchecked(range).to_vec()
377 }
378 }
379 }
380
381 #[inline]
386 pub fn into_full_bytes(self) -> Vec<u8> {
387 match self.bytes.try_unwrap() {
388 Ok(bytes) => bytes.into(),
389 Err(slice) => slice.to_vec()
390 }
391 }
392
393 #[inline]
398 pub fn into_string(self) -> String {
399 let vec = self.into_bytes();
400 unsafe { String::from_utf8_unchecked(vec) }
402 }
403
404 #[inline]
410 pub fn into_full_string(self) -> String {
411 let vec = self.into_full_bytes();
412 unsafe { String::from_utf8_unchecked(vec) }
413 }
414
415 #[inline]
430 pub fn push(self, ch: char) -> String {
431 let mut s = self.into_string();
432 s.push(ch);
433 s
434 }
435
436 #[inline]
451 pub fn push_str(self, string: &str) -> String {
452 let mut s = self.into_string();
453 s.push_str(string);
454 s
455 }
456
457 #[inline]
467 pub fn split_off(&mut self, at: usize) -> Self {
468 if at == 0 {
469 let c = self.clone();
470 self.len = 0;
471 return c
472 }
473
474 assert!(self.is_char_boundary(at));
476
477 let n_len = self.len - at;
478 self.len = at;
479
480 Self {
481 start: self.start + at,
482 len: n_len,
483 bytes: self.bytes.clone()
484 }
485 }
486
487 #[inline]
505 pub fn split(self, byte: u8) -> Split<R> {
506 Split::new(self.start, self.len, self.bytes, byte)
507 }
508
509 #[inline]
530 pub fn lines(self) -> Lines<R> {
531 Lines::new(self.start, self.len, self.bytes)
532 }
533
534 #[inline]
542 pub fn truncate(&mut self, new_len: usize) {
543 if new_len < self.len {
544 assert!(self.is_char_boundary(new_len));
545 self.len = new_len;
546 }
547 }
548}
549
550impl<R> fmt::Display for SharedGenString<R>
551where R: RefCounter {
552 #[inline]
553 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
554 fmt::Display::fmt(self.as_str(), f)
555 }
556}
557
558impl<R> fmt::Debug for SharedGenString<R>
559where R: RefCounter {
560 #[inline]
561 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
562 fmt::Debug::fmt(self.as_str(), f)
563 }
564}
565
566impl<R> hash::Hash for SharedGenString<R>
567where R: RefCounter {
568 #[inline]
569 fn hash<H: hash::Hasher>(&self, hasher: &mut H) {
570 self.as_str().hash(hasher)
571 }
572}
573
574impl<R> ops::Deref for SharedGenString<R>
575where R: RefCounter {
576 type Target = str;
577
578 #[inline]
579 fn deref(&self) -> &str {
580 unsafe { str::from_utf8_unchecked(self.as_bytes()) }
582 }
583}
584
585impl<R> AsRef<str> for SharedGenString<R>
586where R: RefCounter {
587 #[inline]
588 fn as_ref(&self) -> &str {
589 self
590 }
591}
592
593impl<R> borrow::Borrow<str> for SharedGenString<R>
594where R: RefCounter {
595 #[inline]
596 fn borrow(&self) -> &str {
597 self
598 }
599}
600
601impl<R, O> cmp::PartialEq<SharedGenString<O>> for SharedGenString<R>
603where
604 R: RefCounter,
605 O: RefCounter {
606 #[inline]
607 fn eq(&self, other: &SharedGenString<O>) -> bool {
608 self.as_bytes() == other.as_bytes()
609 }
610}
611
612impl<R: RefCounter> cmp::Eq for SharedGenString<R> {}
613
614impl<R> cmp::PartialEq<str> for SharedGenString<R>
615where R: RefCounter {
616 #[inline]
617 fn eq(&self, other: &str) -> bool {
618 self.as_str() == other
619 }
620}
621
622impl<R> cmp::PartialEq<&str> for SharedGenString<R>
623where R: RefCounter {
624 #[inline]
625 fn eq(&self, other: &&str) -> bool {
626 self.as_str() == *other
627 }
628}
629
630impl cmp::PartialEq<SharedString> for str {
631 #[inline]
632 fn eq(&self, other: &SharedString) -> bool {
633 self == other.as_str()
634 }
635}
636
637impl cmp::PartialEq<SharedString> for &str {
638 #[inline]
639 fn eq(&self, other: &SharedString) -> bool {
640 *self == other.as_str()
641 }
642}
643
644impl cmp::PartialEq<SharedSyncString> for str {
645 #[inline]
646 fn eq(&self, other: &SharedSyncString) -> bool {
647 self == other.as_str()
648 }
649}
650
651impl cmp::PartialEq<SharedSyncString> for &str {
652 #[inline]
653 fn eq(&self, other: &SharedSyncString) -> bool {
654 *self == other.as_str()
655 }
656}
657
658impl<R> Default for SharedGenString<R>
661where R: RefCounter {
662 #[inline]
664 fn default() -> Self {
665 Self::new()
666 }
667}
668
669impl<R> From<String> for SharedGenString<R>
670where R: RefCounter {
671 #[inline]
672 fn from(s: String) -> Self {
673 Self {
674 start: 0,
675 len: s.len(),
676 bytes: s.into_bytes().into_boxed_slice().into()
677 }
678 }
679}
680
681impl<R> From<&str> for SharedGenString<R>
682where R: RefCounter {
683 #[inline]
684 fn from(s: &str) -> Self {
685 s.to_string().into()
686 }
687}
688
689impl<R> From<SharedGenString<R>> for String
690where R: RefCounter {
691 #[inline]
692 fn from(s: SharedGenString<R>) -> Self {
693 s.into_string()
694 }
695}
696
697#[cfg(test)]
699mod tests {
700
701 use super::{SharedString, SharedSyncString};
702
703 #[test]
704 fn rc() {
705 let mut hello: SharedString = "Hello, World!".into();
706 assert_eq!(hello.len(), 13);
707
708 let world = hello.split_off(7);
709 assert_eq!(hello, "Hello, ");
710 assert_eq!(hello.len(), 7);
711 assert_eq!(world, "World!");
712 assert_eq!(world.len(), 6);
713 }
714
715 #[test]
716 fn arc() {
717 let mut hello: SharedSyncString = "Hello, World!".into();
718
719 let world = hello.split_off(7);
720
721 std::thread::spawn(move || {
722 assert_eq!(world, "World!");
723 assert_eq!(world.as_full_str(), "Hello, World!");
724 });
725
726 assert_eq!(hello, "Hello, ");
727 }
728
729 #[test]
730 fn into() {
731 let hello = SharedString::from("Hello, World!");
732 let s = hello.into_string();
733 assert_eq!(s, "Hello, World!");
734
735 let mut hello: SharedString = s.into();
736 let world = hello.split_off(7);
737
738 let s = world.into_string();
739 assert_eq!(s, "World!");
740
741 assert!(hello != s.as_str());
742
743 let n_hello = SharedString::from("Hello, ");
744 assert_eq!(hello, n_hello);
745 }
746
747 #[test]
748 fn split_off_zero() {
749 let mut foobar = SharedString::from("foobar");
750 let n_foobar = foobar.split_off(0);
751 assert_eq!("", foobar);
752 assert_eq!("foobar", n_foobar);
753 }
754
755 #[test]
756 #[should_panic]
757 fn panic_char_boundary() {
758 let mut s = SharedString::from("abc 好 def");
759 let _ = s.split_off(5);
760 }
761
762 #[test]
763 #[should_panic]
764 fn panic_length() {
765 let mut s = SharedString::from("abc");
766 let _ = s.split_off(5);
767 }
768
769 #[test]
770 fn range_as_str() {
771 let raw = SharedString::from("Hello, World!");
772 let hello = &raw[..5];
773 let world = &raw[7..];
774
775 assert_eq!(hello, "Hello");
776 assert_eq!(world, "World!");
777 }
778
779 #[test]
780 fn range_with_get() {
781 let raw = SharedString::from("Hello, World!");
782 let hello = raw.get(..5).unwrap();
783 let world = raw.get(7..).unwrap();
784
785 assert_eq!(hello, "Hello");
786 assert_eq!(world, "World!");
787 }
788
789 #[test]
790 fn range_with_idx() {
791 let raw = SharedString::from("Hello, World!");
792 let hello = raw.idx(..5);
793 let world = raw.idx(7..);
794
795 assert_eq!(hello, "Hello");
796 assert_eq!(world, "World!");
797 }
798
799 #[test]
800 fn empty() {
801 let s = SharedString::from("");
802 assert_eq!(s.len(), 0);
803 assert!(s.is_empty());
804
805 assert!(s.get(..).is_some());
806 assert!(s.idx(..).is_empty());
807 assert!(s.get(1..).is_none());
808 }
809
810 #[test]
811 fn equal() {
812 let rc: SharedString = "Hello, World!".into();
813 let arc: SharedSyncString = "Hello, World!".into();
814 assert_eq!(rc, arc);
815 }
816
817 #[test]
818 fn split() {
819 let fullname = SharedString::from("Albert Einstein");
820 let mut split = fullname.split(b' ');
821 assert_eq!(split.next().unwrap(), "Albert");
822 assert_eq!(split.next().unwrap(), "Einstein");
823 assert_eq!(split.next(), None);
824 }
825
826 #[test]
827 fn lines() {
828 let quote = SharedString::from("Wenn die Menschen nur über das sprächen,\nwas sie begreifen,\r\ndann würde es sehr still auf der Welt sein.\n\r\n");
829 let mut lines = quote.lines();
830 assert_eq!(
831 lines.next().unwrap(),
832 "Wenn die Menschen nur über das sprächen,"
833 );
834 assert_eq!(lines.next().unwrap(), "was sie begreifen,");
835 assert_eq!(
836 lines.next().unwrap(),
837 "dann würde es sehr still auf der Welt sein."
838 );
839 assert_eq!(lines.next().unwrap(), "");
840 assert_eq!(lines.next(), None);
841
842 let empty = SharedString::from(" ");
843 let mut lines = empty.lines();
844 assert_eq!(" ", lines.next().unwrap());
845 assert_eq!(lines.next(), None);
846 }
847
848 #[test]
849 fn range_eq_str_range() {
850 let line = "foo: bar";
851 let at = line.find(':').unwrap();
852 let key = &line[..at];
853 let value = &line[(at + 2)..];
854
855 assert_eq!(key, "foo");
856 assert_eq!(value, "bar");
857
858 let line = SharedString::from(line);
859 let key = line.idx(..at);
860 let value = line.idx((at + 2)..);
861
862 assert_eq!(key, "foo");
863 assert_eq!(value, "bar");
864 }
865
866 #[test]
867 fn range_in_range() {
868 let line = "date: Mon, 30 Nov 2020 22:16:22 GMT\nserver: mw1271.eqiad.wmnet\nx-content-type-options: nosniff";
869 let mut lines = SharedString::from(line).lines();
870
871 let _ = lines.next().unwrap();
872 let line = lines.next().unwrap();
873
874 let at = line.find(':').unwrap();
875 assert_eq!(at, 6);
876
877 let key = line.idx(..at);
878 assert_eq!(key, "server");
879
880 let value = line.idx((at + 2)..);
881 assert_eq!(value, "mw1271.eqiad.wmnet");
882 }
883
884 #[test]
885 fn truncate() {
886 let mut foobar = SharedString::from("foobar");
887 foobar.truncate(3);
888 assert_eq!(foobar, "foo");
889 }
890}