Skip to content

Close the Value/Map construction invariants in the public Rust API (BigInt newtype, private Map storage) #53

Closed

Description

@sinkog

Follow-up to #52. #52 makes the canonicalizer fail closed; this issue removes the possibility of constructing the invalid states at all, so the "closed data set" claim holds for the public Rust API and not only for the reader path.

Today:

  • pub enum Value { ..., BigInt(String), ..., Map(Map) } — BigInt's digit-run invariant is only documented.
  • pub struct Map(pub Vec<(String, Value)>) — the field is public, and Map::push intentionally skips the duplicate check.

Proposal

  • BigInt carries a newtype with a private field and a fallible constructor (BigIntValue::try_new(&str) -> Result<Self>, validating an optional sign followed by one or more ASCII digits). The reader constructs it after its own scan.
  • Map's inner Vec becomes private. insert keeps its replace semantics; push becomes either private/pub(crate) (the reader is the only caller that has already proven uniqueness) or checks and returns Result. Provide Map::from_pairs(...) -> Result<Map> that rejects duplicates, and read access via iter()/keys()/get() (already present).
  • Fix the call sites (plan.rs, collection.rs, digest_projection.rs, cli) and the tests that construct Map(vec![...]) directly.
  • The Go peer already has canonical.IsValue, deep copy and private fields at the MaterializedObject boundary; check that the Rust side offers the same guarantee and say so in the module docs.

This is a breaking change of the public Rust API. The README states "Nothing here is a stable API", so it is cheapest now, before an API freeze.

Acceptance

  • Value::BigInt with a non-digit string and a Map with a duplicate key are not expressible outside the crate (compile-fail tests or doc-tests showing the constructors reject them).
  • The expect(...) calls that relied on those invariants are either gone or provably unreachable and say why.
  • Public API change listed in the PR description and in the docs.

Activity

  1. sinkog commented on Oct 17, 2026

    @sinkog
    MemberAuthor

    Resolved by #56 (merge 3debff6). The Value/Map construction invariants are closed in the public Rust API. PR check was green on the merged head; main gate is green at 463ffde.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions