croma-core 1.4.0

Library-first ABC to MusicXML exporter
Documentation
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct Diagnostic {
    pub severity: Severity,
    pub code: &'static str,
    pub message: String,
    pub span: Span,
    pub spec_reference: Option<SpecReference>,
    pub recovery_note: Option<RecoveryNote>,
}

impl Diagnostic {
    pub fn new(
        severity: Severity,
        code: &'static str,
        message: impl Into<String>,
        span: Span,
    ) -> Self {
        Self {
            severity,
            code,
            message: message.into(),
            span,
            spec_reference: None,
            recovery_note: None,
        }
    }

    pub fn with_spec_reference(mut self, spec_reference: SpecReference) -> Self {
        self.spec_reference = Some(spec_reference);
        self
    }

    pub fn with_recovery_note(mut self, recovery_note: RecoveryNote) -> Self {
        self.recovery_note = Some(recovery_note);
        self
    }
}

#[derive(Debug, Clone, PartialEq, Eq)]
pub struct SpecReference {
    pub label: String,
    pub url: Option<String>,
}

impl SpecReference {
    pub fn new(label: impl Into<String>) -> Self {
        Self {
            label: label.into(),
            url: None,
        }
    }

    pub fn with_url(mut self, url: impl Into<String>) -> Self {
        self.url = Some(url.into());
        self
    }
}

#[derive(Debug, Clone, PartialEq, Eq)]
pub struct RecoveryNote {
    pub message: String,
}

impl RecoveryNote {
    pub fn new(message: impl Into<String>) -> Self {
        Self {
            message: message.into(),
        }
    }
}

#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum Severity {
    Error,
    Warning,
    Info,
}

#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
pub struct Span {
    pub start: usize,
    pub end: usize,
}

impl Span {
    pub fn new(start: usize, end: usize) -> Self {
        Self { start, end }
    }

    pub fn len(self) -> usize {
        self.end.saturating_sub(self.start)
    }

    pub fn is_empty(self) -> bool {
        self.start == self.end
    }

    pub fn contains(self, offset: usize) -> bool {
        self.start <= offset && offset < self.end
    }

    pub fn contains_span(self, span: Span) -> bool {
        self.start <= span.start && span.end <= self.end
    }
}

#[cfg(test)]
#[path = "diagnostic_tests.rs"]
mod tests;