Arithmetic: address stepping#123
Conversation
Add `next()`, `previous()`, and `offset(int)` to `Contracts\ArithmeticInterface`.
Greptile SummaryThis PR adds
Confidence Score: 4/5Safe to merge; the arithmetic logic, overflow detection, and Multi embedding-strategy branching are all correct and well-tested. The core Binary::addIntegerOffset carry algorithm was already battle-tested; the new code wires it up cleanly and the Multi override correctly isolates stepping within the IPv4 address space. A single documentation nuance — the non-canonical bit-preservation guarantee is stated unconditionally but silently degrades for strategies that don't implement CanonicalEmbeddingInterface — is worth a follow-up but does not affect runtime correctness. docs/04-helpers.md — the preservation guarantee needs a caveat for CanonicalEmbeddingInterface-less strategies. Important Files Changed
Flowchart%%{init: {'theme': 'neutral'}}%%
flowchart TD
A["caller: ip->offset(n) / next() / previous()"] --> B{Instance type?}
B -->|IPv4 or IPv6\nAbstractIP| C["Binary::addIntegerOffset(binary, n)"]
C -->|carry != 0| D["throw OverflowException"]
C -->|carry == 0| E["new static(newBinary)"]
B -->|Multi| F{isEmbedded?}
F -->|No — pure IPv6| G["parent::offset(n)\n→ Binary::addIntegerOffset on 16-byte binary"]
G -->|carry != 0| D
G -->|ok| H["new static(newBinary, clone strategy)"]
F -->|Yes — IPv4 embedded| I["getShortBinary()\n→ extract 4-byte IPv4"]
I --> J["new IPv4(short)->offset(n)"]
J -->|OverflowException\nat IPv4 boundary| D
J -->|ok: newV4| K{strategy implements\nCanonicalEmbeddingInterface?}
K -->|Yes| L["strategy->packIntoNonCanonical(ipv6, newV4)\npreserves non-IPv4 bits"]
K -->|No — graceful degradation| M["strategy->pack(newV4)\nreturns canonical form"]
L --> N["new static(packed16, clone strategy)"]
M --> N
%%{init: {'theme': 'base', 'themeVariables': {"darkMode": true, "background": "#0d1117", "primaryColor": "#21262d", "primaryTextColor": "#e6edf3", "primaryBorderColor": "#8b949e", "lineColor": "#8b949e", "textColor": "#e6edf3", "edgeLabelBackground": "#161b22", "actorBkg": "#21262d", "actorBorder": "#8b949e", "actorTextColor": "#e6edf3", "actorLineColor": "#8b949e", "signalColor": "#8b949e", "signalTextColor": "#e6edf3", "noteBkgColor": "#373320", "noteBorderColor": "#d4a72c", "noteTextColor": "#f0e6c0", "labelBoxBkgColor": "#21262d", "labelBoxBorderColor": "#8b949e", "labelTextColor": "#e6edf3", "loopTextColor": "#e6edf3", "activationBkgColor": "#30363d", "activationBorderColor": "#8b949e"}}}%%
flowchart TD
A["caller: ip->offset(n) / next() / previous()"] --> B{Instance type?}
B -->|IPv4 or IPv6\nAbstractIP| C["Binary::addIntegerOffset(binary, n)"]
C -->|carry != 0| D["throw OverflowException"]
C -->|carry == 0| E["new static(newBinary)"]
B -->|Multi| F{isEmbedded?}
F -->|No — pure IPv6| G["parent::offset(n)\n→ Binary::addIntegerOffset on 16-byte binary"]
G -->|carry != 0| D
G -->|ok| H["new static(newBinary, clone strategy)"]
F -->|Yes — IPv4 embedded| I["getShortBinary()\n→ extract 4-byte IPv4"]
I --> J["new IPv4(short)->offset(n)"]
J -->|OverflowException\nat IPv4 boundary| D
J -->|ok: newV4| K{strategy implements\nCanonicalEmbeddingInterface?}
K -->|Yes| L["strategy->packIntoNonCanonical(ipv6, newV4)\npreserves non-IPv4 bits"]
K -->|No — graceful degradation| M["strategy->pack(newV4)\nreturns canonical form"]
L --> N["new static(packed16, clone strategy)"]
M --> N
Reviews (1): Last reviewed commit: "feature(arithmetic): ✨ step IP addresses..." | Re-trigger Greptile |
| ### Address Arithmetic | ||
|
|
||
| Arithmetic is performed within the address space of the instance. For an | ||
| IPv4-embedded `Multi` address the embedded IPv4 address is stepped and re-packed |
There was a problem hiding this comment.
Non-canonical bit preservation caveat missing from docs
The statement "preserving any bits the strategy does not own" is only accurate for embedding strategies that implement CanonicalEmbeddingInterface. For a legacy or user-defined strategy that implements only EmbeddingStrategyInterface, packIntoNonCanonical falls back to calling the deprecated pack($ipv4), which creates a fully canonical address and silently discards any non-canonical bits (SLA ID, interface ID, etc.) — the same graceful-degradation behaviour already present in getNetworkIp and getBroadcastIp.
Adding a short qualifier (e.g. "…re-packed according to its embedding strategy (preserving any bits the strategy does not own, provided the strategy implements CanonicalEmbeddingInterface)…") would prevent users with custom strategies from being surprised.
Add
next(),previous(), andoffset(int)toContracts\ArithmeticInterface.