cfdkim/
bytes.rs

1//! Various utility functions to operate on bytes
2
3pub(crate) fn get_all_after<'a>(bytes: &'a [u8], end: &[u8]) -> &'a [u8] {
4    if let Some(mut end_index) = find(bytes, end) {
5        end_index += end.len();
6        &bytes[end_index..]
7    } else {
8        &[]
9    }
10}
11
12/// Find the offset of specific bytes in bytes
13pub(crate) fn find(bytes: &[u8], search: &[u8]) -> Option<usize> {
14    bytes
15        .windows(search.len())
16        .position(|window| window == search)
17}
18
19pub(crate) fn replace(bytes: &mut [u8], from: char, to: char) {
20    for byte in bytes.iter_mut() {
21        if *byte == from as u8 {
22            *byte = to as u8;
23        }
24    }
25}
26
27pub(crate) fn replace_slice(source: &[u8], from: &[u8], to: &[u8]) -> Vec<u8> {
28    let mut result = source.to_vec();
29    let from_len = from.len();
30    let to_len = to.len();
31
32    let mut i = 0;
33    while i + from_len <= result.len() {
34        if result[i..].starts_with(from) {
35            result.splice(i..i + from_len, to.iter().cloned());
36            i += to_len;
37        } else {
38            i += 1;
39        }
40    }
41
42    result
43}
44
45#[cfg(test)]
46mod tests {
47    use super::*;
48
49    #[test]
50    fn it_find() {
51        assert_eq!(find(&[97, 98, 99], &[1]), None);
52        assert_eq!(find(&[97, 98, 99], &[97]), Some(0));
53        assert_eq!(find(&[97, 98, 99], &[97, 98]), Some(0));
54    }
55
56    #[test]
57    fn it_replace_slice() {
58        let source = "aba".as_bytes();
59        assert_eq!(replace_slice(source, &[97], &[99]), "cbc".as_bytes());
60        assert_eq!(replace_slice(source, &[97, 98], &[]), "a".as_bytes());
61    }
62}