pub fn require_valid_versao_requirement<E>(
versao: &str,
on_empty: impl FnOnce() -> E,
on_invalid: impl FnOnce(String) -> E,
) -> Result<(), E>Expand description
Bracket a :versao requirement-string axis with the shared
“empty-first, then crate::parse_requirement” gate pair every
dep-shaped :versao slot carries. Returns on_empty() when
versao.is_empty(), on_invalid(reason) when
crate::parse_requirement rejects the non-empty input, Ok(())
otherwise.
The empty-first arm strictly precedes the parse arm so a literal
"" value surfaces the self-locating empty diagnostic every
per-axis error variant already documents an “omit the axis to
express any-version” remediation for, rather than the misleading
parse-side no-op — crate::parse_requirement("")
hits semver::VersionReq::parse("") which returns
Ok(VersionReq { comparators: [] }) (semantically identical to
semver::VersionReq::STAR), so without the empty-first arm an
authored blank :versao "" would silently round-trip as an
implicit "*" — the same “silent widening” footgun the peer
require_positive_bounded_u32 closes on its zero-floor arm.
The three existing call sites — crate::dep::Dep::validate on
crate::dep::Dep::versao (empty → crate::DepError::VersaoEmpty,
invalid → crate::DepError::VersaoInvalid),
crate::AplicacaoSpec::validate_membros on
crate::aplicacao::Membro::versao (empty →
crate::AplicacaoError::MembroVersaoEmpty, invalid →
crate::AplicacaoError::MembroVersaoInvalid), and
crate::SupervisorSpec::validate on
crate::supervisor::ChildSpec::versao (empty →
crate::SupervisorError::EmptyChildVersion, invalid →
crate::SupervisorError::ChildVersaoInvalid) — each formerly
inlined this two-arm cascade verbatim. Lifting to one canonical
entry-point closes the drift footgun structurally: a future
widening of the accepted requirement-shape (a hypothetical
git-tag-prefix leniency, a per-axis strictness override, or the
M4 typed-resolver’s constraint: axis on
[ABSORPTION-ROADMAP.md]’s per-resolver-step trajectory) reaches
every dep-shaped :versao consumer by one edit at this helper,
not a coordinated rewrite across three modules.
Peer of require_positive_bounded_u32 /
require_positive_bounded_u64 on the same closure-based
caller-error-variant discipline — the caller owns the enum
variant + its self-locating discriminator fields
(nome/caixa, versao), this helper only sequences the two
gate arms in canonical order and threads the parser’s
semver-shaped reason into the invalid arm’s reason: field.
§Errors
Returns on_empty() for versao.is_empty(); returns
on_invalid(reason) when crate::parse_requirement rejects
the non-empty input (the parser’s to_string() output threaded
through as the invalid arm’s reason:); returns Ok(())
otherwise.