use crate::types::*;
const DEFAULT_BASE_URL: &str = "https://nfcfyi.com/api";
pub struct Client {
base_url: String,
http: reqwest::Client,
}
impl Client {
pub fn new() -> Self {
Self {
base_url: DEFAULT_BASE_URL.to_string(),
http: reqwest::Client::new(),
}
}
pub fn with_base_url(base_url: &str) -> Self {
Self {
base_url: base_url.to_string(),
http: reqwest::Client::new(),
}
}
async fn get<T: serde::de::DeserializeOwned>(&self, path: &str) -> Result<T, NfcFyiError> {
let url = format!("{}{}", self.base_url, path);
let resp = self.http.get(&url).send().await?;
if !resp.status().is_success() {
return Err(NfcFyiError::Api {
status: resp.status().as_u16(),
body: resp.text().await.unwrap_or_default(),
});
}
Ok(resp.json().await?)
}
pub async fn search(&self, query: &str) -> Result<SearchResult, NfcFyiError> {
let encoded = urlencoding(query);
self.get(&format!("/search/?q={}", encoded)).await
}
pub async fn chip(&self, slug: &str) -> Result<ChipDetail, NfcFyiError> {
self.get(&format!("/chip/{}/", slug)).await
}
pub async fn chip_family(&self, slug: &str) -> Result<ChipFamilyDetail, NfcFyiError> {
self.get(&format!("/chip-family/{}/", slug)).await
}
pub async fn standard(&self, slug: &str) -> Result<StandardDetail, NfcFyiError> {
self.get(&format!("/standard/{}/", slug)).await
}
pub async fn operating_mode(&self, slug: &str) -> Result<OperatingModeDetail, NfcFyiError> {
self.get(&format!("/operating-mode/{}/", slug)).await
}
pub async fn ndef_type(&self, slug: &str) -> Result<NdefTypeDetail, NfcFyiError> {
self.get(&format!("/ndef-type/{}/", slug)).await
}
pub async fn use_case(&self, slug: &str) -> Result<UseCaseDetail, NfcFyiError> {
self.get(&format!("/use-case/{}/", slug)).await
}
pub async fn glossary_term(&self, slug: &str) -> Result<GlossaryTerm, NfcFyiError> {
self.get(&format!("/glossary/{}/", slug)).await
}
pub async fn compare(&self, slug_a: &str, slug_b: &str) -> Result<CompareResult, NfcFyiError> {
self.get(&format!("/compare/?a={}&b={}", slug_a, slug_b)).await
}
pub async fn random(&self) -> Result<ChipDetail, NfcFyiError> {
self.get("/random/").await
}
}
impl Default for Client {
fn default() -> Self {
Self::new()
}
}
fn urlencoding(s: &str) -> String {
s.chars()
.map(|c| match c {
'A'..='Z' | 'a'..='z' | '0'..='9' | '-' | '_' | '.' | '~' => c.to_string(),
' ' => "+".to_string(),
_ => format!("%{:02X}", c as u32),
})
.collect()
}