use std::collections::BTreeMap;
use std::sync::Arc;
pub trait Definitions {
fn structure(&self, url: &str) -> Option<Arc<Structure>>;
fn covers(&self, url: &str) -> bool {
let _ = url;
false
}
}
#[derive(Debug, Default, Clone, Copy)]
pub struct NoDefinitions;
impl Definitions for NoDefinitions {
fn structure(&self, _url: &str) -> Option<Arc<Structure>> {
None
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub enum Kind {
PrimitiveType,
ComplexType,
Resource,
Logical,
}
#[derive(Debug, Clone, PartialEq)]
pub struct Structure {
pub url: String,
pub name: String,
pub type_name: String,
pub kind: Kind,
pub is_abstract: bool,
pub base: Option<String>,
pub elements: BTreeMap<String, Element>,
}
#[derive(Debug, Clone, Default, PartialEq)]
pub struct Element {
pub types: Vec<String>,
pub choices: Vec<String>,
pub array: bool,
pub children: Arc<BTreeMap<String, Element>>,
pub content_reference: Option<(String, Vec<String>)>,
pub choice_of: Option<String>,
pub index: Option<usize>,
}
impl Element {
pub fn is_choice(&self) -> bool {
!self.choices.is_empty() || self.types.len() > 1
}
}
pub fn type_url(code: &str, context_url: &str) -> String {
if code.contains("://") || code.starts_with("urn:") {
return code.to_owned();
}
match versioned_core(context_url) {
Some(prefix) => format!("{prefix}/StructureDefinition/{code}"),
None => format!("http://hl7.org/fhir/StructureDefinition/{code}"),
}
}
pub fn versioned_core(url: &str) -> Option<&str> {
let url = url.split('|').next().unwrap_or(url);
let version = url
.strip_prefix("http://hl7.org/fhir/")?
.split_once("/StructureDefinition/")?
.0;
let is_version = !version.is_empty() && version.chars().all(|c| c.is_ascii_digit() || c == '.');
is_version.then(|| &url[.."http://hl7.org/fhir/".len() + version.len()])
}
pub fn same_primitive(a: &str, b: &str) -> bool {
let system = |code: &str| -> String {
match code {
"String" | "string" | "code" | "id" | "markdown" | "uri" | "url" | "canonical"
| "oid" | "uuid" | "base64Binary" | "xhtml" => "String".into(),
"Integer" | "integer" | "positiveInt" | "unsignedInt" => "Integer".into(),
"Integer64" | "integer64" => "Long".into(),
"Decimal" | "decimal" => "Decimal".into(),
"Boolean" | "boolean" => "Boolean".into(),
"Date" | "date" => "Date".into(),
"DateTime" | "dateTime" | "instant" => "DateTime".into(),
"Time" | "time" => "Time".into(),
other => other.into(),
}
};
system(a) == system(b)
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn type_codes_resolve_in_the_release_of_the_structure() {
let core = "http://hl7.org/fhir/StructureDefinition/HumanName";
assert_eq!(
type_url(
"HumanName",
"http://hl7.org/fhir/StructureDefinition/Patient"
),
core
);
assert_eq!(
type_url(
"HumanName",
"http://hl7.org/fhir/4.0/StructureDefinition/Patient|4.0.1"
),
"http://hl7.org/fhir/4.0/StructureDefinition/HumanName"
);
assert_eq!(
type_url(
"HumanName",
"http://hl7.org/fhir/us/core/StructureDefinition/us-core-patient"
),
core
);
assert_eq!(
type_url("HumanName", "http://example.org/StructureDefinition/P"),
core
);
assert_eq!(
type_url("http://example.org/T", core),
"http://example.org/T"
);
}
}