use super::ExternalScanner;
use crate::external_scanner_ffi::{CExternalScanner, TSExternalScannerData};
use std::sync::{Arc, Mutex};
pub enum ScannerWrapper {
Rust(Arc<Mutex<dyn ExternalScanner + Send + Sync>>),
C(ScannerGuard),
}
impl ScannerWrapper {
pub fn new_rust(scanner: Arc<Mutex<dyn ExternalScanner + Send + Sync>>) -> Self {
ScannerWrapper::Rust(scanner)
}
pub unsafe fn new_c(data: &TSExternalScannerData) -> Option<Self> {
unsafe { CExternalScanner::new(data) }
.map(|scanner| ScannerWrapper::C(ScannerGuard(Box::new(scanner))))
}
pub fn scan(&mut self, lexer: &mut impl super::Lexer, valid_symbols: &[bool]) -> bool {
match self {
ScannerWrapper::Rust(scanner) => scanner
.lock()
.unwrap_or_else(|err| err.into_inner())
.scan(lexer, valid_symbols)
.is_some(),
ScannerWrapper::C(_guard) => {
false
}
}
}
pub fn serialize(&self, buffer: &mut Vec<u8>) {
match self {
ScannerWrapper::Rust(scanner) => scanner
.lock()
.unwrap_or_else(|err| err.into_inner())
.serialize(buffer),
ScannerWrapper::C(_guard) => {
}
}
}
pub fn deserialize(&mut self, buffer: &[u8]) {
match self {
ScannerWrapper::Rust(scanner) => scanner
.lock()
.unwrap_or_else(|err| err.into_inner())
.deserialize(buffer),
ScannerWrapper::C(_guard) => {
}
}
}
}
#[allow(dead_code)]
pub struct ScannerGuard(pub(crate) Box<CExternalScanner>);
impl Drop for ScannerGuard {
fn drop(&mut self) {
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::external_scanner::ScanResult;
use std::sync::{
Arc, Mutex,
atomic::{AtomicUsize, Ordering},
};
struct TestScanner {
drop_counter: Arc<AtomicUsize>,
}
impl ExternalScanner for TestScanner {
fn scan(
&mut self,
_lexer: &mut dyn crate::external_scanner::Lexer,
_valid_symbols: &[bool],
) -> Option<ScanResult> {
None
}
fn serialize(&self, _buffer: &mut Vec<u8>) {}
fn deserialize(&mut self, _buffer: &[u8]) {}
}
impl Drop for TestScanner {
fn drop(&mut self) {
self.drop_counter.fetch_add(1, Ordering::SeqCst);
}
}
#[test]
fn test_scanner_cleanup() {
let drop_counter = Arc::new(AtomicUsize::new(0));
{
let scanner = TestScanner {
drop_counter: drop_counter.clone(),
};
let _wrapper = ScannerWrapper::new_rust(Arc::new(Mutex::new(scanner)));
assert_eq!(drop_counter.load(Ordering::SeqCst), 0);
}
}
}