use haste_fhir_model::r4::generated::types::{
FHIRBoolean, FHIRDecimal, FHIRInteger, FHIRPositiveInt, FHIRUnsignedInt,
};
use haste_reflect::MetaValue;
#[derive(Debug, PartialEq)]
pub enum ConvertedValue {
String(String),
Boolean(bool),
Number(f64),
}
impl ToString for ConvertedValue {
fn to_string(&self) -> String {
match self {
ConvertedValue::String(s) => s.clone(),
ConvertedValue::Boolean(b) => b.to_string(),
ConvertedValue::Number(n) => n.to_string(),
}
}
}
fn downcast_string(value: &dyn MetaValue) -> Option<String> {
match value.fhir_type() {
"canonical" | "base64Binary" | "code" | "string" | "oid" | "id" | "uri" | "url"
| "uuid" | "xhtml" => downcast_string(value.get_field("value").unwrap_or(&"".to_string())),
"date" => value
.as_any()
.downcast_ref::<haste_fhir_model::r4::generated::types::FHIRDate>()
.and_then(|dt| dt.value.as_ref())
.map(|d| d.to_string()),
"dateTime" => value
.as_any()
.downcast_ref::<haste_fhir_model::r4::generated::types::FHIRDateTime>()
.and_then(|dt| dt.value.as_ref())
.map(|d| d.to_string()),
"instant" => value
.as_any()
.downcast_ref::<haste_fhir_model::r4::generated::types::FHIRInstant>()
.and_then(|dt| dt.value.as_ref())
.map(|d| d.to_string()),
"http://hl7.org/fhirpath/System.String" => {
value.as_any().downcast_ref::<String>().map(|v| v.clone())
}
_ => None,
}
}
fn downcast_number(value: &dyn MetaValue) -> Option<f64> {
match value.fhir_type() {
"integer" => value
.as_any()
.downcast_ref::<FHIRInteger>()
.and_then(|fp_int| downcast_number(fp_int.value.as_ref().unwrap_or(&0))),
"decimal" => value
.as_any()
.downcast_ref::<FHIRDecimal>()
.and_then(|fp_dec| downcast_number(fp_dec.value.as_ref().unwrap_or(&(0 as f64)))),
"positiveInt" => value
.as_any()
.downcast_ref::<FHIRPositiveInt>()
.and_then(|fp_pint| downcast_number(fp_pint.value.as_ref().unwrap_or(&(0 as u64)))),
"unsignedInt" => value
.as_any()
.downcast_ref::<FHIRUnsignedInt>()
.and_then(|fp_uint| downcast_number(fp_uint.value.as_ref().unwrap_or(&(0 as u64)))),
"http://hl7.org/fhirpath/System.Integer" => {
value.as_any().downcast_ref::<i64>().map(|v| *v as f64)
}
"http://hl7.org/fhirpath/System.Decimal" => {
value.as_any().downcast_ref::<f64>().map(|v| *v)
}
_ => None,
}
}
fn downcast_bool(value: &dyn MetaValue) -> Option<bool> {
match value.fhir_type() {
"http://hl7.org/fhirpath/System.Boolean" => {
value.as_any().downcast_ref::<bool>().map(|v| *v)
}
"boolean" => value
.as_any()
.downcast_ref::<FHIRBoolean>()
.and_then(|fp_bool| downcast_bool(fp_bool.value.as_ref().unwrap_or(&false))),
_ => None,
}
}
pub fn convert_meta_value(value: &dyn MetaValue) -> Option<ConvertedValue> {
if let Some(s) = downcast_string(value) {
return Some(ConvertedValue::String(s));
} else if let Some(i) = downcast_number(value) {
return Some(ConvertedValue::Number(i));
} else if let Some(b) = downcast_bool(value) {
return Some(ConvertedValue::Boolean(b));
} else {
Some(ConvertedValue::String(format!("{:?}", value)))
}
}
pub fn convert_string_value(value: &str) -> Option<ConvertedValue> {
if value == "true" || value == "false" {
if let Ok(b) = value.parse::<bool>() {
return Some(ConvertedValue::Boolean(b));
}
None
} else if let Ok(i) = value.parse::<f64>() {
return Some(ConvertedValue::Number(i));
} else {
return Some(ConvertedValue::String(value.to_string()));
}
}