Skip to content

Commit

Permalink
feat: only scan for a unique pattern, return err on not
Browse files Browse the repository at this point in the history
  • Loading branch information
Jakobzs committed Jul 1, 2024
1 parent 82d49e8 commit 8e8fdd6
Showing 1 changed file with 22 additions and 17 deletions.
39 changes: 22 additions & 17 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,22 +23,16 @@ impl PatternScanner {
bytes: T,
pattern: U,
) -> Result<Option<usize>, PatternScannerError> {
let pattern_bytes = create_bytes_from_string(pattern)?;
// Scan for all occurrences of the pattern in the bytes
let results = self.scan_all_with_bytes(bytes, pattern)?;

// Scan the bytes for the unique pattern using the rayon crate
Ok(self.threadpool.install(|| {
bytes
.as_ref()
.par_windows(pattern_bytes.len())
.position_any(|window| {
window
.iter()
.zip(pattern_bytes.iter())
.all(|(byte, pattern_byte)| {
pattern_byte.is_none() || Some(*byte) == *pattern_byte
})
})
}))
// Check if there are multiple occurrences of the pattern
if results.len() > 1 {
return Err(PatternScannerError::NonUniquePattern);
}

// Return the first (and only) result, if any
Ok(results.first().copied())
}

pub fn scan_all<T: AsRef<str>>(&self, pattern: T) -> Result<Vec<usize>, PatternScannerError> {
Expand Down Expand Up @@ -119,6 +113,8 @@ pub enum PatternScannerError {
ByteLength(String),
//#[error("invalid header (expected {expected:?}, found {found:?})")]
//InvalidHeader { expected: String, found: String },
#[error("pattern is not unique")]
NonUniquePattern,
#[error("unknown pattern scanner error")]
Unknown,
}
Expand Down Expand Up @@ -229,15 +225,24 @@ mod tests {
#[test]
fn test_pattern_scan() {
let result = PatternScannerBuilder::builder()
.with_bytes(&[0x00, 0x01, 0x02, 0x33, 0x35, 0x33, 0x35, 0x07, 0x08, 0x09])
.with_threads(1)
.with_bytes(&[0x00, 0x01, 0x02, 0x33, 0x35, 0x33, 0x36, 0x07, 0x08, 0x09])
.build()
.scan("33 35")
.unwrap();

assert_eq!(result, Some(3));
}

#[test]
fn test_pattern_scan_nonunique() {
let result = PatternScannerBuilder::builder()
.with_bytes(&[0x00, 0x01, 0x02, 0x33, 0x35, 0x33, 0x35, 0x07, 0x08, 0x09])
.build()
.scan("33 35");

assert_eq!(result, Err(PatternScannerError::NonUniquePattern));
}

#[test]
fn test_pattern_scan_all() {
let result = PatternScannerBuilder::builder()
Expand Down

0 comments on commit 8e8fdd6

Please sign in to comment.