use crate::core::error::ScanError;
use crate::core::input::FileInput;
use crate::core::result::ScanResult;
use async_trait::async_trait;
use std::fmt::Debug;
use std::time::Duration;
#[async_trait]
pub trait Scanner: Send + Sync + Debug {
fn name(&self) -> &str;
async fn scan(&self, input: &FileInput) -> Result<ScanResult, ScanError>;
async fn health_check(&self) -> Result<(), ScanError>;
fn max_file_size(&self) -> Option<u64> {
None
}
async fn signature_version(&self) -> Option<String> {
None
}
fn supports_streaming(&self) -> bool {
false
}
}
pub trait ScannerConfig: Debug + Clone + Send + Sync {
fn connection_timeout(&self) -> Duration;
fn scan_timeout(&self) -> Duration;
fn max_file_size(&self) -> u64;
fn debug(&self) -> bool {
false
}
}
#[derive(Debug, Clone)]
pub struct DefaultScannerConfig {
pub connection_timeout: Duration,
pub scan_timeout: Duration,
pub max_file_size: u64,
pub debug: bool,
}
impl Default for DefaultScannerConfig {
fn default() -> Self {
Self {
connection_timeout: Duration::from_secs(10),
scan_timeout: Duration::from_secs(300), max_file_size: 100 * 1024 * 1024, debug: false,
}
}
}
impl ScannerConfig for DefaultScannerConfig {
fn connection_timeout(&self) -> Duration {
self.connection_timeout
}
fn scan_timeout(&self) -> Duration {
self.scan_timeout
}
fn max_file_size(&self) -> u64 {
self.max_file_size
}
fn debug(&self) -> bool {
self.debug
}
}
impl DefaultScannerConfig {
pub fn new() -> Self {
Self::default()
}
pub fn with_connection_timeout(mut self, timeout: Duration) -> Self {
self.connection_timeout = timeout;
self
}
pub fn with_scan_timeout(mut self, timeout: Duration) -> Self {
self.scan_timeout = timeout;
self
}
pub fn with_max_file_size(mut self, size: u64) -> Self {
self.max_file_size = size;
self
}
pub fn with_debug(mut self, debug: bool) -> Self {
self.debug = debug;
self
}
}
pub type BoxedScanner = Box<dyn Scanner>;
pub type ArcScanner = std::sync::Arc<dyn Scanner>;
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_default_config() {
let config = DefaultScannerConfig::default();
assert_eq!(config.connection_timeout(), Duration::from_secs(10));
assert_eq!(config.scan_timeout(), Duration::from_secs(300));
assert_eq!(config.max_file_size(), 100 * 1024 * 1024);
assert!(!config.debug());
}
#[test]
fn test_config_builder() {
let config = DefaultScannerConfig::new()
.with_connection_timeout(Duration::from_secs(5))
.with_scan_timeout(Duration::from_secs(60))
.with_max_file_size(50 * 1024 * 1024)
.with_debug(true);
assert_eq!(config.connection_timeout(), Duration::from_secs(5));
assert_eq!(config.scan_timeout(), Duration::from_secs(60));
assert_eq!(config.max_file_size(), 50 * 1024 * 1024);
assert!(config.debug());
}
}