sounding_base/
station_info.rs

1use metfor::Meters;
2use optional::Optioned;
3
4/// Station information including location data and identification number.
5#[derive(Debug, Clone, Copy, PartialEq, Default)]
6pub struct StationInfo {
7    /// station number, USAF number, eg 727730
8    num: Optioned<i32>,
9    /// Latitude and longitude.
10    location: Option<(f64, f64)>,
11    /// Elevation, this may be in model terrain which is not necessarily the same as the real world.
12    elevation: Optioned<Meters>,
13}
14
15impl StationInfo {
16    /// Create a new `StationInfo` object.
17    ///
18    /// # Arguments
19    /// station_num: The USAF station identifier, or None.
20    ///
21    /// location: The latitude and longitude as a tuple, or None.
22    ///
23    /// elevation: The elevation of the station **in meters**.
24    ///
25    /// # Examples
26    ///
27    /// ```rust
28    /// use metfor::{Meters, Feet};
29    /// use sounding_base::StationInfo;
30    /// use optional::{some, none};
31    ///
32    /// let _stn = StationInfo::new_with_values(12345, (45.2,-113.5), Meters(2000.0));
33    /// let _stn = StationInfo::new_with_values(12345, (45.2,-113.5), Feet(2000.0));
34    /// let _stn = StationInfo::new_with_values(12345, (45.2,-113.5), some(Meters(2000.0)));
35    /// let _stn = StationInfo::new_with_values(12345, (45.2,-113.5), some(Feet(2000.0)));
36    /// let _stn = StationInfo::new_with_values(12345, Some((45.2,-113.5)), Meters(2000.0));
37    /// let _stn = StationInfo::new_with_values(12345, Some((45.2,-113.5)), Feet(2000.0));
38    /// let _stn = StationInfo::new_with_values(12345, Some((45.2,-113.5)), some(Meters(2000.0)));
39    /// let _stn = StationInfo::new_with_values(12345, Some((45.2,-113.5)), some(Feet(2000.0)));
40    /// let _stn = StationInfo::new_with_values(Some(12345), None, Meters(2000.0));
41    /// let _stn = StationInfo::new_with_values(Some(12345), None, Feet(2000.0));
42    /// let _stn = StationInfo::new_with_values(None, (45.2,-113.5), some(Meters(2000.0)));
43    /// let _stn = StationInfo::new_with_values(None, (45.2,-113.5), some(Feet(2000.0)));
44    ///
45    /// // Note that lat-lon is an `Option` and not an `Optioned`
46    /// let _stn = StationInfo::new_with_values(some(12345), None, none::<Feet>());
47    /// let _stn = StationInfo::new_with_values(some(12345), None, none::<Meters>());
48    /// ```
49    #[inline]
50    pub fn new_with_values<T, U, V, W>(station_num: T, location: U, elevation: V) -> Self
51    where
52        T: Into<Optioned<i32>>,
53        U: Into<Option<(f64, f64)>>,
54        Optioned<W>: From<V>,
55        W: optional::Noned + metfor::Length,
56        Meters: From<W>,
57    {
58        let elev: Optioned<W> = Optioned::from(elevation);
59        let elev: Optioned<Meters> = elev.map_t(Meters::from);
60
61        StationInfo {
62            num: station_num.into(),
63            location: location.into(),
64            elevation: elev,
65        }
66    }
67
68    /// Create a new object with default values.
69    ///
70    /// # Examples
71    ///
72    /// ```rust
73    /// use sounding_base::StationInfo;
74    ///
75    /// assert!(StationInfo::new().station_num().is_none());
76    /// assert!(StationInfo::new().location().is_none());
77    /// assert!(StationInfo::new().elevation().is_none());
78    ///
79    /// ```
80    #[inline]
81    pub fn new() -> Self {
82        Self::default()
83    }
84
85    /// Builder method to add a station number.
86    ///
87    /// # Examples
88    ///
89    /// ```rust
90    /// use sounding_base::StationInfo;
91    ///
92    /// assert_eq!(StationInfo::new().with_station(12345).station_num().unwrap(), 12345);
93    /// assert_eq!(StationInfo::new().with_station(Some(12345)).station_num().unwrap(), 12345);
94    ///
95    /// ```
96    #[inline]
97    pub fn with_station<T>(mut self, number: T) -> Self
98    where
99        Optioned<i32>: From<T>,
100    {
101        self.num = Optioned::from(number);
102
103        self
104    }
105
106    /// Builder method to add a location.
107    ///
108    /// # Examples
109    ///
110    /// ```rust
111    /// use sounding_base::StationInfo;
112    ///
113    /// assert_eq!(
114    ///     StationInfo::new().with_lat_lon((45.0, -116.0)).location().unwrap(), (45.0, -116.0));
115    /// assert_eq!(
116    ///     StationInfo::new().with_lat_lon(Some((45.0, -116.0)))
117    ///         .location()
118    ///         .unwrap(),
119    ///     (45.0, -116.0));
120    ///
121    /// ```
122    #[inline]
123    pub fn with_lat_lon<T>(mut self, coords: T) -> Self
124    where
125        Option<(f64, f64)>: From<T>,
126    {
127        self.location = Option::from(coords);
128        self
129    }
130
131    /// Builder method to add elevation.
132    ///
133    /// # Examples
134    ///```rust
135    /// use metfor::{Meters, Feet, Km};
136    /// use sounding_base::StationInfo;
137    /// use optional::{some, none};
138    ///
139    /// let _info = StationInfo::new().with_elevation(Feet(200.0));
140    /// let _info = StationInfo::new().with_elevation(Meters(200.0));
141    /// let _info = StationInfo::new().with_elevation(Km(2.0));
142    /// let _info = StationInfo::new().with_elevation(some(Feet(200.0)));
143    /// let _info = StationInfo::new().with_elevation(some(Meters(200.0)));
144    /// let _info = StationInfo::new().with_elevation(some(Km(2.0)));
145    /// let _info = StationInfo::new().with_elevation(none::<Feet>());
146    /// let _info = StationInfo::new().with_elevation(none::<Meters>());
147    /// let _info = StationInfo::new().with_elevation(none::<Km>());
148    ///```
149    #[inline]
150    pub fn with_elevation<T, U>(mut self, elev: T) -> Self
151    where
152        Optioned<U>: From<T>,
153        U: optional::Noned + metfor::Length,
154        Meters: From<U>,
155    {
156        let elevation: Optioned<U> = Optioned::from(elev);
157        let elevation: Optioned<Meters> = elevation.map_t(Meters::from);
158
159        self.elevation = elevation;
160        self
161    }
162
163    /// station number, USAF number, eg 727730
164    #[inline]
165    pub fn station_num(&self) -> Optioned<i32> {
166        self.num
167    }
168
169    /// Latitude and longitude.
170    #[inline]
171    pub fn location(&self) -> Option<(f64, f64)> {
172        self.location
173    }
174
175    /// Elevation in meters, this may be in model terrain, not necessarily the same as
176    /// the real world.
177    #[inline]
178    pub fn elevation(&self) -> Optioned<Meters> {
179        self.elevation
180    }
181}