ruma_client/client/
builder.rs

1use std::sync::{Arc, Mutex};
2
3use ruma::api::{
4    client::discovery::get_supported_versions, MatrixVersion, SendAccessToken, SupportedVersions,
5};
6
7use super::{Client, ClientData};
8use crate::{DefaultConstructibleHttpClient, Error, HttpClient, HttpClientExt};
9
10/// A [`Client`] builder.
11///
12/// This type can be used to construct a `Client` through a few method calls.
13pub struct ClientBuilder {
14    homeserver_url: Option<String>,
15    access_token: Option<String>,
16    supported_matrix_versions: Option<SupportedVersions>,
17}
18
19impl ClientBuilder {
20    pub(super) fn new() -> Self {
21        Self { homeserver_url: None, access_token: None, supported_matrix_versions: None }
22    }
23
24    /// Set the homeserver URL.
25    ///
26    /// The homeserver URL must be set before calling [`build()`][Self::build] or
27    /// [`http_client()`][Self::http_client].
28    pub fn homeserver_url(self, url: String) -> Self {
29        Self { homeserver_url: Some(url), ..self }
30    }
31
32    /// Set the access token.
33    pub fn access_token(self, access_token: Option<String>) -> Self {
34        Self { access_token, ..self }
35    }
36
37    /// Set the supported Matrix versions.
38    ///
39    /// This method generally *shouldn't* be called. The [`build()`][Self::build] or
40    /// [`http_client()`][Self::http_client] method will take care of doing a
41    /// [`get_supported_versions`] request to find out about the supported versions.
42    pub fn supported_matrix_versions(self, versions: SupportedVersions) -> Self {
43        Self { supported_matrix_versions: Some(versions), ..self }
44    }
45
46    /// Finish building the [`Client`].
47    ///
48    /// Uses [`DefaultConstructibleHttpClient::default()`] to create an HTTP client instance.
49    /// Unless the supported Matrix versions were manually set via
50    /// [`supported_matrix_versions`][Self::supported_matrix_versions], this will do a
51    /// [`get_supported_versions`] request to find out about the supported versions.
52    pub async fn build<C>(self) -> Result<Client<C>, Error<C::Error, ruma::api::client::Error>>
53    where
54        C: DefaultConstructibleHttpClient,
55    {
56        self.http_client(C::default()).await
57    }
58
59    /// Set the HTTP client to finish building the [`Client`].
60    ///
61    /// Unless the supported Matrix versions were manually set via
62    /// [`supported_matrix_versions`][Self::supported_matrix_versions], this will do a
63    /// [`get_supported_versions`] request to find out about the supported versions.
64    pub async fn http_client<C>(
65        self,
66        http_client: C,
67    ) -> Result<Client<C>, Error<C::Error, ruma::api::client::Error>>
68    where
69        C: HttpClient,
70    {
71        let homeserver_url = self
72            .homeserver_url
73            .expect("homeserver URL has to be set prior to calling .build() or .http_client()");
74
75        let supported_matrix_versions = match self.supported_matrix_versions {
76            Some(versions) => versions,
77            None => http_client
78                .send_matrix_request(
79                    &homeserver_url,
80                    SendAccessToken::None,
81                    &SupportedVersions {
82                        versions: [MatrixVersion::V1_0].into(),
83                        features: Default::default(),
84                    },
85                    get_supported_versions::Request::new(),
86                )
87                .await?
88                .as_supported_versions(),
89        };
90
91        Ok(Client(Arc::new(ClientData {
92            homeserver_url,
93            http_client,
94            access_token: Mutex::new(self.access_token),
95            supported_matrix_versions,
96        })))
97    }
98}