knave-expand 0.14.22

The reading, scoping and expansion stages of knave
Documentation
use std::rc::Rc;

use super::DiagnosticCode;

pub struct CodeStage {
    member: DiagnosticCode,
}

impl CodeStage {
    pub const MACROS: Self = Self {
        member: DiagnosticCode::MACRO_FAILED,
    };
    pub const LINTS: Self = Self {
        member: DiagnosticCode::UNMATCHED_LINK,
    };
    const STAGE_PREFIX_LENGTH: usize = 3;

    pub fn code_named(&self, name: &str) -> Option<DiagnosticCode> {
        self.codes()
            .find(|(source_name, _)| source_name == name)
            .map(|(_, code)| code)
    }

    pub fn names(&self) -> Vec<Rc<str>> {
        self.codes()
            .map(|(source_name, _)| Rc::from(source_name))
            .collect()
    }

    pub fn name_of(&self, wanted: &DiagnosticCode) -> Option<String> {
        self.codes()
            .find(|(_, code)| code == wanted)
            .map(|(source_name, _)| source_name)
    }

    fn codes(&self) -> impl Iterator<Item = (String, DiagnosticCode)> {
        DiagnosticCode::named()
            .filter(|(_, code)| self.holds(code))
            .map(|(constant, code)| (Self::source_name(constant), code))
    }

    fn holds(&self, code: &DiagnosticCode) -> bool {
        Self::stage_prefix(code) == Self::stage_prefix(&self.member)
    }

    fn stage_prefix(code: &DiagnosticCode) -> &str {
        &code.as_str()[..Self::STAGE_PREFIX_LENGTH]
    }

    fn source_name(constant: &str) -> String {
        constant.replace('_', "-").to_lowercase()
    }
}