mod generated;
pub use crate::meta::{BindingMeta, BindingStrength, ElementMeta, TypeRef};
#[must_use]
pub fn element(path: &str) -> Option<&'static ElementMeta> {
crate::meta::find(generated::ELEMENTS, path)
}
#[must_use]
pub fn elements() -> &'static [ElementMeta] {
generated::ELEMENTS
}
pub fn elements_of(type_name: &str) -> impl Iterator<Item = &'static ElementMeta> {
let prefix = format!("{type_name}.");
generated::ELEMENTS.iter().filter(move |e| e.path.starts_with(&prefix))
}
#[must_use]
pub fn struct_prefix(struct_name: &str) -> Option<&'static str> {
use std::collections::HashMap;
use std::sync::LazyLock;
static PREFIXES: LazyLock<HashMap<String, &'static str>> =
LazyLock::new(|| crate::meta::struct_prefixes(generated::ELEMENTS));
PREFIXES.get(struct_name).copied()
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn table_is_non_empty_and_sorted() {
let all = elements();
assert!(all.len() > 5000, "expected thousands of elements, got {}", all.len());
assert!(
all.windows(2).all(|w| w[0].path <= w[1].path),
"ELEMENTS must be sorted by path for binary search"
);
}
#[test]
fn patient_gender_binding() {
let gender = element("Patient.gender").expect("Patient.gender");
let binding = gender.binding.expect("gender has a binding");
assert_eq!(binding.strength, BindingStrength::Required);
assert!(
binding.value_set.unwrap().contains("administrative-gender"),
"value_set was {:?}",
binding.value_set
);
}
#[test]
fn observation_value_choice_types() {
let value = element("Observation.value[x]").expect("Observation.value[x]");
assert!(value.is_choice());
assert_eq!(value.types.len(), 11, "R4 Observation.value[x] type count");
for code in ["Quantity", "CodeableConcept", "string", "Range", "Period"] {
assert!(value.type_codes().any(|c| c == code), "missing type {code}");
}
assert!(!value.type_codes().any(|c| c == "Attachment"), "Attachment is R5-only");
}
#[test]
fn observation_subject_targets() {
let subject = element("Observation.subject").expect("Observation.subject");
let targets: Vec<&str> = subject.types.iter().flat_map(TypeRef::target_names).collect();
for want in ["Patient", "Group", "Device", "Location"] {
assert!(targets.contains(&want), "subject should target {want}: {targets:?}");
}
}
#[test]
fn cardinality_helpers() {
let status = element("Observation.status").expect("Observation.status");
assert!(status.is_required());
assert!(!status.is_multiple());
let identifier = element("Observation.identifier").expect("Observation.identifier");
assert!(!identifier.is_required());
assert!(identifier.is_multiple());
}
#[test]
fn elements_of_a_type() {
let count = elements_of("Patient").count();
assert!(count > 20, "Patient should have many elements, got {count}");
assert!(elements_of("Patient").all(|e| e.path.starts_with("Patient.")));
}
}