sub-strs 0.29.2

For finding sub strings...
Documentation
/*
==--==--==--==--==--==--==--==--==--==--==--==--==--==--==--==--

sub-strs

Copyright (C) 2019-2023  Anonymous

There are several releases over multiple years,
they are listed as ranges, such as: "2019-2023".

This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU Lesser General Public License for more details.

You should have received a copy of the GNU Lesser General Public License
along with this program.  If not, see <https://www.gnu.org/licenses/>.

::--::--::--::--::--::--::--::--::--::--::--::--::--::--::--::--
*/

//! # Some kit processing sub strings...

use {
    alloc::vec::Vec,
    core::ops::Range,
    crate::Order,
};

/// # Checks if string `s` has all sub strings in given order
///
/// - If the iterator is empty, the function returns `true`.
/// - Overlapped sub strings will not be counted.
///
/// ## Examples
///
/// ```
/// use sub_strs::Order;
///
/// for (s, sub_strs) in &[
///     ("123 456 abc 789", &["123", "456", "abc", "789"][..]),
///     ("123456abc789", &["123", "456", "abc", "789"]),
///     ("123456abc789", &[]),
/// ] {
///     assert!(sub_strs::has_all(s, sub_strs.iter(), Order::Exact));
/// }
///
/// for (s, sub_strs) in &[
///     ("123 456 abc 789", &["123", "456", "789", "abc"]),
///     ("123456abc789", &["123", "3456", "6abc", "c789"]),
/// ] {
///     assert!(sub_strs::has_all(s, sub_strs.iter(), Order::Exact) == false);
/// }
///
/// for (s, sub_strs) in &[
///     ("123 456 abc 789", ["123", "456", "789", "abc"]),
/// ] {
///     assert!(sub_strs::has_all(s, sub_strs, Order::Any));
/// }
///
/// for (s, sub_strs) in &[
///     ("123456abc789", ["1234", "456", "789", "abc"]),
/// ] {
///     assert!(sub_strs::has_all(s, sub_strs, Order::Any) == false);
/// }
/// ```
pub fn has_all<S0, S1, I>(s: S0, sub_strs: I, order: Order) -> bool where S0: AsRef<str>, S1: AsRef<str>, I: IntoIterator<Item=S1> {
    match order {
        Order::Any => has_all_in_any_order(s, sub_strs),
        Order::Exact => has_all_in_exact_order(s, sub_strs),
    }
}

/// # Checks if string `s` has all sub strings in *any* order
fn has_all_in_any_order<S0, S1, I>(s: S0, sub_strs: I) -> bool where S0: AsRef<str>, S1: AsRef<str>, I: IntoIterator<Item=S1> {
    let s = s.as_ref();

    let mut sub_strs = sub_strs.into_iter();
    sub_strs.try_fold(Vec::<Range<_>>::with_capacity(sub_strs.size_hint().0.max(3)), |mut result, next| {
        let next = next.as_ref();
        match s.find(next) {
            Some(i) => {
                let next = i..i + next.len();
                if result.iter().any(|r| r.contains(&next.start) || r.contains(&next.end)) {
                    None
                } else {
                    result.push(next);
                    Some(result)
                }
            },
            None => None,
        }
    }).is_some()
}

/// # Checks if string `s` has all sub strings in *exact* order
fn has_all_in_exact_order<S0, S1, I>(s: S0, sub_strs: I) -> bool where S0: AsRef<str>, S1: AsRef<str>, I: IntoIterator<Item=S1> {
    let s = s.as_ref();

    let mut sub_strs = sub_strs.into_iter();
    sub_strs.try_fold(s, |result, next| {
        let next = next.as_ref();
        match result.find(next) {
            Some(i) => Some(&result[i + next.len()..]),
            None => None,
        }
    }).is_some()
}

#[test]
fn test_has_all_in_exact_order() {
    for (s, sub_strs) in &[
        (concat!(r#"macro_rules! code_name  { () => { ""#, code_name!(), "}}"), &["macro_rules!", "code_name", crate::CODE_NAME][..]),
    ] {
        assert_eq!(sub_strs.len(), sub_strs.iter().size_hint().0);
        assert!(has_all_in_exact_order(s, sub_strs.iter()));
    }
}