weather_util_rust/
latitude.rs

1use derive_more::{Display, FromStr, Into};
2use serde::{Deserialize, Serialize};
3use std::{
4    convert::{From, TryFrom},
5    hash::Hash,
6};
7
8use crate::{Error, angle::Angle};
9
10/// Latitude in degrees, required be within the range -90.0 to 90.0
11#[derive(
12    Into,
13    derive_more::From,
14    Clone,
15    Copy,
16    Display,
17    FromStr,
18    Debug,
19    Serialize,
20    Deserialize,
21    PartialEq,
22    Eq,
23    Hash,
24    Default,
25)]
26pub struct Latitude(Angle);
27
28impl From<Latitude> for f64 {
29    fn from(item: Latitude) -> Self {
30        item.0.deg()
31    }
32}
33
34impl TryFrom<f64> for Latitude {
35    type Error = Error;
36    fn try_from(item: f64) -> Result<Self, Self::Error> {
37        if (-90.0..90.0).contains(&item) {
38            Ok(Angle::from_deg(item).into())
39        } else {
40            Err(Error::InvalidLatitude)
41        }
42    }
43}
44
45#[cfg(test)]
46mod test {
47    use std::{
48        collections::hash_map::DefaultHasher,
49        convert::TryFrom,
50        hash::{Hash, Hasher},
51    };
52
53    use crate::{Error, latitude::Latitude};
54
55    #[test]
56    fn test_latitude() -> Result<(), Error> {
57        let h = Latitude::try_from(41.0)?;
58        let v: f64 = h.into();
59        assert_eq!(v, 41.0);
60
61        let h1 = Latitude::try_from(41.0000)?;
62        assert_eq!(h, h1);
63
64        let mut hasher0 = DefaultHasher::new();
65        h.hash(&mut hasher0);
66        let mut hasher1 = DefaultHasher::new();
67        h1.hash(&mut hasher1);
68        assert_eq!(hasher0.finish(), hasher1.finish());
69
70        let h = Latitude::try_from(-360.0);
71        assert!(h.is_err());
72        assert_eq!(&h.err().unwrap().to_string(), "Invalid Latitude",);
73        Ok(())
74    }
75
76    #[test]
77    fn test_latitude_not_eq_neg() -> Result<(), Error> {
78        let a = Latitude::try_from(41.0)?;
79        let b = Latitude::try_from(-41.0)?;
80        assert_ne!(a, b);
81        Ok(())
82    }
83}