use crate::category::Category;
use crate::receive::ReceivedDocument;
pub const LOINC: &str = "http://loinc.org";
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct DocumentType {
pub system: &'static str,
pub code: &'static str,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct Profiles {
pub bundle: &'static str,
pub composition: &'static str,
}
impl Category {
#[must_use]
pub const fn document_type(self) -> Option<DocumentType> {
match self {
#[cfg(feature = "patient-summary")]
Self::PatientSummary => Some(DocumentType {
system: LOINC,
code: "60591-5",
}),
#[cfg_attr(
not(any(
feature = "prescription",
feature = "dispensation",
feature = "imaging",
feature = "laboratory",
feature = "discharge",
)),
expect(
unreachable_patterns,
reason = "a build with none of these features carries at most the patient summary, \
which its own arm receives"
)
)]
_ => None,
}
}
#[must_use]
pub const fn profiles(self) -> Option<Profiles> {
match self {
#[cfg(feature = "patient-summary")]
Self::PatientSummary => Some(Profiles {
bundle: "http://hl7.eu/fhir/eps/StructureDefinition/bundle-eu-eps",
composition: "http://hl7.eu/fhir/eps/StructureDefinition/composition-eu-eps",
}),
#[cfg_attr(
not(any(
feature = "prescription",
feature = "dispensation",
feature = "imaging",
feature = "laboratory",
feature = "discharge",
)),
expect(
unreachable_patterns,
reason = "a build with none of these features carries at most the patient summary, \
which its own arm receives"
)
)]
_ => None,
}
}
}
impl ReceivedDocument {
pub fn category(&self) -> Result<Category, Uncategorised> {
let codings = &self.composition().r#type.coding;
let mut named = Category::ENABLED.iter().copied().filter(|category| {
category.document_type().is_some_and(|wanted| {
codings.iter().any(|coding| {
coding
.system
.as_ref()
.and_then(|system| system.value.as_deref())
== Some(wanted.system)
&& coding.code.as_ref().and_then(|code| code.value.as_deref())
== Some(wanted.code)
})
})
});
match (named.next(), named.next()) {
(Some(category), None) => Ok(category),
(Some(_), Some(_)) => Err(Uncategorised::Several),
(None, _) => Err(Uncategorised::Unknown),
}
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, thiserror::Error)]
#[non_exhaustive]
pub enum Uncategorised {
#[error("the document's Composition.type names no category this system receives")]
Unknown,
#[error("the document's Composition.type names more than one category")]
Several,
}