openmeteo-rs 1.0.0

Rust client for the Open-Meteo weather API.
Documentation
use std::borrow::Cow;

use crate::query::AsApiStr;

/// Model selector for climate projection requests.
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
#[non_exhaustive]
pub enum ClimateModel {
    /// CMCC CM2 VHR4 high-resolution climate model.
    CmccCm2Vhr4,
    /// EC-Earth3P HR high-resolution climate model.
    EcEarth3PHr,
    /// FGOALS f3 H high-resolution climate model.
    FgoalsF3H,
    /// HiRAM SIT HR high-resolution climate model.
    HiramSitHr,
    /// MPI ESM1.2 XR high-resolution climate model.
    MpiEsm12Xr,
    /// MRI AGCM3.2 S high-resolution climate model.
    MriAgcm32S,
    /// NICAM16 8S high-resolution climate model.
    Nicam168S,
    /// Exact Open-Meteo climate model token not yet represented by this enum.
    ///
    /// The token is passed through unchanged and is not validated by the crate.
    Other(Cow<'static, str>),
}

impl ClimateModel {
    /// Creates an exact Open-Meteo climate model token not yet represented by this enum.
    ///
    /// The token is passed through unchanged and is not validated by the crate.
    pub fn other(token: impl Into<Cow<'static, str>>) -> Self {
        Self::Other(token.into())
    }
}

impl AsApiStr for ClimateModel {
    fn as_api_str(&self) -> Cow<'static, str> {
        match self {
            Self::CmccCm2Vhr4 => Cow::Borrowed("CMCC_CM2_VHR4"),
            Self::EcEarth3PHr => Cow::Borrowed("EC_Earth3P_HR"),
            Self::FgoalsF3H => Cow::Borrowed("FGOALS_f3_H"),
            Self::HiramSitHr => Cow::Borrowed("HiRAM_SIT_HR"),
            Self::MpiEsm12Xr => Cow::Borrowed("MPI_ESM1_2_XR"),
            Self::MriAgcm32S => Cow::Borrowed("MRI_AGCM3_2_S"),
            Self::Nicam168S => Cow::Borrowed("NICAM16_8S"),
            Self::Other(token) => token.clone(),
        }
    }
}

/// Daily variables for climate projection requests.
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
#[non_exhaustive]
pub enum ClimateDailyVar {
    /// Maximum 2 m temperature.
    Temperature2mMax,
    /// Minimum 2 m temperature.
    Temperature2mMin,
    /// Mean 2 m temperature.
    Temperature2mMean,
    /// Mean cloud cover.
    CloudCoverMean,
    /// Maximum 2 m relative humidity.
    RelativeHumidity2mMax,
    /// Minimum 2 m relative humidity.
    RelativeHumidity2mMin,
    /// Mean 2 m relative humidity.
    RelativeHumidity2mMean,
    /// Mean soil moisture fraction in the 0-10 cm layer.
    SoilMoisture0To10cmMean,
    /// Daily precipitation sum.
    PrecipitationSum,
    /// Daily rain sum.
    RainSum,
    /// Daily snowfall sum.
    SnowfallSum,
    /// Mean 10 m wind speed.
    WindSpeed10mMean,
    /// Maximum 10 m wind speed.
    WindSpeed10mMax,
    /// Mean sea-level pressure.
    PressureMslMean,
    /// Daily shortwave radiation sum.
    ShortwaveRadiationSum,
    /// Exact Open-Meteo climate daily variable token not yet represented by this enum.
    ///
    /// The token is passed through unchanged and is not validated by the crate.
    Other(Cow<'static, str>),
}

impl ClimateDailyVar {
    /// Creates an exact Open-Meteo climate daily variable token not yet represented by this enum.
    ///
    /// The token is passed through unchanged and is not validated by the crate.
    pub fn other(token: impl Into<Cow<'static, str>>) -> Self {
        Self::Other(token.into())
    }
}

impl AsApiStr for ClimateDailyVar {
    fn as_api_str(&self) -> Cow<'static, str> {
        match self {
            Self::Temperature2mMax => Cow::Borrowed("temperature_2m_max"),
            Self::Temperature2mMin => Cow::Borrowed("temperature_2m_min"),
            Self::Temperature2mMean => Cow::Borrowed("temperature_2m_mean"),
            Self::CloudCoverMean => Cow::Borrowed("cloud_cover_mean"),
            Self::RelativeHumidity2mMax => Cow::Borrowed("relative_humidity_2m_max"),
            Self::RelativeHumidity2mMin => Cow::Borrowed("relative_humidity_2m_min"),
            Self::RelativeHumidity2mMean => Cow::Borrowed("relative_humidity_2m_mean"),
            Self::SoilMoisture0To10cmMean => Cow::Borrowed("soil_moisture_0_to_10cm_mean"),
            Self::PrecipitationSum => Cow::Borrowed("precipitation_sum"),
            Self::RainSum => Cow::Borrowed("rain_sum"),
            Self::SnowfallSum => Cow::Borrowed("snowfall_sum"),
            Self::WindSpeed10mMean => Cow::Borrowed("wind_speed_10m_mean"),
            Self::WindSpeed10mMax => Cow::Borrowed("wind_speed_10m_max"),
            Self::PressureMslMean => Cow::Borrowed("pressure_msl_mean"),
            Self::ShortwaveRadiationSum => Cow::Borrowed("shortwave_radiation_sum"),
            Self::Other(token) => token.clone(),
        }
    }
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn climate_tokens_are_formatted() {
        assert_eq!(ClimateModel::CmccCm2Vhr4.as_api_str(), "CMCC_CM2_VHR4");
        assert_eq!(ClimateModel::EcEarth3PHr.as_api_str(), "EC_Earth3P_HR");
        assert_eq!(ClimateModel::FgoalsF3H.as_api_str(), "FGOALS_f3_H");
        assert_eq!(ClimateModel::HiramSitHr.as_api_str(), "HiRAM_SIT_HR");
        assert_eq!(ClimateModel::MpiEsm12Xr.as_api_str(), "MPI_ESM1_2_XR");
        assert_eq!(ClimateModel::MriAgcm32S.as_api_str(), "MRI_AGCM3_2_S");
        assert_eq!(ClimateModel::Nicam168S.as_api_str(), "NICAM16_8S");
        assert_eq!(
            ClimateModel::other("custom_climate_model").as_api_str(),
            "custom_climate_model"
        );
        assert_eq!(
            ClimateDailyVar::SoilMoisture0To10cmMean.as_api_str(),
            "soil_moisture_0_to_10cm_mean"
        );
        assert_eq!(
            ClimateDailyVar::other("custom_daily_var").as_api_str(),
            "custom_daily_var"
        );
    }
}