use std::path::PathBuf;
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum Version {
R2,
R3,
R4,
R5,
R6,
}
impl Version {
pub const ALL: [Version; 5] = [
Version::R2,
Version::R3,
Version::R4,
Version::R5,
Version::R6,
];
#[must_use]
pub fn parse(token: &str) -> Option<Self> {
match token.to_ascii_lowercase().as_str() {
"r2" | "dstu2" | "2" | "1.0" | "1.0.2" => Some(Version::R2),
"r3" | "stu3" | "3" | "3.0" | "3.0.1" | "3.0.2" => Some(Version::R3),
"r4" | "4" | "4.0" | "4.0.1" => Some(Version::R4),
"r5" | "5" | "5.0" | "5.0.0" => Some(Version::R5),
"r6" | "6" | "6.0" | "6.0.0-ballot3" => Some(Version::R6),
_ => None,
}
}
#[must_use]
pub fn module(self) -> &'static str {
match self {
Version::R2 => "r2",
Version::R3 => "r3",
Version::R4 => "r4",
Version::R5 => "r5",
Version::R6 => "r6",
}
}
#[must_use]
pub fn label(self) -> &'static str {
match self {
Version::R2 => "R2",
Version::R3 => "R3",
Version::R4 => "R4",
Version::R5 => "R5",
Version::R6 => "R6",
}
}
#[must_use]
pub fn version_string(self) -> &'static str {
match self {
Version::R2 => "1.0.2",
Version::R3 => "3.0.2",
Version::R4 => "4.0.1",
Version::R5 => "5.0.0",
Version::R6 => "6.0.0-ballot3",
}
}
#[must_use]
pub fn spec_url(self) -> &'static str {
match self {
Version::R2 => "https://hl7.org/fhir/DSTU2/",
Version::R3 => "https://hl7.org/fhir/STU3/",
Version::R4 => "https://hl7.org/fhir/R4/",
Version::R5 => "https://hl7.org/fhir/R5/",
Version::R6 => "https://hl7.org/fhir/6.0.0-ballot3/",
}
}
#[must_use]
pub fn definitions_dir(self) -> PathBuf {
crate_root()
.join("doc")
.join("fhir-specifications")
.join(self.module())
.join("fhir-definitions-json")
}
#[must_use]
pub fn source_dir(self) -> PathBuf {
crate_root()
.join(format!(
"fhir-release-{}",
self.module().trim_start_matches('r')
))
.join("src")
}
#[must_use]
pub fn types_bundle(self) -> PathBuf {
self.definitions_dir().join("profiles-types.json")
}
#[must_use]
pub fn resources_bundle(self) -> PathBuf {
self.definitions_dir().join("profiles-resources.json")
}
#[must_use]
pub fn code_system_bundles(self) -> Vec<PathBuf> {
vec![self.definitions_dir().join("valuesets.json")]
}
}
pub(crate) fn crate_root() -> PathBuf {
PathBuf::from(env!("CARGO_MANIFEST_DIR"))
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn parse_tokens() {
assert_eq!(Version::parse("r3"), Some(Version::R3));
assert_eq!(Version::parse("STU3"), Some(Version::R3));
assert_eq!(Version::parse("r4"), Some(Version::R4));
assert_eq!(Version::parse("R5"), Some(Version::R5));
assert_eq!(Version::parse("4.0.1"), Some(Version::R4));
assert_eq!(Version::parse("r6"), Some(Version::R6));
assert_eq!(Version::parse("6.0.0-ballot3"), Some(Version::R6));
assert_eq!(Version::parse("r7"), None);
assert_eq!(Version::parse("nonsense"), None);
}
#[test]
fn paths_are_release_scoped() {
for version in Version::ALL {
assert!(version.definitions_dir().ends_with("fhir-definitions-json"));
assert!(version.source_dir().ends_with("src"));
assert!(version.source_dir().parent().is_some_and(|p| {
p.ends_with(format!(
"fhir-release-{}",
version.module().trim_start_matches('r')
))
}));
assert!(version.types_bundle().ends_with("profiles-types.json"));
}
}
}