Skip to content

Instantly share code, notes, and snippets.

@rust-play
Created September 9, 2020 10:06
Show Gist options
  • Save rust-play/6f4932a58832875b81e37306cf6f16cd to your computer and use it in GitHub Desktop.
Save rust-play/6f4932a58832875b81e37306cf6f16cd to your computer and use it in GitHub Desktop.
Code shared from the Rust Playground
pub trait Pattern<T: ?Sized>: Sized {
type Searcher: Search<T>;
fn into_searcher(self) -> Self::Searcher;
fn search(self, haystack: &T) -> SearchSteps<'_, Self::Searcher, T> {
self.into_searcher().search(haystack)
}
fn search_back(self, haystack: &T) -> SearchStepsBack<'_, Self::Searcher, T>
where Self::Searcher: SearchBack<T>
{
self.into_searcher().search_back(haystack)
}
}
// Safety requirements
//
// The safety requirements are determined by the type `T`
//
// For `str`:
// - `start` and `end` of `SearchStep` returned by `step`
// are both on a utf-8 code point boundary within haystack
pub unsafe trait Search<T: ?Sized>: Sized {
fn step(&mut self, haystack: &T) -> Option<SearchStep>;
fn search(self, haystack: &T) -> SearchSteps<'_, Self, T> {
SearchSteps { haystack, searcher: self }
}
}
// Safety requirements
//
// The safety requirements are determined by the type `T`
//
// For `str`:
// - `start` and `end` of `SearchStep` returned by `step_back`
// are both on a utf-8 code point boundary within haystack
pub unsafe trait SearchBack<T: ?Sized>: Search<T> {
fn step_back(&mut self, haystack: &T) -> Option<SearchStep>;
fn search_back(self, haystack: &T) -> SearchStepsBack<'_, Self, T> {
SearchStepsBack { haystack, searcher: self }
}
}
pub struct SearchStep {
pub matches: bool,
pub start: usize,
pub end: usize,
}
pub struct SearchSteps<'a, S, T: ?Sized> {
haystack: &'a T,
searcher: S,
}
impl<'a, S: Search<T>, T: ?Sized> Iterator for SearchSteps<'a, S, T> {
type Item = SearchStep;
fn next(&mut self) -> Option<SearchStep> {
self.searcher.step(self.haystack)
}
}
pub struct SearchStepsBack<'a, S, T: ?Sized> {
haystack: &'a T,
searcher: S,
}
impl<'a, S: SearchBack<T>, T: ?Sized> Iterator for SearchStepsBack<'a, S, T> {
type Item = SearchStep;
fn next(&mut self) -> Option<SearchStep> {
self.searcher.step_back(self.haystack)
}
}
// For example:
pub fn str_contains(s: &str, pat: impl Pattern<str>) -> bool {
pat.search(s).any(|step| step.matches)
}
pub fn slice_contains<T>(s: &[T], pat: impl Pattern<[T]>) -> bool {
pat.search(s).any(|step| step.matches)
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment