ocpi 0.3.5

Unofficial, in progress, OCPI implementation
Documentation
use crate::{types, Result};
use async_trait::async_trait;
use std::collections::HashMap;

#[async_trait]
pub trait VersionsStore {
    fn base_url(&self) -> types::Url;

    fn url_path(&self, path: &[impl AsRef<str>]) -> types::Url {
        let mut url = self.base_url();

        url.path_segments_mut()
            // Unwrap bc check in new
            .unwrap()
            .extend(path);
        url
    }

    async fn versions_get_all(&self) -> Result<Vec<types::Version>>;
    async fn versions_get_details(
        &self,
        version_number: types::VersionNumber,
    ) -> Result<Option<types::VersionDetails>>;
}

pub struct SimpleVersionsStore {
    pub base_url: types::Url,
    pub endpoints: HashMap<types::VersionNumber, Vec<types::Endpoint>>,
}

impl SimpleVersionsStore {
    pub fn new(base_url: types::Url) -> Self {
        if base_url.cannot_be_a_base() {
            panic!("Invalid base Url `{}`", base_url);
        }

        Self {
            base_url,
            endpoints: HashMap::new(),
        }
    }
}

#[async_trait]
impl VersionsStore for SimpleVersionsStore {
    fn base_url(&self) -> types::Url {
        self.base_url.clone()
    }

    async fn versions_get_all(&self) -> Result<Vec<types::Version>> {
        Ok(self
            .endpoints
            .keys()
            .map(|&version| types::Version {
                version,
                url: self.url_path(&["versions", &version.to_string()]),
            })
            .collect())
    }
    async fn versions_get_details(
        &self,
        version_number: types::VersionNumber,
    ) -> Result<Option<types::VersionDetails>> {
        Ok(self
            .endpoints
            .get(&version_number)
            .map(|endpoints| types::VersionDetails {
                version: version_number,
                endpoints: endpoints.clone(),
            }))
    }
}

#[cfg(test)]
pub fn test(base_url: types::Url) -> SimpleVersionsStore {
    let mut store = SimpleVersionsStore::new(base_url);

    store.endpoints.insert(
        types::VersionNumber::V2_2,
        vec![
            types::Endpoint {
                identifier: types::ModuleId::Credentials,
                role: types::InterfaceRole::Receiver,
                url: store.url_path(&["2.2", "credentials"]),
            },
            types::Endpoint {
                identifier: types::ModuleId::Commands,
                role: types::InterfaceRole::Receiver,
                url: store.url_path(&["2.2", "commands"]),
            },
            types::Endpoint {
                identifier: types::ModuleId::Sessions,
                role: types::InterfaceRole::Sender,
                url: store.url_path(&["2.2", "sessions"]),
            },
        ],
    );

    store
}