add proptest-based properties for varint/zigzag codecs;
generate valid Params and verify semantic round trips/presence;
verify repeated known tags are last-value-wins;
verify unknown tags preserve known values.
Properties
uvarint_round_trips / signed_varint_round_trips: every u64/i64 round-trips through encode_uvarint/decode_uvarint and encode_varint/decode_varint, with used == encoded.len() and 1 <= encoded.len() <= 10.
zigzag_round_trips_from_signed / zigzag_round_trips_from_unsigned: zigzag encode/decode is a bijection across the full i64 and u64 domains.
valid_params_round_trip: generated Params (scalar fields over the full i64 domain, constructive enum strategies, Option<ServerFill> bounded to MAX_SERVER_FILL_BYTES) round-trip through encode/decode byte-for-byte semantically.
encoded_param_presence_matches_omission_rules: decode_with_presence presence exactly matches Params::encode's omission rule (zero/default scalar and enum values omit their tag; Clock::Unspecified is the one enum whose zero is wire-omission-only; server_fill presence follows Option::is_some, including Some("")).
repeated_*_is_last_wins (one per known tag 1-8, plus server_fill tag 9): two explicit values for the same tag decode to the second value, with presence true.
unknown_scalar_tag_prefix_does_not_disturb_known_params / ..._suffix_...: an unknown tag (10..=u16::MAX) with an arbitrary u64 value placed before or after a valid encoded Params leaves the decoded value and known-tag presence unchanged.
omitted_vs_explicit_zero_presence_for_zero_valid_fields (deterministic table): omitted vs. explicit-zero decode to the same value but different presence for every field where explicit zero is valid; confirms explicit Clock=0 is rejected outright rather than accepted-as-present.
Existing hand-picked deterministic tests and byte vectors in varint.rs/params.rs are unchanged.
Dependency impact
proptest is a dev-dependency of irtt-proto only (release 1.11.0, MSRV 1.85, compatible with the workspace's 1.88 MSRV);
production dependencies unchanged;
root Cargo.lock changed only for the proptest dependency closure (new bit-set/bit-vec/rand versions added alongside existing ones used by other crates, not replacing them);
no crate versions changed;
fuzz/Cargo.lock and the fuzz workspace are unchanged.
Verification
cargo test -p irtt-proto --locked — run twice, stable, all passing (63 unit + 17/14/14 integration tests, including the new properties).
cargo publish -p irtt-proto --dry-run --locked — packages and verifies cleanly (expected warning that 0.5.0 already exists on crates.io, since this PR intentionally does not bump the version).
cd fuzz && cargo +nightly fuzz build — all fuzz targets still build.
No property failures were discovered; no production/protocol code was changed.
## Summary
- add proptest-based properties for varint/zigzag codecs;
- generate valid Params and verify semantic round trips/presence;
- verify repeated known tags are last-value-wins;
- verify unknown tags preserve known values.
## Properties
- `uvarint_round_trips` / `signed_varint_round_trips`: every `u64`/`i64` round-trips through `encode_uvarint`/`decode_uvarint` and `encode_varint`/`decode_varint`, with `used == encoded.len()` and `1 <= encoded.len() <= 10`.
- `zigzag_round_trips_from_signed` / `zigzag_round_trips_from_unsigned`: zigzag encode/decode is a bijection across the full `i64` and `u64` domains.
- `valid_params_round_trip`: generated `Params` (scalar fields over the full `i64` domain, constructive enum strategies, `Option<ServerFill>` bounded to `MAX_SERVER_FILL_BYTES`) round-trip through `encode`/`decode` byte-for-byte semantically.
- `encoded_param_presence_matches_omission_rules`: `decode_with_presence` presence exactly matches `Params::encode`'s omission rule (zero/default scalar and enum values omit their tag; `Clock::Unspecified` is the one enum whose zero is wire-omission-only; `server_fill` presence follows `Option::is_some`, including `Some("")`).
- `repeated_*_is_last_wins` (one per known tag 1-8, plus `server_fill` tag 9): two explicit values for the same tag decode to the second value, with presence `true`.
- `unknown_scalar_tag_prefix_does_not_disturb_known_params` / `..._suffix_...`: an unknown tag (10..=u16::MAX) with an arbitrary `u64` value placed before or after a valid encoded `Params` leaves the decoded value and known-tag presence unchanged.
- `omitted_vs_explicit_zero_presence_for_zero_valid_fields` (deterministic table): omitted vs. explicit-zero decode to the same value but different presence for every field where explicit zero is valid; confirms explicit `Clock=0` is rejected outright rather than accepted-as-present.
Existing hand-picked deterministic tests and byte vectors in `varint.rs`/`params.rs` are unchanged.
## Dependency impact
- `proptest` is a dev-dependency of `irtt-proto` only (release 1.11.0, MSRV 1.85, compatible with the workspace's 1.88 MSRV);
- production dependencies unchanged;
- root `Cargo.lock` changed only for the `proptest` dependency closure (new `bit-set`/`bit-vec`/`rand` versions added alongside existing ones used by other crates, not replacing them);
- no crate versions changed;
- `fuzz/Cargo.lock` and the fuzz workspace are unchanged.
## Verification
- `cargo test -p irtt-proto --locked` — run twice, stable, all passing (63 unit + 17/14/14 integration tests, including the new properties).
- `cargo fmt --all -- --check` — clean.
- `cargo check --workspace --all-targets --all-features --locked` — clean.
- `cargo test --workspace --all-targets --all-features --locked` — clean.
- `cargo clippy --workspace --all-targets --all-features --locked -- -D warnings` — clean.
- `RUSTDOCFLAGS="-D warnings" cargo doc --workspace --all-features --no-deps --locked` — clean.
- `cargo check --workspace --all-targets --no-default-features --locked` — clean.
- `cargo publish -p irtt-proto --dry-run --locked` — packages and verifies cleanly (expected warning that 0.5.0 already exists on crates.io, since this PR intentionally does not bump the version).
- `cd fuzz && cargo +nightly fuzz build` — all fuzz targets still build.
- No property failures were discovered; no production/protocol code was changed.
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
Summary
Properties
uvarint_round_trips/signed_varint_round_trips: everyu64/i64round-trips throughencode_uvarint/decode_uvarintandencode_varint/decode_varint, withused == encoded.len()and1 <= encoded.len() <= 10.zigzag_round_trips_from_signed/zigzag_round_trips_from_unsigned: zigzag encode/decode is a bijection across the fulli64andu64domains.valid_params_round_trip: generatedParams(scalar fields over the fulli64domain, constructive enum strategies,Option<ServerFill>bounded toMAX_SERVER_FILL_BYTES) round-trip throughencode/decodebyte-for-byte semantically.encoded_param_presence_matches_omission_rules:decode_with_presencepresence exactly matchesParams::encode's omission rule (zero/default scalar and enum values omit their tag;Clock::Unspecifiedis the one enum whose zero is wire-omission-only;server_fillpresence followsOption::is_some, includingSome("")).repeated_*_is_last_wins(one per known tag 1-8, plusserver_filltag 9): two explicit values for the same tag decode to the second value, with presencetrue.unknown_scalar_tag_prefix_does_not_disturb_known_params/..._suffix_...: an unknown tag (10..=u16::MAX) with an arbitraryu64value placed before or after a valid encodedParamsleaves the decoded value and known-tag presence unchanged.omitted_vs_explicit_zero_presence_for_zero_valid_fields(deterministic table): omitted vs. explicit-zero decode to the same value but different presence for every field where explicit zero is valid; confirms explicitClock=0is rejected outright rather than accepted-as-present.Existing hand-picked deterministic tests and byte vectors in
varint.rs/params.rsare unchanged.Dependency impact
proptestis a dev-dependency ofirtt-protoonly (release 1.11.0, MSRV 1.85, compatible with the workspace's 1.88 MSRV);Cargo.lockchanged only for theproptestdependency closure (newbit-set/bit-vec/randversions added alongside existing ones used by other crates, not replacing them);fuzz/Cargo.lockand the fuzz workspace are unchanged.Verification
cargo test -p irtt-proto --locked— run twice, stable, all passing (63 unit + 17/14/14 integration tests, including the new properties).cargo fmt --all -- --check— clean.cargo check --workspace --all-targets --all-features --locked— clean.cargo test --workspace --all-targets --all-features --locked— clean.cargo clippy --workspace --all-targets --all-features --locked -- -D warnings— clean.RUSTDOCFLAGS="-D warnings" cargo doc --workspace --all-features --no-deps --locked— clean.cargo check --workspace --all-targets --no-default-features --locked— clean.cargo publish -p irtt-proto --dry-run --locked— packages and verifies cleanly (expected warning that 0.5.0 already exists on crates.io, since this PR intentionally does not bump the version).cd fuzz && cargo +nightly fuzz build— all fuzz targets still build.