use std::io;
use std::path::Path;
use std::path::PathBuf;
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct Project {
directory: &'static str,
contexts: &'static [&'static str],
files: &'static [File],
accounted: &'static [&'static str],
}
#[derive(Debug, Clone, PartialEq, Eq, thiserror::Error)]
#[error("the {project} project compiles no context mapping named `{context}`")]
pub struct UnknownContext {
pub project: &'static str,
pub context: String,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct File {
pub name: &'static str,
pub text: &'static str,
}
impl Project {
#[must_use]
pub const fn directory(&self) -> &'static str {
self.directory
}
#[must_use]
pub const fn contexts(&self) -> &'static [&'static str] {
self.contexts
}
pub fn with_context(self, name: &str) -> Result<Self, UnknownContext> {
let contexts = self.contexts;
let chosen = contexts
.iter()
.find(|held| **held == name)
.ok_or_else(|| UnknownContext {
project: self.directory,
context: name.to_owned(),
})?;
Ok(Self {
contexts: std::slice::from_ref(chosen),
..self
})
}
#[must_use]
pub const fn files(&self) -> &'static [File] {
self.files
}
#[must_use]
pub const fn accounted(&self) -> &'static [&'static str] {
self.accounted
}
pub fn write_to(&self, directory: &Path) -> io::Result<Vec<PathBuf>> {
self.files
.iter()
.map(|file| {
let path = directory.join(file.name);
std::fs::write(&path, file.text).map(|()| path)
})
.collect()
}
}
#[cfg(any(
feature = "prescription",
feature = "dispensation",
feature = "imaging",
feature = "laboratory",
feature = "patient-summary",
feature = "discharge"
))]
macro_rules! shipped {
($directory:literal, $name:literal) => {
File {
name: $name,
text: include_str!(concat!(
env!("CARGO_MANIFEST_DIR"),
"/mappings/",
$directory,
"/",
$name
)),
}
};
}
#[cfg(any(feature = "prescription", feature = "dispensation"))]
pub const MPD: Project = Project {
directory: "mpd",
contexts: &[
"ferrobridge_eu_mpd_request.context",
"ferrobridge_eu_mpd_dispense.context",
],
files: &[
shipped!("mpd", "ferrobridge_eu_mpd_request.context.yml"),
shipped!("mpd", "ferrobridge_medication_order.v3.yml"),
shipped!("mpd", "ferrobridge_medication.v2.yml"),
shipped!("mpd", "ferrobridge_dosage.v2.yml"),
shipped!("mpd", "ferrobridge_eu_mpd_request.yml"),
shipped!("mpd", "ferrobridge_eu_mpd_medication.yml"),
shipped!("mpd", "ferrobridge_eu_mpd_dispense.context.yml"),
shipped!("mpd", "ferrobridge_medication.v1.yml"),
shipped!("mpd", "ferrobridge_eu_mpd_dispense.yml"),
],
accounted: &[],
};
#[cfg(feature = "imaging")]
pub const IMAGING: Project = Project {
directory: "imaging",
contexts: &["ferrobridge_eu_imaging.context"],
files: &[
shipped!("imaging", "ferrobridge_eu_imaging.context.yml"),
shipped!("imaging", "ferrobridge_imaging_exam_result.v1.yml"),
shipped!("imaging", "ferrobridge_eu_imaging_report.yml"),
],
accounted: &[],
};
#[cfg(feature = "laboratory")]
pub const LABORATORY: Project = Project {
directory: "laboratory",
contexts: &[
"ferrobridge_eu_laboratory.context",
"ferrobridge_eu_lab_composition.context",
],
files: &[
shipped!("laboratory", "ferrobridge_eu_laboratory.context.yml"),
shipped!("laboratory", "ferrobridge_laboratory_test_result.v1.yml"),
shipped!("laboratory", "ferrobridge_laboratory_test_analyte.v1.yml"),
shipped!("laboratory", "ferrobridge_specimen.v1.yml"),
shipped!("laboratory", "ferrobridge_eu_laboratory_result.yml"),
shipped!("laboratory", "ferrobridge_eu_laboratory_analyte.yml"),
shipped!("laboratory", "ferrobridge_eu_laboratory_specimen.yml"),
shipped!("laboratory", "ferrobridge_eu_lab_composition.context.yml"),
shipped!("laboratory", "ferrobridge_report_result.v1.Composition.yml"),
shipped!("laboratory", "ferrobridge_eu_lab_composition.yml"),
shipped!("laboratory", "ferrobridge_eu_lab_composition_report.yml"),
],
accounted: &[
"DiagnosticReport.basedOn.reference",
"DiagnosticReport.basedOn.identifier",
"DiagnosticReport.basedOn.display",
"DiagnosticReport.basedOn.extension",
"Observation.basedOn",
"Observation.referenceRange",
],
};
#[cfg(feature = "patient-summary")]
pub const EPS: Project = Project {
directory: "eps",
contexts: &["ferrobridge_eu_eps.context"],
files: &[
shipped!("eps", "ferrobridge_eu_eps.context.yml"),
shipped!("eps", "ferrobridge_health_summary.v1.Composition.yml"),
shipped!("eps", "ferrobridge_eu_eps_medication.context.yml"),
shipped!("eps", "ferrobridge_section_adhoc.v1.yml"),
shipped!("eps", "ferrobridge_eu_eps_medication_section.yml"),
shipped!(
"eps",
"ferrobridge_medication_order.v3.MedicationStatement.yml"
),
shipped!("eps", "ferrobridge_medication.v1.MedicationStatement.yml"),
shipped!("eps", "ferrobridge_eu_eps_immunization.context.yml"),
shipped!("eps", "ferrobridge_section_immunisation_list.v0.yml"),
shipped!("eps", "ferrobridge_eu_eps_immunization_section.yml"),
shipped!("eps", "ferrobridge_medication.v1.Immunization.yml"),
],
accounted: &[],
};
#[cfg(feature = "discharge")]
pub const HDR: Project = Project {
directory: "hdr",
contexts: &["ferrobridge_eu_hdr.context"],
files: &[
shipped!("hdr", "ferrobridge_eu_hdr.context.yml"),
shipped!("hdr", "ferrobridge_transfer_summary.v1.Composition.yml"),
shipped!("hdr", "ferrobridge_problem_diagnosis.v1.yml"),
shipped!("hdr", "ferrobridge_procedure.v1.yml"),
shipped!("hdr", "ferrobridge_medication_order.v3.yml"),
],
accounted: &[],
};