pcloud/
builder.rs

1use std::borrow::Cow;
2
3/// Errors that may occur during client configuration and building.
4#[derive(Debug, thiserror::Error)]
5pub enum Error {
6    /// Returned when the underlying HTTP client could not be built.
7    #[error("unable to build reqwest client")]
8    Reqwest(#[from] reqwest::Error),
9}
10
11/// Builder for constructing a [`Client`](crate::Client) with custom configuration.
12///
13/// This allows specifying the API region, base URL, credentials, and optionally
14/// customizing the inner `reqwest::ClientBuilder`.
15#[derive(Debug)]
16pub struct ClientBuilder {
17    base_url: Cow<'static, str>,
18    client_builder: Option<reqwest::ClientBuilder>,
19    credentials: crate::Credentials,
20}
21
22impl Default for ClientBuilder {
23    /// Creates a new `ClientBuilder` with default settings:
24    ///
25    /// - Base URL is set to the EU region.
26    /// - No credentials are set.
27    /// - No custom `reqwest::ClientBuilder` is used.
28    fn default() -> Self {
29        Self {
30            base_url: Cow::Borrowed(crate::EU_REGION),
31            client_builder: None,
32            credentials: crate::Credentials::Anonymous,
33        }
34    }
35}
36
37impl ClientBuilder {
38    /// Creates a builder pre-configured using environment variables.
39    ///
40    /// - Uses `PCLOUD_REGION` or `PCLOUD_BASE_URL` for the endpoint.
41    /// - Uses `PCLOUD_ACCESS_TOKEN` or `PCLOUD_USERNAME`/`PCLOUD_PASSWORD` for credentials.
42    ///
43    /// Falls back to the EU region if none is specified.
44    pub fn from_env() -> Self {
45        let base_url = crate::Region::from_env()
46            .map(|region| Cow::Borrowed(region.base_url()))
47            .or_else(|| std::env::var("PCLOUD_BASE_URL").ok().map(Cow::Owned))
48            .unwrap_or(Cow::Borrowed(crate::EU_REGION));
49        let credentials = crate::Credentials::from_env();
50
51        Self {
52            base_url,
53            client_builder: None,
54            credentials,
55        }
56    }
57}
58
59impl ClientBuilder {
60    /// Sets the API region.
61    pub fn set_region(&mut self, region: crate::Region) {
62        self.base_url = region.base_url().into();
63    }
64
65    /// Sets the API region and returns the modified builder.
66    pub fn with_region(mut self, region: crate::Region) -> Self {
67        self.set_region(region);
68        self
69    }
70
71    /// Sets a custom base URL.
72    pub fn set_base_url(&mut self, base_url: impl Into<Cow<'static, str>>) {
73        self.base_url = base_url.into();
74    }
75
76    /// Sets a custom base URL and returns the modified builder.
77    pub fn with_base_url(mut self, base_url: impl Into<Cow<'static, str>>) -> Self {
78        self.set_base_url(base_url);
79        self
80    }
81
82    /// Sets a custom `reqwest::ClientBuilder`.
83    pub fn set_client_builder(&mut self, client_builder: reqwest::ClientBuilder) {
84        self.client_builder = Some(client_builder);
85    }
86
87    /// Sets a custom `reqwest::ClientBuilder` and returns the modified builder.
88    pub fn with_client_builder(mut self, client_builder: reqwest::ClientBuilder) -> Self {
89        self.set_client_builder(client_builder);
90        self
91    }
92
93    /// Sets the credentials for API authentication.
94    pub fn set_credentials(&mut self, credentials: crate::Credentials) {
95        self.credentials = credentials;
96    }
97
98    /// Sets the credentials and returns the modified builder.
99    pub fn with_credentials(mut self, credentials: crate::Credentials) -> Self {
100        self.set_credentials(credentials);
101        self
102    }
103
104    /// Builds the [`Client`](crate::Client) with the configured options.
105    ///
106    /// # Errors
107    ///
108    /// Returns [`Error::MissingCredentials`] if no credentials were set.
109    /// Returns [`Error::Reqwest`] if the HTTP client could not be built.
110    pub fn build(self) -> Result<crate::Client, Error> {
111        let builder = self
112            .client_builder
113            .unwrap_or_default()
114            .user_agent(crate::USER_AGENT);
115        Ok(crate::Client {
116            base_url: self.base_url,
117            credentials: self.credentials,
118            inner: builder.build()?,
119        })
120    }
121}