diff options
| author | Murilo Ijanc <[email protected]> | 2026-07-27 20:33:24 -0300 |
|---|---|---|
| committer | Murilo Ijanc <[email protected]> | 2026-07-27 20:33:24 -0300 |
| commit | d7ca2d6f4b1c5c1f5f1b6ce6ffad35aaffee5b0f (patch) | |
| tree | 21aca875c28f4d7d9ec3b0a807e7c7f15a6766d8 /README.md | |
| parent | 72a4b451c9d06f7a97cac2f43f1b7f52fafcd3b7 (diff) | |
| download | swift-0.2.0.tar.gz | |
A CEP that fails a lookup is rarely a random number: it is almost always
someone who knows the city and guessed the digits. The classic guess is
the -000, which 957 municipalities never received. Answering that with a
bare "not found" throws away what the API knows — that the number is in
Areal/RJ's band — and leaves the caller unable to tell a typo apart from
a city that has no such CEP.
The 404 now carries an optional faixa, so cepNotFound carries it too. It
decorates the error and never replaces it: the CEP still does not exist
and the call still throws. Parsing is deliberately incapable of
escalating — a faixa that is absent, null, empty or malformed becomes
nil, because losing the decoration must never cost the clean not-found
underneath it.
Faixa offers no contains(): cep_ini and cep_fim are the smallest and
largest CEP that actually exist, not the bounds the Correios publish,
and the range between them is sparse — Areal's 118 CEPs are spread over
some 4,900 numbers. Only a lookup can answer whether a CEP exists, and
an API that appeared to answer it from the pair would be lying.
Widening cepNotFound's payload breaks anyone matching the case with a
single binding, hence 0.2.0.
Diffstat (limited to 'README.md')
| -rw-r--r-- | README.md | 50 |
1 files changed, 48 insertions, 2 deletions
@@ -20,7 +20,7 @@ Add the package to `Package.swift`: ```swift dependencies: [ - .package(url: "https://git.cep.is/swift.git", from: "0.1.0") + .package(url: "https://git.cep.is/swift.git", from: "0.2.0") ] ``` @@ -169,7 +169,7 @@ make**, not by the HTTP status that caused them: | case | when | does retrying help? | | --- | --- | --- | | `invalidCEP` | not 8 digits | no | -| `cepNotFound` | well-formed, not in the database | no | +| `cepNotFound` | well-formed, not in the database; carries `faixa` | no | | `rateLimited` | 429; carries `retryAfter` | yes, later | | `serverError` | 5xx; carries `status` | yes, later | | `networkError` | DNS, connection, timeout, TLS | yes, later | @@ -190,6 +190,52 @@ do { answering instead of it — a captive Wi-Fi portal, a corporate proxy, an HTML error page. Useful as a diagnosis: the problem is not in your code. +### Which city the missing CEP belonged to + +A CEP that fails is rarely a random number. It is usually someone who knows the +city and guessed the digits — and the classic guess is the `-000`, which 957 +municipalities never received. + +So `cepNotFound` carries a `Faixa`: the municipality the CEP *would* have +belonged to, when the API can say. + +```swift +do { + let address = try await Client.shared.lookup("25845-000") +} catch CepisError.cepNotFound(let message, let faixa) { + if let faixa { + print("\(message) — that range is \(faixa.localidadeUF)") + // … does not exist in the DNE database — that range is Areal/RJ + faixa.ibge // "3300225" + faixa.cepIni // "25845001" + faixa.cepFim // "25849899" + faixa.ceps // 118 + } +} +``` + +`error.faixa` reaches the same value without pattern-matching, and +`error.description` (and `errorDescription`) already names the municipality when +there is one. `error.message` stays exactly what it was. + +Three things to keep straight: + +- **It is still a 404.** The CEP does not exist. A `Faixa` is context for the + error, never an address — it can turn *"not found"* into *"not a CEP, but you + are looking at Areal/RJ"*, and nothing more. +- **`cepIni`/`cepFim` are not the Correios' published bounds.** They are the + smallest and largest CEP that *actually exist* there. The DNE's own start for + Areal is `25845000` — precisely the CEP that just failed. `cepIni` is + `25845001`. +- **The range is sparse.** It is not a list of valid CEPs and iterating it is + wrong: Areal's 118 CEPs are scattered across the ~4,900 numbers between the + two bounds, about one in forty. That is what `ceps` is for. + +The field is **omitted, never null**, when the CEP falls in a band no +municipality owns, so `faixa == nil` is ordinary and must be handled. It is also +`nil` when the response could not be understood: a malformed `faixa` never +escalates a clean not-found into a decoding failure. + ## Development ```sh |