Skip to main content

rust_zmanim/complex_zmanim_calendar/
registry.rs

1//! A registry enumerating every zero-argument *zman* accessor on
2//! [`ComplexZmanimCalendar`], for callers (such as a CLI) that need to look up
3//! *zmanim* by name or iterate over all of them.
4//!
5//! [`ALL_ZMANIM`] is a compile-time table of [`ZmanEntry`] values. Each entry
6//! pairs a *zman*'s method name with a function pointer that invokes the
7//! corresponding accessor. Because those function pointers call the real
8//! methods, a renamed or removed method is a compile error. A companion test
9//! (`tests/registry_completeness.rs`) guards against *forgetting* to list a
10//! method here.
11
12use super::ComplexZmanimCalendar;
13use jiff::{SignedDuration, Zoned};
14
15/// Whether a *zman* is an instant in time or a duration.
16///
17/// Most *zmanim* are instants ([`Time`](ZmanKind::Time)). The *shaah zmanis*
18/// ("temporal hour") *zmanim* are durations ([`Duration`](ZmanKind::Duration)).
19#[derive(Debug, Clone, Copy, PartialEq, Eq)]
20pub enum ZmanKind {
21    /// An instant in time, returned as a [`Zoned`].
22    Time,
23    /// A length of time, returned as a [`SignedDuration`].
24    Duration,
25}
26
27/// The computed value of a *zman*: either an instant or a duration.
28#[derive(Debug, Clone)]
29pub enum ZmanValue {
30    /// An instant in time (e.g. sunrise, *tzeis*).
31    Time(Zoned),
32    /// A length of time (a *shaah zmanis*).
33    Duration(SignedDuration),
34}
35
36/// A single entry in the [`ALL_ZMANIM`] registry, describing one *zman*
37/// accessor by name and providing a function to compute it.
38#[derive(Debug, Clone, Copy)]
39pub struct ZmanEntry {
40    /// The name of the accessor method, e.g. `"sof_zman_shema_gra"`.
41    pub name: &'static str,
42    /// Whether this *zman* is an instant or a duration.
43    pub kind: ZmanKind,
44    /// Computes the *zman* for the given calendar, returning [`None`] when the
45    /// underlying solar event does not occur (e.g. in polar regions).
46    pub compute: fn(&ComplexZmanimCalendar) -> Option<ZmanValue>,
47}
48
49/// Looks up a [`ZmanEntry`] by its exact method name.
50///
51/// Returns [`None`] if no *zman* has that name.
52#[must_use]
53pub fn find_zman(name: &str) -> Option<&'static ZmanEntry> {
54    ALL_ZMANIM.iter().find(|entry| entry.name == name)
55}
56
57/// Expands a grouped list of method names into the [`ALL_ZMANIM`] table. Each
58/// name becomes a [`ZmanEntry`] whose `compute` closure calls the method of the
59/// same name, so a stale name fails to compile.
60macro_rules! zman_registry {
61    ( times: [ $($t:ident),* $(,)? ], durations: [ $($d:ident),* $(,)? ] $(,)? ) => {
62        /// Every zero-argument *zman* accessor on [`ComplexZmanimCalendar`].
63        ///
64        /// Time *zmanim* come first, then duration *zmanim*. Within each group
65        /// the order follows the source order of the accessor definitions.
66        pub const ALL_ZMANIM: &[ZmanEntry] = &[
67            $(
68                ZmanEntry {
69                    name: stringify!($t),
70                    kind: ZmanKind::Time,
71                    compute: |czc| czc.$t().map(ZmanValue::Time),
72                },
73            )*
74            $(
75                ZmanEntry {
76                    name: stringify!($d),
77                    kind: ZmanKind::Duration,
78                    compute: |czc| czc.$d().map(ZmanValue::Duration),
79                },
80            )*
81        ];
82    };
83}
84
85zman_registry! {
86    times: [
87        // hand-written (Option<Zoned>)
88        sea_level_sunrise,
89        sea_level_sunset,
90        elevation_sunrise,
91        elevation_sunset,
92        hanetz,
93        shkia,
94        chatzos_hayom,
95        chatzos_hayom_as_half_day,
96        chatzos_halayla,
97        mincha_gedola_30_minutes,
98        sof_zman_shema_gra,
99        sof_zman_tefila_gra,
100        sof_zman_biur_chametz_gra,
101        mincha_gedola_gra,
102        mincha_gedola_gra_greater_than_30_minutes,
103        samuch_lemincha_ketana_gra,
104        mincha_ketana_gra,
105        plag_gra,
106        alos_baal_hatanya,
107        hanetz_amiti_baal_hatanya,
108        shkia_amiti_baal_hatanya,
109        sof_zman_shema_baal_hatanya,
110        sof_zman_tefila_baal_hatanya,
111        sof_zman_biur_chametz_baal_hatanya,
112        mincha_gedola_baal_hatanya,
113        mincha_gedola_baal_hatanya_greater_than_30_minutes,
114        mincha_ketana_baal_hatanya,
115        plag_baal_hatanya,
116        tzeis_baal_hatanya,
117        fixed_local_chatzos_hayom,
118        sof_zman_shema_mga_alos_18_to_fixed_local_chatzos,
119        sof_zman_shema_mga_alos_16_1_to_fixed_local_chatzos,
120        sof_zman_shema_mga_90_minutes_to_fixed_local_chatzos,
121        sof_zman_shema_mga_72_minutes_to_fixed_local_chatzos,
122        sof_zman_shema_gra_sunrise_to_fixed_local_chatzos,
123        sof_zman_tefila_gra_sunrise_to_fixed_local_chatzos,
124        mincha_gedola_gra_fixed_local_chatzos_30_minutes,
125        mincha_ketana_gra_fixed_local_chatzos_to_sunset,
126        plag_gra_fixed_local_chatzos_to_sunset,
127        tzeis_50_minutes,
128        mincha_gedola_ahavat_shalom,
129        mincha_ketana_ahavat_shalom,
130        plag_ahavat_shalom,
131        sof_zman_shema_ateret_torah,
132        sof_zman_tefila_ateret_torah,
133        mincha_gedola_ateret_torah,
134        mincha_ketana_ateret_torah,
135        plag_ateret_torah,
136        tzeis_ateret_torah,
137        polar_sunrise_ben_ish_chai,
138        polar_plag_ben_ish_chai,
139        polar_sunset_ben_ish_chai,
140        sof_zman_shema_3_hrs_before_chatzos,
141        sof_zman_tefila_2_hrs_before_chatzos,
142        sof_zman_shema_alos_16_1_to_sunset,
143        plag_alos_16_1_to_sunset,
144        sof_zman_shema_alos_16_1_to_tzeis_7_083,
145        plag_alos_16_1_to_tzeis_7_083,
146        alos_19_degrees,
147        misheyakir_12_85_degrees,
148        misheyakir_11_5_degrees,
149        misheyakir_11_degrees,
150        misheyakir_10_2_degrees,
151        misheyakir_9_5_degrees,
152        misheyakir_7_65_degrees,
153        bein_hashmashos_yereim_18_minutes,
154        bein_hashmashos_yereim_3_05_degrees,
155        bein_hashmashos_yereim_16_875_minutes,
156        bein_hashmashos_yereim_2_8_degrees,
157        bein_hashmashos_yereim_13_5_minutes,
158        bein_hashmashos_yereim_2_1_degrees,
159        bein_hashmashos_rt_13_24_degrees,
160        bein_hashmashos_rt_58_5_minutes,
161        bein_hashmashos_rt_13_5_minutes_before_7_083_degrees,
162        bein_hashmashos_rt_2_stars,
163        tzeis_geonim_3_7_degrees,
164        tzeis_geonim_3_8_degrees,
165        tzeis_geonim_4_42_degrees,
166        tzeis_geonim_4_66_degrees,
167        tzeis_geonim_4_8_degrees,
168        tzeis_geonim_5_95_degrees,
169        tzeis_geonim_6_45_degrees,
170        tzeis_geonim_7_083_degrees,
171        tzeis_geonim_7_67_degrees,
172        tzeis_geonim_8_5_degrees,
173        tzeis_geonim_9_3_degrees,
174        tzeis_geonim_9_75_degrees,
175        // macro-generated (zmanim_for_offset!)
176        alos_16_1_degrees,
177        tzeis_16_1_degrees,
178        sof_zman_shema_mga_16_1_degrees,
179        sof_zman_tefila_mga_16_1_degrees,
180        sof_zman_biur_chametz_mga_16_1_degrees,
181        mincha_gedola_mga_16_1_degrees,
182        samuch_lemincha_ketana_mga_16_1_degrees,
183        mincha_ketana_mga_16_1_degrees,
184        plag_mga_16_1_degrees,
185        alos_18_degrees,
186        tzeis_18_degrees,
187        sof_zman_shema_mga_18_degrees,
188        sof_zman_tefila_mga_18_degrees,
189        plag_mga_18_degrees,
190        alos_19_8_degrees,
191        tzeis_19_8_degrees,
192        sof_zman_shema_mga_19_8_degrees,
193        sof_zman_tefila_mga_19_8_degrees,
194        plag_mga_19_8_degrees,
195        alos_26_degrees,
196        tzeis_26_degrees,
197        plag_mga_26_degrees,
198        alos_60_minutes,
199        tzeis_60_minutes,
200        plag_mga_60_minutes,
201        alos_72_minutes,
202        tzeis_72_minutes,
203        sof_zman_shema_mga_72_minutes,
204        sof_zman_tefila_mga_72_minutes,
205        sof_zman_biur_chametz_mga_72_minutes,
206        mincha_gedola_mga_72_minutes,
207        samuch_lemincha_ketana_mga_72_minutes,
208        mincha_ketana_mga_72_minutes,
209        plag_mga_72_minutes,
210        alos_72_minutes_zmanis,
211        tzeis_72_minutes_zmanis,
212        sof_zman_shema_mga_72_minutes_zmanis,
213        sof_zman_tefila_mga_72_minutes_zmanis,
214        sof_zman_biur_chametz_mga_72_minutes_zmanis,
215        plag_mga_72_minutes_zmanis,
216        alos_90_minutes,
217        tzeis_90_minutes,
218        sof_zman_shema_mga_90_minutes,
219        sof_zman_tefila_mga_90_minutes,
220        plag_mga_90_minutes,
221        alos_90_minutes_zmanis,
222        tzeis_90_minutes_zmanis,
223        sof_zman_shema_mga_90_minutes_zmanis,
224        sof_zman_tefila_mga_90_minutes_zmanis,
225        plag_mga_90_minutes_zmanis,
226        alos_96_minutes,
227        tzeis_96_minutes,
228        sof_zman_shema_mga_96_minutes,
229        sof_zman_tefila_mga_96_minutes,
230        plag_mga_96_minutes,
231        alos_96_minutes_zmanis,
232        tzeis_96_minutes_zmanis,
233        sof_zman_shema_mga_96_minutes_zmanis,
234        sof_zman_tefila_mga_96_minutes_zmanis,
235        plag_mga_96_minutes_zmanis,
236        alos_120_minutes,
237        tzeis_120_minutes,
238        sof_zman_shema_mga_120_minutes,
239        sof_zman_tefila_mga_120_minutes,
240        plag_mga_120_minutes,
241        alos_120_minutes_zmanis,
242        tzeis_120_minutes_zmanis,
243        plag_mga_120_minutes_zmanis,
244    ],
245    durations: [
246        // hand-written (Option<SignedDuration>)
247        shaah_zmanis_gra,
248        shaah_zmanis_baal_hatanya,
249        shaah_zmanis_alos_16_1_to_tzeis_3_8,
250        shaah_zmanis_alos_16_1_to_tzeis_3_7,
251        shaah_zmanis_ateret_torah,
252        shaah_zmanis_alos_16_1_to_tzeis_7_083,
253        // macro-generated (zmanim_for_offset!)
254        shaah_zmanis_mga_16_1_degrees,
255        shaah_zmanis_mga_18_degrees,
256        shaah_zmanis_mga_19_8_degrees,
257        shaah_zmanis_mga_26_degrees,
258        shaah_zmanis_mga_60_minutes,
259        shaah_zmanis_mga_72_minutes,
260        shaah_zmanis_mga_72_minutes_zmanis,
261        shaah_zmanis_mga_90_minutes,
262        shaah_zmanis_mga_90_minutes_zmanis,
263        shaah_zmanis_mga_96_minutes,
264        shaah_zmanis_mga_96_minutes_zmanis,
265        shaah_zmanis_mga_120_minutes,
266        shaah_zmanis_mga_120_minutes_zmanis,
267    ]
268}