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()
.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
}