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}