extern crate alloc;
use alloc::format;
use alloc::string::{String, ToString};
use alloc::vec::Vec;
use core::fmt::{self, Display};
use facet_reflect::ReflectError;
pub use facet_reflect::Span;
#[derive(Debug)]
pub struct YamlError {
pub kind: YamlErrorKind,
pub span: Option<Span>,
pub source_code: Option<String>,
}
impl Display for YamlError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{}", self.kind)
}
}
impl core::error::Error for YamlError {}
impl YamlError {
pub const fn new(kind: YamlErrorKind, span: Span) -> Self {
YamlError {
kind,
span: Some(span),
source_code: None,
}
}
pub const fn without_span(kind: YamlErrorKind) -> Self {
YamlError {
kind,
span: None,
source_code: None,
}
}
pub fn with_source(mut self, source: &str) -> Self {
self.source_code = Some(source.to_string());
self
}
}
#[derive(Debug)]
pub enum YamlErrorKind {
Parse(String),
UnexpectedEvent {
got: String,
expected: &'static str,
},
UnexpectedEof {
expected: &'static str,
},
TypeMismatch {
expected: &'static str,
got: &'static str,
},
UnknownField {
field: String,
expected: Vec<&'static str>,
suggestion: Option<&'static str>,
},
MissingField {
field: &'static str,
},
InvalidValue {
message: String,
},
Reflect(ReflectError),
NumberOutOfRange {
value: String,
target_type: &'static str,
},
DuplicateKey {
key: String,
},
InvalidUtf8(core::str::Utf8Error),
Solver(String),
Unsupported(String),
Io(String),
}
impl Display for YamlErrorKind {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
YamlErrorKind::Parse(e) => write!(f, "YAML parse error: {e}"),
YamlErrorKind::UnexpectedEvent { got, expected } => {
write!(f, "unexpected YAML event: got {got}, expected {expected}")
}
YamlErrorKind::UnexpectedEof { expected } => {
write!(f, "unexpected end of input, expected {expected}")
}
YamlErrorKind::TypeMismatch { expected, got } => {
write!(f, "type mismatch: expected {expected}, got {got}")
}
YamlErrorKind::UnknownField {
field, expected, ..
} => {
write!(f, "unknown field `{field}`, expected one of: {expected:?}")
}
YamlErrorKind::MissingField { field } => {
write!(f, "missing required field `{field}`")
}
YamlErrorKind::InvalidValue { message } => {
write!(f, "invalid value: {message}")
}
YamlErrorKind::Reflect(e) => write!(f, "reflection error: {e}"),
YamlErrorKind::NumberOutOfRange { value, target_type } => {
write!(f, "number `{value}` out of range for {target_type}")
}
YamlErrorKind::DuplicateKey { key } => {
write!(f, "duplicate key `{key}`")
}
YamlErrorKind::InvalidUtf8(e) => write!(f, "invalid UTF-8 sequence: {e}"),
YamlErrorKind::Solver(msg) => write!(f, "solver error: {msg}"),
YamlErrorKind::Unsupported(msg) => write!(f, "unsupported: {msg}"),
YamlErrorKind::Io(msg) => write!(f, "IO error: {msg}"),
}
}
}
impl YamlErrorKind {
pub const fn code(&self) -> &'static str {
match self {
YamlErrorKind::Parse(_) => "yaml::parse",
YamlErrorKind::UnexpectedEvent { .. } => "yaml::unexpected_event",
YamlErrorKind::UnexpectedEof { .. } => "yaml::unexpected_eof",
YamlErrorKind::TypeMismatch { .. } => "yaml::type_mismatch",
YamlErrorKind::UnknownField { .. } => "yaml::unknown_field",
YamlErrorKind::MissingField { .. } => "yaml::missing_field",
YamlErrorKind::InvalidValue { .. } => "yaml::invalid_value",
YamlErrorKind::Reflect(_) => "yaml::reflect",
YamlErrorKind::NumberOutOfRange { .. } => "yaml::number_out_of_range",
YamlErrorKind::DuplicateKey { .. } => "yaml::duplicate_key",
YamlErrorKind::InvalidUtf8(_) => "yaml::invalid_utf8",
YamlErrorKind::Solver(_) => "yaml::solver",
YamlErrorKind::Unsupported(_) => "yaml::unsupported",
YamlErrorKind::Io(_) => "yaml::io",
}
}
pub fn label(&self) -> String {
match self {
YamlErrorKind::Parse(_) => "parse error here".to_string(),
YamlErrorKind::UnexpectedEvent { got, .. } => format!("unexpected {got}"),
YamlErrorKind::UnexpectedEof { expected } => format!("expected {expected}"),
YamlErrorKind::TypeMismatch { expected, got } => {
format!("expected {expected}, got {got}")
}
YamlErrorKind::UnknownField { field, .. } => format!("unknown field `{field}`"),
YamlErrorKind::MissingField { field } => format!("missing `{field}`"),
YamlErrorKind::InvalidValue { message } => message.clone(),
YamlErrorKind::Reflect(e) => format!("{e}"),
YamlErrorKind::NumberOutOfRange { target_type, .. } => {
format!("out of range for {target_type}")
}
YamlErrorKind::DuplicateKey { key } => format!("duplicate key `{key}`"),
YamlErrorKind::InvalidUtf8(_) => "invalid UTF-8".to_string(),
YamlErrorKind::Solver(msg) => msg.clone(),
YamlErrorKind::Unsupported(msg) => msg.clone(),
YamlErrorKind::Io(msg) => msg.clone(),
}
}
}
impl From<ReflectError> for YamlError {
fn from(e: ReflectError) -> Self {
YamlError::without_span(YamlErrorKind::Reflect(e))
}
}
impl From<ReflectError> for YamlErrorKind {
fn from(e: ReflectError) -> Self {
YamlErrorKind::Reflect(e)
}
}