1use powerio_tx::format::routing::TransmissionFormat;
9
10#[derive(Clone, Copy, Debug, Eq, PartialEq, serde::Serialize)]
19#[non_exhaustive]
20pub struct FormatInfo {
21 pub token: &'static str,
24 pub extension: Option<&'static str>,
26 pub is_directory: bool,
29 pub can_emit: bool,
31}
32
33const fn info(
34 token: &'static str,
35 extension: Option<&'static str>,
36 is_directory: bool,
37 can_emit: bool,
38) -> FormatInfo {
39 FormatInfo {
40 token,
41 extension,
42 is_directory,
43 can_emit,
44 }
45}
46
47#[must_use]
55pub fn resolve_format(name: &str) -> Option<FormatInfo> {
56 match name {
57 "bmopf-json@0.1.0" => return Some(info("bmopf-json@0.1.0", Some("json"), false, true)),
58 "bmopf-json@0.2.0" => return Some(info("bmopf-json@0.2.0", Some("json"), false, true)),
59 _ => {}
60 }
61
62 if crate::is_geo_layer_token(name) {
63 return Some(info(
64 "geo-json",
65 Some(powerio_tx::geo::GEO_LAYER_EXTENSION),
66 false,
67 true,
68 ));
69 }
70 if crate::is_pwd_display_token(name) {
71 return Some(info("powerworld-pwd", Some("pwd"), false, false));
72 }
73 if let Some(kind) = crate::contingency_file_of_token(name) {
74 return Some(info(kind.token(), Some(kind.extension()), false, true));
75 }
76 if let Some(format) = powerio_tx::format::parse_target_format(name) {
77 let is_cgmes = format == powerio_tx::TargetFormat::Cgmes;
78 return Some(info(
79 format.token(),
80 (!is_cgmes).then_some(format.extension()),
81 is_cgmes,
82 !matches!(format, powerio_tx::TargetFormat::DeepMindOpfDataJson),
83 ));
84 }
85
86 if let Some(format) = powerio_dist::parse_dist_target_format(name) {
87 return Some(match format.name() {
88 "dss" => info("dss", Some("dss"), true, true),
89 "pmd-json" => info("pmd-json", Some("json"), false, true),
90 "bmopf-json" => info("bmopf-json", Some("json"), false, true),
91 _ => return None,
92 });
93 }
94
95 match powerio_tx::format::routing::parse_transmission_format(name) {
96 Some(TransmissionFormat::PypsaCsv) => Some(info("pypsa-csv", None, true, true)),
97 Some(TransmissionFormat::Pwb) => Some(info("pwb", Some("pwb"), false, false)),
98 Some(TransmissionFormat::Gridfm) => Some(info("gridfm", None, true, true)),
99 Some(TransmissionFormat::IeeeCdf) => Some(info("ieee-cdf", Some("txt"), false, false)),
102 _ => None,
103 }
104}
105
106#[cfg(test)]
107mod tests {
108 use super::*;
109
110 #[test]
111 fn aliases_resolve_to_one_canonical_descriptor() {
112 assert_eq!(resolve_format("m"), resolve_format("MATPOWER"));
113 assert_eq!(resolve_format("pm").unwrap().token, "powermodels-json");
114 assert_eq!(resolve_format("engineering").unwrap().token, "pmd-json");
115 assert_eq!(resolve_format("xiidm").unwrap().token, "xiidm");
116 assert_eq!(resolve_format("jiidm").unwrap().token, "jiidm");
117 assert_eq!(resolve_format("jiidm").unwrap().extension, Some("jiidm"));
118 assert!(resolve_format("cgmes").unwrap().is_directory);
119 assert_eq!(resolve_format("iidm"), None);
120 assert_eq!(resolve_format("rawx"), None);
121 assert_eq!(resolve_format("psse-rawx").unwrap().token, "psse-rawx");
122 assert_eq!(resolve_format("con"), resolve_format("PSSE_CON"));
123 assert_eq!(resolve_format("subsystem").unwrap().token, "psse-sub");
124 assert_eq!(resolve_format("mon").unwrap().extension, Some("mon"));
125 }
126
127 #[test]
128 fn destination_and_read_only_shapes_are_explicit() {
129 let dss = resolve_format("opendss").unwrap();
130 assert!(dss.is_directory);
131 assert!(dss.can_emit);
132 assert_eq!(dss.extension, Some("dss"));
133
134 let pypsa = resolve_format("pypsa").unwrap();
135 assert!(pypsa.is_directory);
136 assert_eq!(pypsa.extension, None);
137
138 let pwb = resolve_format("pwb").unwrap();
139 assert!(!pwb.is_directory);
140 assert!(!pwb.can_emit);
141 assert_eq!(pwb.extension, Some("pwb"));
142
143 let cdf = resolve_format("cdf").unwrap();
144 assert_eq!(cdf.token, "ieee-cdf");
145 assert!(!cdf.is_directory);
146 assert!(!cdf.can_emit);
147 assert_eq!(cdf.extension, Some("txt"));
148 }
149
150 #[test]
151 fn nonformats_do_not_resolve() {
152 assert_eq!(resolve_format("not-a-format"), None);
153 assert_eq!(resolve_format("json"), None);
154 assert_eq!(resolve_format("pio-json"), None);
155 }
156}