Skip to main content

hocon/
error.rs

1use std::fmt;
2
3/// Error returned when HOCON input contains a syntax error.
4///
5/// Includes the line and column where the error was detected.
6#[non_exhaustive]
7#[derive(Debug, Clone)]
8pub struct ParseError {
9    /// Human-readable description of the error.
10    pub message: String,
11    /// 1-based line number.
12    pub line: usize,
13    /// 1-based column number.
14    pub col: usize,
15}
16
17impl fmt::Display for ParseError {
18    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
19        write!(
20            f,
21            "ParseError at {}:{}: {}",
22            self.line, self.col, self.message
23        )
24    }
25}
26
27impl std::error::Error for ParseError {}
28
29/// Error returned when substitution resolution fails (e.g., missing
30/// required substitution, cyclic reference).
31#[non_exhaustive]
32#[derive(Debug, Clone)]
33pub struct ResolveError {
34    /// Human-readable description of the error.
35    pub message: String,
36    /// The substitution path that failed (e.g., `"db.host"`).
37    pub path: String,
38    /// 1-based line number where the substitution appeared.
39    pub line: usize,
40    /// 1-based column number where the substitution appeared.
41    pub col: usize,
42}
43
44impl fmt::Display for ResolveError {
45    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
46        write!(
47            f,
48            "ResolveError at {}:{}: {} (path: {})",
49            self.line, self.col, self.message, self.path
50        )
51    }
52}
53
54impl std::error::Error for ResolveError {}
55
56/// Error returned by [`Config`](crate::Config) getters when a key is missing
57/// or the value has the wrong type.
58#[non_exhaustive]
59#[derive(Debug, Clone)]
60pub struct ConfigError {
61    /// Human-readable description of the error.
62    pub message: String,
63    /// The dot-separated path that was looked up.
64    pub path: String,
65}
66
67impl fmt::Display for ConfigError {
68    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
69        write!(f, "ConfigError: {} (path: {})", self.message, self.path)
70    }
71}
72
73impl std::error::Error for ConfigError {}
74
75/// Unified error type returned by top-level parse functions.
76///
77/// Wraps the three possible failure modes: syntax errors ([`ParseError`]),
78/// substitution resolution failures ([`ResolveError`]), and file I/O
79/// errors ([`std::io::Error`]).
80#[non_exhaustive]
81#[derive(Debug)]
82pub enum HoconError {
83    /// Syntax error during lexing or parsing.
84    Parse(ParseError),
85    /// Substitution resolution failure (missing key, cycle, etc.).
86    Resolve(ResolveError),
87    /// File I/O error when reading the top-level config file.
88    Io(std::io::Error),
89}
90
91impl fmt::Display for HoconError {
92    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
93        match self {
94            HoconError::Parse(e) => write!(f, "{}", e),
95            HoconError::Resolve(e) => write!(f, "{}", e),
96            HoconError::Io(e) => write!(f, "I/O error: {}", e),
97        }
98    }
99}
100
101impl std::error::Error for HoconError {
102    fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
103        match self {
104            HoconError::Parse(e) => Some(e),
105            HoconError::Resolve(e) => Some(e),
106            HoconError::Io(e) => Some(e),
107        }
108    }
109}
110
111impl From<ParseError> for HoconError {
112    fn from(e: ParseError) -> Self {
113        HoconError::Parse(e)
114    }
115}
116
117impl From<ResolveError> for HoconError {
118    fn from(e: ResolveError) -> Self {
119        HoconError::Resolve(e)
120    }
121}
122
123impl From<std::io::Error> for HoconError {
124    fn from(e: std::io::Error) -> Self {
125        HoconError::Io(e)
126    }
127}