1
use std::{marker::PhantomData, sync::Arc};
2

            
3
use bonsaidb_core::{custom_api::CustomApi, networking::CURRENT_PROTOCOL_VERSION};
4
#[cfg(not(target_arch = "wasm32"))]
5
use fabruic::Certificate;
6
use url::Url;
7

            
8
use crate::{client::CustomApiCallback, Client, Error};
9

            
10
/// Builds a new [`Client`] with custom settings.
11
#[must_use]
12
pub struct Builder<A: CustomApi = ()> {
13
    url: Url,
14
    protocol_version: &'static str,
15
    custom_api_callback: Option<Arc<dyn CustomApiCallback<A>>>,
16
    #[cfg(not(target_arch = "wasm32"))]
17
    certificate: Option<fabruic::Certificate>,
18
    _api: PhantomData<A>,
19
}
20

            
21
impl Builder<()> {
22
    /// Creates a new builder for a client connecting to `url`.
23
1827
    pub(crate) fn new(url: Url) -> Self {
24
1827
        Self {
25
1827
            url,
26
1827
            protocol_version: CURRENT_PROTOCOL_VERSION,
27
1827
            custom_api_callback: None,
28
1827
            #[cfg(not(target_arch = "wasm32"))]
29
1827
            certificate: None,
30
1827
            _api: PhantomData::default(),
31
1827
        }
32
1827
    }
33

            
34
    /// Enables using a [`CustomApi`] with this client. If you want to receive
35
    /// out-of-band API requests, set a callback using
36
    /// `with_custom_api_callback` instead.
37
5
    pub fn with_custom_api<A: CustomApi>(self) -> Builder<A> {
38
5
        Builder {
39
5
            url: self.url,
40
5
            protocol_version: self.protocol_version,
41
5
            custom_api_callback: None,
42
5
            #[cfg(not(target_arch = "wasm32"))]
43
5
            certificate: self.certificate,
44
5
            _api: PhantomData::default(),
45
5
        }
46
5
    }
47

            
48
    /// Enables using a [`CustomApi`] with this client. `callback` will be
49
    /// invoked when custom API responses are received from the server.
50
    pub fn with_custom_api_callback<A: CustomApi, C: CustomApiCallback<A>>(
51
        self,
52
        callback: C,
53
    ) -> Builder<A> {
54
        Builder {
55
            url: self.url,
56
            protocol_version: self.protocol_version,
57
            custom_api_callback: Some(Arc::new(callback)),
58
            #[cfg(not(target_arch = "wasm32"))]
59
            certificate: self.certificate,
60
            _api: PhantomData::default(),
61
        }
62
    }
63
}
64

            
65
impl<A: CustomApi> Builder<A> {
66
    /// Connects to a server using a pinned `certificate`. Only supported with BonsaiDb protocol-based connections.
67
    #[cfg(not(target_arch = "wasm32"))]
68
63
    pub fn with_certificate(mut self, certificate: Certificate) -> Self {
69
63
        self.certificate = Some(certificate);
70
63
        self
71
63
    }
72

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

            
80
    /// Finishes building the client.
81
87
    pub async fn finish(self) -> Result<Client<A>, Error<A::Error>> {
82
87
        Client::<A>::new_from_parts(
83
87
            self.url,
84
87
            self.protocol_version,
85
87
            self.custom_api_callback,
86
87
            #[cfg(not(target_arch = "wasm32"))]
87
87
            self.certificate,
88
87
        )
89
        .await
90
87
    }
91
}