rust_assembler/bytes/
contains_bytes.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_bytes {
12    ( $bytes:expr; $array:expr ) => ({
13        let bytes_len = $bytes.len();
14        // The start of the pattern that has to be checked, initialized as a `u8`.
15        let mut pat_start = 0u8;
16        // It is assigned the first character of the first non empty string.
17        for slice in $array {
18            if !slice.is_empty() {
19                pat_start = slice[0];
20                break
21            }
22        }
23        let array_len = $array.len();
24
25        let mut is_contained = false;
26
27        // Counter needed when there are matches, so as to keep track of how many characters have already matched.
28        let mut counter = 0;
29
30        'outer: for i in 0..bytes_len {
31            // Counter is reset.
32            counter = 0;
33            // If first character matches..
34            if pat_start == $bytes[i] {
35                'inner: for ii in 0..array_len {
36                    let slice = $array[ii];
37                    let len = slice.len();
38                    // If slice is empty, skip iteration. If it's last one, returns true.
39                    if len == 0 { if ii == array_len - 1 {
40                        is_contained = true;
41                        break 'outer
42                    } else {
43                        continue 'inner
44                    } }
45                    // Avoids out of bounds index.
46                    if i + len > bytes_len {
47                        break 'outer
48                    }
49
50                    // If `slice` matches to the specified portion of `$string`.
51                    if *slice == $bytes[i + counter..i + counter + len] {
52                        // If it's the last element in the array, break the loop.
53                        if ii == array_len - 1 {
54                            is_contained = true;
55                            break 'outer
56                        } else { // Else increase the number of characters that have already matched.
57                            counter += len
58                        }
59                    } else {
60                        continue 'outer
61                    }
62                }
63            }
64        }
65
66        is_contained
67    });
68}