summaryrefslogtreecommitdiffstats
path: root/src/Cepis/Faixa.cs
diff options
context:
space:
mode:
Diffstat (limited to 'src/Cepis/Faixa.cs')
-rw-r--r--src/Cepis/Faixa.cs99
1 files changed, 99 insertions, 0 deletions
diff --git a/src/Cepis/Faixa.cs b/src/Cepis/Faixa.cs
new file mode 100644
index 0000000..e2477b6
--- /dev/null
+++ b/src/Cepis/Faixa.cs
@@ -0,0 +1,99 @@
+using System.Text.Json.Serialization;
+
+namespace Cepis;
+
+/// <summary>
+/// The municipality a CEP that does not exist would have belonged to.
+/// </summary>
+/// <remarks>
+/// <para>
+/// This is <b>context for an error, never an address</b>. It rides on the 404
+/// of <see cref="CepisClient.LookupAsync(string, CancellationToken)"/>, hanging
+/// off <see cref="CepNotFoundException.Faixa"/>. The CEP that was asked for
+/// still does not exist, and nothing here says otherwise: filling a form from
+/// these fields would be inventing an address.
+/// </para>
+/// <para>
+/// It is worth having because a CEP that fails is rarely random — it is usually
+/// someone who knows the city and guessed the number. The classic guess is the
+/// <c>-000</c>, which 957 municipalities never received. Knowing where the
+/// guess landed is what turns "CEP not found" into "did you mean a street in
+/// Areal/RJ?".
+/// </para>
+/// <para>
+/// <see cref="CepIni"/> and <see cref="CepFim"/> are the smallest and the
+/// largest CEP that <b>actually exist</b> in that municipality, <i>not</i> the
+/// bounds the Correios publish. For Areal the DNE's own range starts at
+/// <c>25845000</c> — exactly the CEP that just failed — while
+/// <see cref="CepIni"/> is <c>25845001</c>.
+/// </para>
+/// <para>
+/// The range is <b>sparse</b>, and the pair is not a list of valid CEPs. Areal
+/// has 118 of them (<see cref="Ceps"/>) spread across the ~4,900 numbers
+/// between its two ends, so a number picked in between overwhelmingly does not
+/// exist either. Never iterate the interval, and never show it as a set of
+/// usable CEPs.
+/// </para>
+/// <para>
+/// The property names are the API's own, in Portuguese, with only the casing
+/// adapted — the same rule the rest of the data follows. On the wire they are
+/// <c>localidade</c>, <c>uf</c>, <c>estado</c>, <c>regiao</c>, <c>ibge</c>,
+/// <c>cep_ini</c>, <c>cep_fim</c> and <c>ceps</c>.
+/// </para>
+/// </remarks>
+public sealed record Faixa
+{
+ /// <summary>The municipality. Wire name <c>localidade</c>.</summary>
+ [JsonPropertyName("localidade")]
+ public string Localidade { get; init; } = "";
+
+ /// <summary>The two-letter state code. Wire name <c>uf</c>.</summary>
+ [JsonPropertyName("uf")]
+ public string UF { get; init; } = "";
+
+ /// <summary>The state's name. Wire name <c>estado</c>.</summary>
+ [JsonPropertyName("estado")]
+ public string Estado { get; init; } = "";
+
+ /// <summary>The region of the country. Wire name <c>regiao</c>.</summary>
+ [JsonPropertyName("regiao")]
+ public string Regiao { get; init; } = "";
+
+ /// <summary>The IBGE municipality code. Wire name <c>ibge</c>.</summary>
+ [JsonPropertyName("ibge")]
+ public string Ibge { get; init; } = "";
+
+ /// <summary>
+ /// The smallest CEP that exists in that municipality, unmasked. Wire name
+ /// <c>cep_ini</c>.
+ /// </summary>
+ /// <remarks>
+ /// The smallest one <i>in the database</i>, not the start of the range the
+ /// Correios publish — the published start may itself be a CEP that was never
+ /// issued, which is often precisely the one the caller just tried.
+ /// </remarks>
+ [JsonPropertyName("cep_ini")]
+ public string CepIni { get; init; } = "";
+
+ /// <summary>
+ /// The largest CEP that exists in that municipality, unmasked. Wire name
+ /// <c>cep_fim</c>.
+ /// </summary>
+ /// <remarks>
+ /// Together with <see cref="CepIni"/> it bounds the CEPs of the
+ /// municipality; it does not enumerate them. See <see cref="Ceps"/>.
+ /// </remarks>
+ [JsonPropertyName("cep_fim")]
+ public string CepFim { get; init; } = "";
+
+ /// <summary>
+ /// How many CEPs the municipality actually has. Wire name <c>ceps</c>.
+ /// </summary>
+ /// <remarks>
+ /// This field exists to keep <see cref="CepIni"/> and <see cref="CepFim"/>
+ /// from being read as a contiguous interval. Areal's 118 CEPs sit inside a
+ /// span of about 4,900 numbers: the range is mostly empty.
+ /// </remarks>
+ [JsonPropertyName("ceps")]
+ public int Ceps { get; init; }
+}