use powerio_tx::format::routing::TransmissionFormat;
#[derive(Clone, Copy, Debug, Eq, PartialEq, serde::Serialize)]
#[non_exhaustive]
pub struct FormatInfo {
pub token: &'static str,
pub extension: Option<&'static str>,
pub is_directory: bool,
pub can_emit: bool,
}
const fn info(
token: &'static str,
extension: Option<&'static str>,
is_directory: bool,
can_emit: bool,
) -> FormatInfo {
FormatInfo {
token,
extension,
is_directory,
can_emit,
}
}
#[must_use]
pub fn resolve_format(name: &str) -> Option<FormatInfo> {
match name {
"bmopf-json@0.1.0" => return Some(info("bmopf-json@0.1.0", Some("json"), false, true)),
"bmopf-json@0.2.0" => return Some(info("bmopf-json@0.2.0", Some("json"), false, true)),
_ => {}
}
if crate::is_geo_layer_token(name) {
return Some(info(
"geo-json",
Some(powerio_tx::geo::GEO_LAYER_EXTENSION),
false,
true,
));
}
if crate::is_pwd_display_token(name) {
return Some(info("powerworld-pwd", Some("pwd"), false, false));
}
if let Some(kind) = crate::contingency_file_of_token(name) {
return Some(info(kind.token(), Some(kind.extension()), false, true));
}
if let Some(format) = powerio_tx::format::parse_target_format(name) {
let is_cgmes = format == powerio_tx::TargetFormat::Cgmes;
return Some(info(
format.token(),
(!is_cgmes).then_some(format.extension()),
is_cgmes,
!matches!(format, powerio_tx::TargetFormat::DeepMindOpfDataJson),
));
}
if let Some(format) = powerio_dist::parse_dist_target_format(name) {
return Some(match format.name() {
"dss" => info("dss", Some("dss"), true, true),
"pmd-json" => info("pmd-json", Some("json"), false, true),
"bmopf-json" => info("bmopf-json", Some("json"), false, true),
_ => return None,
});
}
match powerio_tx::format::routing::parse_transmission_format(name) {
Some(TransmissionFormat::PypsaCsv) => Some(info("pypsa-csv", None, true, true)),
Some(TransmissionFormat::Pwb) => Some(info("pwb", Some("pwb"), false, false)),
Some(TransmissionFormat::Gridfm) => Some(info("gridfm", None, true, true)),
Some(TransmissionFormat::IeeeCdf) => Some(info("ieee-cdf", Some("txt"), false, false)),
_ => None,
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn aliases_resolve_to_one_canonical_descriptor() {
assert_eq!(resolve_format("m"), resolve_format("MATPOWER"));
assert_eq!(resolve_format("pm").unwrap().token, "powermodels-json");
assert_eq!(resolve_format("engineering").unwrap().token, "pmd-json");
assert_eq!(resolve_format("xiidm").unwrap().token, "xiidm");
assert_eq!(resolve_format("jiidm").unwrap().token, "jiidm");
assert_eq!(resolve_format("jiidm").unwrap().extension, Some("jiidm"));
assert!(resolve_format("cgmes").unwrap().is_directory);
assert_eq!(resolve_format("iidm"), None);
assert_eq!(resolve_format("rawx"), None);
assert_eq!(resolve_format("psse-rawx").unwrap().token, "psse-rawx");
assert_eq!(resolve_format("con"), resolve_format("PSSE_CON"));
assert_eq!(resolve_format("subsystem").unwrap().token, "psse-sub");
assert_eq!(resolve_format("mon").unwrap().extension, Some("mon"));
}
#[test]
fn destination_and_read_only_shapes_are_explicit() {
let dss = resolve_format("opendss").unwrap();
assert!(dss.is_directory);
assert!(dss.can_emit);
assert_eq!(dss.extension, Some("dss"));
let pypsa = resolve_format("pypsa").unwrap();
assert!(pypsa.is_directory);
assert_eq!(pypsa.extension, None);
let pwb = resolve_format("pwb").unwrap();
assert!(!pwb.is_directory);
assert!(!pwb.can_emit);
assert_eq!(pwb.extension, Some("pwb"));
let cdf = resolve_format("cdf").unwrap();
assert_eq!(cdf.token, "ieee-cdf");
assert!(!cdf.is_directory);
assert!(!cdf.can_emit);
assert_eq!(cdf.extension, Some("txt"));
}
#[test]
fn nonformats_do_not_resolve() {
assert_eq!(resolve_format("not-a-format"), None);
assert_eq!(resolve_format("json"), None);
assert_eq!(resolve_format("pio-json"), None);
}
}