Skip to main content

ct_regex_internal/haystack/
string.rs

1use std::ops::Range;
2
3use crate::haystack::{
4    HaystackIter, HaystackSlice, IntoHaystack, OwnedHaystackable, first_char, first_char_and_width
5};
6
7/// A haystack type for matching against the [`char`]s in a [`&str`](str). This type abstracts over
8/// the variable width scalars contained, to allow indexing without panics.
9///
10/// To accomodate, calls to [`go_to`](Self::go_to) should only be made with an index previously
11/// produced by this type for the specific haystack. Failure to do so, may cause a panic if indexing
12/// on an invalid unicode boundary.
13#[derive(#[automatically_derived]
impl<'a> ::core::fmt::Debug for StrStack<'a> {
    #[inline]
    fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
        ::core::fmt::Formatter::debug_struct_field2_finish(f, "StrStack",
            "inner", &self.inner, "index", &&self.index)
    }
}Debug, #[automatically_derived]
impl<'a> ::core::clone::Clone for StrStack<'a> {
    #[inline]
    fn clone(&self) -> StrStack<'a> {
        StrStack {
            inner: ::core::clone::Clone::clone(&self.inner),
            index: ::core::clone::Clone::clone(&self.index),
        }
    }
}Clone, #[automatically_derived]
impl<'a> ::core::cmp::PartialEq for StrStack<'a> {
    #[inline]
    fn eq(&self, other: &StrStack<'a>) -> bool {
        self.inner == other.inner && self.index == other.index
    }
}PartialEq, #[automatically_derived]
impl<'a> ::core::cmp::Eq for StrStack<'a> {
    #[inline]
    #[doc(hidden)]
    #[coverage(off)]
    fn assert_fields_are_eq(&self) {
        let _: ::core::cmp::AssertParamIsEq<&'a str>;
        let _: ::core::cmp::AssertParamIsEq<usize>;
    }
}Eq, #[automatically_derived]
impl<'a> ::core::hash::Hash for StrStack<'a> {
    #[inline]
    fn hash<__H: ::core::hash::Hasher>(&self, state: &mut __H) {
        ::core::hash::Hash::hash(&self.inner, state);
        ::core::hash::Hash::hash(&self.index, state)
    }
}Hash)]
14pub struct StrStack<'a> {
15    inner: &'a str,
16    index: usize,
17}
18
19impl<'a> Iterator for StrStack<'a> {
20    type Item = char;
21
22    fn next(&mut self) -> Option<Self::Item> {
23        let (width, first) = first_char_and_width(self.remainder_as_slice());
24        // The width won't exceed the remaining slice, so it can't overflow then length.
25        self.index += width;
26        first
27    }
28}
29
30impl<'a> HaystackIter<'a> for StrStack<'a> {
31    type Slice = &'a str;
32
33    fn current_item(&self) -> Option<Self::Item> {
34        first_char(self.remainder_as_slice())
35    }
36
37    fn prev_item(&self) -> Option<Self::Item> {
38        let prev_index = self.inner.floor_char_boundary(self.index.checked_sub(1)?);
39        first_char(&self.inner[prev_index..])
40    }
41
42    fn current_index(&self) -> usize {
43        self.index
44    }
45
46    fn whole_slice(&self) -> Self::Slice {
47        self.inner
48    }
49
50    fn remainder_as_slice(&self) -> Self::Slice {
51        &self.inner[self.index..]
52    }
53
54    fn go_to(&mut self, index: usize) {
55        self.index = index;
56    }
57}
58
59impl<'a> HaystackSlice<'a> for &'a str {
60    type Item = char;
61
62    fn slice_with(&self, range: Range<usize>) -> Self {
63        &self[range]
64    }
65}
66
67impl<'a> IntoHaystack<'a, StrStack<'a>> for &'a str {
68    fn into_haystack(self) -> StrStack<'a> {
69        StrStack {
70            inner: self,
71            index: 0,
72        }
73    }
74}
75
76impl<'a> IntoHaystack<'a, StrStack<'a>> for &'a String {
77    fn into_haystack(self) -> StrStack<'a> {
78        StrStack {
79            inner: self,
80            index: 0,
81        }
82    }
83}
84
85impl OwnedHaystackable<char> for String {
86    type Hay<'a> = StrStack<'a>;
87
88    fn replace_range<'a>(
89        &mut self,
90        range: Range<usize>,
91        with: <Self::Hay<'a> as HaystackIter<'a>>::Slice
92    ) where Self: 'a {
93        self.replace_range(range, with);
94    }
95
96    fn as_haystack<'a>(&'a self) -> Self::Hay<'a> {
97        self.into_haystack()
98    }
99
100    fn as_slice<'a>(&'a self) -> <Self::Hay<'a> as HaystackIter<'a>>::Slice {
101        self
102    }
103
104    fn len(&self) -> usize {
105        self.len()
106    }
107}