patterns/
lib.rs

1//! # Pattern matching library
2//! Allows you to search for a pattern within data via an iterator interface.
3//! This library uses the core::simd abstraction and is fully no_std compatible.
4//!
5//! ## Usage
6//! ```
7//! use patterns::Pattern;
8//!
9//! let data = [0_u8; 1_000_00];
10//! // Allows . and ? as wildcard.
11//! // Any number of wildcard characters between spaces is considered a wildcard byte.
12//! let pattern: Pattern = "01 02 00 ? 59 ff".parse().unwrap();
13//! let mut iterator = pattern.matches(&data);
14//!
15//! for _found in iterator {
16//!     // use _found
17//! }
18//! ```
19//!
20//! ## Limitations
21//! - The maximum amount of bytes supported inside a pattern are 64 bytes
22//! - Target alignment of the pattern to search for must be less or equal to 64
23//! - The pointer of data to search through must follow these invariants:
24//!   - `data.as_ptr() - 64 > `[`usize::MIN`]
25//!   - `data.as_ptr() + data.len() + 64 < `[`usize::MAX`]
26
27// todos
28// optimize pattern.len() <= alignment
29// explore getting rid of pattern.length
30
31#![feature(portable_simd)]
32#![no_std]
33// untested on big endian
34#![cfg(target_endian = "little")]
35
36pub use crate::{pattern::Pattern, scanner::Scanner};
37
38mod const_utils;
39mod masks;
40mod pattern;
41mod scanner;
42
43/// The type that holds a bit for each byte in [`BYTES`]
44pub type BytesMask = u64;
45
46const V128: usize = 16;
47const V256: usize = 32;
48const V512: usize = 64;
49const VUNKNOWN: usize = V512;
50
51/// Provides a constant optimizing `BYTES` (see [`Pattern`]) to target cpu simd
52/// width. This is a best-effort, defaulting to maximum supported bytes.
53///
54/// Note that `BYTES` also determines maximum pattern length.
55pub const OPTIMAL_BYTES: usize = default_vector_target_width();
56
57const fn default_vector_target_width() -> usize {
58    if (cfg!(target_arch = "arm") || cfg!(target_arch = "aarch64")) && cfg!(target_feature = "neon")
59    {
60        return V128;
61    }
62    if cfg!(target_arch = "hexagon") {
63        if cfg!(target_feature = "hvx-length128b") {
64            // 1024 bits
65            return V512;
66        }
67        if cfg!(target_feature = "hvx") {
68            return V512;
69        }
70    }
71    if cfg!(target_arch = "mips") && cfg!(target_feature = "msa") {
72        return V128;
73    }
74    if cfg!(target_arch = "powerpc")
75        && (cfg!(target_feature = "vsx") || cfg!(target_feature = "altivec"))
76    {
77        return V128;
78    }
79    if (cfg!(target_arch = "riscv32") || cfg!(target_arch = "riscv64"))
80        && cfg!(target_feature = "v")
81    {
82        return V128;
83    }
84    if (cfg!(target_arch = "wasm32") || cfg!(target_arch = "wasm64"))
85        && cfg!(target_feature = "simd128")
86    {
87        return V128;
88    }
89    if cfg!(target_arch = "x86") {
90        if cfg!(target_feature = "avx512f") {
91            return V512;
92        }
93        if cfg!(target_feature = "avx2") {
94            return V256;
95        }
96        if cfg!(target_feature = "sse2") {
97            return V128;
98        }
99    }
100    VUNKNOWN
101}