Skip to main content

es_fluent_shared/
error.rs

1//! Common error types shared across the es-fluent ecosystem.
2
3use std::path::PathBuf;
4use thiserror::Error;
5use unic_langid::LanguageIdentifier;
6
7/// Common error types shared across the es-fluent ecosystem.
8#[derive(Debug, Error)]
9pub enum EsFluentError {
10    /// Configuration file not found.
11    #[error("Configuration file not found: {path}")]
12    ConfigNotFound { path: PathBuf },
13
14    /// Failed to parse configuration file.
15    #[error("Failed to parse configuration file: {0}")]
16    ConfigParseError(#[from] toml::de::Error),
17
18    /// Assets directory not found.
19    #[error("Assets directory not found: {path}")]
20    AssetsNotFound { path: PathBuf },
21
22    /// Fallback language directory not found.
23    #[error("Fallback language directory not found: {language}")]
24    FallbackLanguageNotFound { language: String },
25
26    /// Invalid language identifier.
27    #[error("Invalid language identifier '{identifier}': {reason}")]
28    InvalidLanguageIdentifier { identifier: String, reason: String },
29
30    /// Language not supported.
31    #[error("Language '{0}' is not supported")]
32    LanguageNotSupported(LanguageIdentifier),
33
34    /// Fluent parsing error.
35    #[error("Fluent parsing error: {0:?}")]
36    FluentParseError(Vec<fluent_syntax::parser::ParserError>),
37
38    /// Fluent serialization error.
39    #[error("Fluent serialization error: {0}")]
40    FluentSerializeError(#[from] std::fmt::Error),
41
42    /// IO error during file operations.
43    #[error("IO error: {0}")]
44    IoError(#[from] std::io::Error),
45
46    /// Environment variable error.
47    #[error("Environment variable error: {0}")]
48    EnvVarError(#[from] std::env::VarError),
49
50    /// Generic backend error.
51    #[error("Backend error: {0}")]
52    BackendError(#[from] anyhow::Error),
53
54    /// Missing package name.
55    #[error("Missing package name")]
56    MissingPackageName,
57}
58
59impl EsFluentError {
60    /// Creates a configuration not found error.
61    pub fn config_not_found(path: impl Into<PathBuf>) -> Self {
62        Self::ConfigNotFound { path: path.into() }
63    }
64
65    /// Creates an assets not found error.
66    pub fn assets_not_found(path: impl Into<PathBuf>) -> Self {
67        Self::AssetsNotFound { path: path.into() }
68    }
69
70    /// Creates an invalid language identifier error.
71    pub fn invalid_language_identifier(
72        identifier: impl Into<String>,
73        reason: impl Into<String>,
74    ) -> Self {
75        Self::InvalidLanguageIdentifier {
76            identifier: identifier.into(),
77            reason: reason.into(),
78        }
79    }
80
81    /// Creates a fallback language not found error.
82    pub fn fallback_language_not_found(language: impl Into<String>) -> Self {
83        Self::FallbackLanguageNotFound {
84            language: language.into(),
85        }
86    }
87}
88
89/// A result type for common es-fluent operations.
90pub type EsFluentResult<T> = Result<T, EsFluentError>;
91
92#[cfg(test)]
93mod tests {
94    use super::*;
95
96    #[test]
97    fn helper_constructors_build_expected_variants() {
98        let config = EsFluentError::config_not_found("/tmp/i18n.toml");
99        assert!(matches!(config, EsFluentError::ConfigNotFound { .. }));
100
101        let assets = EsFluentError::assets_not_found("/tmp/i18n");
102        assert!(matches!(assets, EsFluentError::AssetsNotFound { .. }));
103
104        let invalid = EsFluentError::invalid_language_identifier("bad", "parse failure");
105        assert!(matches!(
106            invalid,
107            EsFluentError::InvalidLanguageIdentifier { .. }
108        ));
109
110        let fallback = EsFluentError::fallback_language_not_found("en-US");
111        assert!(matches!(
112            fallback,
113            EsFluentError::FallbackLanguageNotFound { .. }
114        ));
115    }
116}