rust_assembler/bytes/
find_bytes.rs

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