rosetta_build/
error.rs

1//! Errors returned when generating code.
2
3use std::{
4    error::Error,
5    fmt::{self, Display},
6    path::PathBuf,
7};
8
9/// Error type returned when the configuration passed to [`RosettaBuilder`] is invalid.
10///
11/// [`RosettaBuilder`]: crate::RosettaBuilder
12#[derive(Debug, Clone, PartialEq, Eq)]
13pub enum ConfigError {
14    /// Invalid language identifier
15    InvalidLanguage(String),
16    /// No source provided
17    MissingSource,
18    /// No fallback language provided
19    MissingFallback,
20    /// The fallback language doesn't match any source
21    InvalidFallback,
22}
23
24impl Error for ConfigError {}
25
26impl Display for ConfigError {
27    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
28        match self {
29            ConfigError::InvalidLanguage(value) => {
30                write!(f, "`{}` is not a valid language identifier", value)
31            }
32            ConfigError::MissingSource => {
33                write!(f, "at least one translations source file is required")
34            }
35            ConfigError::MissingFallback => write!(f, "a fallback language must be provided"),
36            ConfigError::InvalidFallback => write!(
37                f,
38                "no source corresponding to the fallback language was found"
39            ),
40        }
41    }
42}
43
44/// Error type returned when the code generation failed for some reason.
45#[derive(Debug)]
46pub enum BuildError {
47    Config(ConfigError),
48    FileRead {
49        file: PathBuf,
50        source: std::io::Error,
51    },
52    FileWrite(std::io::Error),
53    JsonParse {
54        file: PathBuf,
55        source: tinyjson::JsonParseError,
56    },
57    Parse(ParseError),
58    Var(std::env::VarError),
59    Fmt(std::io::Error),
60}
61
62impl Error for BuildError {}
63
64impl Display for BuildError {
65    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
66        match self {
67            BuildError::Config(error) => write!(f, "invalid configuration: {}", error),
68            BuildError::FileRead { file, source } => {
69                write!(f, "failed to read `{:?}`: {}", file, source)
70            }
71            BuildError::FileWrite(error) => write!(f, "failed to write output: {}", error),
72            BuildError::JsonParse { file, source } => {
73                write!(f, "failed to load {:?}: {}", file, source)
74            }
75            BuildError::Parse(error) => write!(f, "failed to parse translations: {}", error),
76            BuildError::Var(error) => write!(f, "failed to read environment variable: {}", error),
77            BuildError::Fmt(error) => write!(f, "failed to run rustfmt: {}", error),
78        }
79    }
80}
81
82impl From<ConfigError> for BuildError {
83    fn from(error: ConfigError) -> Self {
84        Self::Config(error)
85    }
86}
87
88impl From<ParseError> for BuildError {
89    fn from(error: ParseError) -> Self {
90        Self::Parse(error)
91    }
92}
93
94impl From<std::io::Error> for BuildError {
95    fn from(error: std::io::Error) -> Self {
96        Self::FileWrite(error)
97    }
98}
99
100impl From<std::env::VarError> for BuildError {
101    fn from(error: std::env::VarError) -> Self {
102        Self::Var(error)
103    }
104}
105
106/// Error type returned when a parsing error occurs.
107#[derive(Debug, Clone, PartialEq, Eq)]
108pub enum ParseError {
109    /// File root is not a JSON object
110    InvalidRoot,
111    /// Invalid key type (raw parsing)
112    InvalidValue { key: String },
113    /// Invalid key type (doesn't match previous parsed keys)
114    InvalidType { key: String, expected: &'static str },
115    /// Invalid parameters supplied to interpolated key (missing and/or unknown parameters)
116    InvalidParameters {
117        key: String,
118        missing: Vec<String>,
119        unknown: Vec<String>,
120    },
121    /// Invalid language identifier (not ISO 693-1 compliant)
122    InvalidLanguageId { value: String },
123}
124
125impl Error for ParseError {}
126
127impl Display for ParseError {
128    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
129        match self {
130            ParseError::InvalidRoot => write!(f, "file root must be a json object"),
131            ParseError::InvalidValue { key } => write!(f, "`{}` has an invalid type", key),
132            ParseError::InvalidType { key, expected } => write!(
133                f,
134                "`{}` doesn't match previous parsed key (expected {})",
135                key, expected
136            ),
137            ParseError::InvalidParameters {
138                key,
139                missing,
140                unknown,
141            } => write!(
142                f,
143                "invalid parameters supplied to `{}` (missing: {:?}, unknown: {:?})",
144                key, missing, unknown
145            ),
146            ParseError::InvalidLanguageId { value } => write!(
147                f,
148                "`{}` is not a valid ISO 693-1 language identifier",
149                value
150            ),
151        }
152    }
153}