smarty_rust_sdk/sdk/
mod.rs

1use crate::sdk::error::SmartyError;
2use reqwest::Response;
3use reqwest_middleware::RequestBuilder;
4use serde::de::DeserializeOwned;
5use serde_repr::{Deserialize_repr, Serialize_repr};
6use std::fmt::{Display, Formatter};
7
8pub mod authentication;
9pub mod batch;
10pub mod client;
11pub mod error;
12pub mod logging;
13pub mod options;
14pub mod retry_strategy;
15
16pub const VERSION: &str = env!("CARGO_PKG_VERSION");
17pub const MAX_BATCH_SIZE: usize = 100;
18
19#[derive(Default, Debug, Clone, PartialEq, Serialize_repr, Deserialize_repr)]
20#[repr(u8)]
21pub enum CoordinateLicense {
22    #[default]
23    CoordinateLicenseSmartyStreets = 0,
24    CoordinateLicenseSmartyStreetsProprietary = 1,
25}
26
27impl Display for CoordinateLicense {
28    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
29        match self {
30            CoordinateLicense::CoordinateLicenseSmartyStreets => {
31                write!(f, "SmartyStreets")
32            }
33            CoordinateLicense::CoordinateLicenseSmartyStreetsProprietary => {
34                write!(f, "SmartyStreets Proprietary")
35            }
36        }
37    }
38}
39
40pub(crate) async fn send_request_full(request: RequestBuilder) -> Result<Response, SmartyError> {
41    request.send().await.map_err(|e| match e {
42        reqwest_middleware::Error::Middleware(e) => SmartyError::from(e),
43        reqwest_middleware::Error::Reqwest(e) => SmartyError::from(e),
44    })
45}
46
47pub(crate) async fn parse_response_json<C: DeserializeOwned>(
48    response: Response,
49) -> Result<C, SmartyError> {
50    if !response.status().is_success() {
51        let status_code = response.status();
52        let body = response.text().await?;
53
54        return Err(SmartyError::HttpError {
55            code: status_code,
56            detail: body,
57        });
58    }
59
60    Ok(response.json::<C>().await?)
61}
62
63pub(crate) async fn send_request<C: DeserializeOwned>(
64    request: RequestBuilder,
65) -> Result<C, SmartyError> {
66    let response = send_request_full(request).await?;
67    parse_response_json(response).await
68}
69
70/// This is only used for Serializing for post
71#[allow(clippy::trivially_copy_pass_by_ref)]
72pub(crate) fn is_zero(num: &i64) -> bool {
73    *num == 0
74}
75
76pub(crate) fn has_param<P: PartialEq + Display + Default>(
77    name: String,
78    param: P,
79) -> Option<(String, String)> {
80    if param != P::default() {
81        Some((name, param.to_string()))
82    } else {
83        None
84    }
85}
86
87pub(crate) fn has_vec_param(
88    name: String,
89    separator: &'static str,
90    param: Vec<String>,
91) -> Option<(String, String)> {
92    if !param.is_empty() {
93        Some((name, param.join(separator)))
94    } else {
95        None
96    }
97}
98
99// Tests
100#[cfg(test)]
101mod tests {
102    use crate::sdk::authentication::SecretKeyCredential;
103    use crate::sdk::batch::Batch;
104    use crate::sdk::client::Client;
105    use crate::sdk::options::OptionsBuilder;
106
107    #[test]
108    fn batch_test() {
109        let lookup = "Hello World".to_string();
110        let mut batch = Batch::default();
111        batch.push(lookup).unwrap();
112
113        assert_eq!(batch.len(), 1);
114        assert_eq!(batch.records()[0], "Hello World".to_string())
115    }
116
117    #[test]
118    fn authentication_test() {
119        let authentication = SecretKeyCredential::new("1234".to_string(), "ABCD".to_string());
120
121        assert_eq!(authentication.auth_id, "1234".to_string());
122        assert_eq!(authentication.auth_token, "ABCD".to_string());
123    }
124
125    #[test]
126    fn client_test() {
127        let client = Client::new(
128            "https://www.smarty.com".parse().unwrap(),
129            OptionsBuilder::new(None).build(),
130            "docs",
131        )
132        .unwrap();
133
134        assert_eq!(client.url.to_string(), "https://www.smarty.com/docs");
135    }
136}