summaryrefslogtreecommitdiffstats
path: root/README.md
diff options
context:
space:
mode:
Diffstat (limited to 'README.md')
-rw-r--r--README.md49
1 files changed, 46 insertions, 3 deletions
diff --git a/README.md b/README.md
index 3129bd8..2b1a652 100644
--- a/README.md
+++ b/README.md
@@ -62,10 +62,12 @@ exceptions:
| `TCepisAddressList` from `LookupMany` | you — and freeing it frees the addresses inside |
| `TCepisHealth` from `Health` | you |
| `TCepisGeo` on an address | its address |
+| `TCepisFaixa` on an `ECepisNotFound` | its exception, when the handler ends |
| the client behind `CepisLookup` and friends | the `Cepis` unit, at finalisation |
-`TCepisAddressList.Extract` and `TCepisAddress.ExtractGeo` hand ownership over
-when you need one item to outlive its container.
+`TCepisAddressList.Extract`, `TCepisAddress.ExtractGeo` and
+`ECepisNotFound.ExtractFaixa` hand ownership over when you need one item to
+outlive its container.
## Usage
@@ -218,7 +220,7 @@ have to make**, not by the HTTP status that caused it:
| error | when | does retrying help? |
| --- | --- | --- |
| `ECepisInvalidCEP` | not 8 digits | no |
-| `ECepisNotFound` | well-formed, not in the database | no |
+| `ECepisNotFound` | well-formed, not in the database; may carry `Faixa` | no |
| `ECepisRateLimited` | 429; carries `RetryAfter` | yes, later |
| `ECepisServerError` | 5xx; carries `Status` | yes, later |
| `ECepisNetworkError` | DNS, connection, timeout, TLS | yes, later |
@@ -235,6 +237,47 @@ except
end;
```
+### A not-found that says where the CEP would be
+
+A CEP that fails is rarely a random number: it is usually someone who knows the
+city and guessed the last digits, and the classic guess is the `-000` that 957
+municipalities never received. When the API can place the failed number inside
+a municipality's band, the 404 says which one, and `ECepisNotFound` carries it
+as a `TCepisFaixa`:
+
+```pascal
+try
+ Address := CepisLookup('25845-000');
+except
+ on E: ECepisNotFound do
+ if E.HasFaixa then
+ WriteLn('No such CEP in ', E.Faixa.Localidade, '/', E.Faixa.UF,
+ ' — it has ', E.Faixa.Ceps, ' CEPs, from ',
+ E.Faixa.CepIni, ' to ', E.Faixa.CepFim)
+ // No such CEP in Areal/RJ — it has 118 CEPs, from 25845001 to 25849899
+ else
+ WriteLn('No such CEP');
+end;
+```
+
+**It is still a 404.** The faixa is context for an error, not an address: it
+names the municipality the number *would* belong to, and the CEP asked for does
+not exist. `E.Faixa` is `nil` — and `E.HasFaixa` is `False` — whenever the
+number falls in a band no municipality owns; the API omits the field there
+rather than sending `null`, and a malformed one is dropped the same way. The
+exception owns the faixa and frees it when the handler ends; `E.ExtractFaixa`
+takes it over if you need it to outlive the `except` block.
+
+Two traps in the pair of bounds:
+
+- **They are not the published range.** `CepIni` and `CepFim` are the smallest
+ and the largest CEP that *actually exist* in the municipality. The DNE's own
+ start for Areal is `25845000` — exactly the CEP that just failed — while
+ `CepIni` is `25845001`.
+- **The range is sparse.** Areal's 118 CEPs are scattered over the ~4,900
+ numbers between `25845001` and `25849899`. Never treat the pair as a list of
+ valid CEPs, and never count from it: that is what `Ceps` is for.
+
`CepisNormalizeCEP` strips the mask and validates the 8 digits on its own, for
code that wants to check before it asks: