1use chrono::NaiveDate;
4use serde::{Serialize, Deserialize};
5use std::fmt;
6
7pub const HIJRI_MIN_YEAR: i32 = 1938;
9pub const HIJRI_MAX_YEAR: i32 = 2076;
11
12#[derive(Debug, Clone, Serialize, Deserialize)]
14pub enum ShaumError {
15 DateOutOfRange {
17 date: NaiveDate,
18 min: NaiveDate,
19 max: NaiveDate,
20 },
21
22 InvalidConfiguration { reason: String },
24
25 AnalysisError(String),
27
28 HijriConversionError(String),
30
31 SunsetCalculationError(String),
33
34 MoonProviderError(String),
36
37 ValidationError(String),
39
40 AstronomyError(String),
42
43 DatabaseError(String),
45
46 NetworkError(String),
48}
49
50impl fmt::Display for ShaumError {
51 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
52 match self {
53 Self::DateOutOfRange { date, min, max } => {
54 write!(f, "Date {} is out of supported range ({} to {})", date, min, max)
55 }
56 Self::InvalidConfiguration { reason } => write!(f, "Invalid configuration: {}", reason),
57 Self::AnalysisError(s) => write!(f, "Analysis failed: {}", s),
58 Self::HijriConversionError(s) => write!(f, "Hijri conversion failed: {}", s),
59 Self::SunsetCalculationError(s) => write!(f, "Sunset calculation failed: {}", s),
60 Self::MoonProviderError(s) => write!(f, "Moon provider error: {}", s),
61 Self::ValidationError(s) => write!(f, "Validation error: {}", s),
62 Self::AstronomyError(s) => write!(f, "Astronomy error: {}", s),
63 Self::DatabaseError(s) => write!(f, "Database error: {}", s),
64 Self::NetworkError(s) => write!(f, "Network error: {}", s),
65 }
66 }
67}
68
69impl std::error::Error for ShaumError {}
70
71impl ShaumError {
72 pub fn date_out_of_range(date: NaiveDate) -> Self {
74 Self::DateOutOfRange {
75 date,
76 min: NaiveDate::from_ymd_opt(HIJRI_MIN_YEAR, 1, 1)
77 .unwrap_or_else(|| NaiveDate::from_ymd_opt(1938, 1, 1).unwrap()),
78 max: NaiveDate::from_ymd_opt(HIJRI_MAX_YEAR, 12, 31)
79 .unwrap_or_else(|| NaiveDate::from_ymd_opt(2076, 12, 31).unwrap()),
80 }
81 }
82
83 pub fn invalid_config(reason: impl Into<String>) -> Self {
85 Self::InvalidConfiguration { reason: reason.into() }
86 }
87}