use std::fmt;
use thiserror::Error;
#[derive(Debug, Clone, Error)]
pub enum Error {
#[error("IO error: {0}")]
Io(String),
#[error("Syntax error at line {line}, column {col}:\n{context}\n{msg}{suggestion}")]
Syntax {
line: usize,
col: usize,
msg: String,
context: String,
suggestion: String,
},
#[error("Type mismatch at line {line}, column {col}: expected {expected}, found {found}")]
TypeMismatch {
line: usize,
col: usize,
expected: String,
found: String,
},
#[error("Indentation error at line {line}, column {col}:\n{context}\nExpected {expected} spaces, found {found} spaces\nHelp: TOON uses 2-space indentation for nested objects")]
IndentationError {
line: usize,
col: usize,
expected: usize,
found: usize,
context: String,
},
#[error("Unsupported type: {0}")]
UnsupportedType(String),
#[error("Invalid TOON format at line {line}, column {col}: {msg}")]
InvalidFormat {
line: usize,
col: usize,
msg: String,
},
#[error(
"Unexpected end of input at line {line}, column {col}\n{context}\nExpected: {expected}"
)]
UnexpectedEof {
line: usize,
col: usize,
expected: String,
context: String,
},
#[error("Error: {0}")]
Custom(String),
#[error("{0}")]
Message(String),
}
impl Error {
pub fn syntax(line: usize, col: usize, msg: &str) -> Self {
Error::Syntax {
line,
col,
msg: msg.to_string(),
context: String::new(),
suggestion: String::new(),
}
}
pub fn syntax_with_context(
line: usize,
col: usize,
msg: &str,
context: &str,
suggestion: Option<&str>,
) -> Self {
Error::Syntax {
line,
col,
msg: msg.to_string(),
context: context.to_string(),
suggestion: suggestion
.map(|s| format!("\nHelp: {}", s))
.unwrap_or_default(),
}
}
pub fn type_mismatch(line: usize, col: usize, expected: &str, found: &str) -> Self {
Error::TypeMismatch {
line,
col,
expected: expected.to_string(),
found: found.to_string(),
}
}
pub fn indentation_error(
line: usize,
col: usize,
expected: usize,
found: usize,
context: &str,
) -> Self {
Error::IndentationError {
line,
col,
expected,
found,
context: context.to_string(),
}
}
pub fn invalid_format(line: usize, col: usize, msg: &str) -> Self {
Error::InvalidFormat {
line,
col,
msg: msg.to_string(),
}
}
pub fn unexpected_eof(line: usize, col: usize, expected: &str, context: &str) -> Self {
Error::UnexpectedEof {
line,
col,
expected: expected.to_string(),
context: context.to_string(),
}
}
pub fn unsupported_type(msg: &str) -> Self {
Error::UnsupportedType(msg.to_string())
}
pub fn custom<T: fmt::Display>(msg: T) -> Self {
Error::Custom(msg.to_string())
}
pub fn io(msg: &str) -> Self {
Error::Io(msg.to_string())
}
}
impl serde::ser::Error for Error {
fn custom<T: fmt::Display>(msg: T) -> Self {
Error::Custom(msg.to_string())
}
}
impl serde::de::Error for Error {
fn custom<T: fmt::Display>(msg: T) -> Self {
Error::Custom(msg.to_string())
}
}
pub type Result<T> = std::result::Result<T, Error>;