//! Rust client for the public CEP API at [cep.is](https://cep.is). Official //! Correios data (DNE), refreshed every two weeks. //! //! Quick use — for a script, the free functions are enough: //! //! ```no_run //! let address = cepis::lookup("01001-000")?; //! println!("{} {}", address.localidade, address.uf); // São Paulo SP //! # Ok::<_, cepis::Error>(()) //! ``` //! //! In an application — build a [`Client`] once and reuse it: //! //! ```no_run //! use std::time::Duration; //! //! let client = cepis::Client::builder() //! .timeout(Duration::from_secs(5)) //! .total_timeout(Some(Duration::from_secs(15))) //! .build(); //! //! let address = client.lookup("01001000")?; //! # Ok::<_, cepis::Error>(()) //! ``` //! //! Pointing at a local instance (the API repo brings one up with `just up`): //! //! ```no_run //! let client = cepis::Client::builder() //! .base_url("http://localhost:8080") //! .build(); //! # let _ = client; //! ``` //! //! Errors are one type, split by decision — whether retrying helps or not: //! //! ```no_run //! # let cep_from_form = "01001000"; //! match cepis::lookup(cep_from_form) { //! Ok(address) => println!("{}", address.localidade), //! Err(cepis::Error::NotFound { .. }) => {} // ask the user for another CEP //! Err(err) if err.is_retriable() => {} // network, server, rate limit //! Err(err) => eprintln!("{err}"), //! } //! ``` //! //! Note on field names: the API surface is English, but the **data fields keep //! the API's own Portuguese names** (`logradouro`, `bairro`, `localidade`). //! What you read in the JSON is what you access on the value. //! //! The free functions share one default client, built on first use. It keeps no //! state between calls and is safe to share across threads. Anyone needing //! different settings should build their own [`Client`]. #![forbid(unsafe_code)] #![warn(missing_docs)] mod client; mod csv; mod error; mod model; mod retry; pub use crate::client::{ Client, ClientBuilder, DEFAULT_URL, MAX_BATCH, RETRIABLE_STATUS, normalize_cep, }; pub use crate::error::{Error, Result}; pub use crate::model::{Address, Geo, Health}; /// The version of this library, as sent in the `User-Agent`. pub const VERSION: &str = env!("CARGO_PKG_VERSION"); use std::sync::OnceLock; fn default_client() -> &'static Client { static DEFAULT: OnceLock = OnceLock::new(); DEFAULT.get_or_init(Client::new) } /// Look up a CEP using the default configuration. /// /// Shorthand for `Client::new().lookup(cep)`; see [`Client::lookup`]. pub fn lookup(cep: &str) -> Result
{ default_client().lookup(cep) } /// Look up many CEPs in one batch, using the default configuration. /// /// Shorthand for [`Client::lookup_many`] — read that one, especially the /// warning that batches carry no coordinate. pub fn lookup_many(ceps: &[impl AsRef]) -> Result>> { default_client().lookup_many(ceps) } /// Query the API's health using the default configuration. /// /// Shorthand for [`Client::health`]. pub fn health() -> Result { default_client().health() }