1
use std::{collections::HashMap, sync::Arc};
2

            
3
use bonsaidb_core::{api, networking::CURRENT_PROTOCOL_VERSION, schema::ApiName};
4
#[cfg(not(target_arch = "wasm32"))]
5
use fabruic::Certificate;
6
#[cfg(not(target_arch = "wasm32"))]
7
use tokio::runtime::Handle;
8
use url::Url;
9

            
10
use crate::{
11
    client::{AnyApiCallback, ApiCallback},
12
    Client, Error,
13
};
14

            
15
/// Builds a new [`Client`] with custom settings.
16
#[must_use]
17
pub struct Builder {
18
    url: Url,
19
    protocol_version: &'static str,
20
    custom_apis: HashMap<ApiName, Option<Arc<dyn AnyApiCallback>>>,
21
    #[cfg(not(target_arch = "wasm32"))]
22
    certificate: Option<fabruic::Certificate>,
23
    #[cfg(not(target_arch = "wasm32"))]
24
    tokio: Option<Handle>,
25
}
26

            
27
impl Builder {
28
    /// Creates a new builder for a client connecting to `url`.
29
1634
    pub(crate) fn new(url: Url) -> Self {
30
1634
        Self {
31
1634
            url,
32
1634
            protocol_version: CURRENT_PROTOCOL_VERSION,
33
1634
            custom_apis: HashMap::new(),
34
1634
            #[cfg(not(target_arch = "wasm32"))]
35
1634
            certificate: None,
36
1634
            #[cfg(not(target_arch = "wasm32"))]
37
1634
            tokio: Handle::try_current().ok(),
38
1634
        }
39
1634
    }
40

            
41
    /// Specifies the tokio runtime this client should use for its async tasks.
42
    /// If not specified, `Client` will try to acquire a handle via
43
    /// `tokio::runtime::Handle::try_current()`.
44
    #[cfg(not(target_arch = "wasm32"))]
45
    #[allow(clippy::missing_const_for_fn)]
46
    pub fn with_runtime(mut self, handle: Handle) -> Self {
47
        self.tokio = Some(handle);
48
        self
49
    }
50

            
51
    /// Enables using a [`Api`](api::Api) with this client. If you want to
52
    /// receive out-of-band API requests, set a callback using
53
    /// `with_custom_api_callback` instead.
54
1
    pub fn with_api<Api: api::Api>(mut self) -> Self {
55
1
        self.custom_apis.insert(Api::name(), None);
56
1
        self
57
1
    }
58

            
59
    /// Enables using a [`Api`](api::Api) with this client. `callback` will be
60
    /// invoked when custom API responses are received from the server.
61
    pub fn with_api_callback<Api: api::Api>(mut self, callback: ApiCallback<Api>) -> Self {
62
        self.custom_apis
63
            .insert(Api::name(), Some(Arc::new(callback)));
64
        self
65
    }
66

            
67
    /// Connects to a server using a pinned `certificate`. Only supported with BonsaiDb protocol-based connections.
68
    #[cfg(not(target_arch = "wasm32"))]
69
    #[allow(clippy::missing_const_for_fn)]
70
1197
    pub fn with_certificate(mut self, certificate: Certificate) -> Self {
71
1197
        self.certificate = Some(certificate);
72
1197
        self
73
1197
    }
74

            
75
    /// Overrides the protocol version. Only for testing purposes.
76
    #[cfg(feature = "test-util")]
77
    #[allow(clippy::missing_const_for_fn)]
78
38
    pub fn with_protocol_version(mut self, version: &'static str) -> Self {
79
38
        self.protocol_version = version;
80
38
        self
81
38
    }
82

            
83
    /// Finishes building the client.
84
1634
    pub fn finish(self) -> Result<Client, Error> {
85
1634
        Client::new_from_parts(
86
1634
            self.url,
87
1634
            self.protocol_version,
88
1634
            self.custom_apis,
89
1634
            #[cfg(not(target_arch = "wasm32"))]
90
1634
            self.certificate,
91
1634
            #[cfg(not(target_arch = "wasm32"))]
92
1634
            self.tokio,
93
1634
        )
94
1634
    }
95
}