pub trait Search {
fn search<'a, P: SearchIn<'a>>(&'a self, needle: P) -> Option<usize>;
fn rsearch<'a, P: SearchIn<'a>>(&'a self, needle: P) -> Option<usize>;
fn search_indices<'a, P: SearchIn<'a>>(&'a self, needle: P) -> SearchIndices<'a, P>;
fn rsearch_indices<'a, P: SearchIn<'a>>(&'a self, needle: P) -> RevSearchIndices<'a, P>;
fn includes<'a, P: SearchIn<'a>>(&'a self, needle: P) -> bool;
fn search_ignore_ascii_case<'a, P: SearchIn<'a>>(&'a self, needle: P) -> Option<usize>;
fn rsearch_ignore_ascii_case<'a, P: SearchIn<'a>>(&'a self, needle: P) -> Option<usize>;
fn search_indices_ignore_ascii_case<'a, P: SearchIn<'a>>(
&'a self,
needle: P,
) -> SearchIndicesIgnoreAsciiCase<'a, P>;
fn rsearch_indices_ignore_ascii_case<'a, P: SearchIn<'a>>(
&'a self,
needle: P,
) -> RevSearchIndicesIgnoreAsciiCase<'a, P>;
fn includes_ignore_ascii_case<'a, P: SearchIn<'a>>(&'a self, needle: P) -> bool;
}
impl<'c> Search for &'c str {
#[inline]
fn search<'a, P: SearchIn<'a>>(&'a self, needle: P) -> Option<usize> {
needle.search_in(self)
}
#[inline]
fn rsearch<'a, P: SearchIn<'a>>(&'a self, needle: P) -> Option<usize> {
needle.rsearch_in(self)
}
#[inline]
fn search_indices<'a, P: SearchIn<'a>>(&'a self, needle: P) -> SearchIndices<'a, P> {
SearchIndices::new(self, needle)
}
#[inline]
fn rsearch_indices<'a, P: SearchIn<'a>>(&'a self, needle: P) -> RevSearchIndices<'a, P> {
RevSearchIndices::new(self, needle)
}
#[inline]
fn includes<'a, P: SearchIn<'a>>(&'a self, needle: P) -> bool {
needle.includes_in(self)
}
#[inline]
fn search_ignore_ascii_case<'a, P: SearchIn<'a>>(&'a self, needle: P) -> Option<usize> {
needle.search_in_ignore_ascii_case(self)
}
#[inline]
fn rsearch_ignore_ascii_case<'a, P: SearchIn<'a>>(&'a self, needle: P) -> Option<usize> {
needle.rsearch_in_ignore_ascii_case(self)
}
#[inline]
fn search_indices_ignore_ascii_case<'a, P: SearchIn<'a>>(
&'a self,
needle: P,
) -> SearchIndicesIgnoreAsciiCase<'a, P> {
SearchIndicesIgnoreAsciiCase::new(self, needle)
}
#[inline]
fn rsearch_indices_ignore_ascii_case<'a, P: SearchIn<'a>>(
&'a self,
needle: P,
) -> RevSearchIndicesIgnoreAsciiCase<'a, P> {
RevSearchIndicesIgnoreAsciiCase::new(self, needle)
}
#[inline]
fn includes_ignore_ascii_case<'a, P: SearchIn<'a>>(&'a self, needle: P) -> bool {
needle.includes_in_ignore_ascii_case(self)
}
}
impl Search for String {
#[inline]
fn search<'a, P: SearchIn<'a>>(&'a self, needle: P) -> Option<usize> {
needle.search_in(self.as_str())
}
#[inline]
fn rsearch<'a, P: SearchIn<'a>>(&'a self, needle: P) -> Option<usize> {
needle.rsearch_in(self.as_str())
}
#[inline]
fn search_indices<'a, P: SearchIn<'a>>(&'a self, needle: P) -> SearchIndices<'a, P> {
SearchIndices::new(self.as_str(), needle)
}
#[inline]
fn rsearch_indices<'a, P: SearchIn<'a>>(&'a self, needle: P) -> RevSearchIndices<'a, P> {
RevSearchIndices::new(self.as_str(), needle)
}
#[inline]
fn includes<'a, P: SearchIn<'a>>(&'a self, needle: P) -> bool {
needle.includes_in(self)
}
#[inline]
fn search_ignore_ascii_case<'a, P: SearchIn<'a>>(&'a self, needle: P) -> Option<usize> {
needle.search_in_ignore_ascii_case(self.as_str())
}
#[inline]
fn rsearch_ignore_ascii_case<'a, P: SearchIn<'a>>(&'a self, needle: P) -> Option<usize> {
needle.rsearch_in_ignore_ascii_case(self.as_str())
}
#[inline]
fn search_indices_ignore_ascii_case<'a, P: SearchIn<'a>>(
&'a self,
needle: P,
) -> SearchIndicesIgnoreAsciiCase<'a, P> {
SearchIndicesIgnoreAsciiCase::new(self.as_str(), needle)
}
#[inline]
fn rsearch_indices_ignore_ascii_case<'a, P: SearchIn<'a>>(
&'a self,
needle: P,
) -> RevSearchIndicesIgnoreAsciiCase<'a, P> {
RevSearchIndicesIgnoreAsciiCase::new(self.as_str(), needle)
}
#[inline]
fn includes_ignore_ascii_case<'a, P: SearchIn<'a>>(&'a self, needle: P) -> bool {
needle.includes_in_ignore_ascii_case(self)
}
}
pub trait SearchBytes {
fn search_bytes<'a, P: SearchInBytes<'a>>(&'a self, needle: P) -> Option<usize>;
fn rsearch_bytes<'a, P: SearchInBytes<'a>>(&'a self, needle: P) -> Option<usize>;
fn search_indices_bytes<'a, P>(&'a self, needle: P) -> SearchIndicesBytes<'a, P>
where
P: SearchInBytes<'a>;
fn rsearch_indices_bytes<'a, P>(&'a self, needle: P) -> RevSearchIndicesBytes<'a, P>
where
P: SearchInBytes<'a>;
fn includes_bytes<'a, P: SearchInBytes<'a>>(&'a self, needle: P) -> bool;
fn search_bytes_ignore_ascii_case<'a, P: SearchInBytes<'a>>(
&'a self,
needle: P,
) -> Option<usize>;
fn rsearch_bytes_ignore_ascii_case<'a, P: SearchInBytes<'a>>(
&'a self,
needle: P,
) -> Option<usize>;
fn search_indices_bytes_ignore_ascii_case<'a, P>(
&'a self,
needle: P,
) -> SearchIndicesBytesIgnoreAsciiCase<'a, P>
where
P: SearchInBytes<'a>;
fn rsearch_indices_bytes_ignore_ascii_case<'a, P>(
&'a self,
needle: P,
) -> RevSearchIndicesBytesIgnoreAsciiCase<'a, P>
where
P: SearchInBytes<'a>;
fn includes_bytes_ignore_ascii_case<'a, P: SearchInBytes<'a>>(&'a self, needle: P) -> bool;
}
impl<'c> SearchBytes for &'c [u8] {
#[inline]
fn search_bytes<'a, P: SearchInBytes<'a>>(&'a self, needle: P) -> Option<usize> {
needle.search_in(self)
}
#[inline]
fn rsearch_bytes<'a, P: SearchInBytes<'a>>(&'a self, needle: P) -> Option<usize> {
needle.rsearch_in(self)
}
#[inline]
fn search_indices_bytes<'a, P>(&'a self, needle: P) -> SearchIndicesBytes<'a, P>
where
P: SearchInBytes<'a>,
{
SearchIndicesBytes::new(self, needle)
}
#[inline]
fn rsearch_indices_bytes<'a, P>(&'a self, needle: P) -> RevSearchIndicesBytes<'a, P>
where
P: SearchInBytes<'a>,
{
RevSearchIndicesBytes::new(self, needle)
}
#[inline]
fn includes_bytes<'a, P: SearchInBytes<'a>>(&'a self, needle: P) -> bool {
needle.includes_in(self)
}
#[inline]
fn search_bytes_ignore_ascii_case<'a, P: SearchInBytes<'a>>(
&'a self,
needle: P,
) -> Option<usize> {
needle.search_in_ignore_ascii_case(self)
}
#[inline]
fn rsearch_bytes_ignore_ascii_case<'a, P: SearchInBytes<'a>>(
&'a self,
needle: P,
) -> Option<usize> {
needle.rsearch_in_ignore_ascii_case(self)
}
#[inline]
fn search_indices_bytes_ignore_ascii_case<'a, P>(
&'a self,
needle: P,
) -> SearchIndicesBytesIgnoreAsciiCase<'a, P>
where
P: SearchInBytes<'a>,
{
SearchIndicesBytesIgnoreAsciiCase::new(self, needle)
}
#[inline]
fn rsearch_indices_bytes_ignore_ascii_case<'a, P>(
&'a self,
needle: P,
) -> RevSearchIndicesBytesIgnoreAsciiCase<'a, P>
where
P: SearchInBytes<'a>,
{
RevSearchIndicesBytesIgnoreAsciiCase::new(self, needle)
}
#[inline]
fn includes_bytes_ignore_ascii_case<'a, P: SearchInBytes<'a>>(&'a self, needle: P) -> bool {
needle.includes_in_ignore_ascii_case(self)
}
}
impl<'c> SearchBytes for &'c str {
#[inline]
fn search_bytes<'a, P: SearchInBytes<'a>>(&'a self, needle: P) -> Option<usize> {
needle.search_in(self.as_bytes())
}
#[inline]
fn rsearch_bytes<'a, P: SearchInBytes<'a>>(&'a self, needle: P) -> Option<usize> {
needle.rsearch_in(self.as_bytes())
}
#[inline]
fn search_indices_bytes<'a, P>(&'a self, needle: P) -> SearchIndicesBytes<'a, P>
where
P: SearchInBytes<'a>,
{
SearchIndicesBytes::new(self.as_bytes(), needle)
}
#[inline]
fn rsearch_indices_bytes<'a, P>(&'a self, needle: P) -> RevSearchIndicesBytes<'a, P>
where
P: SearchInBytes<'a>,
{
RevSearchIndicesBytes::new(self.as_bytes(), needle)
}
#[inline]
fn includes_bytes<'a, P: SearchInBytes<'a>>(&'a self, needle: P) -> bool {
needle.includes_in(self.as_bytes())
}
#[inline]
fn search_bytes_ignore_ascii_case<'a, P: SearchInBytes<'a>>(
&'a self,
needle: P,
) -> Option<usize> {
needle.search_in_ignore_ascii_case(self.as_bytes())
}
#[inline]
fn rsearch_bytes_ignore_ascii_case<'a, P: SearchInBytes<'a>>(
&'a self,
needle: P,
) -> Option<usize> {
needle.rsearch_in_ignore_ascii_case(self.as_bytes())
}
#[inline]
fn search_indices_bytes_ignore_ascii_case<'a, P>(
&'a self,
needle: P,
) -> SearchIndicesBytesIgnoreAsciiCase<'a, P>
where
P: SearchInBytes<'a>,
{
SearchIndicesBytesIgnoreAsciiCase::new(self.as_bytes(), needle)
}
#[inline]
fn rsearch_indices_bytes_ignore_ascii_case<'a, P>(
&'a self,
needle: P,
) -> RevSearchIndicesBytesIgnoreAsciiCase<'a, P>
where
P: SearchInBytes<'a>,
{
RevSearchIndicesBytesIgnoreAsciiCase::new(self.as_bytes(), needle)
}
#[inline]
fn includes_bytes_ignore_ascii_case<'a, P: SearchInBytes<'a>>(&'a self, needle: P) -> bool {
needle.includes_in_ignore_ascii_case(self.as_bytes())
}
}
impl SearchBytes for String {
#[inline]
fn search_bytes<'a, P: SearchInBytes<'a>>(&'a self, needle: P) -> Option<usize> {
needle.search_in(self.as_bytes())
}
#[inline]
fn rsearch_bytes<'a, P: SearchInBytes<'a>>(&'a self, needle: P) -> Option<usize> {
needle.rsearch_in(self.as_bytes())
}
#[inline]
fn search_indices_bytes<'a, P>(&'a self, needle: P) -> SearchIndicesBytes<'a, P>
where
P: SearchInBytes<'a>,
{
SearchIndicesBytes::new(self.as_bytes(), needle)
}
#[inline]
fn rsearch_indices_bytes<'a, P>(&'a self, needle: P) -> RevSearchIndicesBytes<'a, P>
where
P: SearchInBytes<'a>,
{
RevSearchIndicesBytes::new(self.as_bytes(), needle)
}
#[inline]
fn includes_bytes<'a, P: SearchInBytes<'a>>(&'a self, needle: P) -> bool {
needle.includes_in(self.as_bytes())
}
#[inline]
fn search_bytes_ignore_ascii_case<'a, P: SearchInBytes<'a>>(
&'a self,
needle: P,
) -> Option<usize> {
needle.search_in_ignore_ascii_case(self.as_bytes())
}
#[inline]
fn rsearch_bytes_ignore_ascii_case<'a, P: SearchInBytes<'a>>(
&'a self,
needle: P,
) -> Option<usize> {
needle.rsearch_in_ignore_ascii_case(self.as_bytes())
}
#[inline]
fn search_indices_bytes_ignore_ascii_case<'a, P>(
&'a self,
needle: P,
) -> SearchIndicesBytesIgnoreAsciiCase<'a, P>
where
P: SearchInBytes<'a>,
{
SearchIndicesBytesIgnoreAsciiCase::new(self.as_bytes(), needle)
}
#[inline]
fn rsearch_indices_bytes_ignore_ascii_case<'a, P>(
&'a self,
needle: P,
) -> RevSearchIndicesBytesIgnoreAsciiCase<'a, P>
where
P: SearchInBytes<'a>,
{
RevSearchIndicesBytesIgnoreAsciiCase::new(self.as_bytes(), needle)
}
#[inline]
fn includes_bytes_ignore_ascii_case<'a, P: SearchInBytes<'a>>(&'a self, needle: P) -> bool {
needle.includes_in_ignore_ascii_case(self.as_bytes())
}
}
pub struct SearchIndices<'a, P: SearchIn<'a>> {
curr_idx: usize,
haystack: &'a str,
needle: P,
}
impl<'a, P: SearchIn<'a>> SearchIndices<'a, P> {
fn new(a_haystack: &'a str, a_needle: P) -> SearchIndices<'a, P> {
SearchIndices {
curr_idx: 0,
haystack: a_haystack,
needle: a_needle,
}
}
}
impl<'a, P: SearchIn<'a>> Iterator for SearchIndices<'a, P> {
type Item = (usize, &'a str);
#[inline(always)]
fn next(&mut self) -> Option<Self::Item> {
match self.needle.search_in(&self.haystack[self.curr_idx..]) {
Some(idx) => {
self.curr_idx += idx;
let st = self.curr_idx;
let ed = st + self.needle.len();
self.curr_idx = ed;
Some((st, &self.haystack[st..ed]))
}
None => None,
}
}
}
pub struct SearchIndicesBytes<'a, P: SearchInBytes<'a>> {
curr_idx: usize,
haystack: &'a [u8],
needle: P,
}
impl<'a, P: SearchInBytes<'a>> SearchIndicesBytes<'a, P> {
fn new(a_haystack: &'a [u8], a_needle: P) -> SearchIndicesBytes<'a, P> {
SearchIndicesBytes {
curr_idx: 0,
haystack: a_haystack,
needle: a_needle,
}
}
}
impl<'a, P: SearchInBytes<'a>> Iterator for SearchIndicesBytes<'a, P> {
type Item = (usize, &'a [u8]);
#[inline(always)]
fn next(&mut self) -> Option<Self::Item> {
match self.needle.search_in(&self.haystack[self.curr_idx..]) {
Some(idx) => {
self.curr_idx += idx;
let st = self.curr_idx;
let ed = st + self.needle.len();
self.curr_idx = ed;
Some((st, &self.haystack[st..ed]))
}
None => None,
}
}
}
pub struct RevSearchIndices<'a, P: SearchIn<'a>> {
curr_ed: usize,
haystack: &'a str,
needle: P,
}
impl<'a, P: SearchIn<'a>> RevSearchIndices<'a, P> {
fn new(a_haystack: &'a str, a_needle: P) -> RevSearchIndices<'a, P> {
RevSearchIndices {
curr_ed: a_haystack.len(),
haystack: a_haystack,
needle: a_needle,
}
}
}
impl<'a, P: SearchIn<'a>> Iterator for RevSearchIndices<'a, P> {
type Item = (usize, &'a str);
#[inline(always)]
fn next(&mut self) -> Option<Self::Item> {
match self.needle.rsearch_in(&self.haystack[0..self.curr_ed]) {
Some(idx) => {
let st = idx;
let ed = st + self.needle.len();
self.curr_ed = st;
Some((st, &self.haystack[st..ed]))
}
None => None,
}
}
}
pub struct RevSearchIndicesBytes<'a, P: SearchInBytes<'a>> {
curr_ed: usize,
haystack: &'a [u8],
needle: P,
}
impl<'a, P: SearchInBytes<'a>> RevSearchIndicesBytes<'a, P> {
fn new(a_haystack: &'a [u8], a_needle: P) -> RevSearchIndicesBytes<'a, P> {
RevSearchIndicesBytes {
curr_ed: a_haystack.len(),
haystack: a_haystack,
needle: a_needle,
}
}
}
impl<'a, P: SearchInBytes<'a>> Iterator for RevSearchIndicesBytes<'a, P> {
type Item = (usize, &'a [u8]);
#[inline(always)]
fn next(&mut self) -> Option<Self::Item> {
match self.needle.rsearch_in(&self.haystack[0..self.curr_ed]) {
Some(idx) => {
let st = idx;
let ed = st + self.needle.len();
self.curr_ed = st;
Some((st, &self.haystack[st..ed]))
}
None => None,
}
}
}
pub struct SearchIndicesIgnoreAsciiCase<'a, P: SearchIn<'a>> {
curr_idx: usize,
haystack: &'a str,
needle: P,
}
impl<'a, P: SearchIn<'a>> SearchIndicesIgnoreAsciiCase<'a, P> {
fn new(a_haystack: &'a str, a_needle: P) -> SearchIndicesIgnoreAsciiCase<'a, P> {
SearchIndicesIgnoreAsciiCase {
curr_idx: 0,
haystack: a_haystack,
needle: a_needle,
}
}
}
impl<'a, P: SearchIn<'a>> Iterator for SearchIndicesIgnoreAsciiCase<'a, P> {
type Item = (usize, &'a str);
#[inline(always)]
fn next(&mut self) -> Option<Self::Item> {
match self
.needle
.search_in_ignore_ascii_case(&self.haystack[self.curr_idx..])
{
Some(idx) => {
self.curr_idx += idx;
let st = self.curr_idx;
let ed = st + self.needle.len();
self.curr_idx = ed;
Some((st, &self.haystack[st..ed]))
}
None => None,
}
}
}
pub struct SearchIndicesBytesIgnoreAsciiCase<'a, P: SearchInBytes<'a>> {
curr_idx: usize,
haystack: &'a [u8],
needle: P,
}
impl<'a, P: SearchInBytes<'a>> SearchIndicesBytesIgnoreAsciiCase<'a, P> {
fn new(a_haystack: &'a [u8], a_needle: P) -> SearchIndicesBytesIgnoreAsciiCase<'a, P> {
SearchIndicesBytesIgnoreAsciiCase {
curr_idx: 0,
haystack: a_haystack,
needle: a_needle,
}
}
}
impl<'a, P: SearchInBytes<'a>> Iterator for SearchIndicesBytesIgnoreAsciiCase<'a, P> {
type Item = (usize, &'a [u8]);
#[inline(always)]
fn next(&mut self) -> Option<Self::Item> {
match self
.needle
.search_in_ignore_ascii_case(&self.haystack[self.curr_idx..])
{
Some(idx) => {
self.curr_idx += idx;
let st = self.curr_idx;
let ed = st + self.needle.len();
self.curr_idx = ed;
Some((st, &self.haystack[st..ed]))
}
None => None,
}
}
}
pub struct RevSearchIndicesIgnoreAsciiCase<'a, P: SearchIn<'a>> {
curr_ed: usize,
haystack: &'a str,
needle: P,
}
impl<'a, P: SearchIn<'a>> RevSearchIndicesIgnoreAsciiCase<'a, P> {
fn new(a_haystack: &'a str, a_needle: P) -> RevSearchIndicesIgnoreAsciiCase<'a, P> {
RevSearchIndicesIgnoreAsciiCase {
curr_ed: a_haystack.len(),
haystack: a_haystack,
needle: a_needle,
}
}
}
impl<'a, P: SearchIn<'a>> Iterator for RevSearchIndicesIgnoreAsciiCase<'a, P> {
type Item = (usize, &'a str);
#[inline(always)]
fn next(&mut self) -> Option<Self::Item> {
match self
.needle
.rsearch_in_ignore_ascii_case(&self.haystack[0..self.curr_ed])
{
Some(idx) => {
let st = idx;
let ed = st + self.needle.len();
self.curr_ed = st;
Some((st, &self.haystack[st..ed]))
}
None => None,
}
}
}
pub struct RevSearchIndicesBytesIgnoreAsciiCase<'a, P: SearchInBytes<'a>> {
curr_ed: usize,
haystack: &'a [u8],
needle: P,
}
impl<'a, P: SearchInBytes<'a>> RevSearchIndicesBytesIgnoreAsciiCase<'a, P> {
fn new(a_haystack: &'a [u8], a_needle: P) -> RevSearchIndicesBytesIgnoreAsciiCase<'a, P> {
RevSearchIndicesBytesIgnoreAsciiCase {
curr_ed: a_haystack.len(),
haystack: a_haystack,
needle: a_needle,
}
}
}
impl<'a, P: SearchInBytes<'a>> Iterator for RevSearchIndicesBytesIgnoreAsciiCase<'a, P> {
type Item = (usize, &'a [u8]);
#[inline(always)]
fn next(&mut self) -> Option<Self::Item> {
match self
.needle
.rsearch_in_ignore_ascii_case(&self.haystack[0..self.curr_ed])
{
Some(idx) => {
let st = idx;
let ed = st + self.needle.len();
self.curr_ed = st;
Some((st, &self.haystack[st..ed]))
}
None => None,
}
}
}
pub trait SearchIn<'a>: Sized {
fn search_in(&self, haystack: &'a str) -> Option<usize>;
fn rsearch_in(&self, haystack: &'a str) -> Option<usize>;
fn search_in_ignore_ascii_case(&self, haystack: &'a str) -> Option<usize>;
fn rsearch_in_ignore_ascii_case(&self, haystack: &'a str) -> Option<usize>;
fn len(&self) -> usize;
fn is_empty(&self) -> bool {
self.len() == 0
}
#[inline]
fn includes_in(&self, haystack: &'a str) -> bool {
self.search_in(haystack).is_some()
}
#[inline]
fn includes_in_ignore_ascii_case(&self, haystack: &'a str) -> bool {
self.search_in_ignore_ascii_case(haystack).is_some()
}
}
impl<'a, 'b> SearchIn<'a> for &'b str {
#[inline]
fn search_in(&self, haystack: &'a str) -> Option<usize> {
naive_opt_mc_bytes(haystack.as_bytes(), self.as_bytes())
}
#[inline]
fn rsearch_in(&self, haystack: &'a str) -> Option<usize> {
naive_opt_mc_rev_bytes(haystack.as_bytes(), self.as_bytes())
}
#[inline]
fn search_in_ignore_ascii_case(&self, haystack: &'a str) -> Option<usize> {
naive_opt_mc_bytes_iac(haystack.as_bytes(), self.as_bytes())
}
#[inline]
fn rsearch_in_ignore_ascii_case(&self, haystack: &'a str) -> Option<usize> {
naive_opt_mc_rev_bytes_iac(haystack.as_bytes(), self.as_bytes())
}
#[inline]
fn len(&self) -> usize {
self.as_bytes().len()
}
}
impl<'a, 'b> SearchIn<'a> for &'b String {
#[inline]
fn search_in(&self, haystack: &'a str) -> Option<usize> {
naive_opt_mc_bytes(haystack.as_bytes(), self.as_str().as_bytes())
}
#[inline]
fn rsearch_in(&self, haystack: &'a str) -> Option<usize> {
naive_opt_mc_rev_bytes(haystack.as_bytes(), self.as_str().as_bytes())
}
#[inline]
fn search_in_ignore_ascii_case(&self, haystack: &'a str) -> Option<usize> {
naive_opt_mc_bytes_iac(haystack.as_bytes(), self.as_str().as_bytes())
}
#[inline]
fn rsearch_in_ignore_ascii_case(&self, haystack: &'a str) -> Option<usize> {
naive_opt_mc_rev_bytes_iac(haystack.as_bytes(), self.as_str().as_bytes())
}
#[inline]
fn len(&self) -> usize {
self.as_str().len()
}
}
impl<'a> SearchIn<'a> for char {
#[inline]
fn search_in(&self, haystack: &'a str) -> Option<usize> {
naive_opt_mc_bytes(haystack.as_bytes(), self.to_string().as_str().as_bytes())
}
#[inline]
fn rsearch_in(&self, haystack: &'a str) -> Option<usize> {
naive_opt_mc_rev_bytes(haystack.as_bytes(), self.to_string().as_str().as_bytes())
}
#[inline]
fn search_in_ignore_ascii_case(&self, haystack: &'a str) -> Option<usize> {
naive_opt_mc_bytes_iac(haystack.as_bytes(), self.to_string().as_str().as_bytes())
}
#[inline]
fn rsearch_in_ignore_ascii_case(&self, haystack: &'a str) -> Option<usize> {
naive_opt_mc_rev_bytes_iac(haystack.as_bytes(), self.to_string().as_str().as_bytes())
}
#[inline]
fn len(&self) -> usize {
self.to_string().as_bytes().len()
}
}
pub trait SearchInBytes<'a>: Sized {
fn search_in(&self, haystack: &'a [u8]) -> Option<usize>;
fn rsearch_in(&self, haystack: &'a [u8]) -> Option<usize>;
fn search_in_ignore_ascii_case(&self, haystack: &'a [u8]) -> Option<usize>;
fn rsearch_in_ignore_ascii_case(&self, haystack: &'a [u8]) -> Option<usize>;
fn len(&self) -> usize;
fn is_empty(&self) -> bool {
self.len() == 0
}
#[inline]
fn includes_in(&self, haystack: &'a [u8]) -> bool {
self.search_in(haystack).is_some()
}
#[inline]
fn includes_in_ignore_ascii_case(&self, haystack: &'a [u8]) -> bool {
self.search_in_ignore_ascii_case(haystack).is_some()
}
}
impl<'a, 'b> SearchInBytes<'a> for &'b [u8] {
#[inline]
fn search_in(&self, haystack: &'a [u8]) -> Option<usize> {
naive_opt_mc_bytes(haystack, self)
}
#[inline]
fn rsearch_in(&self, haystack: &'a [u8]) -> Option<usize> {
naive_opt_mc_rev_bytes(haystack, self)
}
#[inline]
fn search_in_ignore_ascii_case(&self, haystack: &'a [u8]) -> Option<usize> {
naive_opt_mc_bytes_iac(haystack, self)
}
#[inline]
fn rsearch_in_ignore_ascii_case(&self, haystack: &'a [u8]) -> Option<usize> {
naive_opt_mc_rev_bytes_iac(haystack, self)
}
#[inline]
fn len(&self) -> usize {
u8_len(self)
}
}
#[inline(always)]
fn u8_len(a: &[u8]) -> usize {
a.len()
}
impl<'a, 'b> SearchInBytes<'a> for &'b str {
#[inline]
fn search_in(&self, haystack: &'a [u8]) -> Option<usize> {
naive_opt_mc_bytes(haystack, self.as_bytes())
}
#[inline]
fn rsearch_in(&self, haystack: &'a [u8]) -> Option<usize> {
naive_opt_mc_rev_bytes(haystack, self.as_bytes())
}
#[inline]
fn search_in_ignore_ascii_case(&self, haystack: &'a [u8]) -> Option<usize> {
naive_opt_mc_bytes_iac(haystack, self.as_bytes())
}
#[inline]
fn rsearch_in_ignore_ascii_case(&self, haystack: &'a [u8]) -> Option<usize> {
naive_opt_mc_rev_bytes_iac(haystack, self.as_bytes())
}
#[inline]
fn len(&self) -> usize {
self.as_bytes().len()
}
}
impl<'a, 'b> SearchInBytes<'a> for &'b String {
#[inline]
fn search_in(&self, haystack: &'a [u8]) -> Option<usize> {
naive_opt_mc_bytes(haystack, self.as_bytes())
}
#[inline]
fn rsearch_in(&self, haystack: &'a [u8]) -> Option<usize> {
naive_opt_mc_rev_bytes(haystack, self.as_bytes())
}
#[inline]
fn search_in_ignore_ascii_case(&self, haystack: &'a [u8]) -> Option<usize> {
naive_opt_mc_bytes_iac(haystack, self.as_bytes())
}
#[inline]
fn rsearch_in_ignore_ascii_case(&self, haystack: &'a [u8]) -> Option<usize> {
naive_opt_mc_rev_bytes_iac(haystack, self.as_bytes())
}
#[inline]
fn len(&self) -> usize {
self.as_str().len()
}
}
impl<'a> SearchInBytes<'a> for char {
#[inline]
fn search_in(&self, haystack: &'a [u8]) -> Option<usize> {
naive_opt_mc_bytes(haystack, self.to_string().as_bytes())
}
#[inline]
fn rsearch_in(&self, haystack: &'a [u8]) -> Option<usize> {
naive_opt_mc_rev_bytes(haystack, self.to_string().as_bytes())
}
#[inline]
fn search_in_ignore_ascii_case(&self, haystack: &'a [u8]) -> Option<usize> {
naive_opt_mc_bytes_iac(haystack, self.to_string().as_bytes())
}
#[inline]
fn rsearch_in_ignore_ascii_case(&self, haystack: &'a [u8]) -> Option<usize> {
naive_opt_mc_rev_bytes_iac(haystack, self.to_string().as_bytes())
}
#[inline]
fn len(&self) -> usize {
self.to_string().as_bytes().len()
}
}
pub fn string_search(haystack: &str, needle: &str) -> Option<usize> {
naive_opt_mc_bytes(haystack.as_bytes(), needle.as_bytes())
}
pub fn string_rsearch(haystack: &str, needle: &str) -> Option<usize> {
naive_opt_mc_rev_bytes(haystack.as_bytes(), needle.as_bytes())
}
pub fn string_search_bytes(haystack: &[u8], needle: &[u8]) -> Option<usize> {
naive_opt_mc_bytes(haystack, needle)
}
pub fn string_rsearch_bytes(haystack: &[u8], needle: &[u8]) -> Option<usize> {
naive_opt_mc_rev_bytes(haystack, needle)
}
pub fn string_search_ignore_ascii_case(haystack: &str, needle: &str) -> Option<usize> {
naive_opt_mc_bytes_iac(haystack.as_bytes(), needle.as_bytes())
}
pub fn string_search_bytes_ignore_ascii_case(haystack: &[u8], needle: &[u8]) -> Option<usize> {
naive_opt_mc_bytes_iac(haystack, needle)
}
pub fn string_rsearch_ignore_ascii_case(haystack: &str, needle: &str) -> Option<usize> {
naive_opt_mc_rev_bytes_iac(haystack.as_bytes(), needle.as_bytes())
}
pub fn string_rsearch_bytes_ignore_ascii_case(haystack: &[u8], needle: &[u8]) -> Option<usize> {
naive_opt_mc_rev_bytes_iac(haystack, needle)
}
pub fn string_search_indices<'a, P: SearchIn<'a>>(
haystack: &'a str,
needle: P,
) -> SearchIndices<'a, P> {
SearchIndices::new(haystack, needle)
}
pub fn string_search_indices_bytes<'a, P: SearchInBytes<'a>>(
haystack: &'a [u8],
needle: P,
) -> SearchIndicesBytes<'a, P> {
SearchIndicesBytes::new(haystack, needle)
}
pub fn string_rsearch_indices<'a, P: SearchIn<'a>>(
haystack: &'a str,
needle: P,
) -> RevSearchIndices<'a, P> {
RevSearchIndices::new(haystack, needle)
}
pub fn string_rsearch_indices_bytes<'a, P: SearchInBytes<'a>>(
haystack: &'a [u8],
needle: P,
) -> RevSearchIndicesBytes<'a, P> {
RevSearchIndicesBytes::new(haystack, needle)
}
pub fn string_search_indices_ignore_ascii_case<'a, P: SearchIn<'a>>(
haystack: &'a str,
needle: P,
) -> SearchIndicesIgnoreAsciiCase<'a, P> {
SearchIndicesIgnoreAsciiCase::new(haystack, needle)
}
pub fn string_search_indices_bytes_ignore_ascii_case<'a, P: SearchInBytes<'a>>(
haystack: &'a [u8],
needle: P,
) -> SearchIndicesBytesIgnoreAsciiCase<'a, P> {
SearchIndicesBytesIgnoreAsciiCase::new(haystack, needle)
}
pub fn string_rsearch_indices_ignore_ascii_case<'a, P: SearchIn<'a>>(
haystack: &'a str,
needle: P,
) -> RevSearchIndicesIgnoreAsciiCase<'a, P> {
RevSearchIndicesIgnoreAsciiCase::new(haystack, needle)
}
pub fn string_rsearch_indices_bytes_ignore_ascii_case<'a, P: SearchInBytes<'a>>(
haystack: &'a [u8],
needle: P,
) -> RevSearchIndicesBytesIgnoreAsciiCase<'a, P> {
RevSearchIndicesBytesIgnoreAsciiCase::new(haystack, needle)
}
#[cfg(not(feature = "only_mc_last"))]
mod mc_1st;
#[cfg(not(feature = "only_mc_1st"))]
mod mc_last;
#[inline(always)]
fn naive_opt_mc_bytes(hay_bytes: &[u8], nee_bytes: &[u8]) -> Option<usize> {
#[cfg(feature = "only_mc_1st")]
{
mc_1st::naive_opt_mc_1st_bytes(hay_bytes, nee_bytes)
}
#[cfg(feature = "only_mc_last")]
{
mc_last::naive_opt_mc_last_bytes(hay_bytes, nee_bytes)
}
#[cfg(all(not(feature = "only_mc_1st"), not(feature = "only_mc_last")))]
{
if nee_bytes.is_empty() {
return Some(0);
}
let byte_1st = nee_bytes[0];
let byte_last = nee_bytes[nee_bytes.len() - 1];
if byte_1st.is_ascii() && byte_last.is_ascii() {
let weight_1st = _ASCII_STOCHAS[byte_1st as usize];
let weight_last = _ASCII_STOCHAS[byte_last as usize];
if weight_1st <= weight_last {
mc_1st::naive_opt_mc_1st_bytes(hay_bytes, nee_bytes)
} else {
mc_last::naive_opt_mc_last_bytes(hay_bytes, nee_bytes)
}
} else {
mc_last::naive_opt_mc_last_bytes(hay_bytes, nee_bytes)
}
}
}
#[inline(always)]
fn naive_opt_mc_rev_bytes(hay_bytes: &[u8], nee_bytes: &[u8]) -> Option<usize> {
#[cfg(feature = "only_mc_1st")]
{
mc_1st::naive_opt_mc_1st_rev_bytes(hay_bytes, nee_bytes)
}
#[cfg(feature = "only_mc_last")]
{
mc_last::naive_opt_mc_last_rev_bytes(hay_bytes, nee_bytes)
}
#[cfg(all(not(feature = "only_mc_1st"), not(feature = "only_mc_last")))]
{
if nee_bytes.is_empty() {
return Some(hay_bytes.len());
}
let byte_1st = nee_bytes[0];
let byte_last = nee_bytes[nee_bytes.len() - 1];
if byte_1st.is_ascii() && byte_last.is_ascii() {
let weight_1st = _ASCII_STOCHAS[byte_1st as usize];
let weight_last = _ASCII_STOCHAS[byte_last as usize];
if weight_1st <= weight_last {
mc_1st::naive_opt_mc_1st_rev_bytes(hay_bytes, nee_bytes)
} else {
mc_last::naive_opt_mc_last_rev_bytes(hay_bytes, nee_bytes)
}
} else {
mc_last::naive_opt_mc_last_rev_bytes(hay_bytes, nee_bytes)
}
}
}
const _ASCII_STOCHAS: [u8; 128] = [
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
255, 0, 2, 0, 0, 0, 0, 0, 1, 1, 0, 3, 6, 14, 19, 1, 3, 4, 3, 2, 2, 1, 1, 1, 1, 1, 2, 0, 0, 1,
0, 0, 0, 4, 1, 5, 2, 4, 3, 0, 1, 5, 0, 0, 2, 3, 3, 2, 5, 0, 4, 6, 6, 1, 0, 0, 0, 0, 0, 1, 0, 1,
0, 1, 0, 39, 7, 20, 19, 69, 11, 9, 18, 39, 0, 2, 18, 12, 38, 38, 12, 1, 34, 35, 50, 13, 5, 5,
2, 7, 0, 0, 2, 0, 0, 0,
];
#[inline(always)]
fn naive_opt_mc_bytes_iac(hay_bytes: &[u8], nee_bytes: &[u8]) -> Option<usize> {
#[cfg(feature = "only_mc_1st")]
{
mc_1st::naive_opt_mc_1st_bytes_iac(hay_bytes, nee_bytes)
}
#[cfg(feature = "only_mc_last")]
{
mc_last::naive_opt_mc_last_bytes_iac(hay_bytes, nee_bytes)
}
#[cfg(all(not(feature = "only_mc_1st"), not(feature = "only_mc_last")))]
{
if nee_bytes.is_empty() {
return Some(0);
}
let byte_1st = nee_bytes[0];
let byte_last = nee_bytes[nee_bytes.len() - 1];
if byte_1st.is_ascii() && byte_last.is_ascii() {
let weight_1st = _ASCII_STOCHAS[byte_1st as usize];
let weight_last = _ASCII_STOCHAS[byte_last as usize];
if weight_1st <= weight_last {
mc_1st::naive_opt_mc_1st_bytes_iac(hay_bytes, nee_bytes)
} else {
mc_last::naive_opt_mc_last_bytes_iac(hay_bytes, nee_bytes)
}
} else {
mc_last::naive_opt_mc_last_bytes_iac(hay_bytes, nee_bytes)
}
}
}
#[inline(always)]
fn naive_opt_mc_rev_bytes_iac(hay_bytes: &[u8], nee_bytes: &[u8]) -> Option<usize> {
#[cfg(feature = "only_mc_1st")]
{
mc_1st::naive_opt_mc_1st_rev_bytes_iac(hay_bytes, nee_bytes)
}
#[cfg(feature = "only_mc_last")]
{
mc_last::naive_opt_mc_last_rev_bytes_iac(hay_bytes, nee_bytes)
}
#[cfg(all(not(feature = "only_mc_1st"), not(feature = "only_mc_last")))]
{
if nee_bytes.is_empty() {
return Some(hay_bytes.len());
}
let byte_1st = nee_bytes[0];
let byte_last = nee_bytes[nee_bytes.len() - 1];
if byte_1st.is_ascii() && byte_last.is_ascii() {
let weight_1st = _ASCII_STOCHAS[byte_1st as usize];
let weight_last = _ASCII_STOCHAS[byte_last as usize];
if weight_1st <= weight_last {
mc_1st::naive_opt_mc_1st_rev_bytes_iac(hay_bytes, nee_bytes)
} else {
mc_last::naive_opt_mc_last_rev_bytes_iac(hay_bytes, nee_bytes)
}
} else {
mc_last::naive_opt_mc_last_rev_bytes_iac(hay_bytes, nee_bytes)
}
}
}