diff options
| author | Murilo Ijanc <[email protected]> | 2026-07-27 20:33:51 -0300 |
|---|---|---|
| committer | Murilo Ijanc <[email protected]> | 2026-07-27 20:33:51 -0300 |
| commit | 2fb251996798798af38903fe535b8d147084a50a (patch) | |
| tree | 9bcbb6ead9c7c4c1910495186707dc0f8859169d /include/cepis/errors.hpp | |
| parent | b71faa6e95a0736f1ff171e006b171467b65db90 (diff) | |
| download | cpp-2fb251996798798af38903fe535b8d147084a50a.tar.gz | |
A CEP that fails a lookup is rarely random: it is usually someone who
knows the city and guessed the number, and the classic guess is the -000
that 957 municipalities never received. The API now names, on the 404
itself, the municipality that CEP would have belonged to, so a caller can
say "not found — did you mean somewhere in Areal/RJ?" instead of just
"not found".
CepNotFound carries it as an optional Faixa. It stays an error: the block
is context, not an address, and the range it describes is sparse, which
is why it reports a count alongside the first and last CEP that actually
exist there rather than the bounds the Correios publish. Parsing it is
best-effort on purpose — a missing, empty or malformed block leaves the
optional empty, since a 404 is already the answer and reading the hint
attached to it must never cost the diagnosis.
Diffstat (limited to 'include/cepis/errors.hpp')
| -rw-r--r-- | include/cepis/errors.hpp | 30 |
1 files changed, 30 insertions, 0 deletions
diff --git a/include/cepis/errors.hpp b/include/cepis/errors.hpp index 0420ecd..fa928f0 100644 --- a/include/cepis/errors.hpp +++ b/include/cepis/errors.hpp @@ -4,6 +4,9 @@ #include <optional> #include <stdexcept> #include <string> +#include <utility> + +#include "cepis/models.hpp" namespace cepis { @@ -38,9 +41,36 @@ class InvalidCep : public Error { }; /// The CEP is well-formed but does not exist in the DNE database. +/// +/// The API often says **where it would have been** — see `faixa()`. That is +/// still a not-found: the extra context does not make the CEP deliverable, and +/// this remains the exception thrown for it. class CepNotFound : public Error { public: using Error::Error; + + CepNotFound(const std::string& message, std::optional<Faixa> faixa) + : Error(message), faixa_(std::move(faixa)) {} + + /// The municipality the CEP would have belonged to, when the API names one. + /// + /// `std::nullopt` when the CEP falls in a band no municipality owns — the + /// API **omits** the block there, it never sends null — and also whenever + /// the block cannot be read. Read `Faixa` before showing any of it: the + /// range it describes is sparse, and the CEP does not exist either way. + /// + /// ```cpp + /// } catch (const cepis::CepNotFound& error) { + /// if (error.faixa()) { + /// std::cerr << "not found; did you mean somewhere in " + /// << error.faixa()->localidade << '/' << error.faixa()->uf << "?\n"; + /// } + /// } + /// ``` + [[nodiscard]] const std::optional<Faixa>& faixa() const noexcept { return faixa_; } + + private: + std::optional<Faixa> faixa_; }; /// The request never completed: DNS, refused connection, timeout, TLS. |