diman_unit_system 0.3.0

Internal procedural macros for diman.
Documentation
use syn::Ident;

use crate::{
    dimension_math::DimensionsAndFactor,
    types::{
        Constant, ConstantEntry, Dimensions, Quantity, QuantityDefinition, QuantityEntry,
        QuantityIdent, Unit, UnitEntry, UnitFactor,
    },
};

use super::item::{IdentOrFactor, ResolvedItem, UnresolvedItem, ValueOrExpr};

pub trait ItemConversion {
    type Resolved;

    fn to_unresolved_item(&self) -> UnresolvedItem;
    fn into_resolved(self, item: ResolvedItem) -> Self::Resolved;
    fn ident(&self) -> &Ident;
}

impl ItemConversion for QuantityEntry {
    type Resolved = Quantity;

    fn to_unresolved_item(&self) -> UnresolvedItem {
        let val = match &self.rhs {
            QuantityDefinition::Dimensions(dimensions) => ValueOrExpr::Value(DimensionsAndFactor {
                dimensions: dimensions.clone(),
                factor: 1.0,
            }),
            QuantityDefinition::Expression(expr) => {
                ValueOrExpr::Expr(expr.clone().map(|val| match val {
                    QuantityIdent::One => IdentOrFactor::Factor(DimensionsAndFactor {
                        dimensions: Dimensions { fields: vec![] },
                        factor: 1.0,
                    }),
                    QuantityIdent::Quantity(ident) => IdentOrFactor::Ident(ident),
                }))
            }
        };
        UnresolvedItem {
            name: self.name.clone(),
            val,
        }
    }

    fn into_resolved(self, item: ResolvedItem) -> Self::Resolved {
        Quantity {
            name: self.name,
            dimension: item.val.dimensions,
        }
    }

    fn ident(&self) -> &Ident {
        &self.name
    }
}

impl ItemConversion for UnitEntry {
    type Resolved = Unit;

    fn to_unresolved_item(&self) -> UnresolvedItem {
        let val = ValueOrExpr::Expr(self.rhs.clone().map(|x| match x {
            UnitFactor::UnitOrQuantity(ident) => IdentOrFactor::Ident(ident),
            UnitFactor::Number(factor) => IdentOrFactor::Factor(DimensionsAndFactor {
                factor,
                dimensions: Dimensions::none(),
            }),
        }));
        UnresolvedItem {
            name: self.name.clone(),
            val,
        }
    }

    fn into_resolved(self, item: ResolvedItem) -> Self::Resolved {
        Unit {
            name: self.name,
            dimension: item.val.dimensions,
            factor: item.val.factor,
            symbol: self.symbol,
        }
    }

    fn ident(&self) -> &Ident {
        &self.name
    }
}

impl ItemConversion for ConstantEntry {
    type Resolved = Constant;

    fn to_unresolved_item(&self) -> UnresolvedItem {
        let val = ValueOrExpr::Expr(self.rhs.clone().map(|x| match x {
            UnitFactor::UnitOrQuantity(ident) => IdentOrFactor::Ident(ident),
            UnitFactor::Number(factor) => IdentOrFactor::Factor(DimensionsAndFactor {
                factor,
                dimensions: Dimensions::none(),
            }),
        }));
        UnresolvedItem {
            name: self.name.clone(),
            val,
        }
    }

    fn into_resolved(self, item: ResolvedItem) -> Self::Resolved {
        Constant {
            name: self.name,
            dimension: item.val.dimensions,
            factor: item.val.factor,
        }
    }

    fn ident(&self) -> &Ident {
        &self.name
    }
}