summaryrefslogtreecommitdiffstats
path: root/README.md
diff options
context:
space:
mode:
Diffstat (limited to 'README.md')
-rw-r--r--README.md56
1 files changed, 55 insertions, 1 deletions
diff --git a/README.md b/README.md
index 26e957d..a4b0cc1 100644
--- a/README.md
+++ b/README.md
@@ -200,7 +200,7 @@ to make**, not by the HTTP status that caused it:
| error | when | does retrying help? |
| --- | --- | --- |
| `error.InvalidCep` | not 8 digits | no |
-| `error.NotFound` | well-formed, not in the database | no |
+| `error.NotFound` | well-formed, not in the database; `faixa` in the diagnostics | no |
| `error.RateLimited` | 429; `retry_after_ms` in the diagnostics | yes, later |
| `error.ServerError` | 5xx; `status` in the diagnostics | yes, later |
| `error.NetworkError` | DNS, connection, timeout, TLS | yes, later |
@@ -228,6 +228,60 @@ const address = client.lookup(cep_from_form, .{ .diagnostics = &diag }) catch |e
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.
+### A CEP that does not exist
+
+`GET /{cep}` answers **404** for a CEP the DNE does not have, and this package
+turns that into `error.NotFound`. When the number falls inside a band that
+belongs to a municipality, the 404 also names it, and `diag.faixa()` gives you
+that:
+
+```zig
+var diag: cepis.Diagnostics = .{};
+
+client.lookup("25845-000", .{ .diagnostics = &diag }) catch |err| switch (err) {
+ error.NotFound => {
+ if (diag.faixa()) |f| {
+ f.localidade; // "Areal"
+ f.uf; // "RJ"
+ f.estado; // "Rio de Janeiro"
+ f.regiao; // "Sudeste"
+ f.ibge; // "3300225"
+ f.cep_ini; // "25845001"
+ f.cep_fim; // "25849899"
+ f.ceps; // 118
+ }
+ return askForAnotherCep();
+ },
+ else => return err,
+};
+```
+
+Worth having because a failing CEP is rarely random: it is someone who knows the
+city and guessed the number, and the classic guess is the `-000` that 957
+municipalities never received — `25845000` above is exactly that guess for
+Areal.
+
+> **It is still an error.** `faixa` explains *where* the number would have
+> fallen. It is not an address, there is no address, and treating a non-null
+> `faixa` as a successful lookup turns a clean failure into wrong data.
+
+Two things about the range, both of which make it wrong to hand it to a user as
+a list of CEPs to try:
+
+- **`cep_ini` and `cep_fim` are not the Correios' bounds.** They are the
+ smallest and the largest CEP that *actually exist* in the municipality. The
+ DNE's own start for Areal is `25845000` — the CEP that just failed — while
+ `cep_ini` is `25845001`.
+- **The range is sparse.** Areal's 118 CEPs are scattered over the ~4,900
+ numbers between the two. That is what `ceps` is for; never compute
+ `cep_fim - cep_ini` and call it a count.
+
+`faixa()` is null whenever the API said nothing — the CEP fell in a band no
+municipality owns, and there the field is **omitted**, never sent as null. Null
+is the ordinary case, not a sign of trouble. Like `message()`, the value borrows
+the `Diagnostics` and is valid only as long as it is; nothing is allocated and
+there is nothing to free.
+
## Development
Everything runs through `make`, which shells out to `zig`: