nyx-scanner 0.3.0

A CLI security scanner for automating vulnerability checks
Documentation
use serde::de::StdError;
use std::fmt;
use std::sync::PoisonError;
use thiserror::Error;

pub type NyxResult<T, E = NyxError> = Result<T, E>;

#[derive(Debug, Error)]
pub enum NyxError {
    #[error("I/O error: {0}")]
    Io(#[from] std::io::Error),

    #[error("TOML parse error: {0}")]
    Toml(#[from] toml::de::Error),

    #[error("SQLite error: {0}")]
    Sql(#[from] rusqlite::Error),

    #[error("tree-sitter error: {0}")]
    TreeSitter(#[from] tree_sitter::LanguageError),

    #[error("connection-pool error: {0}")]
    Pool(#[from] r2d2::Error),

    #[error("time error: {0}")]
    Time(#[from] std::time::SystemTimeError),

    #[error("poisoned lock: {0}")]
    Poison(String),

    #[error(transparent)]
    Other(#[from] Box<dyn StdError + Send + Sync + 'static>),

    #[error("{0}")]
    Msg(String),
}

impl<T> From<PoisonError<T>> for NyxError
where
    T: fmt::Debug,
{
    fn from(err: PoisonError<T>) -> Self {
        NyxError::Poison(err.to_string())
    }
}

impl From<&str> for NyxError {
    fn from(s: &str) -> Self {
        NyxError::Msg(s.to_owned())
    }
}

impl From<String> for NyxError {
    fn from(s: String) -> Self {
        NyxError::Msg(s)
    }
}

impl From<Box<dyn std::error::Error>> for NyxError {
    fn from(err: Box<dyn std::error::Error>) -> Self {
        NyxError::Msg(err.to_string())
    }
}

#[test]
fn io_conversion_retains_message() {
    let e = std::io::Error::other("boom!");
    let n: NyxError = e.into();
    assert!(matches!(n, NyxError::Io(_)));
    assert!(n.to_string().contains("boom"));
}

#[test]
fn poison_conversion_maps_correct_variant() {
    let lock = std::sync::Arc::new(std::sync::Mutex::new(()));

    {
        let lock2 = std::sync::Arc::clone(&lock);
        std::thread::spawn(move || {
            let _guard = lock2.lock().unwrap();
            panic!("intentional – poison the mutex");
        })
        .join()
        .ok();
    }

    let poison = lock.lock().unwrap_err();
    let nyx: NyxError = poison.into();

    assert!(matches!(nyx, NyxError::Poison(_)));
}

#[test]
fn simple_string_into_msg() {
    let nyx: NyxError = "plain msg".into();
    assert!(matches!(nyx, NyxError::Msg(s) if s == "plain msg"));
}