texform 0.1.0

LaTeX formula parser, editor, and normalizer — the public TeXForm facade
Documentation
use crate::Document;
use crate::ParseDiagnostic;

#[derive(Debug, Clone)]
pub struct ParseResult {
    document: Option<Document>,
    diagnostics: Vec<ParseDiagnostic>,
}

impl ParseResult {
    pub(crate) fn from_core(result: texform_core::parse::ParseResult) -> Self {
        let (document, diagnostics) = result.into_parts();
        Self {
            document: document.map(Document::from_core),
            diagnostics,
        }
    }

    #[doc(hidden)]
    pub fn __from_parts_for_tests(
        document: Option<Document>,
        diagnostics: Vec<ParseDiagnostic>,
    ) -> Self {
        Self {
            document,
            diagnostics,
        }
    }

    pub fn document(&self) -> Option<&Document> {
        self.document.as_ref()
    }

    pub fn diagnostics(&self) -> &[ParseDiagnostic] {
        self.diagnostics.as_slice()
    }

    pub fn into_diagnostics(self) -> Vec<ParseDiagnostic> {
        self.diagnostics
    }

    pub fn has_errors(&self) -> bool {
        self.document.as_ref().is_some_and(Document::has_errors)
    }

    pub fn try_into_document(self) -> Result<(Document, Vec<ParseDiagnostic>), ParseError> {
        match (self.document, self.diagnostics) {
            (Some(document), diagnostics) if !document.has_errors() => Ok((document, diagnostics)),
            (document, diagnostics) => Err(ParseError {
                document: document.map(Box::new),
                diagnostics,
            }),
        }
    }

    pub fn into_parts(self) -> (Option<Document>, Vec<ParseDiagnostic>) {
        (self.document, self.diagnostics)
    }
}

#[derive(Debug, Clone)]
pub struct ParseError {
    pub document: Option<Box<Document>>,
    pub diagnostics: Vec<ParseDiagnostic>,
}

impl ParseError {
    pub fn diagnostics(&self) -> &[ParseDiagnostic] {
        self.diagnostics.as_slice()
    }

    pub fn document(&self) -> Option<&Document> {
        self.document.as_deref()
    }

    pub fn into_diagnostics(self) -> Vec<ParseDiagnostic> {
        self.diagnostics
    }

    pub fn into_parts(self) -> (Option<Document>, Vec<ParseDiagnostic>) {
        (self.document.map(|document| *document), self.diagnostics)
    }
}

impl std::fmt::Display for ParseError {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        if self.document.is_some() {
            f.write_str("parse produced an incomplete document")
        } else {
            f.write_str("parse produced no document")
        }
    }
}

impl std::error::Error for ParseError {}

impl From<texform_core::parse::ParseError> for ParseError {
    fn from(error: texform_core::parse::ParseError) -> Self {
        let (document, diagnostics) = error.into_parts();
        Self {
            document: document.map(Document::from_core).map(Box::new),
            diagnostics,
        }
    }
}