use thiserror::Error;
#[derive(Error, Debug)]
pub enum Error {
#[error("filename does not follow naming conventions")]
NonStandardFilename,
}
#[derive(Debug, Copy, Default, Clone, PartialEq)]
pub enum Region {
Regional,
#[default]
Global,
}
impl std::fmt::Display for Region {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
match self {
Self::Regional => write!(f, "{}", 'R'),
Self::Global => write!(f, "{}", 'G'),
}
}
}
#[derive(Debug, Default, Clone, PartialEq)]
pub struct ProductionAttributes {
pub agency: String,
pub year: u32,
pub doy: u32,
pub region: Region,
#[cfg(feature = "flate2")]
#[cfg_attr(docsrs, doc(cfg(feature = "flate2")))]
pub gzip_compressed: bool,
}
impl ProductionAttributes {
pub(crate) fn format(name: &str, region: char, ddd: &str, yy: &str) -> String {
format!("{}{}{}0.{}I", name, region, ddd, yy,)
}
}
impl std::str::FromStr for ProductionAttributes {
type Err = Error;
fn from_str(filename: &str) -> Result<Self, Self::Err> {
let filename = filename.to_uppercase();
let name_len = filename.len();
if name_len != 12 && name_len != 15 {
return Err(Error::NonStandardFilename);
}
let offset = filename.find('.').unwrap_or(0);
let agency = filename[..4].to_string();
let year = filename[offset + 1..offset + 3]
.parse::<u32>()
.map_err(|_| Error::NonStandardFilename)?;
let region = if filename[4..5].eq("G") {
Region::Global
} else {
Region::Regional
};
Ok(Self {
region,
agency,
year: year + 2_000, doy: {
filename[4..7]
.parse::<u32>()
.map_err(|_| Error::NonStandardFilename)?
},
#[cfg(feature = "flate2")]
gzip_compressed: filename.ends_with(".gz"),
})
}
}
#[cfg(test)]
mod test {
use super::*;
use std::str::FromStr;
#[test]
fn filenames() {
for (filename, agency, year, doy, region) in [
("CKMG0020.22I", "CKM", 2022, 2, Region::Global),
("CKMG0090.21I", "CKM", 2021, 9, Region::Global),
("jplg0010.17i", "JPL", 2017, 1, Region::Global),
("jplr0010.17i", "JPL", 2017, 1, Region::Regional),
] {
println!("Testing IONEX filename \"{}\"", filename);
let attrs = ProductionAttributes::from_str(filename).unwrap();
assert_eq!(attrs.agency, agency);
assert_eq!(attrs.year, year);
assert_eq!(attrs.doy, doy);
assert_eq!(attrs.region, region);
}
}
}