ruma-client 0.17.0

A Matrix client library.
use std::sync::{Arc, Mutex};

use ruma::api::{
    SupportedVersions, auth_scheme::SendAccessToken, client::discovery::get_supported_versions,
};

use super::{Client, ClientData, TokenMode};
use crate::{DefaultConstructibleHttpClient, Error, HttpClient, HttpClientExt};

/// A [`Client`] builder.
///
/// This type can be used to construct a `Client` through a few method calls.
pub struct ClientBuilder {
    homeserver_url: Option<String>,
    access_token: Option<String>,
    token_mode: TokenMode,
    supported_matrix_versions: Option<SupportedVersions>,
}

impl ClientBuilder {
    pub(super) fn new() -> Self {
        Self {
            homeserver_url: None,
            access_token: None,
            token_mode: TokenMode::default(),
            supported_matrix_versions: None,
        }
    }

    /// Set the homeserver URL.
    ///
    /// The homeserver URL must be set before calling [`build()`][Self::build] or
    /// [`http_client()`][Self::http_client].
    pub fn homeserver_url(self, url: String) -> Self {
        Self { homeserver_url: Some(url), ..self }
    }

    /// Set the access token.
    pub fn access_token(self, access_token: Option<String>) -> Self {
        Self { access_token, ..self }
    }

    /// Set how access tokens should be handled when making requests.
    pub fn token_mode(self, token_mode: TokenMode) -> Self {
        Self { token_mode, ..self }
    }

    /// Set the supported Matrix versions.
    ///
    /// This method generally *shouldn't* be called. The [`build()`][Self::build] or
    /// [`http_client()`][Self::http_client] method will take care of doing a
    /// [`get_supported_versions`] request to find out about the supported versions.
    pub fn supported_matrix_versions(self, versions: SupportedVersions) -> Self {
        Self { supported_matrix_versions: Some(versions), ..self }
    }

    /// Finish building the [`Client`].
    ///
    /// Uses [`DefaultConstructibleHttpClient::default()`] to create an HTTP client instance.
    /// Unless the supported Matrix versions were manually set via
    /// [`supported_matrix_versions`][Self::supported_matrix_versions], this will do a
    /// [`get_supported_versions`] request to find out about the supported versions.
    pub async fn build<C>(self) -> Result<Client<C>, Error<C::Error, ruma::api::client::Error>>
    where
        C: DefaultConstructibleHttpClient,
    {
        self.http_client(C::default()).await
    }

    /// Set the HTTP client to finish building the [`Client`].
    ///
    /// Unless the supported Matrix versions were manually set via
    /// [`supported_matrix_versions`][Self::supported_matrix_versions], this will do a
    /// [`get_supported_versions`] request to find out about the supported versions.
    pub async fn http_client<C>(
        self,
        http_client: C,
    ) -> Result<Client<C>, Error<C::Error, ruma::api::client::Error>>
    where
        C: HttpClient,
    {
        let homeserver_url = self
            .homeserver_url
            .expect("homeserver URL has to be set prior to calling .build() or .http_client()");

        let supported_matrix_versions = match self.supported_matrix_versions {
            Some(versions) => versions,
            None => http_client
                .send_matrix_request(
                    &homeserver_url,
                    SendAccessToken::None,
                    (),
                    get_supported_versions::Request::new(),
                )
                .await?
                .as_supported_versions(),
        };

        Ok(Client(Arc::new(ClientData {
            homeserver_url,
            http_client,
            access_token: Mutex::new(self.access_token),
            token_mode: self.token_mode,
            supported_matrix_versions,
        })))
    }
}