diff options
| author | Murilo Ijanc <[email protected]> | 2026-07-26 12:17:46 -0300 |
|---|---|---|
| committer | Murilo Ijanc <[email protected]> | 2026-07-26 12:17:46 -0300 |
| commit | 4a8c3b675df4b1a6b29904fc2af60605002a7f9e (patch) | |
| tree | 5c3dcc6594603d242b6a284c1601fd1ffbfcc8f4 /src/lib.rs | |
| download | rust-4a8c3b675df4b1a6b29904fc2af60605002a7f9e.tar.gz | |
Initial importv0.1.0
Diffstat (limited to 'src/lib.rs')
| -rw-r--r-- | src/lib.rs | 100 |
1 files changed, 100 insertions, 0 deletions
diff --git a/src/lib.rs b/src/lib.rs new file mode 100644 index 0000000..84262d7 --- /dev/null +++ b/src/lib.rs @@ -0,0 +1,100 @@ +//! 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<Client> = 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<Address> { + 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<str>]) -> Result<Vec<Option<Address>>> { + default_client().lookup_many(ceps) +} + +/// Query the API's health using the default configuration. +/// +/// Shorthand for [`Client::health`]. +pub fn health() -> Result<Health> { + default_client().health() +} |