cat_gateway/service/utilities/
convert.rs

1//! Simple general purpose utility functions.
2
3/// Convert an `<T>` to `<R>`. (saturate if out of range.)
4/// Note can convert any int to float, or f32 to f64 as well.
5/// can not convert from float to int, or f64 to f32.
6pub(crate) fn from_saturating<
7    R: Copy + num_traits::identities::Zero + num_traits::Bounded,
8    T: Copy
9        + TryInto<R>
10        + std::ops::Sub<Output = T>
11        + std::cmp::PartialOrd<T>
12        + num_traits::identities::Zero,
13>(
14    value: T,
15) -> R {
16    match value.try_into() {
17        Ok(value) => value,
18        Err(_) => {
19            // If we couldn't convert, its out of range for the destination type.
20            if value > T::zero() {
21                // If the number is positive, its out of range in the positive direction.
22                R::max_value()
23            } else {
24                // Otherwise its out of range in the negative direction.
25                R::min_value()
26            }
27        },
28    }
29}
30
31#[cfg(test)]
32mod tests {
33
34    use super::*;
35
36    #[test]
37    #[allow(clippy::float_cmp)]
38    fn from_saturating_tests() {
39        let x: u32 = from_saturating(0_u8);
40        assert!(x == 0);
41        let x: u32 = from_saturating(255_u8);
42        assert!(x == 255);
43        let x: i8 = from_saturating(0_u32);
44        assert!(x == 0);
45        let x: i8 = from_saturating(512_u32);
46        assert!(x == 127);
47        let x: i8 = from_saturating(-512_i32);
48        assert!(x == -128);
49        let x: u16 = from_saturating(-512_i32);
50        assert!(x == 0);
51        let x: f64 = from_saturating(0.0_f32);
52        assert!(x == 0.0);
53        let x: f64 = from_saturating(0_u32);
54        assert!(x == 0.0);
55        let x: f64 = from_saturating(65536_u32);
56        assert!(x == 65536.0_f64);
57        let x: f64 = from_saturating(i32::MIN);
58        assert!(x == -2_147_483_648.0_f64);
59    }
60}