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:
- Parity gaps — features already planned/missing vs Node.js (suspend/resume, peer info, connection stats, per-topic handles, etc.)
- Configuration/options structs — inherently extensible, new tuning knobs are expected
- Error enums — new error conditions emerge as features are added
- 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.
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:
Exclusion criteria (LEAST likely to change):
HandshakeMessage,HolepunchMessage,NoisePayload,UdxInfo,SecretStreamInfo,RelayThroughInfo,HolepunchPayload,HyperPeer,AnnounceMessage,LookupRawReply,MutablePutRequest,MutableGetResponse,MutableSignable,RelayInfo,HolepunchInfo,PairMessage,UnpairMessageCommand,Message,ControlFrame,DecodedFramepub(crate)or#[doc(hidden)]) typesKeyPair(2-field struct, format locked by libsodium compat)Proposed Changes
Tier 1 — HIGH confidence (config/options structs, strongly evidenced by reference implementation gap analysis)
SwarmConfigpeeroxideJoinOptspeeroxideHyperDhtConfigpeeroxide-dhtDhtConfigpeeroxide-dhtPersistentConfigpeeroxide-dhtServerConfigpeeroxide-dhtTier 2 — HIGH confidence (error enums, new variants expected)
SwarmErrorpeeroxideHyperDhtErrorpeeroxide-dhtDhtErrorpeeroxide-dhtUdxErrorlibudxRelayErrorpeeroxide-dhtSecretStreamErrorpeeroxide-dhtNoiseErrorpeeroxide-dhtNoiseWrapErrorpeeroxide-dhtProtomuxErrorpeeroxide-dhtIoErrorpeeroxide-dhtRouterErrorpeeroxide-dhtSecurePayloadErrorpeeroxide-dhtSocketPoolErrorpeeroxide-dhtEncodingErrorpeeroxide-dhtHeaderErrorlibudxTier 3 — MEDIUM confidence (event/result structs that will grow with features)
SwarmConnectionpeeroxidepeer_info, priority, attempt count, bandwidth statsPeerInfopeeroxidePrioritypeeroxideServerEventpeeroxide-dhtConnectResultpeeroxide-dhtPeerConnectionpeeroxide-dhtLookupResultpeeroxide-dhtAnnounceResultpeeroxide-dhtImmutablePutResultpeeroxide-dhtMutablePutResultpeeroxide-dhtMutableGetResultpeeroxide-dhtQueryReplypeeroxide-dhtQueryResultpeeroxide-dhtHandshakeActionpeeroxide-dhtHolepunchActionpeeroxide-dhtHandlerReplypeeroxide-dhtChannelEventpeeroxide-dhtHolepunchEventpeeroxide-dhtPingResponsepeeroxide-dhtResponseDatapeeroxide-dhtTier 4 — LOW priority (stable but included for completeness)
NoiseWrapResultpeeroxide-dhtHandshakeResult(router)peeroxide-dhtHolepunchResultpeeroxide-dhtForwardEntrypeeroxide-dhtExplicitly 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,RelayThroughInfoHandshakeMessage,HolepunchMessage,HyperPeer,AnnounceMessageLookupRawReply,MutablePutRequest,MutableGetResponse,MutableSignableRelayInfo,HolepunchInfo,PairMessage,UnpairMessage,PairResponseCommand,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, andmatcharms must add wildcards):peeroxide/src/swarm.rs(unit tests)SwarmConfig,JoinOpts,PeerInfoDefault+ field overrides or builderpeeroxide/src/peer_info.rs(unit tests)PeerInfoPeerInfo::new()is fine, but any direct construction would breakpeeroxide/tests/hyperswarm_interop.rsSwarmConfig,JoinOpts,DhtConfig,HyperDhtConfigpeeroxide-dht/tests/hyperdht_interop.rsHyperDhtConfig,DhtConfigpeeroxide-dht/tests/hyperdht_connect_interop.rsHyperDhtConfig,DhtConfig,ServerConfigpeeroxide-dht/tests/dht_interop.rsDhtConfigpeeroxide-dht/src/hyperdht.rs(unit tests)HyperDhtConfig,DhtConfig,PersistentConfig,ConnectResult,NoiseWrapResultNote:
NoisePayloadis in the excluded wire-protocol list, sohyperdht_connect_interop.rsandnoise_ik_golden_interop.rstests are NOT affected.Mitigation strategy for tests
Defaultimpls → tests switch to..Default::default()struct update syntax (works within the same crate where#[non_exhaustive]doesn't apply)tests/) WILL break for non_exhaustive structs → need builder methods orDefault+ setter pattern_ => unreachable!()or..wildcard armsTotal estimated test changes: ~15-25 struct literal sites across 6 test files (integration tests), plus adding wildcard match arms to any exhaustive
matchon affected enums.