Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement subtraction between IpNetworks #126

Open
wants to merge 12 commits into
base: master
Choose a base branch
from

Conversation

jvff
Copy link

@jvff jvff commented Feb 15, 2020

This PR implements the Sub trait for IpNetwork, Ipv4Network and Ipv6Network. There are two possibilities: either a single IP network item is subtracted from the original IP network, or multiple IP network items are subtracted from the original IP network.

The result of the subtraction operation is always an iterator, which can contain zero or more IP network items. For subtracting a single item, the iterator has a rather simple representation in memory and does implement Copy. When subtracting multiple items, a linked list of Box<dyn Iterator> is returned, so the resulting type has a more complex representation.

With this PR it is still not currently possible to subtract between IP networks with different protocols (for example, subtract an IPv4 network from an IPv6 network or vice-versa). Attempting to do so will lead the code to panic.

This is a helper type that is created with an initial IPv4 network,
represented as a `u32` representation of its IP address and a `u8` with
its prefix, and the prefix of a larger IPv4 network which contains the
initial IPv4 network. Since one is contained in the other, the IP
address shares most bits, so it only needs to keep track of it once.
However, proper care must be taken so that the initial network prefix is
larger than the larger network prefix.

The iterator will produce `Ipv4Network` items representing increasing
network ranges that are still inside the larger network but do not
include the initial network.
This is also an iterator, and it wraps around the `Ipv4NetworkSubSet`
type. However, it also includes entries for when the minuend and the
subtrahend don't overlap and for when the subtrahend completly ovelaps
the minuend.

In the former case, there is no overlap of the networks. Therefore,
nothing is subtracted from the original network (the minuend), so the
result is just the original network.

In the latter case, since the subtrahend completly overlaps the minuend,
it is in effect completely removing the original network. Therefore, the
result is no networks at all, and the resulting iterator is empty.
The resulting set is returned through a `Ipv4NetworkSubResult` helper
iterator.
This allows one to subtract multiple `Ipv4Network`s from a single
`Ipv4Network`. This works by having a subtraction chain, where the
original minuend `Ipv4Network` is subtracted by the first `Ipv4Network`
subtrahend, and the result is then subtracted by the second
`Ipv4Network` subtrahend, and so on.

The implementation uses dynamic dispatch because it is impossible to
know how many subtrahends there will be. This is a simple initial
implementation, and tere might be other solutions, such as creating a
custom iterator and looping around all subtrahends to provide the
results, but it quickly becomes more complicated. This might be doable
as future work.

Another possible future work is to remove the dynamic dispatch for known
sizes of subtrahend arrays, but this would probably require const
generics to be stabilized.
This is the IPv6 equivalent of the `Ipv4NetworkSubSet`.

It is a helper type that is created with an initial IPv6 network,
represented as a `u128` representation of its IP address and a `u8` with
its prefix, and the prefix of a larger IPv6 network which contains the
initial IPv6 network. Since one is contained in the other, the IP
address shares most bits, so it only needs to keep track of it once.
However, proper care must be taken so that the initial network prefix is
larger than the larger network prefix.

The iterator will produce `Ipv6Network` items representing increasing
network ranges that are still inside the larger network but do not
include the initial network.
This is the IPv6 equivalent to the `Ipv4NetworkSubResult` type.

This is also an iterator, and it wraps around the `Ipv6NetworkSubSet`
type. However, it also includes entries for when the minuend and the
subtrahend don't overlap and for when the subtrahend completly ovelaps
the minuend.

In the former case, there is no overlap of the networks. Therefore,
nothing is subtracted from the original network (the minuend), so the
result is just the original network.

In the latter case, since the subtrahend completly overlaps the minuend,
it is in effect completely removing the original network. Therefore, the
result is no networks at all, and the resulting iterator is empty.
The resulting set is returned through a `Ipv6NetworkSubResult` helper
iterator.
This allows one to subtract multiple `Ipv6Network`s from a single
`Ipv6Network`. This works by having a subtraction chain, where the
original minuend `Ipv6Network` is subtracted by the first `Ipv6Network`
subtrahend, and the result is then subtracted by the second
`Ipv6Network` subtrahend, and so on.

The implementation uses dynamic dispatch because it is impossible to
know how many subtrahends there will be. This is a simple initial
implementation, and tere might be other solutions, such as creating a
custom iterator and looping around all subtrahends to provide the
results, but it quickly becomes more complicated. This might be doable
as future work.

Another possible future work is to remove the dynamic dispatch for known
sizes of subtrahend arrays, but this would probably require const
generics to be stabilized.
This type represents the result of the subtraction of one `IpNetwork`
from another. The implementation just wraps the resulting subtraction of
the protocol specific (IPv4 or IPv6) subtraction result.

Note that this means that it is not currently possible to subtract
`IpNetwork`s of different protocols (i.e., either an IPv4 network from
an IPv6 network or vice-versa).
The resulting set is returned through a `IpNetworkSubResult` helper
iterator.

Note that it is not currently possible to subtract `IpNetwork`s of
different protocols (i.e., either an IPv4 network from an IPv6 network
or vice-versa).
This allows one to subtract multiple `IpNetwork`s from a single
`IpNetwork`. This works by having a subtraction chain, where the
original minuend `IpNetwork` is subtracted by the first `IpNetwork`
subtrahend, and the result is then subtracted by the second
`IpNetwork` subtrahend, and so on.

Since it isn't currently possible to subtract `IpNetworks` of different
protocols, all operands must be of the same protocol (either IPv4 or
IPv6). Having one operand of a different protocol will cause the code to
panic.

The implementation uses dynamic dispatch because it is impossible to
know how many subtrahends there will be. This is a simple initial
implementation, and tere might be other solutions, such as creating a
custom iterator and looping around all subtrahends to provide the
results, but it quickly becomes more complicated. This might be doable
as future work.

Another possible future work is to remove the dynamic dispatch for known
sizes of subtrahend arrays, but this would probably require const
generics to be stabilized.
@ctrlcctrlv
Copy link
Contributor

this pr is cool

@Alextopher Alextopher mentioned this pull request Apr 29, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

2 participants