cidr-tools 11.3.1 → 11.3.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.ts +1 -5
- package/dist/index.js +90 -65
- package/package.json +15 -14
package/dist/index.d.ts
CHANGED
|
@@ -1,9 +1,5 @@
|
|
|
1
1
|
//#region index.d.ts
|
|
2
|
-
type
|
|
3
|
-
type IPv6Address = string;
|
|
4
|
-
type IPv4CIDR = string;
|
|
5
|
-
type IPv6CIDR = string;
|
|
6
|
-
type Network = IPv4Address | IPv4CIDR | IPv6Address | IPv6CIDR;
|
|
2
|
+
type Network = string;
|
|
7
3
|
type Networks = Network | Array<Network>;
|
|
8
4
|
type ValidIpVersion = 4 | 6;
|
|
9
5
|
type ParsedCidr = {
|
package/dist/index.js
CHANGED
|
@@ -6,8 +6,12 @@ const bits = {
|
|
|
6
6
|
6: 128
|
|
7
7
|
};
|
|
8
8
|
const octetStrings = Array.from({ length: 256 }, (_, i) => String(i));
|
|
9
|
+
const octetDotStrings = Array.from({ length: 256 }, (_, i) => `${i}.`);
|
|
9
10
|
const prefixStrings = Array.from({ length: 129 }, (_, i) => `/${i}`);
|
|
10
|
-
const
|
|
11
|
+
const cmpV4StartEnd = (a, b) => a.start - b.start || a.end - b.end;
|
|
12
|
+
const cmpV4Start = (a, b) => a.start - b.start;
|
|
13
|
+
const cmpV6StartEnd = (a, b) => a.start > b.start ? 1 : a.start < b.start ? -1 : a.end > b.end ? 1 : a.end < b.end ? -1 : 0;
|
|
14
|
+
const cmpV6Start = (a, b) => a.start > b.start ? 1 : a.start < b.start ? -1 : 0;
|
|
11
15
|
function parseIPv4Fast(s, end) {
|
|
12
16
|
let num = 0;
|
|
13
17
|
let octet = 0;
|
|
@@ -17,7 +21,7 @@ function parseIPv4Fast(s, end) {
|
|
|
17
21
|
const c = s.charCodeAt(i);
|
|
18
22
|
if (c === 46) {
|
|
19
23
|
if (digits === 0 || octet > 255) return -1;
|
|
20
|
-
num =
|
|
24
|
+
num = num << 8 | octet;
|
|
21
25
|
octet = 0;
|
|
22
26
|
dots++;
|
|
23
27
|
digits = 0;
|
|
@@ -30,7 +34,7 @@ function parseIPv4Fast(s, end) {
|
|
|
30
34
|
return (num << 8 | octet) >>> 0;
|
|
31
35
|
}
|
|
32
36
|
function formatIPv4Fast(n) {
|
|
33
|
-
return
|
|
37
|
+
return octetDotStrings[n >>> 24 & 255] + octetDotStrings[n >>> 16 & 255] + octetDotStrings[n >>> 8 & 255] + octetStrings[n & 255];
|
|
34
38
|
}
|
|
35
39
|
function parsePrefixNum(str, slashIndex) {
|
|
36
40
|
if (slashIndex === -1) return -1;
|
|
@@ -100,7 +104,7 @@ function parseCidr(str) {
|
|
|
100
104
|
if (v4num !== -1) {
|
|
101
105
|
const prefixNum = prefixPresent ? parsePrefixNum(str, slashIndex) : 32;
|
|
102
106
|
const ip = formatIPv4Fast(v4num);
|
|
103
|
-
const prefix =
|
|
107
|
+
const prefix = String(prefixNum);
|
|
104
108
|
const hostBits = 32 - prefixNum;
|
|
105
109
|
let startNum, endNum;
|
|
106
110
|
if (hostBits >= 32) {
|
|
@@ -126,7 +130,7 @@ function parseCidr(str) {
|
|
|
126
130
|
const { number, version, ipv4mapped, scopeid } = parseIp(ipPart);
|
|
127
131
|
if (!version) throw new Error(`Network is not a CIDR or IP: "${str}"`);
|
|
128
132
|
if (prefixNum === -1) prefixNum = bits[version];
|
|
129
|
-
const prefix =
|
|
133
|
+
const prefix = String(prefixNum);
|
|
130
134
|
const ip = stringifyIp({
|
|
131
135
|
number,
|
|
132
136
|
version,
|
|
@@ -235,13 +239,7 @@ function subparts4(pStart, pEnd, output) {
|
|
|
235
239
|
let biggest = biggestPowerOfTwo4(size);
|
|
236
240
|
let start;
|
|
237
241
|
let end;
|
|
238
|
-
if (
|
|
239
|
-
output.push({
|
|
240
|
-
start: pStart,
|
|
241
|
-
end: pEnd
|
|
242
|
-
});
|
|
243
|
-
return;
|
|
244
|
-
} else if (pStart % biggest === 0) {
|
|
242
|
+
if (pStart % biggest === 0) {
|
|
245
243
|
start = pStart;
|
|
246
244
|
end = start + biggest - 1;
|
|
247
245
|
} else {
|
|
@@ -299,13 +297,7 @@ function subparts6(pStart, pEnd, output) {
|
|
|
299
297
|
let biggest = biggestPowerOfTwo(size);
|
|
300
298
|
let start;
|
|
301
299
|
let end;
|
|
302
|
-
if (
|
|
303
|
-
output.push({
|
|
304
|
-
start: pStart,
|
|
305
|
-
end: pEnd
|
|
306
|
-
});
|
|
307
|
-
return;
|
|
308
|
-
} else if ((pStart & biggest - 1n) === 0n) {
|
|
300
|
+
if ((pStart & biggest - 1n) === 0n) {
|
|
309
301
|
start = pStart;
|
|
310
302
|
end = start + biggest - 1n;
|
|
311
303
|
} else {
|
|
@@ -330,21 +322,17 @@ function subparts6(pStart, pEnd, output) {
|
|
|
330
322
|
if (end !== pEnd) subparts6(end + 1n, pEnd, output);
|
|
331
323
|
}
|
|
332
324
|
function formatPart4(part) {
|
|
333
|
-
|
|
334
|
-
const size = part.end - part.start + 1;
|
|
335
|
-
return ip + prefixStrings[32 - (size <= 1 ? 0 : size >= 4294967296 ? 32 : 31 - Math.clz32(size))];
|
|
325
|
+
return formatIPv4Fast(part.start) + prefixStrings[Math.clz32(part.end - part.start)];
|
|
336
326
|
}
|
|
337
327
|
function formatPart6(part) {
|
|
338
|
-
|
|
328
|
+
return stringifyIp({
|
|
339
329
|
number: part.start,
|
|
340
330
|
version: 6
|
|
341
|
-
});
|
|
342
|
-
const size = part.end - part.start + 1n;
|
|
343
|
-
return ip + prefixStrings[128 - (size <= 1n ? 0 : bigintBitLength(size) - 1)];
|
|
331
|
+
}) + prefixStrings[128 - bigintBitLength(part.end - part.start)];
|
|
344
332
|
}
|
|
345
333
|
function mergeIntervalsRaw4(nets) {
|
|
346
334
|
if (nets.length === 0) return [];
|
|
347
|
-
nets.sort(
|
|
335
|
+
nets.sort(cmpV4StartEnd);
|
|
348
336
|
const merged = [];
|
|
349
337
|
let curStart = nets[0].start;
|
|
350
338
|
let curEnd = nets[0].end;
|
|
@@ -369,7 +357,7 @@ function mergeIntervalsRaw4(nets) {
|
|
|
369
357
|
}
|
|
370
358
|
function mergeIntervalsRaw6(nets) {
|
|
371
359
|
if (nets.length === 0) return [];
|
|
372
|
-
nets.sort(
|
|
360
|
+
nets.sort(cmpV6StartEnd);
|
|
373
361
|
const merged = [];
|
|
374
362
|
let curStart = nets[0].start;
|
|
375
363
|
let curEnd = nets[0].end;
|
|
@@ -507,11 +495,28 @@ function* expandCidr(nets) {
|
|
|
507
495
|
if (n.version === 4) v4.push(n);
|
|
508
496
|
else v6.push(n);
|
|
509
497
|
}
|
|
510
|
-
if (v4.length > 0) for (const part of mergeIntervalsRaw4(v4))
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
498
|
+
if (v4.length > 0) for (const part of mergeIntervalsRaw4(v4)) {
|
|
499
|
+
let prevHigh = -1;
|
|
500
|
+
let prefix = "";
|
|
501
|
+
for (let n = part.start; n <= part.end; n++) {
|
|
502
|
+
const high = n >>> 8;
|
|
503
|
+
if (high !== prevHigh) {
|
|
504
|
+
prefix = octetDotStrings[n >>> 24 & 255] + octetDotStrings[n >>> 16 & 255] + octetDotStrings[n >>> 8 & 255];
|
|
505
|
+
prevHigh = high;
|
|
506
|
+
}
|
|
507
|
+
yield prefix + octetStrings[n & 255];
|
|
508
|
+
}
|
|
509
|
+
}
|
|
510
|
+
if (v6.length > 0) {
|
|
511
|
+
const ipObj = {
|
|
512
|
+
number: 0n,
|
|
513
|
+
version: 6
|
|
514
|
+
};
|
|
515
|
+
for (const part of mergeIntervalsRaw6(v6)) for (let num = part.start; num <= part.end; num++) {
|
|
516
|
+
ipObj.number = num;
|
|
517
|
+
yield stringifyIp(ipObj);
|
|
518
|
+
}
|
|
519
|
+
}
|
|
515
520
|
}
|
|
516
521
|
/** Returns a boolean that indicates if `networksA` overlap (intersect) with `networksB`. */
|
|
517
522
|
function overlapCidr(a, b) {
|
|
@@ -546,8 +551,8 @@ function overlapCidr(a, b) {
|
|
|
546
551
|
const as = v4a[0].start, ae = v4a[0].end;
|
|
547
552
|
for (const el of v4b) if (as <= el.end && el.start <= ae) return true;
|
|
548
553
|
} else {
|
|
549
|
-
v4a.sort(
|
|
550
|
-
v4b.sort(
|
|
554
|
+
v4a.sort(cmpV4Start);
|
|
555
|
+
v4b.sort(cmpV4Start);
|
|
551
556
|
let i = 0, j = 0;
|
|
552
557
|
while (i < v4a.length && j < v4b.length) {
|
|
553
558
|
if (v4a[i].start <= v4b[j].end && v4b[j].start <= v4a[i].end) return true;
|
|
@@ -562,8 +567,8 @@ function overlapCidr(a, b) {
|
|
|
562
567
|
const as = v6a[0].start, ae = v6a[0].end;
|
|
563
568
|
for (const el of v6b) if (as <= el.end && el.start <= ae) return true;
|
|
564
569
|
} else {
|
|
565
|
-
v6a.sort(
|
|
566
|
-
v6b.sort(
|
|
570
|
+
v6a.sort(cmpV6Start);
|
|
571
|
+
v6b.sort(cmpV6Start);
|
|
567
572
|
let i = 0, j = 0;
|
|
568
573
|
while (i < v6a.length && j < v6b.length) {
|
|
569
574
|
if (v6a[i].start <= v6b[j].end && v6b[j].start <= v6a[i].end) return true;
|
|
@@ -601,40 +606,60 @@ function containsCidr(a, b) {
|
|
|
601
606
|
}
|
|
602
607
|
if (v4b.length > 0) {
|
|
603
608
|
if (v4a.length === 0) return false;
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
609
|
+
if (v4b.length === 1) {
|
|
610
|
+
const ts = v4b[0].start, te = v4b[0].end;
|
|
611
|
+
let found = false;
|
|
612
|
+
for (const a of v4a) if (a.start <= ts && a.end >= te) {
|
|
613
|
+
found = true;
|
|
614
|
+
break;
|
|
615
|
+
}
|
|
616
|
+
if (!found) return false;
|
|
617
|
+
} else {
|
|
618
|
+
v4a.sort(cmpV4Start);
|
|
619
|
+
const maxEnd = new Array(v4a.length);
|
|
620
|
+
maxEnd[0] = v4a[0].end;
|
|
621
|
+
for (let i = 1; i < v4a.length; i++) maxEnd[i] = Math.max(v4a[i].end, maxEnd[i - 1]);
|
|
622
|
+
for (const target of v4b) {
|
|
623
|
+
let lo = 0, hi = v4a.length - 1;
|
|
624
|
+
let idx = -1;
|
|
625
|
+
while (lo <= hi) {
|
|
626
|
+
const mid = lo + hi >> 1;
|
|
627
|
+
if (v4a[mid].start <= target.start) {
|
|
628
|
+
idx = mid;
|
|
629
|
+
lo = mid + 1;
|
|
630
|
+
} else hi = mid - 1;
|
|
631
|
+
}
|
|
632
|
+
if (idx < 0 || maxEnd[idx] < target.end) return false;
|
|
617
633
|
}
|
|
618
|
-
if (idx < 0 || maxEnd[idx] < target.end) return false;
|
|
619
634
|
}
|
|
620
635
|
}
|
|
621
636
|
if (v6b.length > 0) {
|
|
622
637
|
if (v6a.length === 0) return false;
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
638
|
+
if (v6b.length === 1) {
|
|
639
|
+
const ts = v6b[0].start, te = v6b[0].end;
|
|
640
|
+
let found = false;
|
|
641
|
+
for (const a of v6a) if (a.start <= ts && a.end >= te) {
|
|
642
|
+
found = true;
|
|
643
|
+
break;
|
|
644
|
+
}
|
|
645
|
+
if (!found) return false;
|
|
646
|
+
} else {
|
|
647
|
+
v6a.sort(cmpV6Start);
|
|
648
|
+
const maxEnd = new Array(v6a.length);
|
|
649
|
+
maxEnd[0] = v6a[0].end;
|
|
650
|
+
for (let i = 1; i < v6a.length; i++) maxEnd[i] = v6a[i].end > maxEnd[i - 1] ? v6a[i].end : maxEnd[i - 1];
|
|
651
|
+
for (const target of v6b) {
|
|
652
|
+
let lo = 0, hi = v6a.length - 1;
|
|
653
|
+
let idx = -1;
|
|
654
|
+
while (lo <= hi) {
|
|
655
|
+
const mid = lo + hi >> 1;
|
|
656
|
+
if (v6a[mid].start <= target.start) {
|
|
657
|
+
idx = mid;
|
|
658
|
+
lo = mid + 1;
|
|
659
|
+
} else hi = mid - 1;
|
|
660
|
+
}
|
|
661
|
+
if (idx < 0 || maxEnd[idx] < target.end) return false;
|
|
636
662
|
}
|
|
637
|
-
if (idx < 0 || maxEnd[idx] < target.end) return false;
|
|
638
663
|
}
|
|
639
664
|
}
|
|
640
665
|
return true;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "cidr-tools",
|
|
3
|
-
"version": "11.3.
|
|
3
|
+
"version": "11.3.3",
|
|
4
4
|
"author": "silverwind <me@silverwind.io>",
|
|
5
5
|
"description": "Tools to work with IPv4 and IPv6 CIDR",
|
|
6
6
|
"repository": "silverwind/cidr-tools",
|
|
@@ -17,22 +17,23 @@
|
|
|
17
17
|
"node": ">=18"
|
|
18
18
|
},
|
|
19
19
|
"dependencies": {
|
|
20
|
-
"ip-bigint": "^8.3.
|
|
20
|
+
"ip-bigint": "^8.3.4"
|
|
21
21
|
},
|
|
22
22
|
"devDependencies": {
|
|
23
|
-
"@types/node": "25.5.
|
|
24
|
-
"@typescript/native-preview": "7.0.0-dev.
|
|
25
|
-
"
|
|
26
|
-
"eslint
|
|
23
|
+
"@types/node": "25.5.2",
|
|
24
|
+
"@typescript/native-preview": "7.0.0-dev.20260409.1",
|
|
25
|
+
"@vitest/coverage-v8": "4.1.4",
|
|
26
|
+
"eslint": "10.2.0",
|
|
27
|
+
"eslint-config-silverwind": "131.0.2",
|
|
27
28
|
"jest-extended": "7.0.0",
|
|
28
|
-
"tsdown": "0.21.
|
|
29
|
-
"tsdown-config-silverwind": "2.0.
|
|
29
|
+
"tsdown": "0.21.7",
|
|
30
|
+
"tsdown-config-silverwind": "2.0.5",
|
|
30
31
|
"typescript": "5.9.3",
|
|
31
|
-
"typescript-config-silverwind": "
|
|
32
|
-
"updates": "17.
|
|
33
|
-
"updates-config-silverwind": "
|
|
34
|
-
"versions": "14.2.
|
|
35
|
-
"vitest": "4.1.
|
|
36
|
-
"vitest-config-silverwind": "
|
|
32
|
+
"typescript-config-silverwind": "17.0.0",
|
|
33
|
+
"updates": "17.14.0",
|
|
34
|
+
"updates-config-silverwind": "2.0.1",
|
|
35
|
+
"versions": "14.2.7",
|
|
36
|
+
"vitest": "4.1.4",
|
|
37
|
+
"vitest-config-silverwind": "11.1.4"
|
|
37
38
|
}
|
|
38
39
|
}
|