use thiserror::Error;
use crate::datetime::{parse_datetime, ParseDateTimeError};
use rinex::constellation::Constellation;
#[derive(Debug, Clone)]
pub struct Receiver {
pub station: String,
pub constellation: Option<Constellation>,
pub group: String,
pub valid_from: chrono::NaiveDateTime,
pub valid_until: chrono::NaiveDateTime,
pub rtype: String,
pub firmware: String,
}
#[derive(Debug, Error)]
pub enum ReceiverError {
#[error("failed to parse datetime field")]
ParseDateError(#[from] chrono::format::ParseError),
#[error("failed to parse datetime:SSSS field")]
ParseFloatError(#[from] std::num::ParseFloatError),
}
impl std::str::FromStr for Receiver {
type Err = ParseDateTimeError;
fn from_str(s: &str) -> Result<Self, Self::Err> {
let (station, rem) = s.split_at(10);
let (constellation, rem) = rem.split_at(2);
let (group, rem) = rem.split_at(10);
let (start, rem) = rem.split_at(15);
let (end, rem) = rem.split_at(15);
let (rtype, rem) = rem.split_at(21);
Ok(Receiver {
station: station.trim().to_string(),
constellation: {
if let Ok(c) = Constellation::from_1_letter_code(constellation.trim()) {
Some(c)
} else {
None
}
},
group: group.trim().to_string(),
valid_from: parse_datetime(start.trim())?,
valid_until: parse_datetime(end.trim())?,
rtype: rtype.trim().to_string(),
firmware: rem.trim().to_string(),
})
}
}
#[cfg(test)]
mod tests {
use super::*;
use std::str::FromStr;
#[test]
fn test_receiver() {
let rcvr = Receiver::from_str(
"MAO0 G @MP0 2015:276:00000 2015:276:86399 JAVAD TRE-G3TH DELTA 3.6.4",
);
assert_eq!(rcvr.is_ok(), true);
let rcvr = rcvr.unwrap();
assert_eq!(rcvr.station, "MAO0");
assert_eq!(rcvr.group, "@MP0");
assert_eq!(rcvr.firmware, "3.6.4");
assert_eq!(rcvr.rtype, "JAVAD TRE-G3TH DELTA");
}
}