Skip to main content

ct_regex_internal/haystack/ext/
bstr.rs

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