qbit_rs/
builder.rs

1#![allow(private_interfaces, private_bounds)]
2
3use std::{fmt::Debug, sync::Mutex};
4
5use reqwest::Client;
6use tap::Pipe;
7use url::Url;
8
9use crate::{LoginState, Qbit, ext::Cookie, model::Credential};
10
11pub struct QbitBuilder<C = (), R = (), E = ()> {
12    credential: C,
13    client: R,
14    endpoint: E,
15}
16
17trait IntoLoginState {
18    fn into_login_state(self) -> LoginState;
19}
20
21impl IntoLoginState for Cookie {
22    fn into_login_state(self) -> LoginState {
23        LoginState::CookieProvided { cookie: self.0 }
24    }
25}
26
27impl IntoLoginState for Credential {
28    fn into_login_state(self) -> LoginState {
29        LoginState::NotLoggedIn { credential: self }
30    }
31}
32
33impl QbitBuilder {
34    pub fn new() -> Self {
35        QbitBuilder {
36            credential: (),
37            client: (),
38            endpoint: (),
39        }
40    }
41}
42
43impl Default for QbitBuilder {
44    fn default() -> Self {
45        Self::new()
46    }
47}
48
49impl<C, R, E> QbitBuilder<C, R, E> {
50    pub fn client(self, client: Client) -> QbitBuilder<C, Client, E> {
51        QbitBuilder {
52            credential: self.credential,
53            client,
54            endpoint: self.endpoint,
55        }
56    }
57
58    #[allow(private_interfaces)]
59    pub fn cookie(self, cookie: impl Into<String>) -> QbitBuilder<Cookie, R, E> {
60        QbitBuilder {
61            credential: Cookie(cookie.into()),
62            client: self.client,
63            endpoint: self.endpoint,
64        }
65    }
66
67    pub fn credential(self, credential: Credential) -> QbitBuilder<Credential, R, E> {
68        QbitBuilder {
69            credential,
70            client: self.client,
71            endpoint: self.endpoint,
72        }
73    }
74
75    pub fn endpoint<U>(self, endpoint: U) -> QbitBuilder<C, R, U>
76    where
77        U: TryInto<Url>,
78    {
79        QbitBuilder {
80            credential: self.credential,
81            client: self.client,
82            endpoint,
83        }
84    }
85}
86
87impl<C, U> QbitBuilder<C, reqwest::Client, U>
88where
89    C: IntoLoginState,
90    U: TryInto<Url>,
91    U::Error: Debug,
92{
93    pub fn build(self) -> Qbit {
94        let endpoint = self.endpoint.try_into().expect("Invalid endpoint");
95        let state = self.credential.into_login_state().pipe(Mutex::new);
96
97        Qbit {
98            client: self.client,
99            endpoint,
100            state,
101        }
102    }
103}
104
105impl<C, U> QbitBuilder<C, (), U>
106where
107    C: IntoLoginState,
108    U: TryInto<Url>,
109    U::Error: Debug,
110{
111    pub fn build(self) -> Qbit {
112        self.client(reqwest::Client::new()).build()
113    }
114}
115
116#[test]
117fn test_builder() {
118    QbitBuilder::new()
119        .client(reqwest::Client::new())
120        .endpoint("http://localhost:8080")
121        .credential(Credential::new("admin", "adminadmin"))
122        .build();
123
124    QbitBuilder::new()
125        .endpoint("http://localhost:8080")
126        .credential(Credential::new("admin", "adminadmin"))
127        .build();
128
129    QbitBuilder::new()
130        .client(reqwest::Client::new())
131        .endpoint("http://localhost:8080")
132        .cookie("SID=1234567890")
133        .build();
134
135    QbitBuilder::new()
136        .endpoint("http://localhost:8080")
137        .cookie("SID=1234567890")
138        .build();
139}