freedom-api 3.2.0

Freedom API for Rustaceans
Documentation
use serde::Serialize;

use crate::{api::Api, error::Error};

use super::{Post, UrlResult};

#[derive(Debug, Clone, PartialEq, Serialize)]
#[serde(rename_all = "camelCase")]
struct SatelliteConfigurationInner {
    name: String,
    doppler: Option<bool>,
    notes: Option<String>,
    band_details: Vec<String>,
}

#[derive(Debug, Clone, PartialEq)]
pub struct SatelliteConfiguration {
    name: String,
    doppler: Option<bool>,
    notes: Option<String>,
    band_details: Vec<UrlResult>,
}

pub struct NoName;

pub struct SatelliteConfigurationBuilder<'a, C, S> {
    pub(crate) client: &'a C,
    state: S,
}

pub(crate) fn new<C>(client: &C) -> SatelliteConfigurationBuilder<'_, C, NoName> {
    SatelliteConfigurationBuilder {
        client,
        state: NoName,
    }
}

impl<'a, C> SatelliteConfigurationBuilder<'a, C, NoName> {
    pub fn name(self, name: impl Into<String>) -> SatelliteConfigurationBuilder<'a, C, NoBand> {
        SatelliteConfigurationBuilder {
            client: self.client,
            state: NoBand { name: name.into() },
        }
    }
}

pub struct NoBand {
    name: String,
}

impl<'a, C> SatelliteConfigurationBuilder<'a, C, NoBand> {
    pub fn band_urls(
        self,
        urls: impl IntoIterator<Item = String>,
    ) -> SatelliteConfigurationBuilder<'a, C, SatelliteConfiguration> {
        let band_details: Vec<_> = urls.into_iter().map(UrlResult::Checked).collect();
        self.band_results(band_details)
    }

    fn band_results(
        self,
        ids: impl IntoIterator<Item = UrlResult>,
    ) -> SatelliteConfigurationBuilder<'a, C, SatelliteConfiguration> {
        let state = SatelliteConfiguration {
            name: self.state.name,
            doppler: None,
            notes: None,
            band_details: ids.into_iter().collect(),
        };

        SatelliteConfigurationBuilder {
            client: self.client,
            state,
        }
    }
}

impl<'a, C> SatelliteConfigurationBuilder<'a, C, NoBand>
where
    C: Api,
{
    pub fn band_ids(
        self,
        ids: impl IntoIterator<Item = i32>,
    ) -> SatelliteConfigurationBuilder<'a, C, SatelliteConfiguration> {
        let client = self.client;
        let results = ids
            .into_iter()
            .map(|id| UrlResult::Unchecked(client.path_to_url(format!("satellite_bands/{}", id))))
            .collect::<Vec<_>>();
        self.band_results(results)
    }
}

impl<C> SatelliteConfigurationBuilder<'_, C, SatelliteConfiguration> {
    pub fn doppler(mut self, doppler: bool) -> Self {
        self.state.doppler = Some(doppler);
        self
    }

    pub fn notes(mut self, notes: impl Into<String>) -> Self {
        self.state.notes = Some(notes.into());
        self
    }
}

impl<C> Post for SatelliteConfigurationBuilder<'_, C, SatelliteConfiguration>
where
    C: Api,
{
    type Response = freedom_models::satellite_configuration::SatelliteConfiguration;

    async fn send(self) -> Result<Self::Response, Error> {
        let client = self.client;

        let mut band_details = Vec::new();
        for result in self.state.band_details {
            let band = result.try_convert()?;
            band_details.push(band);
        }

        let dto = SatelliteConfigurationInner {
            name: self.state.name,
            doppler: self.state.doppler,
            notes: self.state.notes,
            band_details,
        };

        let url = client.path_to_url("satellite_configurations")?;
        client.post_json_map(url, dto).await
    }
}