• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

lduchosal / ipnetwork / 808

17 Aug 2025 08:25AM UTC coverage: 93.223% (-1.0%) from 94.226%
808

push

appveyor

web-flow
Chore: cleanup, breaking changes, enum, tryparse, exception, static ListIPAddress (#363)

* Chore: huge cleanup, enum, tryparse, exception, static ListIPAddress, important changes : IPNetwork comparison and sort order have change to reflect expected behavoir
* Fix: obsolete enums
* Fix: network sorting and member comparison
* Chore: upgrade version number 3.3

1802 of 1933 relevant lines covered (93.22%)

726934.37 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

89.47
/src/System.Net.IPNetwork/IPNetwork2Substract.cs
1
// <copyright file="IPNetwork2Supernet.cs" company="IPNetwork">
2
// Copyright (c) IPNetwork. All rights reserved.
3
// </copyright>
4

5
using System.Collections.Generic;
6
using System.Linq;
7

8
namespace System.Net;
9

10
/// <summary>
11
/// Substract.
12
/// </summary>
13
public sealed partial class IPNetwork2
14
{
15
    /// <summary>
16
    /// Implementation for IP network symmetric difference (subtraction)
17
    /// 0.0.0.0/0 - 10.0.0.1/32 = [
18
    ///     0.0.0.0/5, 8.0.0.0/7, 10.0.0.0/32, 10.0.0.2/31, 10.0.0.4/30, 10.0.0.8/29,
19
    ///     10.0.0.16/28, 10.0.0.32/27, 10.0.0.64/26, 10.0.0.128/25, 10.0.1.0/24, 10.0.2.0/23,
20
    ///     10.0.4.0/22, 10.0.8.0/21, 10.0.16.0/20, 10.0.32.0/19, 10.0.64.0/18, 10.0.128.0/17,
21
    ///     10.1.0.0/16, 10.2.0.0/15, 10.4.0.0/14, 10.8.0.0/13, 10.16.0.0/12, 10.32.0.0/11,
22
    ///     10.64.0.0/10, 10.128.0.0/9, 11.0.0.0/8, 12.0.0.0/6, 16.0.0.0/4, 32.0.0.0/3,
23
    ///     64.0.0.0/2, 128.0.0.0/1
24
    /// ].
25
    /// </summary>
26
    /// <param name="network2">The network to subtract.</param>
27
    /// <returns>A list of IP Network.</returns>
28
    public List<IPNetwork2> Subtract(IPNetwork2 network2)
29
    {
38✔
30
        InternalSubtract(false, this, network2, out List<IPNetwork2> result);
38✔
31
        return result;
36✔
32
    }
36✔
33

34
    /// <summary>
35
    /// Implementation for IP network symmetric difference (subtraction)
36
    /// 0.0.0.0/0 - 10.0.0.1/32 = [
37
    ///     0.0.0.0/5, 8.0.0.0/7, 10.0.0.0/32, 10.0.0.2/31, 10.0.0.4/30, 10.0.0.8/29,
38
    ///     10.0.0.16/28, 10.0.0.32/27, 10.0.0.64/26, 10.0.0.128/25, 10.0.1.0/24, 10.0.2.0/23,
39
    ///     10.0.4.0/22, 10.0.8.0/21, 10.0.16.0/20, 10.0.32.0/19, 10.0.64.0/18, 10.0.128.0/17,
40
    ///     10.1.0.0/16, 10.2.0.0/15, 10.4.0.0/14, 10.8.0.0/13, 10.16.0.0/12, 10.32.0.0/11,
41
    ///     10.64.0.0/10, 10.128.0.0/9, 11.0.0.0/8, 12.0.0.0/6, 16.0.0.0/4, 32.0.0.0/3,
42
    ///     64.0.0.0/2, 128.0.0.0/1
43
    /// ].
44
    /// </summary>
45
    /// <param name="network2">The network to supernet with.</param>
46
    /// <param name="result">The resulting IPNetwork.</param>
47
    /// <returns>true if network2 was subtracted successfully; otherwise, false.</returns>
48
    public bool TrySubtract(IPNetwork2 network2, out List<IPNetwork2> result)
49
    {
11✔
50
        bool parsed = InternalSubtract(true, this, network2, out result);
11✔
51
        return parsed;
11✔
52
    }
11✔
53

54
    /// <summary>
55
    /// Attempts to merge two adjacent IP networks with equal CIDR values into a single supernet.
56
    /// </summary>
57
    /// <param name="trySubtract">If true, suppresses exceptions on failure; otherwise, throws.</param>
58
    /// <param name="network1">The first IP network.</param>
59
    /// <param name="network2">The second IP network.</param>
60
    /// <param name="result">The resulting subtracted.</param>
61
    internal static bool InternalSubtract(
62
        bool trySubtract,
63
        IPNetwork2 network1,
64
        IPNetwork2 network2,
65
        out List<IPNetwork2> result)
66
    {
49✔
67
        if (network1 == null)
49✔
68
        {
×
69
            if (!trySubtract)
×
70
            {
×
71
                throw new ArgumentNullException(nameof(network1));
×
72
            }
73

74
            result = null;
×
75
            return false;
×
76
        }
77

78
        if (network2 == null)
49✔
79
        {
3✔
80
            if (!trySubtract)
3✔
81
            {
2✔
82
                throw new ArgumentNullException(nameof(network2));
2✔
83
            }
84

85
            result = null;
1✔
86
            return false;
1✔
87
        }
88

89
        // If network2 completely contains network1, return empty
90
        if (network2.Contains(network1))
46✔
91
        {
13✔
92
            result = [];
13✔
93
            return true;
13✔
94
        }
95

96
        // If networks don't overlap, return original network
97
        if (!network1.Contains(network2))
33✔
98
        {
8✔
99
            var copy = new IPNetwork2(network1.InternalNetwork, network1.family, network1.Cidr);
8✔
100
            result = [copy];
8✔
101
            return true;
8✔
102
        }
103

104
        // If network1 completely contains network2, we need to split
105
        result = network1.SplitAroundSubnet(network2);
25✔
106
        return true;
25✔
107
    }
47✔
108
    
109
    private List<IPNetwork2> SplitAroundSubnet(IPNetwork2 network2)
110
    {
25✔
111
        var result = new List<IPNetwork2>();
25✔
112
        var queue = new Queue<IPNetwork2>();
25✔
113
        queue.Enqueue(this);
25✔
114
        
115
        while (queue.Count > 0)
766✔
116
        {
741✔
117
            var current = queue.Dequeue();
741✔
118
            
119
            // If current doesn't overlap with hole, add it to result
120
            if (!current.Overlap(network2))
741✔
121
            {
358✔
122
                result.Add(current);
358✔
123
                continue;
358✔
124
            }
125
            
126
            // If hole completely contains current, skip it
127
            if (network2.Contains(current))
383✔
128
            {
25✔
129
                continue;
25✔
130
            }
131
            
132
            // If current is same size or smaller than hole and overlaps, we need to split
133
            var split = current.Subnet((byte)(current.Cidr + 1));
358✔
134
            var leftHalf = split[0];
358✔
135
            var rightHalf = split[1];
358✔
136
            
137
            queue.Enqueue(leftHalf);
358✔
138
            queue.Enqueue(rightHalf);
358✔
139
        }
358✔
140
        
141
        return result.OrderBy(n => n.ipaddress).ToList();
378✔
142
    }
25✔
143
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc