1use std::convert::Infallible;
6
7use lox_core::time::deltas::TimeDelta;
8
9use crate::{
10 offsets::{Offset, OffsetProvider, TryOffset},
11 time_scales::{DynTimeScale, Tai, Tcb, Tcg, Tdb, Tt, Ut1},
12};
13
14macro_rules! impl_noop {
17 ($($scale:ident),*) => {
18 $(
19 impl<T> TryOffset<$scale, $scale> for T
20 where
21 T: OffsetProvider,
22 {
23 type Error = Infallible;
24
25 fn try_offset(
26 &self,
27 _origin: $scale,
28 _target: $scale,
29 _delta: TimeDelta
30 ) -> Result<TimeDelta, Self::Error> {
31 Ok(TimeDelta::default())
32 }
33 }
34 )*
35 };
36}
37
38impl_noop!(Tai, Tcb, Tcg, Tdb, Tt, Ut1);
39
40impl<T> TryOffset<Tai, Tt> for T
43where
44 T: OffsetProvider,
45{
46 type Error = Infallible;
47
48 fn try_offset(
49 &self,
50 _origin: Tai,
51 _target: Tt,
52 _delta: TimeDelta,
53 ) -> Result<TimeDelta, Self::Error> {
54 Ok(self.tai_to_tt())
55 }
56}
57
58impl<T> TryOffset<Tt, Tai> for T
59where
60 T: OffsetProvider,
61{
62 type Error = Infallible;
63
64 fn try_offset(
65 &self,
66 _origin: Tt,
67 _target: Tai,
68 _delta: TimeDelta,
69 ) -> Result<TimeDelta, Self::Error> {
70 Ok(self.tt_to_tai())
71 }
72}
73
74impl<T> TryOffset<Tt, Tcg> for T
77where
78 T: OffsetProvider,
79{
80 type Error = Infallible;
81
82 fn try_offset(
83 &self,
84 _origin: Tt,
85 _target: Tcg,
86 delta: TimeDelta,
87 ) -> Result<TimeDelta, Self::Error> {
88 Ok(self.tt_to_tcg(delta))
89 }
90}
91
92impl<T> TryOffset<Tcg, Tt> for T
93where
94 T: OffsetProvider,
95{
96 type Error = Infallible;
97
98 fn try_offset(
99 &self,
100 _origin: Tcg,
101 _target: Tt,
102 delta: TimeDelta,
103 ) -> Result<TimeDelta, Self::Error> {
104 Ok(self.tcg_to_tt(delta))
105 }
106}
107
108impl<T> TryOffset<Tdb, Tcb> for T
111where
112 T: OffsetProvider,
113{
114 type Error = Infallible;
115
116 fn try_offset(
117 &self,
118 _origin: Tdb,
119 _target: Tcb,
120 delta: TimeDelta,
121 ) -> Result<TimeDelta, Self::Error> {
122 Ok(self.tdb_to_tcb(delta))
123 }
124}
125
126impl<T> TryOffset<Tcb, Tdb> for T
127where
128 T: OffsetProvider,
129{
130 type Error = Infallible;
131
132 fn try_offset(
133 &self,
134 _origin: Tcb,
135 _target: Tdb,
136 delta: TimeDelta,
137 ) -> Result<TimeDelta, Self::Error> {
138 Ok(self.tcb_to_tdb(delta))
139 }
140}
141
142impl<T> TryOffset<Tt, Tdb> for T
145where
146 T: OffsetProvider,
147{
148 type Error = Infallible;
149
150 fn try_offset(
151 &self,
152 _origin: Tt,
153 _target: Tdb,
154 delta: TimeDelta,
155 ) -> Result<TimeDelta, Self::Error> {
156 Ok(self.tt_to_tdb(delta))
157 }
158}
159
160impl<T> TryOffset<Tdb, Tt> for T
161where
162 T: OffsetProvider,
163{
164 type Error = Infallible;
165
166 fn try_offset(
167 &self,
168 _origin: Tdb,
169 _target: Tt,
170 delta: TimeDelta,
171 ) -> Result<TimeDelta, Self::Error> {
172 Ok(self.tdb_to_tt(delta))
173 }
174}
175
176impl<T> TryOffset<Tai, Ut1> for T
179where
180 T: OffsetProvider,
181{
182 type Error = <Self as OffsetProvider>::Error;
183
184 fn try_offset(
185 &self,
186 _origin: Tai,
187 _target: Ut1,
188 delta: TimeDelta,
189 ) -> Result<TimeDelta, Self::Error> {
190 self.tai_to_ut1(delta)
191 }
192}
193
194impl<T> TryOffset<Ut1, Tai> for T
195where
196 T: OffsetProvider,
197{
198 type Error = <Self as OffsetProvider>::Error;
199
200 fn try_offset(
201 &self,
202 _origin: Ut1,
203 _target: Tai,
204 delta: TimeDelta,
205 ) -> Result<TimeDelta, Self::Error> {
206 self.ut1_to_tai(delta)
207 }
208}
209
210macro_rules! impl_two_step {
213 ($(($origin:ident, $via:ident, $target:ident)),*) => {
214 $(
215 impl<T> TryOffset<$origin, $target> for T
216 where
217 T: OffsetProvider,
218 {
219 type Error = Infallible;
220
221 fn try_offset(
222 &self,
223 origin: $origin,
224 target: $target,
225 delta: TimeDelta,
226 ) -> Result<TimeDelta, Self::Error> {
227 Ok(super::two_step_offset(self, origin, $via, target, delta))
228 }
229 }
230
231 impl<T> TryOffset<$target, $origin> for T
232 where
233 T: OffsetProvider,
234 {
235 type Error = Infallible;
236
237 fn try_offset(
238 &self,
239 origin: $target,
240 target: $origin,
241 delta: TimeDelta,
242 ) -> Result<TimeDelta, Self::Error> {
243 Ok(super::two_step_offset(self, origin, $via, target, delta))
244 }
245 }
246 )*
247 }
248}
249
250impl_two_step!(
251 (Tai, Tt, Tdb),
252 (Tdb, Tt, Tcg),
253 (Tai, Tt, Tcg),
254 (Tai, Tdb, Tcb),
255 (Tt, Tdb, Tcb),
256 (Tcb, Tdb, Tcg)
257);
258
259macro_rules! impl_two_step_ut1 {
260 ($($scale:ident),*) => {
261 $(
262 impl<T> TryOffset<$scale, Ut1> for T
263 where
264 T: OffsetProvider,
265 {
266 type Error = <Self as OffsetProvider>::Error;
267
268 fn try_offset(
269 &self,
270 _origin: $scale,
271 _target: Ut1,
272 delta: TimeDelta,
273 ) -> Result<TimeDelta, Self::Error> {
274 let mut offset = self.offset($scale, Tai, delta);
275 offset += self.try_offset(Tai, Ut1, delta + offset)?;
276 Ok(offset)
277 }
278 }
279
280 impl<T> TryOffset<Ut1, $scale> for T
281 where
282 T: OffsetProvider,
283 {
284 type Error = <Self as OffsetProvider>::Error;
285
286 fn try_offset(
287 &self,
288 _origin: Ut1,
289 _target: $scale,
290 delta: TimeDelta,
291 ) -> Result<TimeDelta, Self::Error> {
292 let mut offset = self.try_offset(Ut1, Tai, delta)?;
293 offset += self.offset(Tai, $scale, delta + offset);
294 Ok(offset)
295 }
296 }
297 )*
298 };
299}
300
301impl_two_step_ut1!(Tcb, Tcg, Tdb, Tt);
302
303impl<T> TryOffset<DynTimeScale, DynTimeScale> for T
306where
307 T: OffsetProvider,
308{
309 type Error = <Self as OffsetProvider>::Error;
310
311 fn try_offset(
312 &self,
313 origin: DynTimeScale,
314 target: DynTimeScale,
315 delta: TimeDelta,
316 ) -> Result<TimeDelta, Self::Error> {
317 if origin == target {
318 return Ok(TimeDelta::default());
319 }
320 match (origin, target) {
321 (DynTimeScale::Tai, DynTimeScale::Tcb) => Ok(self.offset(Tai, Tcb, delta)),
322 (DynTimeScale::Tai, DynTimeScale::Tcg) => Ok(self.offset(Tai, Tcg, delta)),
323 (DynTimeScale::Tai, DynTimeScale::Tdb) => Ok(self.offset(Tai, Tdb, delta)),
324 (DynTimeScale::Tai, DynTimeScale::Tt) => Ok(self.offset(Tai, Tt, delta)),
325 (DynTimeScale::Tai, DynTimeScale::Ut1) => self.try_offset(Tai, Ut1, delta),
326 (DynTimeScale::Tcb, DynTimeScale::Tai) => Ok(self.offset(Tcb, Tai, delta)),
327 (DynTimeScale::Tcb, DynTimeScale::Tcg) => Ok(self.offset(Tcb, Tcg, delta)),
328 (DynTimeScale::Tcb, DynTimeScale::Tdb) => Ok(self.offset(Tcb, Tdb, delta)),
329 (DynTimeScale::Tcb, DynTimeScale::Tt) => Ok(self.offset(Tcb, Tt, delta)),
330 (DynTimeScale::Tcb, DynTimeScale::Ut1) => self.try_offset(Tcb, Ut1, delta),
331 (DynTimeScale::Tcg, DynTimeScale::Tai) => Ok(self.offset(Tcg, Tai, delta)),
332 (DynTimeScale::Tcg, DynTimeScale::Tcb) => Ok(self.offset(Tcg, Tcb, delta)),
333 (DynTimeScale::Tcg, DynTimeScale::Tdb) => Ok(self.offset(Tcg, Tdb, delta)),
334 (DynTimeScale::Tcg, DynTimeScale::Tt) => Ok(self.offset(Tcg, Tt, delta)),
335 (DynTimeScale::Tcg, DynTimeScale::Ut1) => self.try_offset(Tcg, Ut1, delta),
336 (DynTimeScale::Tdb, DynTimeScale::Tai) => Ok(self.offset(Tdb, Tai, delta)),
337 (DynTimeScale::Tdb, DynTimeScale::Tcb) => Ok(self.offset(Tdb, Tcb, delta)),
338 (DynTimeScale::Tdb, DynTimeScale::Tcg) => Ok(self.offset(Tdb, Tcg, delta)),
339 (DynTimeScale::Tdb, DynTimeScale::Tt) => Ok(self.offset(Tdb, Tt, delta)),
340 (DynTimeScale::Tdb, DynTimeScale::Ut1) => self.try_offset(Tdb, Ut1, delta),
341 (DynTimeScale::Tt, DynTimeScale::Tai) => Ok(self.offset(Tt, Tai, delta)),
342 (DynTimeScale::Tt, DynTimeScale::Tcb) => Ok(self.offset(Tt, Tcb, delta)),
343 (DynTimeScale::Tt, DynTimeScale::Tcg) => Ok(self.offset(Tt, Tcg, delta)),
344 (DynTimeScale::Tt, DynTimeScale::Tdb) => Ok(self.offset(Tt, Tdb, delta)),
345 (DynTimeScale::Tt, DynTimeScale::Ut1) => self.try_offset(Tt, Ut1, delta),
346 (DynTimeScale::Ut1, DynTimeScale::Tai) => self.try_offset(Ut1, Tai, delta),
347 (DynTimeScale::Ut1, DynTimeScale::Tcb) => self.try_offset(Ut1, Tcb, delta),
348 (DynTimeScale::Ut1, DynTimeScale::Tcg) => self.try_offset(Ut1, Tcg, delta),
349 (DynTimeScale::Ut1, DynTimeScale::Tdb) => self.try_offset(Ut1, Tdb, delta),
350 (DynTimeScale::Ut1, DynTimeScale::Tt) => self.try_offset(Ut1, Tt, delta),
351 (_, _) => Ok(TimeDelta::default()),
352 }
353 }
354}
355
356macro_rules! impl_dyn {
357 ($($scale:ident),*) => {
358 $(
359 impl<T> TryOffset<$scale, DynTimeScale> for T
360 where
361 T: OffsetProvider,
362 {
363 type Error = <Self as OffsetProvider>::Error;
364
365 fn try_offset(
366 &self,
367 origin: $scale,
368 target: DynTimeScale,
369 delta: TimeDelta,
370 ) -> Result<TimeDelta, Self::Error> {
371 let origin: DynTimeScale = origin.into();
372 self.try_offset(origin, target, delta)
373 }
374 }
375
376 impl<T> TryOffset<DynTimeScale, $scale> for T
377 where
378 T: OffsetProvider,
379 {
380 type Error = <Self as OffsetProvider>::Error;
381
382 fn try_offset(
383 &self,
384 origin: DynTimeScale,
385 target: $scale,
386 delta: TimeDelta,
387 ) -> Result<TimeDelta, Self::Error> {
388 let target: DynTimeScale = target.into();
389 self.try_offset(origin, target, delta)
390 }
391 }
392 )*
393 };
394}
395
396impl_dyn!(Tai, Tcb, Tcg, Tdb, Tt, Ut1);