Skip to main content

ct_regex_internal/haystack/ext/
bstr.rs

1use std::ops::Range;
2
3use bstr::{BStr, BString};
4
5use crate::haystack::{Haystack, HaystackSlice, IntoHaystack, OwnedHaystackable};
6
7impl<'a> HaystackSlice<'a> for &'a BStr {
8    type Item = u8;
9
10    fn slice_with(&self, range: Range<usize>) -> Self {
11        &self[range]
12    }
13
14    fn as_bytes(&self) -> &[u8] {
15        self
16    }
17}
18
19/// A haystack type for matching against the [`u8`]s in a [`&'a BStr`](bstr::BStr). This type is a
20/// very basic example of how the haystack traits can be implemented outside of the crate itself.
21#[derive(#[automatically_derived]
impl<'a> ::core::fmt::Debug for BStrStack<'a> {
    #[inline]
    fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
        ::core::fmt::Formatter::debug_struct_field2_finish(f, "BStrStack",
            "inner", &self.inner, "index", &&self.index)
    }
}Debug, #[automatically_derived]
impl<'a> ::core::clone::Clone for BStrStack<'a> {
    #[inline]
    fn clone(&self) -> BStrStack<'a> {
        BStrStack {
            inner: ::core::clone::Clone::clone(&self.inner),
            index: ::core::clone::Clone::clone(&self.index),
        }
    }
}Clone, #[automatically_derived]
impl<'a> ::core::hash::Hash for BStrStack<'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)]
22pub struct BStrStack<'a> {
23    inner: &'a BStr,
24    index: usize,
25}
26
27impl<'a> IntoHaystack<'a, BStrStack<'a>> for &'a BStr {
28    fn into_haystack(self) -> BStrStack<'a> {
29        BStrStack {
30            inner: self,
31            index: 0,
32        }
33    }
34}
35
36// BString implements Deref<Target = Vec<u8>>, so it will implicitly go to the wrong haystack type.
37// This does raise the question of how different the types really are and what benefit there is to
38// restricting everything to BStr when conversions are cheap. Answer: Why not? Its pretty easy to
39// implement.
40impl<'a> IntoHaystack<'a, BStrStack<'a>> for &'a BString {
41    fn into_haystack(self) -> BStrStack<'a> {
42        BStrStack {
43            inner: BStr::new(self),
44            index: 0,
45        }
46    }
47}
48
49impl<'a> Iterator for BStrStack<'a> {
50    type Item = u8;
51
52    fn next(&mut self) -> Option<Self::Item> {
53        let byte = self.inner.get(self.index).copied();
54
55        if byte.is_some() {
56            self.index += 1;
57        }
58
59        byte
60    }
61}
62
63impl<'a> Haystack<'a> for BStrStack<'a> {
64    type Slice = &'a BStr;
65
66    fn item(&self) -> Option<Self::Item> {
67        self.inner.get(self.index).copied()
68    }
69
70    fn prev_item(&self) -> Option<Self::Item> {
71        self.inner.get(self.index.checked_sub(1)?).copied()
72    }
73
74    fn index(&self) -> usize {
75        self.index
76    }
77
78    fn inner_slice(&self) -> Self::Slice {
79        self.inner
80    }
81
82    fn remainder_as_slice(&self) -> Self::Slice {
83        &self.inner[self.index..]
84    }
85
86    fn go_to(&mut self, index: usize) {
87        self.index = index;
88    }
89}
90
91impl OwnedHaystackable<u8> for BString {
92    type Hay<'a> = BStrStack<'a>;
93
94    fn replace_range<'a>(
95        &mut self,
96        range: Range<usize>,
97        with: <Self::Hay<'a> as Haystack<'a>>::Slice
98    ) where Self: 'a {
99        self.splice(range, with.iter().copied());
100    }
101
102    fn as_haystack<'a>(&'a self) -> Self::Hay<'a> {
103        self.into_haystack()
104    }
105
106    fn as_slice<'a>(&'a self) -> <Self::Hay<'a> as Haystack<'a>>::Slice {
107        BStr::new(self)
108    }
109
110    fn len(&self) -> usize {
111        Vec::len(self)
112    }
113}