smt-scope 0.1.7

A library for parsing and analysing SMT traces.
Documentation
use crate::NonMaxU32;

use super::{ConstSplit, Formatter, Matcher};

#[derive(Debug, Clone)]
pub enum TdcError {
    DuplicateExactMatcher(String, Option<NonMaxU32>),
}

#[derive(Debug, Clone)]
pub enum FallbackParseError {
    MaxCaptureTooLarge(NonMaxU32),
    FormatterParseError(FormatterParseError),
}

#[derive(Debug)]
pub enum ConversionError {
    Regex(regex::Error),
    FormatterExpectsRegex(Matcher, Formatter),
    RegexNotEnoughCaptures(Matcher, Formatter),
    MatcherError(MatcherParseError),
    FormatterParseError(FormatterParseError),
}

impl From<regex::Error> for ConversionError {
    fn from(err: regex::Error) -> Self {
        Self::Regex(err)
    }
}

impl From<MatcherParseError> for ConversionError {
    fn from(err: MatcherParseError) -> Self {
        Self::MatcherError(err)
    }
}

impl From<FormatterParseError> for ConversionError {
    fn from(err: FormatterParseError) -> Self {
        Self::FormatterParseError(err)
    }
}

pub type FormatterParseError = ParseError<FormatterError>;
pub type MatcherParseError = ParseError<MatcherError>;

#[derive(Debug, Clone)]
pub struct ParseError<T> {
    pub s: String,
    pub kind: T,
}

impl<T> From<ParseErrorConst<'_, T>> for ParseError<T> {
    fn from(err: ParseErrorConst<'_, T>) -> Self {
        Self {
            s: err.s.to_owned(),
            kind: err.kind,
        }
    }
}

pub type ResultFormatterConst<'a, T> = Result<T, ParseErrorConst<'a, FormatterError>>;
pub type ResultMatcherConst<'a, T> = Result<T, ParseErrorConst<'a, MatcherError>>;
pub type ResultConst<'a, T> = Result<T, ParseErrorConst<'a, EitherError>>;

#[derive(Debug)]
pub struct ParseErrorConst<'a, T> {
    pub s: &'a str,
    pub kind: T,
}

#[derive(Debug, Clone)]
pub enum FormatterError {
    MissingHash,
    MissingRange,
    MissingControl(&'static str),
    TooManyControl(char),
    TooManyChildren,
    UnexpectedPair,
    IncorrectControl,
    InvalidNumber,
    CaptureOverflow,
}

impl FormatterError {
    #[allow(clippy::no_effect)]
    pub const fn const_error<T>(&self, error: bool) -> T {
        use FormatterError::*;
        match self {
            MissingHash => [()][error as usize],
            MissingRange => [()][error as usize],
            MissingControl(_) => [()][error as usize],
            TooManyControl(_) => [()][error as usize],
            TooManyChildren => [()][error as usize],
            UnexpectedPair => [()][error as usize],
            IncorrectControl => [()][error as usize],
            InvalidNumber => [()][error as usize],
            CaptureOverflow => [()][error as usize],
        };
        loop {
            [()][!error as usize];
        }
    }
}

impl<'a> ParseErrorConst<'a, FormatterError> {
    pub(super) const fn missing_hash(s: &'a str) -> Self {
        Self {
            s,
            kind: FormatterError::MissingHash,
        }
    }
    pub(super) const fn invalid_number(s: &'a str) -> Self {
        Self {
            s,
            kind: FormatterError::InvalidNumber,
        }
    }
    pub(super) const fn missing_range(s: &'a str) -> Self {
        Self {
            s,
            kind: FormatterError::MissingRange,
        }
    }
    pub(super) const fn missing_control(s: &'a str, expected: &'static str) -> Self {
        Self {
            s,
            kind: FormatterError::MissingControl(expected),
        }
    }
    pub(super) const fn too_many_control(split: ConstSplit<'a, 1>) -> Self {
        Self {
            s: split.remainder(),
            kind: FormatterError::TooManyControl(split.control()),
        }
    }
    pub(super) const fn too_many_children(s: &'a str) -> Self {
        Self {
            s,
            kind: FormatterError::TooManyChildren,
        }
    }
    pub(super) const fn unexpected_pair(s: &'a str) -> Self {
        Self {
            s,
            kind: FormatterError::UnexpectedPair,
        }
    }
    pub(super) const fn incorrect_control(s: &'a str) -> Self {
        Self {
            s,
            kind: FormatterError::IncorrectControl,
        }
    }
    pub(super) const fn capture_overflow(s: &'a str) -> Self {
        Self {
            s,
            kind: FormatterError::CaptureOverflow,
        }
    }
}

#[derive(Debug, Clone)]
pub enum MatcherError {
    InvalidChildrenSpec,
}

impl MatcherError {
    #[allow(clippy::no_effect)]
    pub const fn const_error<T>(&self, error: bool) -> T {
        use MatcherError::*;
        match self {
            InvalidChildrenSpec => [()][error as usize],
        };
        loop {
            [()][!error as usize];
        }
    }
}

impl<'a> ParseErrorConst<'a, MatcherError> {
    pub(super) const fn invalid_children_spec(s: &'a str) -> Self {
        Self {
            s,
            kind: MatcherError::InvalidChildrenSpec,
        }
    }
}

pub enum EitherError {
    Formatter(FormatterError),
    Matcher(MatcherError),
    InvalidCapture,
}

impl EitherError {
    #[allow(clippy::no_effect)]
    pub const fn const_error<T>(&self, error: bool) -> T {
        use EitherError::*;
        match self {
            Formatter(err) => err.const_error(error),
            Matcher(err) => err.const_error(error),
            InvalidCapture => [()][error as usize],
        };
        loop {
            [()][!error as usize];
        }
    }
}

impl<'a> ParseErrorConst<'a, EitherError> {
    pub(super) const fn formatter(err: ParseErrorConst<'a, FormatterError>) -> Self {
        Self {
            s: err.s,
            kind: EitherError::Formatter(err.kind),
        }
    }
    pub(super) const fn matcher(err: ParseErrorConst<'a, MatcherError>) -> Self {
        Self {
            s: err.s,
            kind: EitherError::Matcher(err.kind),
        }
    }

    pub(super) const fn invalid_capture(s: &'a str) -> Self {
        Self {
            s,
            kind: EitherError::InvalidCapture,
        }
    }
}