summaryrefslogtreecommitdiffstats
path: root/include/cepis/errors.hpp
diff options
context:
space:
mode:
authorMurilo Ijanc <[email protected]>2026-07-27 20:33:51 -0300
committerMurilo Ijanc <[email protected]>2026-07-27 20:33:51 -0300
commit2fb251996798798af38903fe535b8d147084a50a (patch)
tree9bcbb6ead9c7c4c1910495186707dc0f8859169d /include/cepis/errors.hpp
parentb71faa6e95a0736f1ff171e006b171467b65db90 (diff)
downloadcpp-492ee0a03b6f23c3459cd32694cb1ed6bffdf014.tar.gz
Expose the municipality behind a not-found CEPHEADv0.2.0main
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.hpp30
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.