use std::fmt;
use std::io;
use std::path::PathBuf;
pub type Result<T> = std::result::Result<T, Error>;
#[derive(Debug)]
pub enum Error {
Io(io::Error),
Parse {
file: PathBuf,
line: usize,
column: usize,
message: String,
},
Validation {
message: String,
context: Option<String>,
},
Schema {
schema_name: String,
message: String,
},
Query { query_name: String, message: String },
Config { message: String },
CodeGen { message: String },
Project { message: String },
Generic(String),
}
impl fmt::Display for Error {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Error::Io(err) => write!(f, "I/O error: {}", err),
Error::Parse {
file,
line,
column,
message,
} => write!(
f,
"Parse error in {}:{}:{}: {}",
file.display(),
line,
column,
message
),
Error::Validation { message, context } => {
if let Some(ctx) = context {
write!(f, "Validation error in {}: {}", ctx, message)
} else {
write!(f, "Validation error: {}", message)
}
}
Error::Schema {
schema_name,
message,
} => write!(f, "Schema error in '{}': {}", schema_name, message),
Error::Query {
query_name,
message,
} => write!(f, "Query error in '{}': {}", query_name, message),
Error::Config { message } => write!(f, "Configuration error: {}", message),
Error::CodeGen { message } => write!(f, "Code generation error: {}", message),
Error::Project { message } => write!(f, "Project error: {}", message),
Error::Generic(msg) => write!(f, "{}", msg),
}
}
}
impl std::error::Error for Error {
fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
match self {
Error::Io(err) => Some(err),
_ => None,
}
}
}
impl From<io::Error> for Error {
fn from(err: io::Error) -> Self {
Error::Io(err)
}
}
impl From<String> for Error {
fn from(msg: String) -> Self {
Error::Generic(msg)
}
}
impl From<&str> for Error {
fn from(msg: &str) -> Self {
Error::Generic(msg.to_string())
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_error_display() {
let err = Error::Generic("test error".to_string());
assert_eq!(err.to_string(), "test error");
}
#[test]
fn test_parse_error_display() {
let err = Error::Parse {
file: PathBuf::from("test.au"),
line: 10,
column: 5,
message: "unexpected token".to_string(),
};
assert!(err.to_string().contains("test.au"));
assert!(err.to_string().contains("10:5"));
}
#[test]
fn test_schema_error_display() {
let err = Error::Schema {
schema_name: "User".to_string(),
message: "duplicate field 'id'".to_string(),
};
assert!(err.to_string().contains("User"));
assert!(err.to_string().contains("duplicate field"));
}
}