1use serde::{Deserialize, Serialize};
2use std::{mem::take, str::Lines};
3
4#[derive(Debug, Serialize, Deserialize)]
5pub struct WeatherStation {
6 pub id: u32,
7 pub district_id: String,
8 pub name: String,
9 pub start: u16,
10 pub end: Option<u16>,
11 pub latitude: f64,
12 pub longitude: f64,
13 pub source: Option<String>,
14 pub state: String,
15 pub height: Option<f64>,
16 pub barometric_height: Option<f64>,
17 pub wmo_id: Option<u32>,
18}
19
20pub struct StationsTable<'a> {
23 lines: Lines<'a>,
24 widths: [usize; 12],
25}
26
27impl<'a> StationsTable<'a> {
28 pub fn new(station_list: &'a str) -> Self {
29 let mut lines = station_list.lines();
30 lines.nth(4);
31 let widths = [8, 6, 41, 8, 8, 9, 10, 15, 4, 11, 9, 6];
32 Self { lines, widths }
33 }
34}
35
36impl<'a> Iterator for StationsTable<'a> {
37 type Item = WeatherStation;
38
39 fn next(&mut self) -> Option<Self::Item> {
40 let line = self.lines.next()?;
41
42 if line.is_empty() {
43 return None;
44 }
45
46 let mut start = 0;
47 let mut columns = Vec::new();
48 for &width in self.widths.iter() {
49 let end = start + width;
50 let column = &line[start..end].trim();
51 columns.push(column.to_string());
52 start = end;
53 }
54
55 let source = take(&mut columns[7]);
56 let source = if source.starts_with('.') {
57 None
58 } else {
59 Some(source)
60 };
61
62 Some(WeatherStation {
63 id: take(&mut columns[0]).parse().unwrap(),
64 district_id: take(&mut columns[1]),
65 name: take(&mut columns[2]).to_string(),
66 start: take(&mut columns[3]).parse().unwrap(),
67 end: take(&mut columns[4]).parse().ok(),
68 latitude: take(&mut columns[5]).parse().unwrap(),
69 longitude: take(&mut columns[6]).parse().unwrap(),
70 source,
71 state: take(&mut columns[8]).to_string(),
72 height: take(&mut columns[9]).parse().ok(),
73 barometric_height: take(&mut columns[10]).parse().ok(),
74 wmo_id: take(&mut columns[11]).parse().ok(),
75 })
76 }
77}