use crate::parse_util::{parse_f64, parse_i32, parse_kv, parse_naive_date_time};
use chrono::NaiveDateTime;
use metfor::Meters;
use optional::Optioned;
use std::error::Error;
#[derive(Debug)]
pub struct StationInfo {
pub num: i32, pub valid_time: NaiveDateTime, pub lead_time: i32, pub id: Option<String>, pub lat: Optioned<f64>, pub lon: Optioned<f64>, pub elevation: Optioned<Meters>, }
impl StationInfo {
pub fn parse(src: &str) -> Result<StationInfo, Box<dyn Error>> {
let (station_id, mut head) = parse_kv(
src,
"STID",
|c| char::is_alphanumeric(c),
|c| !char::is_alphanumeric(c),
)?;
let station_id = if station_id == "STNM" {
head = src;
None
} else {
Some(station_id.to_owned())
};
let (station_num, head) = parse_i32(head, "STNM")?;
let (val_to_parse, head) = parse_kv(
head,
"TIME",
|c| char::is_digit(c, 10),
|c| !(char::is_digit(c, 10) || c == '/'),
)?;
let vt = parse_naive_date_time(val_to_parse)?;
let (lat, head) = parse_f64(head, "SLAT")?;
let (lon, head) = parse_f64(head, "SLON")?;
let (elv, head) = parse_f64(head, "SELV")?;
let (lt, _) = parse_i32(head, "STIM")?;
Ok(StationInfo {
num: station_num,
id: station_id,
valid_time: vt,
lead_time: lt,
lat,
lon,
elevation: elv.map_t(Meters),
})
}
}
#[test]
fn test_station_info_parse() {
use chrono::NaiveDate;
use optional::some;
let test_data = "STID = STNM = 727730 TIME = 170401/0000
SLAT = 46.92 SLON = -114.08 SELV = 972.0
STIM = 0";
let si = StationInfo::parse(&test_data);
println!("si: {:?}", si);
let StationInfo {
num,
id,
valid_time,
lead_time,
lat,
lon,
elevation,
} = si.unwrap();
assert_eq!(id, None);
assert_eq!(num, 727730);
assert_eq!(valid_time, NaiveDate::from_ymd_opt(2017, 4, 1).unwrap().and_hms_opt(0, 0, 0).unwrap());
assert_eq!(lead_time, 0);
assert_eq!(lat, some(46.92));
assert_eq!(lon, some(-114.08));
assert_eq!(elevation, some(Meters(972.0)));
let test_data = "STID = KMSO STNM = 727730 TIME = 170404/1200
SLAT = 46.87 SLON = -114.16 SELV = 1335.0
STIM = 84";
let si = StationInfo::parse(&test_data);
println!("si: {:?}", si);
let StationInfo {
num,
id,
valid_time,
lead_time,
lat,
lon,
elevation,
} = si.unwrap();
assert_eq!(id.unwrap(), "KMSO");
assert_eq!(num, 727730);
assert_eq!(
valid_time,
NaiveDate::from_ymd_opt(2017, 4, 4).unwrap().and_hms_opt(12, 0, 0).unwrap()
);
assert_eq!(lead_time, 84);
assert_eq!(lat, some(46.87));
assert_eq!(lon, some(-114.16));
assert_eq!(elevation, some(Meters(1335.0)));
}