pub mod create_addressbook;
pub mod find_address_book_home_set;
pub mod find_addressbooks;
pub mod get_addressbook_resources;
pub use create_addressbook::{CreateAddressBook, CreateAddressBookResponse};
pub use find_address_book_home_set::{FindAddressBookHomeSet, FindAddressBookHomeSetResponse};
pub use find_addressbooks::{FindAddressBooks, FindAddressBooksResponse};
pub use get_addressbook_resources::{GetAddressBookResources, GetAddressBookResourcesResponse};
use std::ops::Deref;
use http::Response;
use hyper::{Uri, body::Incoming};
use tower_service::Service;
use crate::{
common::ServiceForUrlError,
dav::WebDavClient,
sd::{BootstrapError, DiscoverableService, FindContextUrlResult, find_context_url},
};
#[derive(Debug)]
pub struct CardDavClient<C>
where
C: Service<http::Request<String>, Response = Response<Incoming>> + Sync + Send + 'static,
{
pub webdav_client: WebDavClient<C>,
}
impl<C> Deref for CardDavClient<C>
where
C: Service<http::Request<String>, Response = Response<Incoming>> + Sync + Send,
{
type Target = WebDavClient<C>;
fn deref(&self) -> &Self::Target {
&self.webdav_client
}
}
impl<C> CardDavClient<C>
where
C: Service<http::Request<String>, Response = Response<Incoming>> + Sync + Send,
<C as Service<http::Request<String>>>::Error: std::error::Error + Send + Sync,
{
pub fn new(webdav_client: WebDavClient<C>) -> CardDavClient<C> {
CardDavClient { webdav_client }
}
pub async fn bootstrap_via_service_discovery(
mut webdav_client: WebDavClient<C>,
) -> Result<CardDavClient<C>, BootstrapError> {
let service = service_for_url(&webdav_client.base_url)?;
match find_context_url(&webdav_client, service).await {
FindContextUrlResult::BaseUrl => {}
FindContextUrlResult::Found(url) => webdav_client.base_url = url,
FindContextUrlResult::NoneFound => return Err(BootstrapError::NoUsableUrl),
FindContextUrlResult::Error(err) => return Err(err.into()),
}
Ok(CardDavClient { webdav_client })
}
}
impl<C> Clone for CardDavClient<C>
where
C: Service<http::Request<String>, Response = Response<Incoming>> + Sync + Send + Clone,
{
fn clone(&self) -> CardDavClient<C> {
CardDavClient {
webdav_client: self.webdav_client.clone(),
}
}
}
pub fn service_for_url(url: &Uri) -> Result<DiscoverableService, ServiceForUrlError> {
match url
.scheme()
.ok_or(ServiceForUrlError::MissingScheme)?
.as_ref()
{
"https" | "carddavs" => Ok(DiscoverableService::CardDavs),
"http" | "carddav" => Ok(DiscoverableService::CardDav),
_ => Err(ServiceForUrlError::UnknownScheme),
}
}