112 lines · 3.2 KB · Rust
RawDownload
use std::fmt::Display; use crate::parse::Error; #[derive(PartialEq, Debug)]pub(crate) enum Kind {    Parse {        line_number: usize,        last_attempted_parser: ParseNode,        parsed_until: bstr::BString,    },    InputTooLarge {        actual: usize,    },} /// A list of parsers that parsing can fail on. This is used for pretty-printing errors#[derive(PartialEq, Debug, Clone, Copy)]pub(crate) enum ParseNode {    SectionHeader,    Name,    Value,} impl Display for ParseNode {    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {        match self {            Self::SectionHeader => write!(f, "section header"),            Self::Name => write!(f, "name"),            Self::Value => write!(f, "value"),        }    }} impl Error {    pub(crate) fn parse(line_number: usize, last_attempted_parser: ParseNode, parsed_until: bstr::BString) -> Self {        Self {            kind: Kind::Parse {                line_number,                last_attempted_parser,                parsed_until,            },        }    }     pub(crate) fn input_too_large(actual: usize) -> Self {        Self {            kind: Kind::InputTooLarge { actual },        }    }     /// The one-indexed line number where the error occurred. This is determined    /// by the number of newlines that were successfully parsed.    #[must_use]    pub const fn line_number(&self) -> usize {        match self.kind {            Kind::Parse { line_number, .. } => line_number + 1,            Kind::InputTooLarge { .. } => 1,        }    }     /// The data that was left unparsed, which contains the cause of the parse error.    #[must_use]    pub fn remaining_data(&self) -> &[u8] {        match &self.kind {            Kind::Parse { parsed_until, .. } => parsed_until,            Kind::InputTooLarge { .. } => &[],        }    }} impl Display for Error {    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {        let (line_number, last_attempted_parser, parsed_until) = match &self.kind {            Kind::InputTooLarge { actual } => {                return write!(                    f,                    "Configuration input is {actual} bytes large, but at most {} bytes are supported",                    u32::MAX                );            }            Kind::Parse {                line_number,                last_attempted_parser,                parsed_until,            } => (line_number, last_attempted_parser, parsed_until),        };        write!(            f,            "Got an unexpected token on line {} while trying to parse a {}: ",            line_number + 1,            last_attempted_parser,        )?;         let data_size = parsed_until.len();        let data = std::str::from_utf8(parsed_until);        match (data, data_size) {            (Ok(data), _) if data_size > 10 => {                write!(                    f,                    "'{}' ... ({} characters omitted)",                    data.chars().take(10).collect::<String>(),                    data_size - 10                )            }            (Ok(data), _) => write!(f, "'{data}'"),            (Err(_), _) => parsed_until.fmt(f),        }    }} impl std::error::Error for Error {}