vsec 0.0.1

Detect secrets and in Rust codebases
Documentation
//! SIMD-accelerated string operations for the scoring engine and filters.
//!
//! This module provides optimized implementations of common string operations
//! using SIMD instructions when available (AVX2, AVX-512, NEON), with automatic
//! fallback to scalar implementations on unsupported platforms.
//!
//! # Supported Platforms
//!
//! - **x86_64**: AVX-512 (512-bit), AVX2 (256-bit), SSE4.2 (128-bit), scalar fallback
//! - **aarch64**: NEON (128-bit), scalar fallback
//! - **Other architectures**: Scalar fallback only
//!
//! # Features
//!
//! - **Character classification**: Fast hex, base64, UUID, alphanumeric validation
//! - **Case conversion**: SIMD-accelerated ASCII lowercase/uppercase
//! - **Entropy calculation**: Vectorized byte frequency histogram
//! - **Speculative decoding**: SIMD Base64/Hex decoding for accurate entropy
//! - **Pattern matching**: Aho-Corasick multi-pattern matching (O(n) instead of O(n*m))
//!
//! # Example
//!
//! ```
//! use vsec::simd;
//!
//! // Character classification
//! assert!(simd::is_all_hex("deadbeef"));
//! assert!(simd::is_uuid_format("550e8400-e29b-41d4-a716-446655440000"));
//!
//! // Case conversion
//! let lower = simd::to_ascii_lowercase("HELLO WORLD");
//! assert_eq!(lower, "hello world");
//!
//! // Entropy calculation
//! let entropy = simd::calculate_entropy_str("random_string_here");
//!
//! // Multi-pattern matching
//! let matcher = simd::PatternMatcher::from_static(&["password", "secret", "key"]);
//! assert!(matcher.is_match("user_password"));
//! ```

pub mod classify;
pub mod decode;
pub mod detect;
pub mod entropy;
pub mod fuzzy;
pub mod lowercase;
pub mod patterns;
pub mod scoring;

// Re-export commonly used items at the module level
pub use classify::{
    has_lowercase, has_uppercase, is_all_alphanumeric, is_all_base64_chars, is_all_hex,
    is_uuid_format,
};
pub use decode::{entropy_with_decode, speculative_decode, DecodeResult, EncodingType};
pub use detect::{cpu_features, CpuFeatures, SimdLevel};
pub use fuzzy::{is_fuzzy_auth_like, is_fuzzy_sensitive, FuzzyMatcher};
pub use entropy::{byte_histogram, calculate_entropy, calculate_entropy_str};
pub use scoring::{quick_score, weighted_sum, FeatureIndex, FeatureVector};
pub use lowercase::{
    to_ascii_lowercase, to_ascii_lowercase_inplace, to_ascii_uppercase,
    to_ascii_uppercase_inplace,
};
pub use patterns::PatternMatcher;

/// Initialize SIMD support and return detected features.
///
/// This is optional - features are automatically detected on first use.
/// Calling this at startup can help avoid detection overhead during hot paths.
#[inline]
pub fn init() -> CpuFeatures {
    CpuFeatures::detect()
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn test_module_exports() {
        // Verify all public items are accessible
        let _ = init();
        let _ = cpu_features();

        assert!(is_all_hex("0123456789abcdef"));
        assert!(is_uuid_format("550e8400-e29b-41d4-a716-446655440000"));
        assert!(is_all_base64_chars("SGVsbG8="));
        assert!(is_all_alphanumeric("Hello123"));
        assert!(has_uppercase("Hello"));
        assert!(has_lowercase("Hello"));

        let lower = to_ascii_lowercase("HELLO");
        assert_eq!(lower, "hello");

        let upper = to_ascii_uppercase("hello");
        assert_eq!(upper, "HELLO");

        let entropy = calculate_entropy_str("test");
        assert!(entropy > 0.0);

        let hist = byte_histogram(b"test");
        assert_eq!(hist[b't' as usize], 2);

        let matcher = PatternMatcher::from_static(&["foo", "bar"]);
        assert!(matcher.is_match("foobar"));
    }

    #[test]
    fn test_prebuilt_matchers() {
        // Verify prebuilt matchers are accessible
        assert!(patterns::prebuilt::logging_functions().is_match("println"));
        assert!(patterns::prebuilt::auth_like().is_match("password"));
        assert!(patterns::prebuilt::command_like().is_match("command"));
        assert!(patterns::prebuilt::input_like().is_match("request"));
        assert!(patterns::prebuilt::placeholders().is_match("changeme"));
    }
}