Skip to content

Add #[non_exhaustive] to public API types likely to evolve #9

@eshork

Description

@eshork

Summary

Add #[non_exhaustive] to public exported structs, enums, and variants that are likely to gain new fields or variants in future non-major releases, based on hyperswarm Node.js reference implementation parity gaps.

This is an API-breaking change. The current expectation is to release it as a minor version change (1.1.0). This is due to the fact that the public API is not yet widely used (recently released, no published downstream crates). Future breaking changes will follow semver guidelines and be released as major version changes.

Methodology

Selection criteria — symbols likely to gain new fields/variants in non-major versions based on:

  1. Parity gaps — features already planned/missing vs Node.js (suspend/resume, peer info, connection stats, per-topic handles, etc.)
  2. Configuration/options structs — inherently extensible, new tuning knobs are expected
  3. Error enums — new error conditions emerge as features are added
  4. Event/result enums — new variants as workflows expand

Exclusion criteria (LEAST likely to change):

  • Wire-protocol message structs (must match Node.js encoding exactly): HandshakeMessage, HolepunchMessage, NoisePayload, UdxInfo, SecretStreamInfo, RelayThroughInfo, HolepunchPayload, HyperPeer, AnnounceMessage, LookupRawReply, MutablePutRequest, MutableGetResponse, MutableSignable, RelayInfo, HolepunchInfo, PairMessage, UnpairMessage
  • Wire-format enums: Command, Message, ControlFrame, DecodedFrame
  • Internal (pub(crate) or #[doc(hidden)]) types
  • Stable crypto primitives: KeyPair (2-field struct, format locked by libsodium compat)

Proposed Changes

Tier 1 — HIGH confidence (config/options structs, strongly evidenced by reference implementation gap analysis)

# Symbol Crate Rationale
1 SwarmConfig peeroxide all require new config fields (suspend policy, connection limits, peer priority config, etc.)
2 JoinOpts peeroxide per-topic discovery options (flush policy, discovery handle config)
3 HyperDhtConfig peeroxide-dht Will grow as NAT/relay/persistence tuning is added
4 DhtConfig peeroxide-dht New bootstrap modes, adaptive concurrency, timeouts
5 PersistentConfig peeroxide-dht Storage tuning knobs will expand
6 ServerConfig peeroxide-dht suspend, relay address override, connection hooks

Tier 2 — HIGH confidence (error enums, new variants expected)

# Symbol Crate Rationale
7 SwarmError peeroxide New error conditions: suspend errors, join_peer failures, connection set errors
8 HyperDhtError peeroxide-dht New error paths as features are added (relay auth, mutable storage conflicts)
9 DhtError peeroxide-dht Network change errors, timeout variants
10 UdxError libudx New transport-layer error conditions (MTU, congestion)
11 RelayError peeroxide-dht New relay failure modes (auth, rate limiting)
12 SecretStreamError peeroxide-dht Rekeying errors, version negotiation
13 NoiseError peeroxide-dht New handshake patterns may introduce error states
14 NoiseWrapError peeroxide-dht Mirrors NoiseError expansion
15 ProtomuxError peeroxide-dht New channel/mux error conditions
16 IoError peeroxide-dht New IO failure modes
17 RouterError peeroxide-dht New routing failure conditions
18 SecurePayloadError peeroxide-dht Versioning, new crypto errors
19 SocketPoolError peeroxide-dht Pool exhaustion, bind failures
20 EncodingError peeroxide-dht New encoding edge cases
21 HeaderError libudx New header validation checks

Tier 3 — MEDIUM confidence (event/result structs that will grow with features)

# Symbol Crate Rationale
22 SwarmConnection peeroxide will gain peer_info, priority, attempt count, bandwidth stats
23 PeerInfo peeroxide will gain new metadata fields (last seen, connection quality, etc.)
24 Priority peeroxide New priority levels possible as scheduling evolves
25 ServerEvent peeroxide-dht network-change events, suspend events, new request types
26 ConnectResult peeroxide-dht New connection metadata (RTT estimate, relay path, NAT type)
27 PeerConnection peeroxide-dht May gain stats, connection type metadata
28 LookupResult peeroxide-dht May gain timing/routing metadata
29 AnnounceResult peeroxide-dht May gain per-node success/failure detail
30 ImmutablePutResult peeroxide-dht May gain replication count, timing
31 MutablePutResult peeroxide-dht May gain conflict info
32 MutableGetResult peeroxide-dht May gain freshness/provenance metadata
33 QueryReply peeroxide-dht New query response metadata
34 QueryResult peeroxide-dht New aggregate stats
35 HandshakeAction peeroxide-dht New routing decisions possible
36 HolepunchAction peeroxide-dht New holepunch strategies
37 HandlerReply peeroxide-dht New reply modes
38 ChannelEvent peeroxide-dht New protomux channel events
39 HolepunchEvent peeroxide-dht New holepunch lifecycle events (Progress, Timeout)
40 PingResponse peeroxide-dht May gain NAT info
41 ResponseData peeroxide-dht May gain metadata

Tier 4 — LOW priority (stable but included for completeness)

# Symbol Crate Rationale
42 NoiseWrapResult peeroxide-dht Unlikely but new crypto metadata possible
43 HandshakeResult (router) peeroxide-dht New relay routing info
44 HolepunchResult peeroxide-dht New punch metadata
45 ForwardEntry peeroxide-dht New routing attributes

Explicitly Excluded (wire-protocol, stable by protocol definition)

These MUST NOT get #[non_exhaustive] — they match the Node.js wire format exactly:

  • NoisePayload, HolepunchPayload, UdxInfo, SecretStreamInfo, RelayThroughInfo
  • HandshakeMessage, HolepunchMessage, HyperPeer, AnnounceMessage
  • LookupRawReply, MutablePutRequest, MutableGetResponse, MutableSignable
  • RelayInfo, HolepunchInfo, PairMessage, UnpairMessage, PairResponse
  • Command, Message, Request, Response (wire messages)
  • ControlFrame, DecodedFrame, BatchItem (protomux wire frames)
  • Ipv4Peer (wire address format)
  • Header, SackRange (UDX wire header)
  • KeyPair (2-field libsodium layout, effectively frozen)
  • Datagram (raw UDP packet representation)
  • Node (routing table node, matches dht-rpc layout)

Test Footprint

Tests that will require updates (struct literal construction becomes invalid with #[non_exhaustive] from external crates, and match arms must add wildcards):

Test File Affected Symbols Impact
peeroxide/src/swarm.rs (unit tests) SwarmConfig, JoinOpts, PeerInfo Struct literal construction → must use Default + field overrides or builder
peeroxide/src/peer_info.rs (unit tests) PeerInfo PeerInfo::new() is fine, but any direct construction would break
peeroxide/tests/hyperswarm_interop.rs SwarmConfig, JoinOpts, DhtConfig, HyperDhtConfig Lines 184-204: struct literal construction
peeroxide-dht/tests/hyperdht_interop.rs HyperDhtConfig, DhtConfig Lines 160-168: struct literal construction
peeroxide-dht/tests/hyperdht_connect_interop.rs HyperDhtConfig, DhtConfig, ServerConfig Lines 43-107: struct literals
peeroxide-dht/tests/dht_interop.rs DhtConfig Lines 55-60: struct literal
peeroxide-dht/src/hyperdht.rs (unit tests) HyperDhtConfig, DhtConfig, PersistentConfig, ConnectResult, NoiseWrapResult Lines 2137-2238: struct literals in tests

Note: NoisePayload is in the excluded wire-protocol list, so hyperdht_connect_interop.rs and noise_ik_golden_interop.rs tests are NOT affected.

Mitigation strategy for tests

  • Config structs already have Default impls → tests switch to ..Default::default() struct update syntax (works within the same crate where #[non_exhaustive] doesn't apply)
  • Cross-crate integration tests (in tests/) WILL break for non_exhaustive structs → need builder methods or Default + setter pattern
  • Result structs constructed only internally (returned from APIs) → no external test impact
  • Enum matches in tests will need _ => unreachable!() or .. wildcard arms

Total estimated test changes: ~15-25 struct literal sites across 6 test files (integration tests), plus adding wildcard match arms to any exhaustive match on affected enums.

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