1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
#[cfg(feature = "pylib")]
use pyo3::prelude::*;
use std::fmt::Display;
mod station_num;
pub use station_num::StationNumber;
mod state_prov;
pub use state_prov::StateProv;
#[cfg_attr(feature = "pylib", pyclass(module = "bufkit_data"))]
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
pub struct SiteInfo {
pub station_num: StationNumber,
pub name: Option<String>,
pub notes: Option<String>,
pub state: Option<StateProv>,
pub time_zone: Option<chrono::FixedOffset>,
}
impl SiteInfo {
pub fn incomplete(&self) -> bool {
self.name.is_none()
|| self.state.is_none()
|| self.time_zone.is_none()
|| !self.station_num.is_valid()
}
pub fn description(&self) -> String {
let mut desc = String::new();
if let Some(ref nm) = self.name {
desc += nm;
if let Some(st) = self.state {
desc += ", ";
desc += st.as_static_str();
}
desc += " ";
}
desc += &format!("({})", self.station_num);
desc
}
}
impl Display for SiteInfo {
fn fmt(&self, formatter: &mut std::fmt::Formatter) -> Result<(), std::fmt::Error> {
writeln!(
formatter,
"Site: station_num - {:6} | name - {:20} | state - {:2} | notes - {}",
self.station_num,
self.name.as_deref().unwrap_or("None"),
self.state.map(|s| s.as_static_str()).unwrap_or("None"),
self.notes.as_deref().unwrap_or("None"),
)
}
}
impl Default for SiteInfo {
fn default() -> Self {
SiteInfo {
station_num: StationNumber::from(0),
name: None,
notes: None,
state: None,
time_zone: None,
}
}
}
#[cfg(feature = "pylib")]
#[cfg_attr(feature = "pylib", pymethods)]
impl SiteInfo {
#[getter]
fn get_station_num(&self) -> StationNumber {
self.station_num
}
#[getter]
fn get_station_name(&self) -> String {
self.name.clone().unwrap_or_else(|| "No Name".to_owned())
}
}
#[cfg(feature = "pylib")]
#[cfg_attr(feature = "pylib", pyproto)]
impl pyo3::PyObjectProtocol<'_> for SiteInfo {
fn __repr__(&self) -> PyResult<String> {
Ok(self.description())
}
}
#[cfg(test)]
mod unit {
use super::*;
#[test]
fn test_site_incomplete() {
let complete_site = SiteInfo {
station_num: StationNumber::from(1),
name: Some("tv station".to_owned()),
state: Some(StateProv::VI),
notes: Some("".to_owned()),
time_zone: Some(chrono::FixedOffset::west(7 * 3600)),
};
let incomplete_site = SiteInfo {
station_num: StationNumber::from(1),
name: Some("tv station".to_owned()),
state: None,
notes: None,
time_zone: None,
};
assert!(!complete_site.incomplete());
assert!(incomplete_site.incomplete());
}
}