1use std::borrow;
2use std::cell::Ref;
3use std::cell::RefCell;
4use std::cmp;
5use std::fmt;
6use std::hash;
7use std::ops;
8use std::rc::Rc;
9
10#[derive(Clone)]
13pub struct RcStr(Rc<Str>);
14
15pub struct Str {
16 string: String,
17 chars: RefCell<Option<Chars>>,
18}
19
20enum Chars {
21 ASCII,
22 Chars(Vec<char>),
23}
24
25impl RcStr {
26 fn new(s: String) -> Self {
27 s.into()
28 }
29 unsafe fn new_ascii(string: String) -> Self {
30 Self(Rc::new(Str {
31 string,
32 chars: RefCell::new(Some(Chars::ASCII)),
33 }))
34 }
35 pub fn len(&self) -> usize {
36 self.0.string.len()
37 }
38 fn chars(&self) -> Ref<Chars> {
39 if self.0.chars.borrow().is_none() {
40 let mut opt_chars = self.0.chars.borrow_mut();
41 *opt_chars = Some(if self.0.string.is_ascii() {
42 Chars::ASCII
43 } else {
44 Chars::Chars(self.0.string.chars().collect())
45 });
46 }
47 Ref::map(self.0.chars.borrow(), |chars| chars.as_ref().unwrap())
48 }
49 pub fn charlen(&self) -> usize {
50 let chars = self.chars();
51 let chars: &Chars = &chars;
52 match chars {
53 Chars::ASCII => self.len(),
54 Chars::Chars(chars) => chars.len(),
55 }
56 }
57 pub fn charslice(&self, start: usize, end: usize) -> RcStr {
58 let chars = self.chars();
59 let chars: &Chars = &chars;
60 match chars {
61 Chars::ASCII => unsafe { Self::new_ascii(self.0.string[start..end].to_owned()) },
62 Chars::Chars(chars) => Self::new(chars[start..end].iter().collect()),
63 }
64 }
65 pub fn getchar(&self, index: usize) -> Option<char> {
66 let chars = self.chars();
67 let chars: &Chars = &chars;
68 match chars {
69 Chars::ASCII => self.0.string.as_bytes().get(index).map(|c| *c as char),
70 Chars::Chars(chars) => chars.get(index).cloned(),
71 }
72 }
73}
74
75impl fmt::Debug for RcStr {
76 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
77 write!(f, "{:?}", self.0.string)
78 }
79}
80
81impl fmt::Display for RcStr {
82 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
83 write!(f, "{}", self.0.string)
84 }
85}
86
87impl borrow::Borrow<str> for RcStr {
88 fn borrow(&self) -> &str {
89 self.0.string.borrow()
90 }
91}
92
93impl ops::Deref for RcStr {
94 type Target = str;
95
96 fn deref(&self) -> &str {
97 self.0.string.deref()
98 }
99}
100
101impl AsRef<str> for RcStr {
102 fn as_ref(&self) -> &str {
103 self.0.string.as_ref()
104 }
105}
106
107impl cmp::PartialOrd for RcStr {
108 fn partial_cmp(&self, other: &Self) -> Option<cmp::Ordering> {
109 self.0.string.partial_cmp(&other.0.string)
110 }
111}
112
113impl cmp::Ord for RcStr {
114 fn cmp(&self, other: &Self) -> cmp::Ordering {
115 self.0.string.cmp(&other.0.string)
116 }
117}
118
119impl cmp::PartialEq for RcStr {
120 fn eq(&self, other: &Self) -> bool {
121 self.0.string.eq(&other.0.string)
122 }
123}
124
125impl cmp::Eq for RcStr {}
126
127impl hash::Hash for RcStr {
128 fn hash<H: hash::Hasher>(&self, state: &mut H) {
129 self.0.string.hash(state)
130 }
131}
132
133impl ops::Index<ops::Range<usize>> for RcStr {
134 type Output = str;
135 fn index(&self, index: ops::Range<usize>) -> &str {
136 self.0.string.index(index)
137 }
138}
139
140impl ops::Index<ops::RangeTo<usize>> for RcStr {
141 type Output = str;
142 fn index(&self, index: ops::RangeTo<usize>) -> &str {
143 self.0.string.index(index)
144 }
145}
146
147impl ops::Index<ops::RangeFrom<usize>> for RcStr {
148 type Output = str;
149 fn index(&self, index: ops::RangeFrom<usize>) -> &str {
150 self.0.string.index(index)
151 }
152}
153
154impl ops::Index<ops::RangeFull> for RcStr {
155 type Output = str;
156 fn index(&self, index: ops::RangeFull) -> &str {
157 self.0.string.index(index)
158 }
159}
160
161impl From<String> for RcStr {
162 fn from(string: String) -> Self {
163 Self(Rc::new(Str {
164 string,
165 chars: RefCell::new(None),
166 }))
167 }
168}
169
170impl From<&String> for RcStr {
171 fn from(string: &String) -> Self {
172 string.clone().into()
173 }
174}
175
176impl From<&str> for RcStr {
177 fn from(s: &str) -> Self {
178 s.to_owned().into()
179 }
180}