1#[cfg(test)]
2mod tests;
3
4use crate::{owned_slice::OwnedSlice, util::range, IndexOutOfBounds, RangeOfSubset, SharedBytes};
5use std::{
6 borrow::{Borrow, Cow},
7 fmt::{self, Debug, Display},
8 io,
9 net::ToSocketAddrs,
10 ops::{Deref, Range, RangeBounds},
11 sync::Arc,
12};
13
14#[derive(Clone)]
15pub struct SharedStr(pub(crate) Flavour);
16
17#[derive(Clone)]
18pub(crate) enum Flavour {
19 Static(&'static str),
20 ArcVecSlice(OwnedSlice<Arc<Vec<u8>>, str>),
21 ArcStringSlice(OwnedSlice<Arc<String>, str>),
22}
23
24impl SharedStr {
25 #[inline]
26 pub const fn new() -> Self {
27 Self(Flavour::Static(""))
28 }
29
30 #[inline]
31 pub const fn from_static(x: &'static str) -> Self {
32 Self(Flavour::Static(x))
33 }
34
35 #[inline]
36 pub fn from_string(x: String) -> Self {
37 Self::from_arc_string(Arc::new(x))
38 }
39
40 #[inline]
41 pub fn from_arc_string(x: Arc<String>) -> Self {
42 Self(Flavour::ArcStringSlice(OwnedSlice::new(x).unwrap()))
43 }
44
45 pub fn from_utf8(bytes: SharedBytes) -> Result<Self, SharedBytes> {
46 use crate::shared_bytes::Flavour::*;
47 let flavour = match bytes.0 {
48 Static(b) => match std::str::from_utf8(b) {
49 Ok(string) => Flavour::Static(string),
50 Err(_) => return Err(bytes),
51 },
52 ArcVecSlice(x) => Flavour::ArcVecSlice(
53 x.try_map_output()
54 .map_err(|x| SharedBytes(ArcVecSlice(x)))?,
55 ),
56 ArcStringSlice(x) => Flavour::ArcStringSlice(
57 x.try_map_output()
58 .map_err(|x| SharedBytes(ArcStringSlice(x)))?,
59 ),
60 };
61 Ok(Self(flavour))
62 }
63
64 pub fn into_string(self) -> String {
65 self.into_static_cow().into_owned()
66 }
67
68 fn into_static_cow(self) -> Cow<'static, str> {
69 match self.0 {
70 Flavour::Static(x) => Cow::Borrowed(x),
71 Flavour::ArcVecSlice(x) => Cow::Owned(
72 x.into_unwrapped(|vec| String::from_utf8(vec).unwrap(), ToOwned::to_owned),
73 ),
74 Flavour::ArcStringSlice(x) => {
75 Cow::Owned(x.into_unwrapped(Into::into, ToOwned::to_owned))
76 }
77 }
78 }
79
80 #[inline]
81 pub fn as_str(&self) -> &str {
82 self.as_slice()
83 }
84
85 #[inline]
86 pub fn as_slice(&self) -> &str {
87 match &self.0 {
88 Flavour::Static(x) => x,
89 Flavour::ArcVecSlice(x) => x,
90 Flavour::ArcStringSlice(x) => x,
91 }
92 }
93
94 pub fn as_static(&self) -> Option<&'static str> {
95 match &self.0 {
96 Flavour::Static(x) => Some(x),
97 _ => None,
98 }
99 }
100
101 pub fn len(&self) -> usize {
102 self.as_slice().len()
103 }
104
105 pub fn is_empty(&self) -> bool {
106 self.as_slice().is_empty()
107 }
108
109 pub fn clear(&mut self) {
110 *self = Self::new()
111 }
112
113 pub fn truncate(&mut self, at: usize) {
114 self.try_slice_mut(..at)
115 .unwrap_or_else(|_| panic!("truncate index '{at}' should be <= len '{}'", self.len()))
116 }
117
118 #[must_use = "consider fn truncate if you don't need the other half"]
119 pub fn split_off(&mut self, at: usize) -> Self {
120 self.try_split_off(at)
121 .unwrap_or_else(|| panic!("split index '{at}' should be <= len '{}'", self.len()))
122 }
123
124 fn try_split_off(&mut self, at: usize) -> Option<Self> {
126 self.as_slice().get(at..)?; let mut split = self.clone();
128 split.slice_mut(at..);
129 self.slice_mut(..at);
130 Some(split)
131 }
132
133 pub fn range_of_subset(&self, subset: &str) -> Range<usize> {
134 RangeOfSubset::range_of_subset(self.as_slice(), subset)
135 }
136
137 pub fn slice_cloned<R: RangeBounds<usize>>(&self, r: R) -> Self {
138 self.non_generic_slice_cloned(self.slice_range_from_bounds(r))
139 }
140
141 fn non_generic_slice_cloned(&self, range: Range<usize>) -> Self {
142 self.non_generic_try_slice_cloned(range.clone())
143 .unwrap_or_else(|_| self.out_of_bounds_panic(range))
144 }
145
146 pub fn try_slice_cloned<R: RangeBounds<usize>>(&self, r: R) -> Result<Self, IndexOutOfBounds> {
147 self.non_generic_try_slice_cloned(self.slice_range_from_bounds(r))
148 }
149
150 fn non_generic_try_slice_cloned(&self, range: Range<usize>) -> Result<Self, IndexOutOfBounds> {
151 if self.as_slice().get(range.clone()).is_none() {
152 return Err(IndexOutOfBounds::new());
153 }
154 Ok(self.clone().slice_into(range))
155 }
156
157 pub fn slice_into<R: RangeBounds<usize>>(self, r: R) -> Self {
158 let range = self.slice_range_from_bounds(r);
159 self.non_generic_slice_into(range)
160 }
161
162 fn non_generic_slice_into(self, range: Range<usize>) -> Self {
163 self.non_generic_try_slice_into(range.clone())
164 .unwrap_or_else(|this| this.out_of_bounds_panic(range))
165 }
166
167 pub fn try_slice_into<R: RangeBounds<usize>>(self, r: R) -> Result<Self, Self> {
168 let range = self.slice_range_from_bounds(r);
169 self.non_generic_try_slice_into(range)
170 }
171
172 fn non_generic_try_slice_into(mut self, range: Range<usize>) -> Result<Self, Self> {
173 match self.internal_try_slice_mut(range) {
174 Ok(()) => Ok(self),
175 Err(()) => Err(self),
176 }
177 }
178
179 pub fn slice_mut<R: RangeBounds<usize>>(&mut self, r: R) {
180 self.non_generic_slice_mut(self.slice_range_from_bounds(r))
181 }
182
183 fn non_generic_slice_mut(&mut self, range: Range<usize>) {
184 self.internal_try_slice_mut(range.clone())
185 .unwrap_or_else(|()| self.out_of_bounds_panic(range))
186 }
187
188 pub fn try_slice_mut<R: RangeBounds<usize>>(&mut self, r: R) -> Result<(), IndexOutOfBounds> {
189 self.non_generic_try_slice_mut(self.slice_range_from_bounds(r))
190 }
191
192 fn non_generic_try_slice_mut(&mut self, range: Range<usize>) -> Result<(), IndexOutOfBounds> {
193 self.internal_try_slice_mut(range)
194 .map_err(|()| IndexOutOfBounds::new())
195 }
196
197 fn slice_range_from_bounds<R: RangeBounds<usize>>(&self, r: R) -> Range<usize> {
198 range::from_slice_bounds(r, || self.len())
199 }
200
201 fn out_of_bounds_panic<R: RangeBounds<usize> + Debug, T>(&self, range: R) -> T {
202 let length = self.len();
203 panic!("slice range {range:?} is out of bounds for length {length}")
204 }
205
206 #[must_use = "`internal_try_slice_mut` may fail to mutate `self`"]
207 fn internal_try_slice_mut(&mut self, range: Range<usize>) -> Result<(), ()> {
208 match &mut self.0 {
209 Flavour::Static(old) => match old.get(range) {
210 None => Err(()),
211 Some(new) => {
212 *old = new;
213 Ok(())
214 }
215 },
216 Flavour::ArcVecSlice(x) => x.try_slice_mut(range),
217 Flavour::ArcStringSlice(x) => x.try_slice_mut(range),
218 }
219 }
220}
221
222impl AsRef<[u8]> for SharedStr {
223 #[inline]
224 fn as_ref(&self) -> &[u8] {
225 self.as_slice().as_bytes()
226 }
227}
228
229impl AsRef<str> for SharedStr {
230 #[inline]
231 fn as_ref(&self) -> &str {
232 self.as_slice()
233 }
234}
235
236impl Borrow<str> for SharedStr {
237 #[inline]
238 fn borrow(&self) -> &str {
239 self.as_slice()
240 }
241}
242
243impl Debug for SharedStr {
244 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
245 Debug::fmt(self.as_str(), f)
246 }
247}
248
249impl Display for SharedStr {
250 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
251 Display::fmt(self.as_str(), f)
252 }
253}
254
255impl Default for SharedStr {
256 #[inline]
257 fn default() -> Self {
258 Self::new()
259 }
260}
261
262impl Deref for SharedStr {
263 type Target = str;
264
265 #[inline]
266 fn deref(&self) -> &Self::Target {
267 self.as_slice()
268 }
269}
270
271impl Eq for SharedStr {}
272
273impl PartialEq for SharedStr {
274 #[inline]
275 fn eq(&self, other: &Self) -> bool {
276 self.as_slice() == other.as_slice()
277 }
278}
279
280impl<Other: ?Sized> PartialEq<&Other> for SharedStr
281where
282 Self: PartialEq<Other>,
283{
284 #[inline]
285 fn eq(&self, other: &&Other) -> bool {
286 self == *other
287 }
288}
289
290impl PartialEq<str> for SharedStr {
291 #[inline]
292 fn eq(&self, other: &str) -> bool {
293 self.as_slice() == other
294 }
295}
296
297impl PartialEq<String> for SharedStr {
298 #[inline]
299 fn eq(&self, other: &String) -> bool {
300 self.as_slice() == other.as_str()
301 }
302}
303
304impl std::hash::Hash for SharedStr {
305 fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
306 self.as_slice().hash(state)
307 }
308}
309
310impl From<&'static str> for SharedStr {
311 #[inline]
312 fn from(x: &'static str) -> Self {
313 Self::from_static(x)
314 }
315}
316
317impl From<String> for SharedStr {
318 #[inline]
319 fn from(x: String) -> Self {
320 Self::from_string(x)
321 }
322}
323
324impl From<Arc<String>> for SharedStr {
325 #[inline]
326 fn from(x: Arc<String>) -> Self {
327 Self::from_arc_string(x)
328 }
329}
330
331impl From<char> for SharedStr {
332 #[inline]
333 fn from(x: char) -> Self {
334 Self::from_string(x.into())
335 }
336}
337
338impl From<SharedStr> for String {
339 fn from(x: SharedStr) -> Self {
340 x.into_string()
341 }
342}
343
344impl FromIterator<char> for SharedStr {
345 #[inline]
346 fn from_iter<T: IntoIterator<Item = char>>(iter: T) -> Self {
347 Self::from_string(iter.into_iter().collect())
348 }
349}
350
351impl<'a> FromIterator<&'a str> for SharedStr {
352 #[inline]
353 fn from_iter<T: IntoIterator<Item = &'a str>>(iter: T) -> Self {
354 Self::from_string(iter.into_iter().collect())
355 }
356}
357
358impl FromIterator<String> for SharedStr {
359 #[inline]
360 fn from_iter<T: IntoIterator<Item = String>>(iter: T) -> Self {
361 Self::from_string(iter.into_iter().collect())
362 }
363}
364
365impl ToSocketAddrs for SharedStr {
366 type Iter = <str as ToSocketAddrs>::Iter;
367
368 #[inline]
369 fn to_socket_addrs(&self) -> io::Result<Self::Iter> {
370 self.as_str().to_socket_addrs()
371 }
372}