use std::sync::Arc;
use ifc_model::Value;
#[derive(Debug, Clone, PartialEq)]
pub enum Scalar {
Bool(bool),
LogicalUnknown,
Integer(i64),
Real(f64),
Text(Arc<str>),
Enum(Arc<str>),
Binary(Arc<str>),
}
impl Scalar {
pub fn as_f64(&self) -> Option<f64> {
match self {
Self::Real(v) => Some(*v),
Self::Integer(v) => Some(*v as f64),
_ => None,
}
}
pub fn as_str(&self) -> Option<&str> {
match self {
Self::Text(v) | Self::Enum(v) => Some(v),
_ => None,
}
}
}
#[derive(Debug, Clone, PartialEq)]
pub struct MeasureValue {
pub measure: Option<Arc<str>>,
pub scalar: Scalar,
}
impl MeasureValue {
pub fn read(value: &Value) -> Option<Self> {
Self::read_inner(value, None)
}
fn read_inner(value: &Value, measure: Option<Arc<str>>) -> Option<Self> {
let scalar = match value {
Value::Typed { type_name, value } => {
let name = measure.unwrap_or_else(|| type_name.clone());
return Self::read_inner(value, Some(name));
}
Value::Bool(v) => Scalar::Bool(*v),
Value::LogicalUnknown => Scalar::LogicalUnknown,
Value::Integer(v) => Scalar::Integer(*v),
Value::Real(v) => Scalar::Real(*v),
Value::Text(v) => Scalar::Text(v.clone()),
Value::Enum(v) => Scalar::Enum(v.clone()),
Value::Binary(v) => Scalar::Binary(v.clone()),
Value::Null | Value::Derived | Value::Ref(_) | Value::List(_) => return None,
};
Some(Self { measure, scalar })
}
pub fn read_list(value: &Value) -> Option<Vec<Self>> {
match value {
Value::List(items) => Some(items.iter().filter_map(Self::read).collect()),
_ => None,
}
}
pub fn as_f64(&self) -> Option<f64> {
self.scalar.as_f64()
}
pub fn measure(&self) -> Option<&str> {
self.measure.as_deref()
}
}