Skip to content

feat(client,server)!: typed CapacityKind in place of the string tag - #151

Merged
JustinKovacich merged 3 commits into
mainfrom
feat/typed-capacity-kind
Aug 24, 2026
Merged

feat(client,server)!: typed CapacityKind in place of the string tag#151
JustinKovacich merged 3 commits into
mainfrom
feat/typed-capacity-kind

Conversation

@JustinKovacich

Copy link
Copy Markdown
Contributor

Closes #146.

Stacked on #150 — merge order is #150 → this. The base is feat/error-surface-and-caps, not main, because both touch client/error.rs and CapacityKind is itself #[non_exhaustive], which #150 establishes.

What

client::Error::Capacity and server::Error::Capacity carried a snake_case string tag, with docs instructing the reader to grep the crate for it to find the governing constant. The five documented tags become CapacityKind variants, each carrying the documentation that used to live in a bulleted list on the variant — the information moves from prose into the type.

// Before
Err(Error::Capacity(tag)) if tag == "service_registry" => ...,

// After
Err(Error::Capacity(CapacityKind::ServiceRegistry)) => ...,

Decisions worth reviewing

One shared kind, not one per error type. The server only produces UdpBuffer today, so a server-specific enum would be smaller and tighter. I went the other way: a consumer handling capacity exhaustion should not learn two vocabularies for one condition, and #[non_exhaustive] means the asymmetry costs nothing as the server grows others. The module doc states this explicitly so it reads as a decision rather than an oversight.

Display is unchanged, and pinned. CapacityKind::as_str returns the exact pre-0.11.0 literals, and a test asserts each one against its literal. Anything reading the rendered error keeps working while it migrates off text-matching — which is the practice this change exists to let consumers stop.

reject_with_capacity keeps its parameter. Every caller passes RequestQueue today, so the parameter could have been dropped. It is typed instead: it exists so that rejection path can name a different structure later, and collapsing it would have to be undone.

Two things the build caught

The Display test cannot use to_string(). capacity is compiled unconditionally, so the test runs under --no-default-features where there is no allocator. It formats through core::fmt::Write into a fixed buffer instead.

Intra-doc links into client / server do not resolve from capacity. Same trap as #150: this module is ungated, those are behind features, so linking their error types fails the single-feature doc builds. They are prose in the module doc, with a comment saying why; the one link that is safe (crate::CapacityKind, ungated) is fully qualified.

This is the second time in this batch that a plausible-looking doc link silently only worked in one configuration. Unlike #145 the doc lane does catch it — worth keeping that lane in CI.

Verification

  • cargo clippy -- -D warnings -D clippy::pedantic on all five lanes CI runs: alloc/host workspace, --no-default-features, and the three bare_metal combinations.
  • cargo test --no-default-features — 253 lib tests (two new), all green.
  • cargo test --features client,bare_metal --test no_alloc_witness green.
  • cargo doc --no-deps with RUSTDOCFLAGS=-D warnings for client, server,bare_metal, and the alloc set.
  • cargo fmt --all -- --check clean.
  • grep -rn 'Capacity("' src/ tests/ examples/ returns nothing — no string tag survives.

@JustinKovacich JustinKovacich added the enhancement New feature or request label Aug 20, 2026
@JustinKovacich JustinKovacich self-assigned this Aug 20, 2026
@JustinKovacich
JustinKovacich marked this pull request as ready for review August 20, 2026 20:16
@JustinKovacich
JustinKovacich force-pushed the feat/error-surface-and-caps branch from ecd4697 to ecb337f Compare August 21, 2026 13:35
@JustinKovacich
JustinKovacich force-pushed the feat/typed-capacity-kind branch from 713039e to 45d2a14 Compare August 21, 2026 13:35
Base automatically changed from feat/error-surface-and-caps to main August 21, 2026 16:48
JustinKovacich and others added 2 commits August 24, 2026 10:15
…acityKind

Closes #146.

`client::Error::Capacity` and `server::Error::Capacity` carried a
`snake_case` string tag, and the docs told the reader to grep the crate for
it to find the governing constant. A consumer wanting to tell "the service
registry is full" from "the UDP buffer overflowed" had to compare text
against a tag set the type system never mentioned — which fails silently, at
runtime, and produces a wrong classification rather than an error when a tag
is reworded.

The five documented tags become `CapacityKind` variants, each carrying the
documentation that used to sit in a bulleted list on the variant. The kind is
shared between client and server rather than split in two, so capacity
exhaustion is handled the same way whichever layer reports it; the server
currently produces only `UdpBuffer`, and `#[non_exhaustive]` keeps that
asymmetry from being a problem as it grows others.

`Display` output is unchanged. `CapacityKind::as_str` returns the exact
pre-0.11.0 literals and a test pins each one, so anything reading the
rendered error keeps working while it migrates.

`reject_with_capacity`'s `structure_name` parameter is typed rather than
removed, even though every caller passes `RequestQueue` today — the
parameter exists so the rejection path can name a different structure later.

Notes:

The `Display` test formats through `core::fmt::Write` into a fixed buffer
rather than `to_string()`, so it runs under `--no-default-features` where
there is no allocator.

`capacity` is compiled unconditionally while `client` and `server` are
feature-gated, so its module docs reference those error types in prose
rather than as intra-doc links — linking them fails the single-feature doc
builds. The doc lane caught it.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
0.11.0 was tagged and released while this branch was open, so the changelog
entry written for it now sits under a shipped section and the `Cargo.toml`
version it assumed is taken.

Move the `CapacityKind` entry into a new `## [0.12.0]` section and bump
`version` to 0.12.0 — the same convention 0.10.0 and 0.11.0 used, where the
version rides in the PR so `cargo-semver-checks` compares against the version
the break actually lands as. `simple-someip-embassy-net` pins the parent by
version (`"0.11"`), so it moves too or the workspace stops resolving.

The 0.11.0 preamble is restored to its released wording, and the three
"pre-0.11.0" references — the `as_str` docs, the `Capacity` variant docs, and
the changelog line about the pinned literals — become "0.12.0", since those
strings did ship in 0.11.0.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@JustinKovacich
JustinKovacich force-pushed the feat/typed-capacity-kind branch from 45d2a14 to ae35a63 Compare August 24, 2026 14:22
`tests/bare_metal_e2e.rs` matches on `Capacity(CapacityKind::UdpBuffer)` in
five places but never imported the type, so the harness failed to compile with
five E0433s.

The gap survived because that binary only builds under the alloc + `bare_metal`
feature set the coverage job selects; the default-feature and per-feature lanes
gate it out entirely, and the branch had no CI run of its own before now.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@codecov-commenter

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 79.09091% with 23 lines in your changes missing coverage. Please review.
✅ All tests successful. No failed tests found.

Files with missing lines Patch % Lines
src/client/inner.rs 72.00% 7 Missing ⚠️
src/server/event_publisher.rs 50.00% 7 Missing ⚠️
src/client/bind_dispatch.rs 50.00% 3 Missing ⚠️
src/client/socket_manager.rs 60.00% 2 Missing ⚠️
src/server/runtime.rs 84.61% 2 Missing ⚠️
src/capacity.rs 97.67% 1 Missing ⚠️
src/server/sd_state.rs 66.66% 1 Missing ⚠️

❌ Your patch status has failed because the patch coverage (79.09%) is below the target coverage (80.00%). You can increase the patch coverage or adjust the target coverage.

Impacted file tree graph

@@            Coverage Diff             @@
##             main     #151      +/-   ##
==========================================
+ Coverage   81.25%   81.30%   +0.04%     
==========================================
  Files          46       47       +1     
  Lines       15470    15514      +44     
==========================================
+ Hits        12570    12613      +43     
- Misses       2900     2901       +1     
Files with missing lines Coverage Δ
src/client/error.rs 100.00% <100.00%> (ø)
src/client/mod.rs 81.92% <ø> (ø)
src/lib.rs 0.00% <ø> (ø)
src/server/error.rs 100.00% <ø> (ø)
src/capacity.rs 97.67% <97.67%> (ø)
src/server/sd_state.rs 56.98% <66.66%> (ø)
src/client/socket_manager.rs 77.70% <60.00%> (ø)
src/server/runtime.rs 77.67% <84.61%> (ø)
src/client/bind_dispatch.rs 50.00% <50.00%> (ø)
src/client/inner.rs 94.39% <72.00%> (+<0.01%) ⬆️
... and 1 more

@JustinKovacich
JustinKovacich added this pull request to the merge queue Aug 24, 2026
Merged via the queue into main with commit 956d0d7 Aug 24, 2026
7 of 8 checks passed
@JustinKovacich
JustinKovacich deleted the feat/typed-capacity-kind branch August 24, 2026 14:45
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

client: replace Capacity(&'static str) with a typed capacity kind

3 participants