fast_str/backend/
mod.rs

1use super::{
2    iter::{
3        MatchIndicesInternal, MatchesInternal, SearcherIterator, SearcherIteratorRev,
4        SplitInclusiveInternal, SplitInternal, SplitNInternal,
5    },
6    pattern::{Pattern, ReverseSearcher, SearchStep, Searcher, StrSearcher},
7};
8use std::{
9    borrow::{Borrow, Cow},
10    error::Error,
11    ffi::OsStr,
12    fmt::{Debug, Display},
13    hash::Hash,
14    ops::{Add, Deref, RangeBounds},
15    path::{Path, PathBuf},
16    rc::Rc,
17    str::FromStr,
18    sync::Arc,
19};
20
21#[doc(hidden)]
22#[cfg(any(
23    not(feature = "stack"),
24    target_pointer_width = "16",
25    target_pointer_width = "32"
26))]
27#[path = "normal.rs"]
28mod internal;
29#[doc(hidden)]
30#[cfg(not(any(
31    not(feature = "stack"),
32    target_pointer_width = "16",
33    target_pointer_width = "32"
34)))]
35#[path = "stack.rs"]
36mod internal;
37
38pub use self::internal::FastStr;
39
40unsafe impl Sync for FastStr {}
41unsafe impl Send for FastStr {}
42
43impl FastStr {
44    /// Creates a new [FastStr] by repeating a string `n` times.
45    ///
46    /// # Examples
47    ///
48    /// Basic usage:
49    ///
50    /// ```
51    /// use fast_str::FastStr;
52    /// assert_eq!(FastStr::from("abc").repeat(4), "abcabcabcabc");
53    /// ```
54    pub fn repeat(&self, n: usize) -> Self {
55        if n == 1 {
56            self.clone()
57        } else {
58            Self::from_string(self.as_str().repeat(n))
59        }
60    }
61
62    /// Returns a copy of this string where each character is mapped to its
63    /// ASCII upper case equivalent.
64    ///
65    /// ASCII letters 'a' to 'z' are mapped to 'A' to 'Z',
66    /// but non-ASCII letters are unchanged.
67    ///
68    /// To uppercase ASCII characters in addition to non-ASCII characters, use
69    /// [`to_uppercase`].
70    ///
71    /// # Examples
72    ///
73    /// ```
74    /// use fast_str::FastStr;
75    /// let s = FastStr::from("Grüße, Jürgen ❤");
76    ///
77    /// assert_eq!("GRüßE, JüRGEN ❤", s.to_ascii_uppercase());
78    /// ```
79    ///
80    /// [`to_uppercase`]: #method.to_uppercase
81    #[inline]
82    pub fn to_ascii_uppercase(&self) -> Self {
83        Self::from_string(self.as_str().to_ascii_uppercase())
84    }
85
86    /// Returns a copy of this string where each character is mapped to its
87    /// ASCII lower case equivalent.
88    ///
89    /// ASCII letters 'A' to 'Z' are mapped to 'a' to 'z',
90    /// but non-ASCII letters are unchanged.
91    ///
92    /// To lowercase ASCII characters in addition to non-ASCII characters, use
93    /// [`to_lowercase`].
94    ///
95    /// # Examples
96    ///
97    /// ```
98    /// use fast_str::FastStr;
99    /// let s = FastStr::from("Grüße, Jürgen ❤");
100    ///
101    /// assert_eq!("grüße, jürgen ❤", s.to_ascii_lowercase());
102    /// ```
103    ///
104    /// [`to_lowercase`]: #method.to_lowercase
105    #[inline]
106    pub fn to_ascii_lowercase(&self) -> Self {
107        Self::from_string(self.as_str().to_ascii_lowercase())
108    }
109
110    /// Returns the uppercase equivalent of this string slice, as a new [FastStr].
111    ///
112    /// 'Uppercase' is defined according to the terms of the Unicode Derived Core Property
113    /// `Uppercase`.
114    ///
115    /// Since some characters can expand into multiple characters when changing
116    /// the case, this function returns a [FastStr] instead of modifying the
117    /// parameter in-place.
118    ///
119    /// # Examples
120    ///
121    /// Basic usage:
122    ///
123    /// ```
124    /// use fast_str::FastStr;
125    /// let s = FastStr::from("hello");
126    ///
127    /// assert_eq!("HELLO", s.to_uppercase());
128    /// ```
129    ///
130    /// Scripts without case are not changed:
131    ///
132    /// ```
133    /// use fast_str::FastStr;
134    /// let new_year = FastStr::from("农历新年");
135    ///
136    /// assert_eq!(new_year, new_year.to_uppercase());
137    /// ```
138    ///
139    /// One character can become multiple:
140    /// ```
141    /// use fast_str::FastStr;
142    /// let s = FastStr::from("tschüß");
143    ///
144    /// assert_eq!("TSCHÜSS", s.to_uppercase());
145    /// ```
146    #[inline]
147    pub fn to_uppercase(&self) -> Self {
148        Self::from_string(self.as_str().to_uppercase())
149    }
150
151    /// Returns the lowercase equivalent of this string slice, as a new [FastStr].
152    ///
153    /// 'Lowercase' is defined according to the terms of the Unicode Derived Core Property
154    /// `Lowercase`.
155    ///
156    /// Since some characters can expand into multiple characters when changing
157    /// the case, this function returns a [FastStr] instead of modifying the
158    /// parameter in-place.
159    ///
160    /// # Examples
161    ///
162    /// Basic usage:
163    ///
164    /// ```
165    /// use fast_str::FastStr;
166    /// let s = FastStr::from("HELLO");
167    ///
168    /// assert_eq!("hello", s.to_lowercase());
169    /// ```
170    ///
171    /// A tricky example, with sigma:
172    ///
173    /// ```
174    /// use fast_str::FastStr;
175    /// let sigma = FastStr::from("Σ");
176    ///
177    /// assert_eq!("σ", sigma.to_lowercase());
178    ///
179    /// // but at the end of a word, it's ς, not σ:
180    /// let odysseus = FastStr::from("ὈΔΥΣΣΕΎΣ");
181    ///
182    /// assert_eq!("ὀδυσσεύς", odysseus.to_lowercase());
183    /// ```
184    ///
185    /// Languages without case are not changed:
186    ///
187    /// ```
188    /// use fast_str::FastStr;
189    /// let new_year = FastStr::from("农历新年");
190    ///
191    /// assert_eq!(new_year, new_year.to_lowercase());
192    /// ```
193    #[inline]
194    pub fn to_lowercase(&self) -> Self {
195        Self::from_string(self.as_str().to_lowercase())
196    }
197
198    /// Converts a string slice to a byte slice.
199    ///
200    /// # Examples
201    ///
202    /// Basic usage:
203    ///
204    /// ```
205    /// use fast_str::FastStr;
206    /// let bytes = FastStr::from("bors").as_bytes();
207    /// assert_eq!(b"bors", bytes);
208    /// ```
209    #[inline]
210    pub fn as_bytes(&self) -> &[u8] {
211        self.as_str().as_bytes()
212    }
213
214    /// Returns an substring of [FastStr].
215    ///
216    /// # Examples
217    ///
218    /// ```
219    /// use fast_str::FastStr;
220    /// let v = FastStr::from("🗻∈🌏");
221    ///
222    /// assert_eq!("🗻", v.slice(0..4));
223    /// assert_eq!("∈", v.slice(4..7));
224    /// assert_eq!("🌏", v.slice(7..11));
225    /// ```
226    pub fn slice<R>(&self, range: R) -> Self
227    where
228        R: RangeBounds<usize>,
229    {
230        use std::ops::Bound;
231
232        self.do_sub_with(|str, wrapper| {
233            let len = str.len();
234
235            let start = match range.start_bound() {
236                Bound::Included(&n) => std::cmp::max(0, n),
237                Bound::Excluded(&n) => std::cmp::max(0, n + 1),
238                Bound::Unbounded => 0,
239            };
240
241            let end = match range.end_bound() {
242                Bound::Included(&n) => std::cmp::min(len, n + 1),
243                Bound::Excluded(&n) => std::cmp::min(len, n),
244                Bound::Unbounded => len,
245            };
246
247            wrapper(&str[start..end])
248        })
249    }
250
251    /// Returns a [FastStr] with leading and trailing whitespace removed.
252    ///
253    /// 'Whitespace' is defined according to the terms of the Unicode Derived
254    /// Core Property `White_Space`, which includes newlines.
255    ///
256    /// # Examples
257    ///
258    /// Basic usage:
259    ///
260    /// ```
261    /// use fast_str::FastStr;
262    /// let s = FastStr::from("\n Hello\tworld\t\n");
263    ///
264    /// assert_eq!("Hello\tworld", s.trim());
265    /// ```
266    #[inline]
267    pub fn trim(&self) -> Self {
268        self.do_sub_with(|str, wrapper| wrapper(str.trim()))
269    }
270
271    #[inline]
272    pub fn trim_into(self) -> Self {
273        self.do_sub_into(|str| str.trim())
274    }
275
276    /// Returns a [FastStr] with leading whitespace removed.
277    ///
278    /// 'Whitespace' is defined according to the terms of the Unicode Derived
279    /// Core Property `White_Space`, which includes newlines.
280    ///
281    /// # Text directionality
282    ///
283    /// A string is a sequence of bytes. `start` in this context means the first
284    /// position of that byte string; for a left-to-right language like English or
285    /// Russian, this will be left side, and for right-to-left languages like
286    /// Arabic or Hebrew, this will be the right side.
287    ///
288    /// # Examples
289    ///
290    /// Basic usage:
291    ///
292    /// ```
293    /// use fast_str::FastStr;
294    /// let s = FastStr::from("\n Hello\tworld\t\n");
295    /// assert_eq!("Hello\tworld\t\n", s.trim_start());
296    /// ```
297    #[inline]
298    pub fn trim_start(&self) -> Self {
299        self.do_sub_with(|str, wrapper| wrapper(str.trim_start()))
300    }
301
302    #[inline]
303    pub fn trim_start_into(self) -> Self {
304        self.do_sub_into(|str| str.trim_start())
305    }
306
307    /// Returns a [FastStr] with leading whitespace removed.
308    ///
309    /// 'Whitespace' is defined according to the terms of the Unicode Derived
310    /// Core Property `White_Space`.
311    ///
312    /// # Text directionality
313    ///
314    /// A string is a sequence of bytes. 'Left' in this context means the first
315    /// position of that byte string; for a language like Arabic or Hebrew
316    /// which are 'right to left' rather than 'left to right', this will be
317    /// the _right_ side, not the left.
318    ///
319    /// # Examples
320    ///
321    /// Basic usage:
322    ///
323    /// ```
324    /// use fast_str::FastStr;
325    /// let s = FastStr::from(" Hello\tworld\t");
326    ///
327    /// assert_eq!("Hello\tworld\t", s.trim_left());
328    /// ```
329    #[inline]
330    pub fn trim_end(&self) -> Self {
331        self.do_sub_with(|str, wrapper| wrapper(str.trim_end()))
332    }
333
334    #[inline]
335    pub fn trim_end_into(self) -> Self {
336        self.do_sub_into(|str| str.trim_end())
337    }
338
339    /// An iterator over the disjoint matches of a pattern within the given [FastStr].
340    ///
341    /// The `pattern` can be a `&str`, `char`, a slice of `char`s, or a
342    /// function or closure that determines if a character matches.
343    ///
344    /// [`rmatches`]: str::matches
345    ///
346    /// # Examples
347    ///
348    /// Basic usage:
349    ///
350    /// ```
351    /// use fast_str::FastStr;
352    /// let v: Vec<&str> = FastStr::from("abcXXXabcYYYabc").matches("abc").collect();
353    /// //["abc", "abc", "abc"];
354    ///
355    /// let v: Vec<&str> = "1abc2abc3".matches(char::is_numeric).collect();
356    /// assert_eq!(v, ["1", "2", "3"]);
357    /// ```
358    pub fn matches<'a, P: Pattern<'a> + 'a>(
359        &'a self,
360        pat: P,
361    ) -> impl Iterator<Item = FastStr> + 'a {
362        self.do_sub_with(move |str, wrapper| {
363            SearcherIterator::new(MatchesInternal::<P>::new(pat.into_searcher(str))).map(wrapper)
364        })
365    }
366
367    /// An iterator over the disjoint matches of a pattern within this [FastStr]
368    /// as well as the index that the match starts at.
369    ///
370    /// For matches of `pat` within `self` that overlap, only the indices
371    /// corresponding to the first match are returned.
372    ///
373    /// The `pattern` can be a `&str`, `char`, a slice of `char`s, or a
374    /// function or closure that determines if a character matches.
375    ///
376    /// # Examples
377    ///
378    /// Basic usage:
379    ///
380    /// ```
381    /// use fast_str::FastStr;
382    /// let v: Vec<_> = FastStr::from("abcXXXabcYYYabc").match_indices("abc").collect();
383    /// //[(0, "abc"), (6, "abc"), (12, "abc")];
384    /// ```
385    pub fn match_indices<'a, P: Pattern<'a> + 'a>(
386        &'a self,
387        pat: P,
388    ) -> impl Iterator<Item = (usize, FastStr)> + 'a {
389        self.do_sub_with(move |str, wrapper| {
390            SearcherIterator::new(MatchIndicesInternal::<P>::new(pat.into_searcher(str)))
391                .map(move |(i, str)| (i, wrapper(str)))
392        })
393    }
394
395    /// An iterator over the disjoint matches of a pattern within this [FastStr],
396    /// yielded in reverse order.
397    ///
398    /// The `pattern` can be a `&str`, `char`, a slice of `char`s, or a
399    /// function or closure that determines if a character matches.
400    ///
401    /// # Examples
402    ///
403    /// Basic usage:
404    ///
405    /// ```
406    /// use fast_str::FastStr;
407    /// let v: Vec<&str> = FastStr::from("abcXXXabcYYYabc").rmatches("abc").collect();
408    /// //["abc", "abc", "abc"];
409    /// ```
410    pub fn rmatches<'a, P: Pattern<'a> + 'a>(&'a self, pat: P) -> impl Iterator<Item = FastStr> + 'a
411    where
412        P::Searcher: ReverseSearcher<'a>,
413    {
414        self.do_sub_with(move |str, wrapper| {
415            SearcherIteratorRev::new(MatchesInternal::<P>::new(pat.into_searcher(str))).map(wrapper)
416        })
417    }
418
419    /// An iterator over the disjoint matches of a pattern within `self`,
420    /// yielded in reverse order along with the index of the match.
421    ///
422    /// For matches of `pat` within `self` that overlap, only the indices
423    /// corresponding to the last match are returned.
424    ///
425    /// The `pattern` can be a `&str`, `char`, a slice of `char`s, or a
426    /// function or closure that determines if a character matches.
427    ///
428    /// # Examples
429    ///
430    /// Basic usage:
431    ///
432    /// ```
433    /// use fast_str::FastStr;
434    /// let v: Vec<_> = FastStr::from("abcXXXabcYYYabc").rmatch_indices("abc").collect();
435    /// // [(12, "abc"), (6, "abc"), (0, "abc")];
436    /// ```
437    pub fn rmatch_indices<'a, P: Pattern<'a> + 'a>(
438        &'a self,
439        pat: P,
440    ) -> impl Iterator<Item = (usize, FastStr)> + 'a
441    where
442        P::Searcher: ReverseSearcher<'a>,
443    {
444        self.do_sub_with(move |str, wrapper| {
445            SearcherIteratorRev::new(MatchIndicesInternal::<P>::new(pat.into_searcher(str)))
446                .map(move |(i, str)| (i, wrapper(str)))
447        })
448    }
449
450    /// Replaces all matches of a pattern with another string.
451    ///
452    /// `replace` creates a new [FastStr], and copies the data from this string slice into it.
453    /// While doing so, it attempts to find matches of a pattern. If it finds any, it
454    /// replaces them with the replacement string slice.
455    ///
456    /// # Examples
457    ///
458    /// Basic usage:
459    ///
460    /// ```
461    /// use fast_str::FastStr;
462    /// let s = FastStr::from("this is old");
463    ///
464    /// assert_eq!("this is new", s.replace("old", "new"));
465    /// assert_eq!("than an old", s.replace("is", "an"));
466    /// ```
467    ///
468    /// When the pattern doesn't match:
469    ///
470    /// ```
471    /// use fast_str::FastStr;
472    /// let s = FastStr::from("this is old");
473    /// assert_eq!(s, s.replace("cookie monster", "little lamb"));
474    /// ```
475    pub fn replace<'a, P: Pattern<'a> + 'a, To: AsRef<str>>(&'a self, from: P, to: To) -> FastStr {
476        let mut result = String::with_capacity(32);
477        let mut last_end = 0;
478        let to = to.as_ref();
479        let str = self.as_str();
480        for (start, part) in
481            SearcherIterator::new(MatchIndicesInternal::<P>::new(from.into_searcher(str)))
482        {
483            result.push_str(unsafe { str.get_unchecked(last_end..start) });
484            result.push_str(to);
485            last_end = start + part.len();
486        }
487        result.push_str(unsafe { str.get_unchecked(last_end..str.len()) });
488        result.into()
489    }
490
491    /// Replaces first N matches of a pattern with another string.
492    ///
493    /// `replacen` creates a new [FastStr], and copies the data from this string slice into it.
494    /// While doing so, it attempts to find matches of a pattern. If it finds any, it
495    /// replaces them with the replacement string slice at most `count` times.
496    ///
497    /// # Examples
498    ///
499    /// Basic usage:
500    ///
501    /// ```
502    /// use fast_str::FastStr;
503    /// let s = FastStr::from("foo foo 123 foo");
504    /// assert_eq!("new new 123 foo", s.replacen("foo", "new", 2));
505    /// assert_eq!("faa fao 123 foo", s.replacen('o', "a", 3));
506    /// assert_eq!("foo foo new23 foo", s.replacen(char::is_numeric, "new", 1));
507    /// ```
508    ///
509    /// When the pattern doesn't match:
510    ///
511    /// ```
512    /// use fast_str::FastStr;
513    /// let s = FastStr::from("this is old");
514    /// assert_eq!(s, s.replacen("cookie monster", "little lamb", 10));
515    /// ```
516    pub fn replacen<'a, P: Pattern<'a> + 'a, To: AsRef<str>>(
517        &'a self,
518        from: P,
519        to: To,
520        count: usize,
521    ) -> FastStr {
522        let mut result = String::with_capacity(32);
523        let mut last_end = 0;
524        let to = to.as_ref();
525        let str = self.as_str();
526        for (start, part) in
527            SearcherIterator::new(MatchIndicesInternal::<P>::new(from.into_searcher(str)))
528                .take(count)
529        {
530            result.push_str(unsafe { str.get_unchecked(last_end..start) });
531            result.push_str(to);
532            last_end = start + part.len();
533        }
534        result.push_str(unsafe { str.get_unchecked(last_end..str.len()) });
535        result.into()
536    }
537
538    /// An iterator over substrings of this string slice, separated by
539    /// characters matched by a pattern.
540    pub fn split<'a, P: Pattern<'a> + 'a>(&'a self, pat: P) -> impl Iterator<Item = FastStr> + 'a {
541        self.do_sub_with(move |str, wrapper| {
542            SearcherIterator::new(SplitInternal::<P> {
543                start: 0,
544                end: str.len(),
545                matcher: pat.into_searcher(str),
546                allow_trailing_empty: true,
547                finished: false,
548            })
549            .map(wrapper)
550        })
551    }
552
553    pub fn splitn<'a, P: Pattern<'a> + 'a>(
554        &'a self,
555        n: usize,
556        pat: P,
557    ) -> impl Iterator<Item = FastStr> + 'a {
558        self.do_sub_with(move |str, wrapper| {
559            SearcherIterator::new(SplitNInternal::<P> {
560                iter: SplitInternal {
561                    start: 0,
562                    end: str.len(),
563                    matcher: pat.into_searcher(str),
564                    allow_trailing_empty: true,
565                    finished: false,
566                },
567                count: n,
568            })
569            .map(wrapper)
570        })
571    }
572
573    pub fn split_terminator<'a, P: Pattern<'a> + 'a>(
574        &'a self,
575        pat: P,
576    ) -> impl Iterator<Item = FastStr> + 'a {
577        self.do_sub_with(move |str, wrapper| {
578            SearcherIterator::new(SplitInternal::<P> {
579                start: 0,
580                end: str.len(),
581                matcher: pat.into_searcher(str),
582                allow_trailing_empty: false,
583                finished: false,
584            })
585            .map(wrapper)
586        })
587    }
588
589    /// An iterator over substrings of this [FastStr], separated by
590    /// characters matched by a pattern. Differs from the iterator produced by
591    /// `split` in that `split_inclusive` leaves the matched part as the
592    /// terminator of the substring.
593    pub fn split_inclusive<'a, P: Pattern<'a> + 'a>(
594        &'a self,
595        pat: P,
596    ) -> impl Iterator<Item = FastStr> + 'a {
597        self.do_sub_with(move |str, wrapper| {
598            SearcherIterator::new(SplitInclusiveInternal::<P>(SplitInternal {
599                start: 0,
600                end: str.len(),
601                matcher: pat.into_searcher(str),
602                allow_trailing_empty: false,
603                finished: false,
604            }))
605            .map(wrapper)
606        })
607    }
608
609    pub fn split_whitespace<'a>(&'a self) -> impl Iterator<Item = FastStr> + 'a {
610        self.split(char::is_whitespace)
611            .filter(|str| !str.is_empty())
612    }
613
614    pub fn split_ascii_whitespace<'a>(&'a self) -> impl Iterator<Item = FastStr> + 'a {
615        self.do_sub_with(move |str, wrapper| {
616            str.as_bytes()
617                .split(u8::is_ascii_whitespace)
618                .filter(|bytes| !bytes.is_empty())
619                .map(move |bytes| wrapper(unsafe { std::str::from_utf8_unchecked(bytes) }))
620        })
621    }
622
623    pub fn split_once<'a, P: Pattern<'a>>(&'a self, delimiter: P) -> Option<(FastStr, FastStr)> {
624        self.do_sub_with(move |str, wrapper| {
625            let (start, end) = delimiter.into_searcher(str).next_match()?;
626            // SAFETY: `Searcher` is known to return valid indices.
627            unsafe {
628                Some((
629                    wrapper(str.get_unchecked(..start)),
630                    wrapper(str.get_unchecked(end..)),
631                ))
632            }
633        })
634    }
635
636    pub fn split_at(&self, mid: usize) -> (FastStr, FastStr) {
637        self.do_sub_with(move |str, wrapper| {
638            // is_char_boundary checks that the index is in [0, .len()]
639            if str.is_char_boundary(mid) {
640                // SAFETY: just checked that `mid` is on a char boundary.
641                unsafe {
642                    (
643                        wrapper(str.get_unchecked(0..mid)),
644                        wrapper(str.get_unchecked(mid..str.len())),
645                    )
646                }
647            } else {
648                panic!("failed to slice string");
649            }
650        })
651    }
652
653    pub fn rsplit<'a, P: Pattern<'a> + 'a>(&'a self, pat: P) -> impl Iterator<Item = FastStr> + 'a
654    where
655        P::Searcher: ReverseSearcher<'a>,
656    {
657        self.do_sub_with(move |str, wrapper| {
658            SearcherIteratorRev::new(SplitInternal::<P> {
659                start: 0,
660                end: str.len(),
661                matcher: pat.into_searcher(str),
662                allow_trailing_empty: true,
663                finished: false,
664            })
665            .map(wrapper)
666        })
667    }
668
669    pub fn rsplitn<'a, P: Pattern<'a> + 'a>(
670        &'a self,
671        n: usize,
672        pat: P,
673    ) -> impl Iterator<Item = FastStr> + 'a
674    where
675        P::Searcher: ReverseSearcher<'a>,
676    {
677        self.do_sub_with(move |str, wrapper| {
678            SearcherIteratorRev::new(SplitNInternal::<P> {
679                iter: SplitInternal {
680                    start: 0,
681                    end: str.len(),
682                    matcher: pat.into_searcher(str),
683                    allow_trailing_empty: true,
684                    finished: false,
685                },
686                count: n,
687            })
688            .map(wrapper)
689        })
690    }
691
692    pub fn rsplit_terminator<'a, P: Pattern<'a> + 'a>(
693        &'a self,
694        pat: P,
695    ) -> impl Iterator<Item = FastStr> + 'a
696    where
697        P::Searcher: ReverseSearcher<'a>,
698    {
699        self.do_sub_with(move |str, wrapper| {
700            SearcherIteratorRev::new(SplitInternal::<P> {
701                start: 0,
702                end: str.len(),
703                matcher: pat.into_searcher(str),
704                allow_trailing_empty: false,
705                finished: false,
706            })
707            .map(wrapper)
708        })
709    }
710
711    pub fn rsplit_once<'a, P: Pattern<'a>>(&'a self, delimiter: P) -> Option<(FastStr, FastStr)>
712    where
713        P::Searcher: ReverseSearcher<'a>,
714    {
715        self.do_sub_with(move |str, wrapper| {
716            let (start, end) = delimiter.into_searcher(str).next_match_back()?;
717            // SAFETY: `Searcher` is known to return valid indices.
718            unsafe {
719                Some((
720                    wrapper(str.get_unchecked(..start)),
721                    wrapper(str.get_unchecked(end..)),
722                ))
723            }
724        })
725    }
726
727    /// Returns a [FastStr] with the prefix removed.
728    ///
729    /// If the string starts with the pattern `prefix`, returns substring after the prefix, wrapped
730    /// in `Some`.  Unlike `trim_start_matches`, this method removes the prefix exactly once.
731    ///
732    /// If the string does not start with `prefix`, returns `None`.
733    ///
734    /// # Examples
735    ///
736    /// ```
737    /// use fast_str::FastStr;
738    /// assert_eq!(FastStr::from("foo:bar").strip_prefix("foo:"), Some(FastStr("bar")));
739    /// assert_eq!(FastStr::from("foo:bar").strip_prefix("bar"), None);
740    /// assert_eq!(FastStr::from("foofoo").strip_prefix("foo"), Some(FastStr("foo")));
741    /// ```
742    pub fn strip_prefix<'a, P: Pattern<'a>>(&'a self, prefix: P) -> Option<FastStr> {
743        self.do_sub_with(|str, wrapper| prefix.strip_prefix_of(str).map(wrapper))
744    }
745
746    /// Returns a [FastStr] with the suffix removed.
747    ///
748    /// If the string ends with the pattern `suffix`, returns the substring before the suffix,
749    /// wrapped in `Some`.  Unlike `trim_end_matches`, this method removes the suffix exactly once.
750    ///
751    /// If the string does not end with `suffix`, returns `None`.
752    ///
753    /// # Examples
754    ///
755    /// ```
756    /// use fast_str::FastStr;
757    /// assert_eq!(FastStr::from("bar:foo").strip_suffix(":foo"), Some(FastStr::from("bar")));
758    /// assert_eq!(FastStr::from("bar:foo").strip_suffix("bar"), None);
759    /// assert_eq!(FastStr::from("foofoo").strip_suffix("foo"), Some(FastStr::from("foo")));
760    /// ```
761    pub fn strip_suffix<'a, P: Pattern<'a>>(&'a self, suffix: P) -> Option<FastStr>
762    where
763        P::Searcher: ReverseSearcher<'a>,
764    {
765        self.do_sub_with(|str, wrapper| suffix.strip_suffix_of(str).map(wrapper))
766    }
767}
768
769impl Default for FastStr {
770    #[inline]
771    fn default() -> Self {
772        Self::new()
773    }
774}
775
776impl Default for &FastStr {
777    #[inline]
778    fn default() -> Self {
779        const FAST_STR_DEFAULT: &FastStr = &FastStr::new();
780        FAST_STR_DEFAULT
781    }
782}
783
784impl Deref for FastStr {
785    type Target = str;
786
787    #[inline]
788    fn deref(&self) -> &Self::Target {
789        self.as_str()
790    }
791}
792
793impl Borrow<str> for FastStr {
794    #[inline]
795    fn borrow(&self) -> &str {
796        self.as_str()
797    }
798}
799
800impl AsRef<str> for FastStr {
801    #[inline]
802    fn as_ref(&self) -> &str {
803        self.as_str()
804    }
805}
806
807impl AsRef<[u8]> for FastStr {
808    #[inline]
809    fn as_ref(&self) -> &[u8] {
810        self.as_str().as_ref()
811    }
812}
813
814impl AsRef<Path> for FastStr {
815    #[inline]
816    fn as_ref(&self) -> &Path {
817        self.as_str().as_ref()
818    }
819}
820
821impl AsRef<OsStr> for FastStr {
822    #[inline]
823    fn as_ref(&self) -> &OsStr {
824        self.as_str().as_ref()
825    }
826}
827
828impl Hash for FastStr {
829    #[inline]
830    fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
831        self.as_str().hash(state)
832    }
833}
834
835impl Eq for FastStr {}
836
837impl PartialEq for FastStr {
838    #[inline]
839    fn eq(&self, other: &Self) -> bool {
840        PartialEq::eq(self, other.as_str())
841    }
842}
843
844impl PartialEq<&FastStr> for FastStr {
845    #[inline]
846    fn eq(&self, other: &&FastStr) -> bool {
847        PartialEq::eq(self, *other)
848    }
849}
850
851impl PartialEq<str> for FastStr {
852    #[inline]
853    fn eq(&self, other: &str) -> bool {
854        let this = self.as_str();
855        std::ptr::eq(std::ptr::addr_of!(*this), std::ptr::addr_of!(*other))
856            || PartialEq::eq(this, other)
857    }
858}
859
860impl PartialEq<FastStr> for str {
861    #[inline]
862    fn eq(&self, other: &FastStr) -> bool {
863        PartialEq::eq(other, self)
864    }
865}
866
867impl PartialEq<&str> for FastStr {
868    #[inline]
869    fn eq(&self, other: &&str) -> bool {
870        PartialEq::eq(self, *other)
871    }
872}
873
874impl PartialEq<FastStr> for &str {
875    #[inline]
876    fn eq(&self, other: &FastStr) -> bool {
877        PartialEq::eq(other, *self)
878    }
879}
880
881impl PartialEq<&FastStr> for str {
882    #[inline]
883    fn eq(&self, other: &&FastStr) -> bool {
884        PartialEq::eq(*other, self)
885    }
886}
887
888impl PartialEq<String> for FastStr {
889    #[inline]
890    fn eq(&self, other: &String) -> bool {
891        PartialEq::eq(self.as_str(), other.as_str())
892    }
893}
894
895impl PartialEq<FastStr> for String {
896    #[inline]
897    fn eq(&self, other: &FastStr) -> bool {
898        PartialEq::eq(other, self)
899    }
900}
901
902impl PartialEq<&String> for FastStr {
903    #[inline]
904    fn eq(&self, other: &&String) -> bool {
905        PartialEq::eq(self.as_str(), other.as_str())
906    }
907}
908
909impl PartialEq<FastStr> for &String {
910    #[inline]
911    fn eq(&self, other: &FastStr) -> bool {
912        PartialEq::eq(other, self)
913    }
914}
915
916impl Ord for FastStr {
917    #[inline]
918    fn cmp(&self, other: &Self) -> std::cmp::Ordering {
919        let str1 = self.as_str();
920        let str2 = other.as_str();
921        if std::ptr::eq(std::ptr::addr_of!(*str1), std::ptr::addr_of!(*str2)) {
922            return std::cmp::Ordering::Equal;
923        }
924        Ord::cmp(str1, str2)
925    }
926}
927
928impl PartialOrd for FastStr {
929    #[inline]
930    fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
931        PartialOrd::partial_cmp(self, other.as_str())
932    }
933}
934
935impl PartialOrd<&FastStr> for FastStr {
936    #[inline]
937    fn partial_cmp(&self, other: &&FastStr) -> Option<std::cmp::Ordering> {
938        PartialOrd::partial_cmp(self, *other)
939    }
940}
941
942impl PartialOrd<str> for FastStr {
943    #[inline]
944    fn partial_cmp(&self, other: &str) -> Option<std::cmp::Ordering> {
945        let str1 = self.as_str();
946        let str2 = other;
947        if std::ptr::eq(std::ptr::addr_of!(*str1), std::ptr::addr_of!(*str2)) {
948            return Some(std::cmp::Ordering::Equal);
949        }
950        PartialOrd::partial_cmp(self.as_str(), other)
951    }
952}
953
954impl PartialOrd<FastStr> for str {
955    #[inline]
956    fn partial_cmp(&self, other: &FastStr) -> Option<std::cmp::Ordering> {
957        PartialOrd::partial_cmp(other, self)
958    }
959}
960
961impl PartialOrd<&str> for FastStr {
962    #[inline]
963    fn partial_cmp(&self, other: &&str) -> Option<std::cmp::Ordering> {
964        PartialOrd::partial_cmp(self.as_str(), *other)
965    }
966}
967
968impl PartialOrd<&FastStr> for str {
969    #[inline]
970    fn partial_cmp(&self, other: &&FastStr) -> Option<std::cmp::Ordering> {
971        PartialOrd::partial_cmp(*other, self)
972    }
973}
974
975impl PartialOrd<FastStr> for &str {
976    #[inline]
977    fn partial_cmp(&self, other: &FastStr) -> Option<std::cmp::Ordering> {
978        PartialOrd::partial_cmp(other, *self)
979    }
980}
981
982impl PartialOrd<String> for FastStr {
983    #[inline]
984    fn partial_cmp(&self, other: &String) -> Option<std::cmp::Ordering> {
985        PartialOrd::partial_cmp(self.as_str(), other.as_str())
986    }
987}
988
989impl PartialOrd<FastStr> for String {
990    #[inline]
991    fn partial_cmp(&self, other: &FastStr) -> Option<std::cmp::Ordering> {
992        PartialOrd::partial_cmp(other, self)
993    }
994}
995
996impl PartialOrd<&String> for FastStr {
997    #[inline]
998    fn partial_cmp(&self, other: &&String) -> Option<std::cmp::Ordering> {
999        PartialOrd::partial_cmp(self.as_str(), other.as_str())
1000    }
1001}
1002
1003impl PartialOrd<FastStr> for &String {
1004    #[inline]
1005    fn partial_cmp(&self, other: &FastStr) -> Option<std::cmp::Ordering> {
1006        PartialOrd::partial_cmp(other, *self)
1007    }
1008}
1009
1010impl Debug for FastStr {
1011    #[inline]
1012    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1013        Debug::fmt(self.as_str(), f)
1014    }
1015}
1016
1017impl Display for FastStr {
1018    #[inline]
1019    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1020        Display::fmt(self.as_str(), f)
1021    }
1022}
1023
1024#[cfg(feature = "serde")]
1025impl serde::Serialize for FastStr {
1026    #[inline]
1027    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
1028    where
1029        S: serde::Serializer,
1030    {
1031        serde::Serialize::serialize(self.as_str(), serializer)
1032    }
1033}
1034
1035#[cfg(feature = "serde")]
1036impl<'de> serde::Deserialize<'de> for FastStr {
1037    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
1038    where
1039        D: serde::Deserializer<'de>,
1040    {
1041        let result = <String as serde::Deserialize>::deserialize(deserializer);
1042
1043        match result {
1044            Ok(ok) => Ok(Self::from_string(ok)),
1045            Err(err) => Err(err),
1046        }
1047    }
1048}
1049
1050impl FromStr for FastStr {
1051    type Err = <String as FromStr>::Err;
1052
1053    #[inline]
1054    fn from_str(s: &str) -> Result<Self, Self::Err> {
1055        let result = FromStr::from_str(s);
1056        match result {
1057            Ok(ok) => Ok(Self::from_string(ok)),
1058            Err(err) => Err(err),
1059        }
1060    }
1061}
1062
1063impl TryFrom<&[u8]> for FastStr {
1064    type Error = std::str::Utf8Error;
1065
1066    fn try_from(value: &[u8]) -> Result<Self, Self::Error> {
1067        std::str::from_utf8(value).map(Self::from_ref)
1068    }
1069}
1070
1071impl TryFrom<Vec<u8>> for FastStr {
1072    type Error = std::string::FromUtf8Error;
1073
1074    fn try_from(value: Vec<u8>) -> Result<Self, Self::Error> {
1075        String::from_utf8(value).map(Self::from_string)
1076    }
1077}
1078
1079impl From<&&str> for FastStr {
1080    #[inline]
1081    fn from(str: &&str) -> Self {
1082        Self::from_ref(*str)
1083    }
1084}
1085
1086impl From<&'static str> for FastStr {
1087    #[inline]
1088    fn from(str: &'static str) -> Self {
1089        Self::from_static(str)
1090    }
1091}
1092
1093impl From<&mut str> for FastStr {
1094    #[inline]
1095    fn from(str: &mut str) -> Self {
1096        Self::from_ref(str)
1097    }
1098}
1099
1100impl From<Rc<str>> for FastStr {
1101    #[inline]
1102    fn from(str: Rc<str>) -> Self {
1103        Self::from_ref(str.as_ref())
1104    }
1105}
1106
1107impl From<Arc<str>> for FastStr {
1108    #[inline]
1109    fn from(str: Arc<str>) -> Self {
1110        Self::from_ref(str.as_ref())
1111    }
1112}
1113
1114impl From<Box<str>> for FastStr {
1115    #[inline]
1116    fn from(str: Box<str>) -> Self {
1117        Self::from_string(str.into())
1118    }
1119}
1120
1121impl From<String> for FastStr {
1122    #[inline]
1123    fn from(str: String) -> Self {
1124        Self::from_string(str)
1125    }
1126}
1127
1128impl From<&String> for FastStr {
1129    #[inline]
1130    fn from(str: &String) -> Self {
1131        Self::from_ref(str)
1132    }
1133}
1134
1135impl From<&FastStr> for FastStr {
1136    #[inline]
1137    fn from(str: &FastStr) -> Self {
1138        str.clone()
1139    }
1140}
1141
1142impl From<Cow<'_, str>> for FastStr {
1143    #[inline]
1144    fn from(str: Cow<'_, str>) -> Self {
1145        Self::from_string(str.into_owned())
1146    }
1147}
1148
1149impl From<&Cow<'_, str>> for FastStr {
1150    #[inline]
1151    fn from(str: &Cow<'_, str>) -> Self {
1152        Self::from_ref(str.as_ref())
1153    }
1154}
1155
1156impl From<Cow<'_, String>> for FastStr {
1157    #[inline]
1158    fn from(str: Cow<'_, String>) -> Self {
1159        Self::from_string(str.into_owned())
1160    }
1161}
1162
1163impl From<&Cow<'_, String>> for FastStr {
1164    #[inline]
1165    fn from(str: &Cow<'_, String>) -> Self {
1166        Self::from_ref(str.as_ref())
1167    }
1168}
1169
1170impl From<()> for FastStr {
1171    #[inline]
1172    fn from(_: ()) -> Self {
1173        Self::new()
1174    }
1175}
1176
1177impl From<&()> for FastStr {
1178    #[inline]
1179    fn from(_: &()) -> Self {
1180        Self::new()
1181    }
1182}
1183
1184impl From<bool> for FastStr {
1185    #[inline]
1186    fn from(b: bool) -> Self {
1187        Self::from_static(if b { "true" } else { "false" })
1188    }
1189}
1190
1191impl From<&bool> for FastStr {
1192    #[inline]
1193    fn from(b: &bool) -> Self {
1194        Self::from(*b)
1195    }
1196}
1197
1198impl From<FastStr> for String {
1199    #[inline]
1200    fn from(str: FastStr) -> Self {
1201        str.into_string()
1202    }
1203}
1204
1205impl From<FastStr> for PathBuf {
1206    #[inline]
1207    fn from(str: FastStr) -> Self {
1208        str.into_string().into()
1209    }
1210}
1211
1212impl From<FastStr> for Box<str> {
1213    #[inline]
1214    fn from(str: FastStr) -> Self {
1215        str.into_string().into()
1216    }
1217}
1218
1219impl From<&FastStr> for Box<str> {
1220    #[inline]
1221    fn from(str: &FastStr) -> Self {
1222        str.as_str().into()
1223    }
1224}
1225
1226impl From<FastStr> for Rc<str> {
1227    #[inline]
1228    fn from(str: FastStr) -> Self {
1229        str.as_str().into()
1230    }
1231}
1232
1233impl From<&FastStr> for Rc<str> {
1234    #[inline]
1235    fn from(str: &FastStr) -> Self {
1236        str.as_str().into()
1237    }
1238}
1239
1240impl From<FastStr> for Arc<str> {
1241    #[inline]
1242    fn from(str: FastStr) -> Self {
1243        str.as_str().into()
1244    }
1245}
1246
1247impl From<&FastStr> for Arc<str> {
1248    #[inline]
1249    fn from(str: &FastStr) -> Self {
1250        str.as_str().into()
1251    }
1252}
1253
1254impl From<FastStr> for Vec<u8> {
1255    #[inline]
1256    fn from(str: FastStr) -> Self {
1257        str.into_string().into()
1258    }
1259}
1260
1261impl From<&FastStr> for Vec<u8> {
1262    #[inline]
1263    fn from(str: &FastStr) -> Self {
1264        str.as_str().into()
1265    }
1266}
1267
1268impl From<FastStr> for Box<dyn Error + 'static> {
1269    fn from(str: FastStr) -> Self {
1270        str.into_string().into()
1271    }
1272}
1273
1274impl From<FastStr> for Box<dyn Error + Send + Sync + 'static> {
1275    fn from(str: FastStr) -> Self {
1276        str.into_string().into()
1277    }
1278}
1279
1280impl From<&FastStr> for Box<dyn Error + 'static> {
1281    fn from(str: &FastStr) -> Self {
1282        str.as_str().into()
1283    }
1284}
1285
1286impl From<&FastStr> for Box<dyn Error + Send + Sync + 'static> {
1287    fn from(str: &FastStr) -> Self {
1288        str.as_str().into()
1289    }
1290}
1291
1292impl<'a> From<FastStr> for Cow<'a, str> {
1293    fn from(str: FastStr) -> Self {
1294        if let Some(str) = str.static_str() {
1295            Cow::Borrowed(str)
1296        } else {
1297            Cow::Owned(str.into_string())
1298        }
1299    }
1300}
1301
1302impl<'a> From<&'a FastStr> for Cow<'a, str> {
1303    #[inline]
1304    fn from(str: &'a FastStr) -> Self {
1305        Cow::Borrowed(str.as_str())
1306    }
1307}
1308
1309impl From<&FastStr> for String {
1310    #[inline]
1311    fn from(str: &FastStr) -> Self {
1312        str.as_str().into()
1313    }
1314}
1315
1316impl<'a> From<&'a FastStr> for &'a str {
1317    #[inline]
1318    fn from(str: &'a FastStr) -> Self {
1319        str.as_str()
1320    }
1321}
1322
1323#[cfg(target_arch = "wasm32")]
1324impl From<js_sys::JsString> for FastStr {
1325    #[inline]
1326    fn from(str: js_sys::JsString) -> Self {
1327        Self::from_string(String::from(str))
1328    }
1329}
1330
1331#[cfg(target_arch = "wasm32")]
1332impl From<&js_sys::JsString> for FastStr {
1333    #[inline]
1334    fn from(str: &js_sys::JsString) -> Self {
1335        Self::from_string(String::from(str))
1336    }
1337}
1338
1339#[cfg(target_arch = "wasm32")]
1340impl From<FastStr> for js_sys::JsString {
1341    #[inline]
1342    fn from(str: FastStr) -> Self {
1343        js_sys::JsString::from(str.as_str())
1344    }
1345}
1346
1347#[cfg(target_arch = "wasm32")]
1348impl From<&FastStr> for js_sys::JsString {
1349    #[inline]
1350    fn from(str: &FastStr) -> Self {
1351        js_sys::JsString::from(str.as_str())
1352    }
1353}
1354
1355#[cfg(target_arch = "wasm32")]
1356impl From<FastStr> for wasm_bindgen::JsValue {
1357    #[inline]
1358    fn from(str: FastStr) -> Self {
1359        wasm_bindgen::JsValue::from_str(str.as_str())
1360    }
1361}
1362
1363#[cfg(target_arch = "wasm32")]
1364impl From<&FastStr> for wasm_bindgen::JsValue {
1365    #[inline]
1366    fn from(str: &FastStr) -> Self {
1367        wasm_bindgen::JsValue::from_str(str.as_str())
1368    }
1369}
1370
1371impl<A> FromIterator<A> for FastStr
1372where
1373    String: FromIterator<A>,
1374{
1375    #[inline]
1376    fn from_iter<T: IntoIterator<Item = A>>(iter: T) -> Self {
1377        Self::from_string(String::from_iter(iter))
1378    }
1379}
1380
1381impl FromIterator<FastStr> for FastStr {
1382    fn from_iter<T: IntoIterator<Item = FastStr>>(iter: T) -> Self {
1383        let mut buf = String::new();
1384        for s in iter.into_iter() {
1385            buf += s.borrow();
1386        }
1387        Self::from(buf)
1388    }
1389}
1390
1391impl<'a> FromIterator<&'a FastStr> for FastStr {
1392    fn from_iter<T: IntoIterator<Item = &'a FastStr>>(iter: T) -> Self {
1393        Self::from_string(String::from_iter(iter.into_iter().map(|s| s.as_str())))
1394    }
1395}
1396
1397impl Add<&str> for FastStr {
1398    type Output = FastStr;
1399
1400    #[inline]
1401    fn add(self, rhs: &str) -> Self::Output {
1402        Self::from_string(String::from(self) + rhs)
1403    }
1404}
1405
1406impl Add<&FastStr> for FastStr {
1407    type Output = FastStr;
1408
1409    #[inline]
1410    fn add(self, rhs: &FastStr) -> Self::Output {
1411        Self::from_string(String::from(self) + rhs.as_str())
1412    }
1413}
1414
1415impl Add<FastStr> for FastStr {
1416    type Output = FastStr;
1417
1418    #[inline]
1419    fn add(self, rhs: FastStr) -> Self::Output {
1420        Self::from_string(String::from(self) + rhs.as_str())
1421    }
1422}
1423
1424impl Add<String> for FastStr {
1425    type Output = FastStr;
1426
1427    #[inline]
1428    fn add(self, rhs: String) -> Self::Output {
1429        Self::from_string(String::from(self) + rhs.as_str())
1430    }
1431}
1432
1433impl Add<&String> for FastStr {
1434    type Output = FastStr;
1435
1436    #[inline]
1437    fn add(self, rhs: &String) -> Self::Output {
1438        Self::from_string(String::from(self) + rhs.as_str())
1439    }
1440}
1441
1442#[cfg(target_arch = "wasm32")]
1443impl wasm_bindgen::describe::WasmDescribe for FastStr {
1444    #[inline]
1445    fn describe() {
1446        <String as wasm_bindgen::describe::WasmDescribe>::describe()
1447    }
1448}
1449
1450#[cfg(target_arch = "wasm32")]
1451impl wasm_bindgen::convert::FromWasmAbi for FastStr {
1452    type Abi = <String as wasm_bindgen::convert::FromWasmAbi>::Abi;
1453
1454    #[inline]
1455    unsafe fn from_abi(js: Self::Abi) -> Self {
1456        Self::from(<String as wasm_bindgen::convert::FromWasmAbi>::from_abi(js))
1457    }
1458}
1459
1460#[cfg(target_arch = "wasm32")]
1461impl wasm_bindgen::convert::IntoWasmAbi for FastStr {
1462    type Abi = <String as wasm_bindgen::convert::IntoWasmAbi>::Abi;
1463
1464    #[inline]
1465    fn into_abi(self) -> Self::Abi {
1466        <String as wasm_bindgen::convert::IntoWasmAbi>::into_abi(self.into_string())
1467    }
1468}
1469
1470#[cfg(target_arch = "wasm32")]
1471impl<'a> wasm_bindgen::convert::IntoWasmAbi for &'a FastStr {
1472    type Abi = <&'a str as wasm_bindgen::convert::IntoWasmAbi>::Abi;
1473
1474    #[inline]
1475    fn into_abi(self) -> Self::Abi {
1476        <&'a str as wasm_bindgen::convert::IntoWasmAbi>::into_abi(self.as_str())
1477    }
1478}
1479
1480#[cfg(target_arch = "wasm32")]
1481impl wasm_bindgen::convert::OptionFromWasmAbi for FastStr {
1482    #[inline]
1483    fn is_none(abi: &Self::Abi) -> bool {
1484        <String as wasm_bindgen::convert::OptionFromWasmAbi>::is_none(abi)
1485    }
1486}
1487
1488#[cfg(target_arch = "wasm32")]
1489impl wasm_bindgen::convert::OptionIntoWasmAbi for FastStr {
1490    #[inline]
1491    fn none() -> Self::Abi {
1492        <String as wasm_bindgen::convert::OptionIntoWasmAbi>::none()
1493    }
1494}
1495
1496#[cfg(feature = "actix-web")]
1497impl actix_web::Responder for FastStr {
1498    type Body = <String as actix_web::Responder>::Body;
1499
1500    #[inline]
1501    fn respond_to(self, req: &actix_web::HttpRequest) -> actix_web::HttpResponse<Self::Body> {
1502        <String as actix_web::Responder>::respond_to(self.into(), req)
1503    }
1504}
1505
1506#[cfg(feature = "actix-web")]
1507impl actix_web::Responder for &FastStr {
1508    type Body = <String as actix_web::Responder>::Body;
1509
1510    #[inline]
1511    fn respond_to(self, req: &actix_web::HttpRequest) -> actix_web::HttpResponse<Self::Body> {
1512        <String as actix_web::Responder>::respond_to(self.into(), req)
1513    }
1514}
1515
1516#[cfg(feature = "arbitrary")]
1517impl<'a> arbitrary::Arbitrary<'a> for FastStr {
1518    #[inline]
1519    fn arbitrary(u: &mut arbitrary::Unstructured<'a>) -> arbitrary::Result<Self> {
1520        <String as arbitrary::Arbitrary<'a>>::arbitrary(u).map(Self::from)
1521    }
1522
1523    #[inline]
1524    fn arbitrary_take_rest(u: arbitrary::Unstructured<'a>) -> arbitrary::Result<Self> {
1525        <String as arbitrary::Arbitrary<'a>>::arbitrary_take_rest(u).map(Self::from)
1526    }
1527
1528    #[inline]
1529    fn size_hint(depth: usize) -> (usize, Option<usize>) {
1530        <String as arbitrary::Arbitrary<'a>>::size_hint(depth)
1531    }
1532}
1533
1534#[cfg(feature = "diffus")]
1535impl diffus::Same for FastStr {
1536    fn same(&self, other: &Self) -> bool {
1537        self == other
1538    }
1539}
1540
1541#[cfg(feature = "diffus")]
1542impl<'a> diffus::Diffable<'a> for FastStr {
1543    type Diff = (&'a Self, &'a Self);
1544
1545    fn diff(&'a self, other: &'a Self) -> diffus::edit::Edit<'a, Self> {
1546        if self == other {
1547            diffus::edit::Edit::Copy(self)
1548        } else {
1549            diffus::edit::Edit::Change((self, other))
1550        }
1551    }
1552}
1553
1554impl<'a> Pattern<'a> for &'a FastStr {
1555    type Searcher = <&'a str as Pattern<'a>>::Searcher;
1556
1557    fn into_searcher(self, haystack: &'a str) -> Self::Searcher {
1558        <&'a str as Pattern<'a>>::into_searcher(self.as_str(), haystack)
1559    }
1560}
1561
1562pub struct FastStrSearch<'a, 'b> {
1563    _str: Box<FastStr>,
1564    searcher: StrSearcher<'a, 'b>,
1565}
1566
1567unsafe impl<'a, 'b> Searcher<'a> for FastStrSearch<'a, 'b> {
1568    #[inline]
1569    fn haystack(&self) -> &'a str {
1570        self.searcher.haystack()
1571    }
1572
1573    #[inline]
1574    fn next(&mut self) -> SearchStep {
1575        self.searcher.next()
1576    }
1577}
1578
1579impl<'a> Pattern<'a> for FastStr {
1580    type Searcher = FastStrSearch<'a, 'a>;
1581
1582    fn into_searcher(self, haystack: &'a str) -> Self::Searcher {
1583        let _str = Box::new(self);
1584        let searcher = <&'a str as Pattern<'a>>::into_searcher(
1585            unsafe { &*std::ptr::addr_of!(*_str.as_str()) },
1586            haystack,
1587        );
1588        FastStrSearch { _str, searcher }
1589    }
1590}