openf1 0.1.0

Unofficial Rust client for the OpenF1 API
Documentation
use std::collections::HashMap;

use crate::keys::OpenF1Key;
use crate::query::{QueryParams, QueryValue};

fn insert_optional(params: &mut QueryParams, key: &str, value: Option<QueryValue>) {
    if let Some(value) = value {
        params.insert(key.to_string(), value);
    }
}

macro_rules! list_params {
    ($name:ident { $($field:ident : $ty:ty),* $(,)? }) => {
        #[derive(Debug, Default, Clone)]
        pub struct $name {
            $(pub $field: Option<$ty>,)*
        }

        impl From<$name> for QueryParams {
            fn from(value: $name) -> Self {
                let mut params = QueryParams::new();
                $(insert_optional(&mut params, stringify!($field), value.$field.map(Into::into));)*
                params
            }
        }
    };
}

list_params!(CarDataListParams {
    driver_number: i64,
    session_key: OpenF1Key,
    speed: QueryFilter,
});

list_params!(ChampionshipDriversListParams {
    session_key: OpenF1Key,
    driver_number: i64,
});

list_params!(ChampionshipTeamsListParams {
    session_key: OpenF1Key,
    team_name: String,
});

list_params!(DriversListParams {
    session_key: OpenF1Key,
    driver_number: i64,
});

list_params!(IntervalsListParams {
    session_key: OpenF1Key,
    interval: QueryFilter,
});

list_params!(LapsListParams {
    session_key: OpenF1Key,
    driver_number: i64,
    lap_number: QueryFilter,
});

list_params!(LocationListParams {
    session_key: OpenF1Key,
    driver_number: i64,
    date: QueryFilter,
});

list_params!(MeetingsListParams {
    year: i64,
    country_name: String,
});

list_params!(OvertakesListParams {
    session_key: OpenF1Key,
});

list_params!(PitListParams {
    session_key: OpenF1Key,
});

list_params!(PositionListParams {
    session_key: OpenF1Key,
    driver_number: i64,
});

list_params!(RaceControlListParams {
    session_key: OpenF1Key,
});

list_params!(SessionsListParams {
    country_name: String,
    session_name: String,
    year: i64,
});

list_params!(SessionResultListParams {
    session_key: OpenF1Key,
    position: QueryFilter,
});

list_params!(StartingGridListParams {
    session_key: OpenF1Key,
});

list_params!(StintsListParams {
    session_key: OpenF1Key,
    driver_number: i64,
});

list_params!(TeamRadioListParams {
    session_key: OpenF1Key,
    driver_number: i64,
});

list_params!(WeatherListParams {
    session_key: OpenF1Key,
});

/// Comparison filter for OpenF1 query operators (`eq`, `gt`, `gte`, `lt`, `lte`).
#[derive(Debug, Clone, Default)]
pub struct QueryFilter {
    pub eq: Option<QueryValue>,
    pub gt: Option<QueryValue>,
    pub gte: Option<QueryValue>,
    pub lt: Option<QueryValue>,
    pub lte: Option<QueryValue>,
}

impl From<QueryFilter> for QueryValue {
    fn from(value: QueryFilter) -> Self {
        let mut filter = HashMap::new();
        if let Some(value) = value.eq {
            filter.insert("eq".to_string(), value);
        }
        if let Some(value) = value.gt {
            filter.insert("gt".to_string(), value);
        }
        if let Some(value) = value.gte {
            filter.insert("gte".to_string(), value);
        }
        if let Some(value) = value.lt {
            filter.insert("lt".to_string(), value);
        }
        if let Some(value) = value.lte {
            filter.insert("lte".to_string(), value);
        }
        QueryValue::Filter(filter)
    }
}

impl From<i64> for QueryValue {
    fn from(value: i64) -> Self {
        QueryValue::Number(value)
    }
}

impl From<i32> for QueryValue {
    fn from(value: i32) -> Self {
        QueryValue::Number(i64::from(value))
    }
}

impl From<f64> for QueryValue {
    fn from(value: f64) -> Self {
        QueryValue::Float(value)
    }
}

impl From<String> for QueryValue {
    fn from(value: String) -> Self {
        QueryValue::Scalar(value)
    }
}

impl From<&str> for QueryValue {
    fn from(value: &str) -> Self {
        QueryValue::Scalar(value.to_string())
    }
}