openmeteo-rs 1.0.0

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

use crate::query::AsApiStr;

/// Hourly variables for the marine forecast endpoint.
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
#[non_exhaustive]
pub enum MarineHourlyVar {
    /// Significant wave height.
    WaveHeight,
    /// Significant wave direction.
    WaveDirection,
    /// Significant wave period.
    WavePeriod,
    /// Significant wave peak period.
    WavePeakPeriod,
    /// Wind-wave height.
    WindWaveHeight,
    /// Wind-wave direction.
    WindWaveDirection,
    /// Wind-wave period.
    WindWavePeriod,
    /// Wind-wave peak period.
    WindWavePeakPeriod,
    /// Swell-wave height.
    SwellWaveHeight,
    /// Swell-wave direction.
    SwellWaveDirection,
    /// Swell-wave period.
    SwellWavePeriod,
    /// Swell-wave peak period.
    SwellWavePeakPeriod,
    /// Secondary swell-wave height.
    SecondarySwellWaveHeight,
    /// Secondary swell-wave direction.
    SecondarySwellWaveDirection,
    /// Secondary swell-wave period.
    SecondarySwellWavePeriod,
    /// Tertiary swell-wave height.
    TertiarySwellWaveHeight,
    /// Tertiary swell-wave direction.
    TertiarySwellWaveDirection,
    /// Tertiary swell-wave period.
    TertiarySwellWavePeriod,
    /// Sea level height above mean sea level.
    SeaLevelHeightMsl,
    /// Sea surface temperature.
    SeaSurfaceTemperature,
    /// Ocean-current velocity.
    OceanCurrentVelocity,
    /// Ocean-current direction.
    OceanCurrentDirection,
    /// Inverted-barometer contribution to sea level height.
    InvertBarometerHeight,
    /// Exact Open-Meteo marine hourly 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 MarineHourlyVar {
    /// Creates an exact Open-Meteo marine hourly 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 MarineHourlyVar {
    fn as_api_str(&self) -> Cow<'static, str> {
        match self {
            Self::WaveHeight => Cow::Borrowed("wave_height"),
            Self::WaveDirection => Cow::Borrowed("wave_direction"),
            Self::WavePeriod => Cow::Borrowed("wave_period"),
            Self::WavePeakPeriod => Cow::Borrowed("wave_peak_period"),
            Self::WindWaveHeight => Cow::Borrowed("wind_wave_height"),
            Self::WindWaveDirection => Cow::Borrowed("wind_wave_direction"),
            Self::WindWavePeriod => Cow::Borrowed("wind_wave_period"),
            Self::WindWavePeakPeriod => Cow::Borrowed("wind_wave_peak_period"),
            Self::SwellWaveHeight => Cow::Borrowed("swell_wave_height"),
            Self::SwellWaveDirection => Cow::Borrowed("swell_wave_direction"),
            Self::SwellWavePeriod => Cow::Borrowed("swell_wave_period"),
            Self::SwellWavePeakPeriod => Cow::Borrowed("swell_wave_peak_period"),
            Self::SecondarySwellWaveHeight => Cow::Borrowed("secondary_swell_wave_height"),
            Self::SecondarySwellWaveDirection => Cow::Borrowed("secondary_swell_wave_direction"),
            Self::SecondarySwellWavePeriod => Cow::Borrowed("secondary_swell_wave_period"),
            Self::TertiarySwellWaveHeight => Cow::Borrowed("tertiary_swell_wave_height"),
            Self::TertiarySwellWaveDirection => Cow::Borrowed("tertiary_swell_wave_direction"),
            Self::TertiarySwellWavePeriod => Cow::Borrowed("tertiary_swell_wave_period"),
            Self::SeaLevelHeightMsl => Cow::Borrowed("sea_level_height_msl"),
            Self::SeaSurfaceTemperature => Cow::Borrowed("sea_surface_temperature"),
            Self::OceanCurrentVelocity => Cow::Borrowed("ocean_current_velocity"),
            Self::OceanCurrentDirection => Cow::Borrowed("ocean_current_direction"),
            Self::InvertBarometerHeight => Cow::Borrowed("invert_barometer_height"),
            Self::Other(token) => token.clone(),
        }
    }
}

/// Current-condition variables for the marine forecast endpoint.
///
/// This enum intentionally omits [`MarineHourlyVar::InvertBarometerHeight`],
/// which is documented as an hourly marine variable. If Open-Meteo accepts it
/// in `current=` for a specific use case, [`MarineCurrentVar::other`] can pass
/// the exact token through.
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
#[non_exhaustive]
pub enum MarineCurrentVar {
    /// Significant wave height.
    WaveHeight,
    /// Significant wave direction.
    WaveDirection,
    /// Significant wave period.
    WavePeriod,
    /// Significant wave peak period.
    WavePeakPeriod,
    /// Wind-wave height.
    WindWaveHeight,
    /// Wind-wave direction.
    WindWaveDirection,
    /// Wind-wave period.
    WindWavePeriod,
    /// Wind-wave peak period.
    WindWavePeakPeriod,
    /// Swell-wave height.
    SwellWaveHeight,
    /// Swell-wave direction.
    SwellWaveDirection,
    /// Swell-wave period.
    SwellWavePeriod,
    /// Swell-wave peak period.
    SwellWavePeakPeriod,
    /// Secondary swell-wave height.
    SecondarySwellWaveHeight,
    /// Secondary swell-wave direction.
    SecondarySwellWaveDirection,
    /// Secondary swell-wave period.
    SecondarySwellWavePeriod,
    /// Tertiary swell-wave height.
    TertiarySwellWaveHeight,
    /// Tertiary swell-wave direction.
    TertiarySwellWaveDirection,
    /// Tertiary swell-wave period.
    TertiarySwellWavePeriod,
    /// Sea level height above mean sea level.
    SeaLevelHeightMsl,
    /// Sea surface temperature.
    SeaSurfaceTemperature,
    /// Ocean-current velocity.
    OceanCurrentVelocity,
    /// Ocean-current direction.
    OceanCurrentDirection,
    /// Exact Open-Meteo marine current 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 MarineCurrentVar {
    /// Creates an exact Open-Meteo marine current 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 MarineCurrentVar {
    fn as_api_str(&self) -> Cow<'static, str> {
        match self {
            Self::WaveHeight => Cow::Borrowed("wave_height"),
            Self::WaveDirection => Cow::Borrowed("wave_direction"),
            Self::WavePeriod => Cow::Borrowed("wave_period"),
            Self::WavePeakPeriod => Cow::Borrowed("wave_peak_period"),
            Self::WindWaveHeight => Cow::Borrowed("wind_wave_height"),
            Self::WindWaveDirection => Cow::Borrowed("wind_wave_direction"),
            Self::WindWavePeriod => Cow::Borrowed("wind_wave_period"),
            Self::WindWavePeakPeriod => Cow::Borrowed("wind_wave_peak_period"),
            Self::SwellWaveHeight => Cow::Borrowed("swell_wave_height"),
            Self::SwellWaveDirection => Cow::Borrowed("swell_wave_direction"),
            Self::SwellWavePeriod => Cow::Borrowed("swell_wave_period"),
            Self::SwellWavePeakPeriod => Cow::Borrowed("swell_wave_peak_period"),
            Self::SecondarySwellWaveHeight => Cow::Borrowed("secondary_swell_wave_height"),
            Self::SecondarySwellWaveDirection => Cow::Borrowed("secondary_swell_wave_direction"),
            Self::SecondarySwellWavePeriod => Cow::Borrowed("secondary_swell_wave_period"),
            Self::TertiarySwellWaveHeight => Cow::Borrowed("tertiary_swell_wave_height"),
            Self::TertiarySwellWaveDirection => Cow::Borrowed("tertiary_swell_wave_direction"),
            Self::TertiarySwellWavePeriod => Cow::Borrowed("tertiary_swell_wave_period"),
            Self::SeaLevelHeightMsl => Cow::Borrowed("sea_level_height_msl"),
            Self::SeaSurfaceTemperature => Cow::Borrowed("sea_surface_temperature"),
            Self::OceanCurrentVelocity => Cow::Borrowed("ocean_current_velocity"),
            Self::OceanCurrentDirection => Cow::Borrowed("ocean_current_direction"),
            Self::Other(token) => token.clone(),
        }
    }
}

/// 15-minute variables for the marine forecast endpoint.
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
#[non_exhaustive]
pub enum MarineMinutely15Var {
    /// Ocean-current velocity.
    OceanCurrentVelocity,
    /// Ocean-current direction.
    OceanCurrentDirection,
    /// Sea level height above mean sea level.
    SeaLevelHeightMsl,
    /// Exact Open-Meteo marine 15-minute 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 MarineMinutely15Var {
    /// Creates an exact Open-Meteo marine 15-minute 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 MarineMinutely15Var {
    fn as_api_str(&self) -> Cow<'static, str> {
        match self {
            Self::OceanCurrentVelocity => Cow::Borrowed("ocean_current_velocity"),
            Self::OceanCurrentDirection => Cow::Borrowed("ocean_current_direction"),
            Self::SeaLevelHeightMsl => Cow::Borrowed("sea_level_height_msl"),
            Self::Other(token) => token.clone(),
        }
    }
}

/// Daily variables for the marine forecast endpoint.
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
#[non_exhaustive]
pub enum MarineDailyVar {
    /// Maximum significant wave height.
    WaveHeightMax,
    /// Dominant significant wave direction.
    WaveDirectionDominant,
    /// Maximum significant wave period.
    WavePeriodMax,
    /// Maximum wind-wave height.
    WindWaveHeightMax,
    /// Dominant wind-wave direction.
    WindWaveDirectionDominant,
    /// Maximum wind-wave period.
    WindWavePeriodMax,
    /// Maximum wind-wave peak period.
    WindWavePeakPeriodMax,
    /// Maximum swell-wave height.
    SwellWaveHeightMax,
    /// Dominant swell-wave direction.
    SwellWaveDirectionDominant,
    /// Maximum swell-wave period.
    SwellWavePeriodMax,
    /// Maximum swell-wave peak period.
    SwellWavePeakPeriodMax,
    /// Exact Open-Meteo marine 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 MarineDailyVar {
    /// Creates an exact Open-Meteo marine 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 MarineDailyVar {
    fn as_api_str(&self) -> Cow<'static, str> {
        match self {
            Self::WaveHeightMax => Cow::Borrowed("wave_height_max"),
            Self::WaveDirectionDominant => Cow::Borrowed("wave_direction_dominant"),
            Self::WavePeriodMax => Cow::Borrowed("wave_period_max"),
            Self::WindWaveHeightMax => Cow::Borrowed("wind_wave_height_max"),
            Self::WindWaveDirectionDominant => Cow::Borrowed("wind_wave_direction_dominant"),
            Self::WindWavePeriodMax => Cow::Borrowed("wind_wave_period_max"),
            Self::WindWavePeakPeriodMax => Cow::Borrowed("wind_wave_peak_period_max"),
            Self::SwellWaveHeightMax => Cow::Borrowed("swell_wave_height_max"),
            Self::SwellWaveDirectionDominant => Cow::Borrowed("swell_wave_direction_dominant"),
            Self::SwellWavePeriodMax => Cow::Borrowed("swell_wave_period_max"),
            Self::SwellWavePeakPeriodMax => Cow::Borrowed("swell_wave_peak_period_max"),
            Self::Other(token) => token.clone(),
        }
    }
}

/// Model selector for the marine forecast endpoint.
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
#[non_exhaustive]
pub enum MarineModel {
    /// Open-Meteo's automatic best-match model.
    BestMatch,
    /// MeteoFrance wave model.
    MeteoFranceWave,
    /// MeteoFrance ocean-current model.
    MeteoFranceCurrents,
    /// DWD EWAM wave model.
    DwdEwam,
    /// DWD GWAM wave model.
    DwdGwam,
    /// ECMWF WAM model.
    EcmwfWam,
    /// ECMWF WAM 0.25 degree model.
    EcmwfWam025,
    /// NCEP GFS Wave 0.25 degree model.
    GfsWave025,
    /// NCEP GFS Wave 0.16 degree model.
    GfsWave016,
    /// ERA5 ocean model.
    Era5Ocean,
    /// Exact Open-Meteo marine 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 MarineModel {
    /// Creates an exact Open-Meteo marine 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 MarineModel {
    fn as_api_str(&self) -> Cow<'static, str> {
        match self {
            Self::BestMatch => Cow::Borrowed("best_match"),
            Self::MeteoFranceWave => Cow::Borrowed("meteofrance_wave"),
            Self::MeteoFranceCurrents => Cow::Borrowed("meteofrance_currents"),
            Self::DwdEwam => Cow::Borrowed("dwd_ewam"),
            Self::DwdGwam => Cow::Borrowed("dwd_gwam"),
            Self::EcmwfWam => Cow::Borrowed("ecmwf_wam"),
            Self::EcmwfWam025 => Cow::Borrowed("ecmwf_wam025"),
            Self::GfsWave025 => Cow::Borrowed("ncep_gfswave025"),
            Self::GfsWave016 => Cow::Borrowed("ncep_gfswave016"),
            Self::Era5Ocean => Cow::Borrowed("era5_ocean"),
            Self::Other(token) => token.clone(),
        }
    }
}

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

    #[test]
    fn custom_marine_variable_tokens_are_passed_through() {
        assert_eq!(
            MarineHourlyVar::other("new_hourly_metric").as_api_str(),
            "new_hourly_metric"
        );
        assert_eq!(
            MarineCurrentVar::other("new_current_metric").as_api_str(),
            "new_current_metric"
        );
        assert_eq!(
            MarineMinutely15Var::other("new_minutely_metric").as_api_str(),
            "new_minutely_metric"
        );
        assert_eq!(
            MarineDailyVar::other("new_daily_metric").as_api_str(),
            "new_daily_metric"
        );
    }
}