ocpi-tariffs 0.43.0

OCPI tariff calculations
Documentation
use crate::{
    expect_string_or_bail, into_caveat, json,
    tariff::Warning,
    warning::{self, IntoCaveat as _},
    Enum, IntoEnum, Verdict,
};

/// Type of tariff component
///
/// See: <https://github.com/ocpi/ocpi/blob/release-2.2.1-bugfixes/mod_tariffs.asciidoc#mod_tariffs_tariffdimensiontype_enum>
/// See: <https://github.com/ocpi/ocpi/blob/release-2.1.1-bugfixes/mod_tariffs.md#44-tariffdimensiontype-enum>
#[derive(Debug, Copy, Clone)]
pub(crate) enum DimensionType {
    /// Defined in kWh, `step_size` multiplier: 1 Wh
    Energy,
    /// Flat fee, no unit for `step_size`
    Flat,
    /// Time not charging: defined in hours, `step_size` multiplier: 1 second
    ParkingTime,
    /// Time charging: defined in hours, `step_size` multiplier: 1 second
    Time,
}

into_caveat!(DimensionType);

impl IntoEnum for DimensionType {
    fn enum_from_str(s: &str) -> Enum<Self> {
        let dt = if s.eq_ignore_ascii_case("energy") {
            DimensionType::Energy
        } else if s.eq_ignore_ascii_case("flat") {
            DimensionType::Flat
        } else if s.eq_ignore_ascii_case("parking_time") {
            DimensionType::ParkingTime
        } else if s.eq_ignore_ascii_case("time") {
            DimensionType::Time
        } else {
            return Enum::Unknown(s.to_string());
        };

        Enum::Known(dt)
    }
}

impl json::FromJson<'_, '_> for Enum<DimensionType> {
    type Warning = Warning;

    fn from_json(elem: &'_ json::Element<'_>) -> Verdict<Self, Self::Warning> {
        let mut warnings = warning::Set::new();
        let s = expect_string_or_bail!(elem, warnings);
        let dt = DimensionType::enum_from_str(&s);
        Ok(dt.into_caveat(warnings))
    }
}

impl json::FromJson<'_, '_> for u64 {
    type Warning = Warning;

    fn from_json(elem: &'_ json::Element<'_>) -> Verdict<Self, Self::Warning> {
        let warnings = warning::Set::new();
        let Some(s) = elem.as_number_str() else {
            return warnings.bail(
                Warning::FieldInvalidType {
                    expected_type: json::ValueKind::Number,
                },
                elem,
            );
        };

        let n = match s.parse::<u64>() {
            Ok(n) => n,
            Err(err) => {
                return warnings.bail(Warning::field_invalid_value(s, err.to_string()), elem);
            }
        };

        Ok(n.into_caveat(warnings))
    }
}