use libfse::{FseMap, FseOpcode, FseScanner, Rule};
use std::alloc::{GlobalAlloc, Layout, System};
use std::sync::atomic::{AtomicUsize, Ordering};
struct TrackingAllocator;
static ALLOC_COUNT: AtomicUsize = AtomicUsize::new(0);
unsafe impl GlobalAlloc for TrackingAllocator {
unsafe fn alloc(&self, layout: Layout) -> *mut u8 {
ALLOC_COUNT.fetch_add(1, Ordering::SeqCst);
System.alloc(layout)
}
unsafe fn dealloc(&self, ptr: *mut u8, layout: Layout) {
System.dealloc(ptr, layout)
}
}
#[global_allocator]
static GLOBAL: TrackingAllocator = TrackingAllocator;
#[test]
fn test_zero_alloc_in_hot_loop() {
let rules = vec![
Rule::new("match_one", FseOpcode::Record(1)),
Rule::new("match_two", FseOpcode::Record(2)),
Rule::new("miss_me", FseOpcode::Record(3)),
];
let map = FseMap::compile(rules).unwrap();
let mut scanner = FseScanner::new(&map).unwrap();
let input = b"This string contains match_one and match_two but excludes the other one. ".repeat(100);
ALLOC_COUNT.store(0, Ordering::SeqCst);
let _ = scanner.scan(&input).unwrap();
let count = ALLOC_COUNT.load(Ordering::SeqCst);
println!("Allocations during scan: {}", count);
assert_eq!(count, 0, "Hot loop performed {} allocations! Expected 0.", count);
}