1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
/// Returns a `bool` saying whether the given string contains the specified pattern, expressed as an array of integers slices (e.g. `[&[20, 30], &[44, 65]]`). Avoids all heap allocations.
/// 
/// # Examples
/// 
/// ```
/// 
/// let bytes = &[20, 54, 115, 97, 97, 242];
/// let a = "s".as_bytes(); // 115
/// let b = "aa".as_bytes(); // 97, 97
/// assert_eq!(Some(2), find_bytes!(bytes; [a, b]));
/// 
#[macro_export]
macro_rules! find_bytes {
    ( $bytes:expr; $array:expr ) => ({
        let bytes_len = $bytes.len();
        // The start of the pattern that has to be checked, initialized as a `u8`.
        let mut pat_start = 0;
        // It is assigned the first character of the first non empty string.
        for slice in $array {
            if !slice.is_empty() {
                pat_start = slice[0];
                break
            }
        }
        let array_len = $array.len();

        let mut opt_index = None;

        // Counter needed when there are matches, so as to keep track of how many characters have already matched.
        let mut counter = 0;

        'outer: for i in 0..bytes_len {
            // Counter is reset.
            counter = 0;
            // If first character matches..
            if pat_start == $bytes[i] {
                'inner: for ii in 0..array_len {
                    let slice = $array[ii];
                    let len = slice.len();
                    // If slice is empty, skip iteration.
                    if len == 0 { continue 'inner }
                    // Avoids out of bounds index.
                    if i + len > bytes_len {
                        break 'outer
                    }

                    // If `slice` matches to the specified portion of `$string`.
                    if *slice == $bytes[i + counter..i + counter + len] {
                        // If it's the last element in the array, break the loop.
                        if ii == array_len - 1 {
                            opt_index = Some(i);
                            break 'outer
                        } else { // Else increase the number of characters that have already matched.
                            counter += len
                        }
                    } else {
                        continue 'outer
                    }
                }
            }
        }

        opt_index
    });
}