pub(crate) mod binding;
mod compose;
pub(crate) mod index;
use fhir_types::codec::Object;
use fhir_types::codec::Value;
use crate::report::Reason;
#[derive(Debug, Clone, PartialEq, Eq)]
pub(crate) enum Membership {
Member,
NotMember,
Unknown(Reason),
}
impl Membership {
fn or(self, other: Self) -> Self {
match (self, other) {
(Self::Member, _) | (_, Self::Member) => Self::Member,
(Self::NotMember, Self::NotMember) => Self::NotMember,
(Self::Unknown(reason), _) | (_, Self::Unknown(reason)) => Self::Unknown(reason),
}
}
fn and(self, other: Self) -> Self {
match (self, other) {
(Self::NotMember, _) | (_, Self::NotMember) => Self::NotMember,
(Self::Member, Self::Member) => Self::Member,
(Self::Unknown(reason), _) | (_, Self::Unknown(reason)) => Self::Unknown(reason),
}
}
fn not(self) -> Self {
match self {
Self::Member => Self::NotMember,
Self::NotMember => Self::Member,
unknown @ Self::Unknown(_) => unknown,
}
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub(crate) struct Coding<'a> {
pub(crate) system: Option<&'a str>,
pub(crate) version: Option<&'a str>,
pub(crate) code: Option<&'a str>,
pub(crate) display: Option<&'a str>,
pub(crate) position: usize,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub(crate) enum Form {
Code,
Coding,
CodeableConcept,
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub(crate) struct Coded<'a> {
pub(crate) form: Form,
pub(crate) codes: Vec<Coding<'a>>,
pub(crate) text: Option<&'a str>,
}
impl<'a> Coded<'a> {
pub(crate) fn infer(value: &'a Value) -> Option<Self> {
match value {
Value::String(code) => Some(Self::code(code)),
Value::Object(object) => {
if object.contains_key("coding") || object.contains_key("text") {
Some(Self::concept(object))
} else {
Some(Self::coding(object))
}
}
_ => None,
}
}
pub(crate) fn code(code: &'a str) -> Self {
Self {
form: Form::Code,
codes: vec![Coding {
system: None,
version: None,
code: Some(code),
display: None,
position: 0,
}],
text: None,
}
}
pub(crate) fn coding(object: &'a Object) -> Self {
Self {
form: Form::Coding,
codes: vec![code_of(0, object)],
text: None,
}
}
pub(crate) fn concept(object: &'a Object) -> Self {
Self {
form: Form::CodeableConcept,
codes: object
.get("coding")
.and_then(Value::as_array)
.unwrap_or_default()
.iter()
.enumerate()
.filter_map(|(position, coding)| Some((position, coding.as_object()?)))
.map(|(position, coding)| code_of(position, coding))
.collect(),
text: object.get("text").and_then(Value::as_str),
}
}
}
fn code_of(position: usize, object: &Object) -> Coding<'_> {
let text = |key: &str| object.get(key).and_then(Value::as_str);
Coding {
system: text("system"),
version: text("version"),
code: text("code"),
display: text("display"),
position,
}
}