use std::fmt;
#[non_exhaustive]
#[derive(Debug, Clone)]
pub struct ParseError {
pub message: String,
pub line: usize,
pub col: usize,
}
impl fmt::Display for ParseError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(
f,
"ParseError at {}:{}: {}",
self.line, self.col, self.message
)
}
}
impl std::error::Error for ParseError {}
#[non_exhaustive]
#[derive(Debug, Clone)]
pub struct ResolveError {
pub message: String,
pub path: String,
pub line: usize,
pub col: usize,
}
impl fmt::Display for ResolveError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(
f,
"ResolveError at {}:{}: {} (path: {})",
self.line, self.col, self.message, self.path
)
}
}
impl ResolveError {
pub(crate) fn concat_type_mismatch(
left_type: &str,
right_type: &str,
line: usize,
col: usize,
) -> Self {
ResolveError {
message: format!(
"value concatenation requires same-kind operands per HOCON S10; \
got {} + {}",
left_type, right_type
),
path: String::new(),
line,
col,
}
}
}
impl std::error::Error for ResolveError {}
#[non_exhaustive]
#[derive(Debug, Clone)]
pub struct ConfigError {
pub message: String,
pub path: String,
}
impl fmt::Display for ConfigError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "ConfigError: {} (path: {})", self.message, self.path)
}
}
impl std::error::Error for ConfigError {}
impl ConfigError {
pub fn is_not_resolved(&self) -> bool {
self.message.starts_with("value is not resolved")
}
}
#[derive(Debug, Clone)]
pub struct NotResolvedError {
pub path: String,
}
impl fmt::Display for NotResolvedError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(
f,
"value at path {:?} is not resolved (call resolve() before accessing values)",
self.path
)
}
}
impl std::error::Error for NotResolvedError {}
#[non_exhaustive]
#[derive(Debug)]
pub enum HoconError {
Parse(ParseError),
Resolve(ResolveError),
Io(std::io::Error),
NotResolved(NotResolvedError),
}
impl fmt::Display for HoconError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
HoconError::Parse(e) => write!(f, "{}", e),
HoconError::Resolve(e) => write!(f, "{}", e),
HoconError::Io(e) => write!(f, "I/O error: {}", e),
HoconError::NotResolved(e) => write!(f, "{}", e),
}
}
}
impl std::error::Error for HoconError {
fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
match self {
HoconError::Parse(e) => Some(e),
HoconError::Resolve(e) => Some(e),
HoconError::Io(e) => Some(e),
HoconError::NotResolved(e) => Some(e),
}
}
}
impl From<ParseError> for HoconError {
fn from(e: ParseError) -> Self {
HoconError::Parse(e)
}
}
impl From<ResolveError> for HoconError {
fn from(e: ResolveError) -> Self {
HoconError::Resolve(e)
}
}
impl From<std::io::Error> for HoconError {
fn from(e: std::io::Error) -> Self {
HoconError::Io(e)
}
}