ocpi-tariffs 0.52.0

OCPI tariff calculations
Documentation
//! Types for parsing all tariff versions.

use std::convert::Infallible;

use crate::{
    schema,
    tariff::Warning,
    warning::{self, IntoCaveat as _},
    FromSchema, 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, Eq, PartialEq, Hash)]
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,
}

impl FromSchema<'_, schema::v211::TariffDimensionType> for DimensionType {
    type Warning = Infallible;

    fn from_schema(source: &schema::v211::TariffDimensionType) -> Verdict<Self, Self::Warning> {
        use schema::v211::TariffDimensionType;

        let v = match source {
            TariffDimensionType::Energy => Self::Energy,
            TariffDimensionType::Flat => Self::Flat,
            TariffDimensionType::ParkingTime => Self::ParkingTime,
            TariffDimensionType::Time => Self::Time,
        };

        Ok(v.into_infallible_caveat())
    }
}

impl FromSchema<'_, schema::v221::TariffDimensionType> for DimensionType {
    type Warning = Infallible;

    fn from_schema(source: &schema::v221::TariffDimensionType) -> Verdict<Self, Self::Warning> {
        use schema::v221::TariffDimensionType;

        let v = match source {
            TariffDimensionType::Energy => Self::Energy,
            TariffDimensionType::Flat => Self::Flat,
            TariffDimensionType::ParkingTime => Self::ParkingTime,
            TariffDimensionType::Time => Self::Time,
        };

        Ok(v.into_infallible_caveat())
    }
}

impl<'buf> FromSchema<'buf, schema::Number<'buf>> for u64 {
    type Warning = Warning;

    fn from_schema(source: &schema::Number<'buf>) -> Verdict<Self, Self::Warning> {
        let warnings = warning::Set::new();

        // The schema proved a valid JSON number literal; the string-encoded form carries an
        // unchecked string. Either way `parse::<u64>` is the final gate - it rejects a
        // fractional, negative, or out-of-range value.
        let (elem, digits) = match source {
            schema::Number::Number { elem, digits } => (elem, *digits),
            schema::Number::StringEncoded { elem, value } => (elem, value.as_unescaped_str()),
        };

        match digits.parse::<u64>() {
            Ok(n) => Ok(n.into_caveat(warnings)),
            Err(err) => warnings.bail(elem, Warning::field_invalid_value(digits, err.to_string())),
        }
    }
}