feat: add IpNetwork::to_ipv6_mapped and to_canonical for dual-stack conversion - #99
Merged
Merged
Conversation
Merged
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes an API gap on the
IpNetworkenum:Ipv4Networkhasto_ipv6_mapped()andIpv6Networkhasto_ipv4_mapped(), but the enum itself had no way to move between address families.The motivating use case is dual-stack comparison. On the enum,
contains/intersectsreturnfalse/Noneacross families by design, so lifting both operands into IPv6 space is the way to compare them meaningfully.API
IpNetwork::to_ipv6_mapped(&self) -> Ipv6Network— embeds the network into IPv6 space.V4delegates toIpv4Network::to_ipv6_mapped(),V6is the identity (the result is therefore not necessarily::ffff:-prefixed).IpNetwork::to_canonical(&self) -> IpNetwork— mirrorscore::net::IpAddr::to_canonical.V4passes through,V6collapses toV4when it is IPv4-mapped.impl From<IpNetwork> for Ipv6Network, next to the existingFrom<Ipv4Network>.Both methods are
const fn,#[inline],#[must_use], and delegate to the existing conversion methods — no bit arithmetic is re-derived.Ipv6Network::is_ipv4_mapped_ipv6requires both the address to be::ffff:-prefixed and the mask's top 96 bits to be all ones, soto_ipv4_mappedis the exact inverse ofto_ipv6_mappedon the image of the embedding, andto_canonicalnever loses addresses.Tests
12 unit tests and 9 property tests. Coverage includes non-contiguous masks in both families, the IPv4-compatible-but-not-mapped case, and the case where the address is
::ffff:-prefixed but the mask does not pin the top 96 bits (the network must stayV6— collapsing it would drop addresses).Two property tests pin the motivating use case:
a.contains(&b) == a.to_ipv6_mapped().contains(&b.to_ipv6_mapped()), and likewise forintersects.No benchmarks: these are two-arm delegating wrappers over already-benchmarked methods, so no new hot path is introduced.