Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 5 additions & 5 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,9 @@ logger:
us_autocomplete_pro_api:
RUST_LOG=trace cargo run --example us_autocomplete_pro_api

us_autocomplete_api:
RUST_LOG=trace cargo run --example us_autocomplete_api

us_extract_api:
RUST_LOG=trace cargo run --example us_extract_api

Expand Down Expand Up @@ -71,9 +74,6 @@ us_enrichment_business_name_search_api:
integration:
cargo test --test us_street_integration -- --ignored

examples: international_autocomplete_api international_postal_code_api international_street_api logger us_autocomplete_pro_api us_extract_api us_reverse_geo_api us_street_api us_street_match_strategy us_zipcode_api us_enrichment_api us_enrichment_address_search_api us_enrichment_business_api

.PHONY: clean test dependencies package examples clippy integration international_autocomplete_api international_postal_code_api international_street_api logger us_autocomplete_pro_api us_extract_api us_reverse_geo_api us_street_api us_street_match_strategy us_street_iana_timezone us_zipcode_api us_enrichment_api us_enrichment_address_search_api us_enrichment_business_api
examples: international_autocomplete_api international_postal_code_api international_street_api logger us_autocomplete_pro_api us_extract_api us_reverse_geo_api us_street_api us_zipcode_api us_enrichment_api us_enrichment_address_search_api us_enrichment_business_api us_enrichment_business_name_search_api
examples: international_autocomplete_api international_postal_code_api international_street_api logger us_autocomplete_pro_api us_autocomplete_api us_extract_api us_reverse_geo_api us_street_api us_street_match_strategy us_zipcode_api us_enrichment_api us_enrichment_address_search_api us_enrichment_business_api us_enrichment_business_name_search_api

.PHONY: clean test dependencies package examples clippy integration international_autocomplete_api international_postal_code_api international_street_api logger us_autocomplete_pro_api us_extract_api us_reverse_geo_api us_street_api us_street_iana_timezone us_zipcode_api us_enrichment_api us_enrichment_address_search_api us_enrichment_business_api us_enrichment_business_name_search_api
.PHONY: clean test dependencies package examples clippy integration international_autocomplete_api international_postal_code_api international_street_api logger us_autocomplete_pro_api us_autocomplete_api us_extract_api us_reverse_geo_api us_street_api us_street_match_strategy us_street_iana_timezone us_zipcode_api us_enrichment_api us_enrichment_address_search_api us_enrichment_business_api us_enrichment_business_name_search_api
3 changes: 3 additions & 0 deletions smarty-rust-sdk/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,9 @@ name = "us_extract_api"
[[example]]
name = "us_autocomplete_pro_api"

[[example]]
name = "us_autocomplete_api"

[[example]]
name = "international_street_api"

Expand Down
62 changes: 62 additions & 0 deletions smarty-rust-sdk/examples/us_autocomplete_api.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
extern crate serde_json;
extern crate smarty_rust_sdk;
extern crate tokio;

// This example is for US Autocomplete (V2). It has the same name as a previous product
// which has been deprecated since 2022, which we refer to as US Autocomplete Basic.
// If you are still using US Autocomplete Basic, this SDK will not work.

use smarty_rust_sdk::sdk::authentication::BasicAuthCredential;
use smarty_rust_sdk::sdk::options::OptionsBuilder;
use smarty_rust_sdk::us_autocomplete_api::client::USAutocompleteClient;
use smarty_rust_sdk::us_autocomplete_api::lookup::{Lookup, PreferGeolocation, Source};
use std::error::Error;

#[tokio::main]
async fn main() -> Result<(), Box<dyn Error>> {
// Documentation for input fields can be found at:
// https://www.smarty.com/docs/apis/us-autocomplete-v2/reference#http-request-input-fields

let lookup = &mut Lookup {
search: "1042 W Center".to_string(),
max_results: 5,
city_filter: vec!["Orem,UT".to_string(), "Madisonville,KY".to_string()],
state_filter: vec!["UT".to_string(), "KY".to_string()],
prefer_state: vec!["KY".to_string()],
prefer_ratio: 3,
prefer_geolocation: PreferGeolocation::GeolocateCity,
source: Some(Source::All),
..Default::default()
};

let authentication = BasicAuthCredential::new(
std::env::var("SMARTY_AUTH_ID").expect("Missing SMARTY_AUTH_ID env variable"),
std::env::var("SMARTY_AUTH_TOKEN").expect("Missing SMARTY_AUTH_TOKEN env variable"),
);

let options = OptionsBuilder::new(Some(authentication))
.with_logging()
.build();

let client = USAutocompleteClient::new(options)?;
client.send(lookup).await?;

println!("{}", serde_json::to_string_pretty(&lookup.results)?);

// Expand the secondaries of a result that has an entry_id by passing it back as the selected address.
if let Some(entry_id) = lookup
.results
.suggestions
.iter()
.find(|suggestion| !suggestion.entry_id.is_empty())
.map(|suggestion| suggestion.entry_id.clone())
{
lookup.selected = entry_id;
client.send(lookup).await?;

println!("Secondaries:");
println!("{}", serde_json::to_string_pretty(&lookup.results)?);
}

Ok(())
}
1 change: 1 addition & 0 deletions smarty-rust-sdk/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ pub mod international_autocomplete_api;
pub mod international_postal_code_api;
pub mod international_street_api;
pub mod sdk;
pub mod us_autocomplete_api;
pub mod us_autocomplete_pro_api;
pub mod us_enrichment_api;
pub mod us_extract_api;
Expand Down
17 changes: 17 additions & 0 deletions smarty-rust-sdk/src/us_autocomplete_api/client.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
use crate::sdk::client::Client;
use crate::sdk::error::SmartyError;
use crate::sdk::options::Options;
use crate::sdk::send_request;
use crate::us_autocomplete_api::lookup::Lookup;
use crate::us_autocomplete_api::suggestion::SuggestionListing;
use reqwest::Method;
use smarty_rust_proc_macro::smarty_api;

#[smarty_api(
api_path = "v2/lookup",
default_url = "https://us-autocomplete.api.smarty.com/",
lookup_style(lookup),
lookup_type = "Lookup",
result_type = "SuggestionListing"
)]
pub struct USAutocompleteClient;
118 changes: 118 additions & 0 deletions smarty-rust-sdk/src/us_autocomplete_api/lookup.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
use crate::sdk::{has_param, has_vec_param};
use crate::us_autocomplete_api::suggestion::SuggestionListing;
use serde::Serialize;
use std::fmt::{Display, Formatter};

#[derive(Clone, Debug, PartialEq)]
pub struct Lookup {
pub search: String,
pub source: Option<Source>,
pub max_results: i32,
pub city_filter: Vec<String>,
pub state_filter: Vec<String>,
pub zip_filter: Vec<String>,
pub exclude_states: Vec<String>,
pub prefer_city: Vec<String>,
pub prefer_state: Vec<String>,
pub prefer_zip: Vec<String>,
pub prefer_ratio: i32,
pub prefer_geolocation: PreferGeolocation,
pub selected: String,
pub exclude: Vec<String>,

pub results: SuggestionListing,
}

impl Default for Lookup {
fn default() -> Self {
Lookup {
search: String::default(),
source: None,
max_results: 0,
city_filter: vec![],
state_filter: vec![],
zip_filter: vec![],
exclude_states: vec![],
prefer_city: vec![],
prefer_state: vec![],
prefer_zip: vec![],
prefer_ratio: 0,
prefer_geolocation: PreferGeolocation::default(),
selected: String::default(),
exclude: vec![],

results: SuggestionListing {
suggestions: vec![],
},
}
}
}

impl Lookup {
pub(crate) fn into_param_array(self) -> Vec<(String, String)> {
let geolocation = self.geolocation_param();
let mut result: Vec<(String, String)> = [
has_param("search".to_string(), self.search),
has_param("max_results".to_string(), self.max_results),
has_vec_param("include_only_cities".to_string(), ";", self.city_filter),
has_vec_param("include_only_states".to_string(), ";", self.state_filter),
has_vec_param("include_only_zip_codes".to_string(), ";", self.zip_filter),
has_vec_param("exclude_states".to_string(), ";", self.exclude_states),
has_vec_param("prefer_cities".to_string(), ";", self.prefer_city),
has_vec_param("prefer_states".to_string(), ";", self.prefer_state),
has_vec_param("prefer_zip_codes".to_string(), ";", self.prefer_zip),
has_param("prefer_ratio".to_string(), self.prefer_ratio),
geolocation,
has_param("selected".to_string(), self.selected),
has_vec_param("exclude".to_string(), ",", self.exclude),
]
.iter()
.filter_map(Option::clone)
.collect::<Vec<_>>();

if let Some(source) = self.source {
result.push(("source".to_string(), source.to_string()));
}

result
}

fn geolocation_param(&self) -> Option<(String, String)> {
if !self.zip_filter.is_empty() || !self.prefer_zip.is_empty() {
return Some(("prefer_geolocation".to_string(), "none".to_string()));
}

match self.prefer_geolocation {
PreferGeolocation::GeolocateCity => {
Some(("prefer_geolocation".to_string(), "city".to_string()))
}
PreferGeolocation::GeolocateNone => {
Some(("prefer_geolocation".to_string(), "none".to_string()))
}
}
}
}

#[derive(Default, Debug, Clone, PartialEq, Serialize)]
pub enum PreferGeolocation {
#[default]
#[serde(rename = "none")]
GeolocateNone,
#[serde(rename = "city")]
GeolocateCity,
}

#[derive(Debug, Clone, PartialEq)]
pub enum Source {
All,
Postal,
}

impl Display for Source {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
match self {
Source::All => write!(f, "all"),
Source::Postal => write!(f, "postal"),
}
}
}
86 changes: 86 additions & 0 deletions smarty-rust-sdk/src/us_autocomplete_api/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
pub mod client;
pub mod lookup;
pub mod suggestion;

#[cfg(test)]
mod tests {
use crate::sdk::options::OptionsBuilder;
use crate::us_autocomplete_api::client::USAutocompleteClient;
use crate::us_autocomplete_api::lookup::{Lookup, PreferGeolocation, Source};

#[test]
fn client_test() {
let client = USAutocompleteClient::new(OptionsBuilder::new(None).build()).unwrap();

assert_eq!(
client.client.url.to_string(),
"https://us-autocomplete.api.smarty.com/v2/lookup".to_string()
)
}

#[test]
fn lookup_test() {
let lookup = Lookup {
search: "1042 W Center".to_string(),
max_results: 5,
city_filter: vec!["Denver,CO".to_string(), "Orem,UT".to_string()],
state_filter: vec!["CO".to_string(), "UT".to_string()],
prefer_city: vec!["Denver".to_string()],
prefer_state: vec!["CO".to_string()],
prefer_ratio: 3,
prefer_geolocation: PreferGeolocation::GeolocateCity,
source: Some(Source::All),
selected: "selectedAddress".to_string(),
exclude: vec![
"excludedAddress".to_string(),
"excludedAddress2".to_string(),
],
..Default::default()
};

let expected_results = vec![
("search".to_string(), "1042 W Center".to_string()),
("max_results".to_string(), "5".to_string()),
(
"include_only_cities".to_string(),
"Denver,CO;Orem,UT".to_string(),
),
("include_only_states".to_string(), "CO;UT".to_string()),
("prefer_cities".to_string(), "Denver".to_string()),
("prefer_states".to_string(), "CO".to_string()),
("prefer_ratio".to_string(), "3".to_string()),
("prefer_geolocation".to_string(), "city".to_string()),
("selected".to_string(), "selectedAddress".to_string()),
(
"exclude".to_string(),
"excludedAddress,excludedAddress2".to_string(),
),
("source".to_string(), "all".to_string()),
];

assert_eq!(lookup.into_param_array(), expected_results)
}

#[test]
fn lookup_excludes_source_when_not_specified() {
let lookup = Lookup {
search: "1042 W Center".to_string(),
..Default::default()
};

let params = lookup.into_param_array();
assert!(!params.iter().any(|(k, _)| k == "source"));
}

#[test]
fn lookup_includes_source_postal() {
let lookup = Lookup {
search: "1042 W Center".to_string(),
source: Some(Source::Postal),
..Default::default()
};

let params = lookup.into_param_array();
assert!(params.iter().any(|(k, v)| k == "source" && v == "postal"));
}
}
21 changes: 21 additions & 0 deletions smarty-rust-sdk/src/us_autocomplete_api/suggestion.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
use serde::{Deserialize, Serialize};

#[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize)]
#[serde(default)]
pub struct SuggestionListing {
pub suggestions: Vec<Suggestion>,
}

#[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize)]
#[serde(default)]
pub struct Suggestion {
pub smarty_key: String,
pub entry_id: String,
pub street_line: String,
pub secondary: String,
pub city: String,
pub state: String,
pub zipcode: String,
pub entries: i32,
Comment thread
mae-smarty marked this conversation as resolved.
pub source: String,
}
1 change: 1 addition & 0 deletions smarty-rust-sdk/src/us_autocomplete_pro_api/lookup.rs
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ impl Lookup {
has_vec_param("include_only_states".to_string(), ";", self.state_filter),
has_vec_param("include_only_zip_codes".to_string(), ";", self.zip_filter),
has_vec_param("exclude_states".to_string(), ";", self.exclude_states),
has_vec_param("prefer_cities".to_string(), ";", self.prefer_city),
has_vec_param("prefer_states".to_string(), ";", self.prefer_state),
has_vec_param("prefer_zip_codes".to_string(), ";", self.prefer_zip),
has_param("prefer_ratio".to_string(), self.prefer_ratio),
Expand Down
2 changes: 2 additions & 0 deletions smarty-rust-sdk/src/us_autocomplete_pro_api/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ mod tests {
max_results: 5,
city_filter: vec!["Denver,CO".to_string(), "Orem,UT".to_string()],
state_filter: vec!["CO".to_string(), "UT".to_string()],
prefer_city: vec!["Denver".to_string()],
prefer_state: vec!["CO".to_string()],
prefer_ratio: 3,
geolocation: Geolocation::GeolocateCity,
Expand All @@ -40,6 +41,7 @@ mod tests {
"Denver,CO;Orem,UT".to_string(),
),
("include_only_states".to_string(), "CO;UT".to_string()),
("prefer_cities".to_string(), "Denver".to_string()),
("prefer_states".to_string(), "CO".to_string()),
("prefer_ratio".to_string(), "3".to_string()),
("prefer_geolocation".to_string(), "city".to_string()),
Expand Down