cidr-tools 11.3.1 → 11.3.2
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.js +86 -48
- package/package.json +11 -11
package/dist/index.js
CHANGED
|
@@ -6,8 +6,13 @@ 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
11
|
const prefixNumStrings = Array.from({ length: 129 }, (_, i) => String(i));
|
|
12
|
+
const cmpV4StartEnd = (a, b) => a.start - b.start || a.end - b.end;
|
|
13
|
+
const cmpV4Start = (a, b) => a.start - b.start;
|
|
14
|
+
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;
|
|
15
|
+
const cmpV6Start = (a, b) => a.start > b.start ? 1 : a.start < b.start ? -1 : 0;
|
|
11
16
|
function parseIPv4Fast(s, end) {
|
|
12
17
|
let num = 0;
|
|
13
18
|
let octet = 0;
|
|
@@ -17,7 +22,7 @@ function parseIPv4Fast(s, end) {
|
|
|
17
22
|
const c = s.charCodeAt(i);
|
|
18
23
|
if (c === 46) {
|
|
19
24
|
if (digits === 0 || octet > 255) return -1;
|
|
20
|
-
num =
|
|
25
|
+
num = num << 8 | octet;
|
|
21
26
|
octet = 0;
|
|
22
27
|
dots++;
|
|
23
28
|
digits = 0;
|
|
@@ -30,7 +35,7 @@ function parseIPv4Fast(s, end) {
|
|
|
30
35
|
return (num << 8 | octet) >>> 0;
|
|
31
36
|
}
|
|
32
37
|
function formatIPv4Fast(n) {
|
|
33
|
-
return
|
|
38
|
+
return octetDotStrings[n >>> 24 & 255] + octetDotStrings[n >>> 16 & 255] + octetDotStrings[n >>> 8 & 255] + octetStrings[n & 255];
|
|
34
39
|
}
|
|
35
40
|
function parsePrefixNum(str, slashIndex) {
|
|
36
41
|
if (slashIndex === -1) return -1;
|
|
@@ -330,21 +335,17 @@ function subparts6(pStart, pEnd, output) {
|
|
|
330
335
|
if (end !== pEnd) subparts6(end + 1n, pEnd, output);
|
|
331
336
|
}
|
|
332
337
|
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))];
|
|
338
|
+
return formatIPv4Fast(part.start) + prefixStrings[Math.clz32(part.end - part.start)];
|
|
336
339
|
}
|
|
337
340
|
function formatPart6(part) {
|
|
338
|
-
|
|
341
|
+
return stringifyIp({
|
|
339
342
|
number: part.start,
|
|
340
343
|
version: 6
|
|
341
|
-
});
|
|
342
|
-
const size = part.end - part.start + 1n;
|
|
343
|
-
return ip + prefixStrings[128 - (size <= 1n ? 0 : bigintBitLength(size) - 1)];
|
|
344
|
+
}) + prefixStrings[128 - bigintBitLength(part.end - part.start)];
|
|
344
345
|
}
|
|
345
346
|
function mergeIntervalsRaw4(nets) {
|
|
346
347
|
if (nets.length === 0) return [];
|
|
347
|
-
nets.sort(
|
|
348
|
+
nets.sort(cmpV4StartEnd);
|
|
348
349
|
const merged = [];
|
|
349
350
|
let curStart = nets[0].start;
|
|
350
351
|
let curEnd = nets[0].end;
|
|
@@ -369,7 +370,7 @@ function mergeIntervalsRaw4(nets) {
|
|
|
369
370
|
}
|
|
370
371
|
function mergeIntervalsRaw6(nets) {
|
|
371
372
|
if (nets.length === 0) return [];
|
|
372
|
-
nets.sort(
|
|
373
|
+
nets.sort(cmpV6StartEnd);
|
|
373
374
|
const merged = [];
|
|
374
375
|
let curStart = nets[0].start;
|
|
375
376
|
let curEnd = nets[0].end;
|
|
@@ -507,11 +508,28 @@ function* expandCidr(nets) {
|
|
|
507
508
|
if (n.version === 4) v4.push(n);
|
|
508
509
|
else v6.push(n);
|
|
509
510
|
}
|
|
510
|
-
if (v4.length > 0) for (const part of mergeIntervalsRaw4(v4))
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
511
|
+
if (v4.length > 0) for (const part of mergeIntervalsRaw4(v4)) {
|
|
512
|
+
let prevHigh = -1;
|
|
513
|
+
let prefix = "";
|
|
514
|
+
for (let n = part.start; n <= part.end; n++) {
|
|
515
|
+
const high = n >>> 8;
|
|
516
|
+
if (high !== prevHigh) {
|
|
517
|
+
prefix = octetDotStrings[n >>> 24 & 255] + octetDotStrings[n >>> 16 & 255] + octetDotStrings[n >>> 8 & 255];
|
|
518
|
+
prevHigh = high;
|
|
519
|
+
}
|
|
520
|
+
yield prefix + octetStrings[n & 255];
|
|
521
|
+
}
|
|
522
|
+
}
|
|
523
|
+
if (v6.length > 0) {
|
|
524
|
+
const ipObj = {
|
|
525
|
+
number: 0n,
|
|
526
|
+
version: 6
|
|
527
|
+
};
|
|
528
|
+
for (const part of mergeIntervalsRaw6(v6)) for (let num = part.start; num <= part.end; num++) {
|
|
529
|
+
ipObj.number = num;
|
|
530
|
+
yield stringifyIp(ipObj);
|
|
531
|
+
}
|
|
532
|
+
}
|
|
515
533
|
}
|
|
516
534
|
/** Returns a boolean that indicates if `networksA` overlap (intersect) with `networksB`. */
|
|
517
535
|
function overlapCidr(a, b) {
|
|
@@ -546,8 +564,8 @@ function overlapCidr(a, b) {
|
|
|
546
564
|
const as = v4a[0].start, ae = v4a[0].end;
|
|
547
565
|
for (const el of v4b) if (as <= el.end && el.start <= ae) return true;
|
|
548
566
|
} else {
|
|
549
|
-
v4a.sort(
|
|
550
|
-
v4b.sort(
|
|
567
|
+
v4a.sort(cmpV4Start);
|
|
568
|
+
v4b.sort(cmpV4Start);
|
|
551
569
|
let i = 0, j = 0;
|
|
552
570
|
while (i < v4a.length && j < v4b.length) {
|
|
553
571
|
if (v4a[i].start <= v4b[j].end && v4b[j].start <= v4a[i].end) return true;
|
|
@@ -562,8 +580,8 @@ function overlapCidr(a, b) {
|
|
|
562
580
|
const as = v6a[0].start, ae = v6a[0].end;
|
|
563
581
|
for (const el of v6b) if (as <= el.end && el.start <= ae) return true;
|
|
564
582
|
} else {
|
|
565
|
-
v6a.sort(
|
|
566
|
-
v6b.sort(
|
|
583
|
+
v6a.sort(cmpV6Start);
|
|
584
|
+
v6b.sort(cmpV6Start);
|
|
567
585
|
let i = 0, j = 0;
|
|
568
586
|
while (i < v6a.length && j < v6b.length) {
|
|
569
587
|
if (v6a[i].start <= v6b[j].end && v6b[j].start <= v6a[i].end) return true;
|
|
@@ -601,40 +619,60 @@ function containsCidr(a, b) {
|
|
|
601
619
|
}
|
|
602
620
|
if (v4b.length > 0) {
|
|
603
621
|
if (v4a.length === 0) return false;
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
622
|
+
if (v4b.length === 1) {
|
|
623
|
+
const ts = v4b[0].start, te = v4b[0].end;
|
|
624
|
+
let found = false;
|
|
625
|
+
for (const a of v4a) if (a.start <= ts && a.end >= te) {
|
|
626
|
+
found = true;
|
|
627
|
+
break;
|
|
628
|
+
}
|
|
629
|
+
if (!found) return false;
|
|
630
|
+
} else {
|
|
631
|
+
v4a.sort(cmpV4Start);
|
|
632
|
+
const maxEnd = new Array(v4a.length);
|
|
633
|
+
maxEnd[0] = v4a[0].end;
|
|
634
|
+
for (let i = 1; i < v4a.length; i++) maxEnd[i] = Math.max(v4a[i].end, maxEnd[i - 1]);
|
|
635
|
+
for (const target of v4b) {
|
|
636
|
+
let lo = 0, hi = v4a.length - 1;
|
|
637
|
+
let idx = -1;
|
|
638
|
+
while (lo <= hi) {
|
|
639
|
+
const mid = lo + hi >> 1;
|
|
640
|
+
if (v4a[mid].start <= target.start) {
|
|
641
|
+
idx = mid;
|
|
642
|
+
lo = mid + 1;
|
|
643
|
+
} else hi = mid - 1;
|
|
644
|
+
}
|
|
645
|
+
if (idx < 0 || maxEnd[idx] < target.end) return false;
|
|
617
646
|
}
|
|
618
|
-
if (idx < 0 || maxEnd[idx] < target.end) return false;
|
|
619
647
|
}
|
|
620
648
|
}
|
|
621
649
|
if (v6b.length > 0) {
|
|
622
650
|
if (v6a.length === 0) return false;
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
651
|
+
if (v6b.length === 1) {
|
|
652
|
+
const ts = v6b[0].start, te = v6b[0].end;
|
|
653
|
+
let found = false;
|
|
654
|
+
for (const a of v6a) if (a.start <= ts && a.end >= te) {
|
|
655
|
+
found = true;
|
|
656
|
+
break;
|
|
657
|
+
}
|
|
658
|
+
if (!found) return false;
|
|
659
|
+
} else {
|
|
660
|
+
v6a.sort(cmpV6Start);
|
|
661
|
+
const maxEnd = new Array(v6a.length);
|
|
662
|
+
maxEnd[0] = v6a[0].end;
|
|
663
|
+
for (let i = 1; i < v6a.length; i++) maxEnd[i] = v6a[i].end > maxEnd[i - 1] ? v6a[i].end : maxEnd[i - 1];
|
|
664
|
+
for (const target of v6b) {
|
|
665
|
+
let lo = 0, hi = v6a.length - 1;
|
|
666
|
+
let idx = -1;
|
|
667
|
+
while (lo <= hi) {
|
|
668
|
+
const mid = lo + hi >> 1;
|
|
669
|
+
if (v6a[mid].start <= target.start) {
|
|
670
|
+
idx = mid;
|
|
671
|
+
lo = mid + 1;
|
|
672
|
+
} else hi = mid - 1;
|
|
673
|
+
}
|
|
674
|
+
if (idx < 0 || maxEnd[idx] < target.end) return false;
|
|
636
675
|
}
|
|
637
|
-
if (idx < 0 || maxEnd[idx] < target.end) return false;
|
|
638
676
|
}
|
|
639
677
|
}
|
|
640
678
|
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.2",
|
|
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,22 @@
|
|
|
17
17
|
"node": ">=18"
|
|
18
18
|
},
|
|
19
19
|
"dependencies": {
|
|
20
|
-
"ip-bigint": "^8.3.
|
|
20
|
+
"ip-bigint": "^8.3.2"
|
|
21
21
|
},
|
|
22
22
|
"devDependencies": {
|
|
23
23
|
"@types/node": "25.5.0",
|
|
24
|
-
"@typescript/native-preview": "7.0.0-dev.
|
|
25
|
-
"eslint": "
|
|
26
|
-
"eslint-config-silverwind": "
|
|
24
|
+
"@typescript/native-preview": "7.0.0-dev.20260324.1",
|
|
25
|
+
"eslint": "10.1.0",
|
|
26
|
+
"eslint-config-silverwind": "127.1.4",
|
|
27
27
|
"jest-extended": "7.0.0",
|
|
28
28
|
"tsdown": "0.21.4",
|
|
29
29
|
"tsdown-config-silverwind": "2.0.2",
|
|
30
30
|
"typescript": "5.9.3",
|
|
31
|
-
"typescript-config-silverwind": "16.
|
|
32
|
-
"updates": "17.
|
|
33
|
-
"updates-config-silverwind": "
|
|
34
|
-
"versions": "14.2.
|
|
35
|
-
"vitest": "4.1.
|
|
36
|
-
"vitest-config-silverwind": "
|
|
31
|
+
"typescript-config-silverwind": "16.1.0",
|
|
32
|
+
"updates": "17.11.2",
|
|
33
|
+
"updates-config-silverwind": "2.0.1",
|
|
34
|
+
"versions": "14.2.4",
|
|
35
|
+
"vitest": "4.1.1",
|
|
36
|
+
"vitest-config-silverwind": "11.0.0"
|
|
37
37
|
}
|
|
38
38
|
}
|