tz/utils/
const_fns.rs

1//! Some useful constant functions.
2
3use crate::error::TzError;
4use crate::timezone::{LeapSecond, Transition};
5
6use core::cmp::Ordering;
7
8/// Compare two values
9pub(crate) const fn cmp(a: i64, b: i64) -> Ordering {
10    if a < b {
11        Ordering::Less
12    } else if a == b {
13        Ordering::Equal
14    } else {
15        Ordering::Greater
16    }
17}
18
19/// Returns the minimum of two values
20pub(crate) const fn min(a: i64, b: i64) -> i64 {
21    match cmp(a, b) {
22        Ordering::Less | Ordering::Equal => a,
23        Ordering::Greater => b,
24    }
25}
26
27/// Macro for implementing integer conversion
28macro_rules! impl_try_into_integer {
29    ($from_type:ty, $to_type:ty, $value:expr) => {{
30        let min = <$to_type>::MIN as $from_type;
31        let max = <$to_type>::MAX as $from_type;
32
33        if min <= $value && $value <= max {
34            Ok($value as $to_type)
35        } else {
36            Err(TzError::OutOfRange)
37        }
38    }};
39}
40
41/// Convert a `i64` value to a `i32` value
42pub(crate) const fn try_into_i32(value: i64) -> Result<i32, TzError> {
43    impl_try_into_integer!(i64, i32, value)
44}
45
46/// Convert a `i128` value to a `i64` value
47pub(crate) const fn try_into_i64(value: i128) -> Result<i64, TzError> {
48    impl_try_into_integer!(i128, i64, value)
49}
50
51/// Macro for implementing binary search
52macro_rules! impl_binary_search {
53    ($slice:expr, $f:expr, $x:expr) => {{
54        let mut size = $slice.len();
55        let mut left = 0;
56        let mut right = size;
57        while left < right {
58            let mid = left + size / 2;
59
60            let v = $f(&$slice[mid]);
61            if v < $x {
62                left = mid + 1;
63            } else if v > $x {
64                right = mid;
65            } else {
66                return Ok(mid);
67            }
68
69            size = right - left;
70        }
71        Err(left)
72    }};
73}
74
75/// Copy the input value
76const fn copied(x: &i64) -> i64 {
77    *x
78}
79
80/// Binary searches a sorted `i64` slice for the given element
81pub(crate) const fn binary_search_i64(slice: &[i64], x: i64) -> Result<usize, usize> {
82    impl_binary_search!(slice, copied, x)
83}
84
85/// Binary searches a sorted `Transition` slice for the given element
86pub(crate) const fn binary_search_transitions(slice: &[Transition], x: i64) -> Result<usize, usize> {
87    impl_binary_search!(slice, Transition::unix_leap_time, x)
88}
89
90/// Binary searches a sorted `LeapSecond` slice for the given element
91pub(crate) const fn binary_search_leap_seconds(slice: &[LeapSecond], x: i64) -> Result<usize, usize> {
92    impl_binary_search!(slice, LeapSecond::unix_leap_time, x)
93}