rust_assembler/str/
contains_str.rs

1/// Returns a `bool` saying whether the given string contains the specified pattern, expressed as an array of `&str`. Avoids all heap allocations.
2/// 
3/// # Examples
4/// 
5/// ```
6/// 
7/// let s = "Come va, amico?";
8/// assert_eq!(contains!(s; ["me", "v", "a, a"]), true);
9/// 
10#[macro_export]
11macro_rules! contains_str {
12    ( $string:expr; $array:expr ) => ({
13        let bytes = $string.as_bytes();
14        let bytes_len = bytes.len();
15        // The start of the pattern that has to be checked, initialized as a `u8`.
16        let mut pat_start = 0u8;
17        // It is assigned the first character of the first non empty string.
18        for slice in $array {
19            if slice != "" {
20                pat_start = slice.as_bytes()[0];
21                break
22            }
23        }
24        let array_len = $array.len();
25
26        let mut is_contained = false;
27
28        // Counter needed when there are matches, so as to keep track of how many characters have already matched.
29        let mut counter = 0;
30
31        'outer: for i in 0..bytes_len {
32            // Counter is reset.
33            counter = 0;
34            // If first character matches..
35            if pat_start == bytes[i] {
36                'inner: for ii in 0..array_len {
37                    let slice = $array[ii].as_bytes();
38                    let len = slice.len();
39                    // If slice is empty, skip iteration. If it's last one, returns true.
40                    if len == 0 { if ii == array_len - 1 {
41                        is_contained = true;
42                        break 'outer
43                    } else {
44                        continue 'inner
45                    } }
46                    // Avoids out of bounds index.
47                    if i + len > bytes_len {
48                        break 'outer
49                    }
50
51                    // If `slice` matches to the specified portion of `$string`.
52                    if *slice == bytes[i + counter..i + counter + len] {
53                        // If it's the last element in the array, returns true and breaks the loop.
54                        if ii == array_len - 1 {
55                            is_contained = true;
56                            break 'outer
57                        } else { // Else increase the number of characters that have already matched.
58                            counter += len
59                        }
60                    } else {
61                        continue 'outer
62                    }
63                }
64            }
65        }
66
67        is_contained
68    });
69}