cidr-tools 12.0.0 → 12.0.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.d.ts +1 -0
- package/dist/index.js +38 -114
- package/package.json +14 -14
package/dist/index.d.ts
CHANGED
|
@@ -23,6 +23,7 @@ declare function parseCidr(str: Network): ParsedCidr;
|
|
|
23
23
|
declare function mergeCidr(nets: Networks): Array<Network>;
|
|
24
24
|
/** Returns an array of merged remaining networks of the subtraction of `excludeNetworks` from `baseNetworks`. */
|
|
25
25
|
declare function excludeCidr(base: Networks, excl: Networks): Array<Network>;
|
|
26
|
+
/** Returns a generator for individual IPs contained in the networks. */
|
|
26
27
|
declare function expandCidr(nets: Networks): Generator<Network>;
|
|
27
28
|
/** Returns a boolean that indicates if `networksA` overlap (intersect) with `networksB`. */
|
|
28
29
|
declare function overlapCidr(a: Networks, b: Networks): boolean;
|
package/dist/index.js
CHANGED
|
@@ -8,6 +8,7 @@ const bits = {
|
|
|
8
8
|
const octetStrings = Array.from({ length: 256 }, (_, i) => String(i));
|
|
9
9
|
const octetDotStrings = Array.from({ length: 256 }, (_, i) => `${i}.`);
|
|
10
10
|
const prefixStrings = Array.from({ length: 129 }, (_, i) => `/${i}`);
|
|
11
|
+
const prefixNumStrings = Array.from({ length: 129 }, (_, i) => String(i));
|
|
11
12
|
const cmpV4StartEnd = (a, b) => a.start - b.start || a.end - b.end;
|
|
12
13
|
const cmpV4Start = (a, b) => a.start - b.start;
|
|
13
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;
|
|
@@ -92,8 +93,7 @@ function doNormalize(cidr, opts) {
|
|
|
92
93
|
}
|
|
93
94
|
/** Returns a string or array (depending on input) with a normalized representation. Will not include a prefix on single IPs. Will set network address to the start of the network. */
|
|
94
95
|
function normalizeCidr(cidr, opts) {
|
|
95
|
-
|
|
96
|
-
else return doNormalize(cidr, opts);
|
|
96
|
+
return Array.isArray(cidr) ? cidr.map((entry) => doNormalize(entry, opts)) : doNormalize(cidr, opts);
|
|
97
97
|
}
|
|
98
98
|
/** Returns a `parsed` Object which is used internally by this module. It can be used to test whether the passed network is IPv4 or IPv6 or to work with the BigInts directly. */
|
|
99
99
|
function parseCidr(str) {
|
|
@@ -104,7 +104,7 @@ function parseCidr(str) {
|
|
|
104
104
|
if (v4num !== -1) {
|
|
105
105
|
const prefixNum = prefixPresent ? parsePrefixNum(str, slashIndex) : 32;
|
|
106
106
|
const ip = formatIPv4Fast(v4num);
|
|
107
|
-
const prefix = String(prefixNum);
|
|
107
|
+
const prefix = prefixNumStrings[prefixNum] ?? String(prefixNum);
|
|
108
108
|
const hostBits = 32 - prefixNum;
|
|
109
109
|
let startNum, endNum;
|
|
110
110
|
if (hostBits >= 32) {
|
|
@@ -130,7 +130,7 @@ function parseCidr(str) {
|
|
|
130
130
|
const { number, version, ipv4mapped, scopeid } = parseIp(ipPart);
|
|
131
131
|
if (!version) throw new Error(`Network is not a CIDR or IP: "${str}"`);
|
|
132
132
|
if (prefixNum === -1) prefixNum = bits[version];
|
|
133
|
-
const prefix = String(prefixNum);
|
|
133
|
+
const prefix = prefixNumStrings[prefixNum] ?? String(prefixNum);
|
|
134
134
|
const ip = stringifyIp({
|
|
135
135
|
number,
|
|
136
136
|
version,
|
|
@@ -206,120 +206,37 @@ function biggestPowerOfTwo4(num) {
|
|
|
206
206
|
return 1 << 31 - Math.clz32(num) >>> 0;
|
|
207
207
|
}
|
|
208
208
|
function subparts4(pStart, pEnd, output) {
|
|
209
|
-
|
|
210
|
-
|
|
209
|
+
let start = pStart;
|
|
210
|
+
while (start <= pEnd) {
|
|
211
|
+
const size = pEnd - start + 1;
|
|
212
|
+
const lowBit = (start & -start) >>> 0;
|
|
213
|
+
const blockSize = lowBit !== 0 && lowBit <= size ? lowBit : biggestPowerOfTwo4(size);
|
|
211
214
|
output.push({
|
|
212
|
-
start
|
|
213
|
-
end:
|
|
214
|
-
});
|
|
215
|
-
return;
|
|
216
|
-
}
|
|
217
|
-
if (pEnd - pStart === 1) {
|
|
218
|
-
if (pEnd % 2 === 0) output.push({
|
|
219
|
-
start: pStart,
|
|
220
|
-
end: pStart
|
|
221
|
-
}, {
|
|
222
|
-
start: pEnd,
|
|
223
|
-
end: pEnd
|
|
224
|
-
});
|
|
225
|
-
else output.push({
|
|
226
|
-
start: pStart,
|
|
227
|
-
end: pEnd
|
|
215
|
+
start,
|
|
216
|
+
end: start + blockSize - 1
|
|
228
217
|
});
|
|
229
|
-
|
|
218
|
+
start += blockSize;
|
|
230
219
|
}
|
|
231
|
-
const size = pEnd - pStart + 1;
|
|
232
|
-
if ((size & size - 1) === 0 && pStart % size === 0) {
|
|
233
|
-
output.push({
|
|
234
|
-
start: pStart,
|
|
235
|
-
end: pEnd
|
|
236
|
-
});
|
|
237
|
-
return;
|
|
238
|
-
}
|
|
239
|
-
let biggest = biggestPowerOfTwo4(size);
|
|
240
|
-
let start;
|
|
241
|
-
let end;
|
|
242
|
-
if (pStart % biggest === 0) {
|
|
243
|
-
start = pStart;
|
|
244
|
-
end = start + biggest - 1;
|
|
245
|
-
} else {
|
|
246
|
-
start = Math.floor(pEnd / biggest) * biggest;
|
|
247
|
-
if (start + biggest - 1 > pEnd) {
|
|
248
|
-
start = (Math.floor(pEnd / biggest) - 1) * biggest;
|
|
249
|
-
while (start < pStart) {
|
|
250
|
-
biggest /= 2;
|
|
251
|
-
start = (Math.floor(pEnd / biggest) - 1) * biggest;
|
|
252
|
-
}
|
|
253
|
-
end = start + biggest - 1;
|
|
254
|
-
} else {
|
|
255
|
-
start = Math.floor(pEnd / biggest) * biggest;
|
|
256
|
-
end = start + biggest - 1;
|
|
257
|
-
}
|
|
258
|
-
}
|
|
259
|
-
if (start !== pStart) subparts4(pStart, start - 1, output);
|
|
260
|
-
output.push({
|
|
261
|
-
start,
|
|
262
|
-
end
|
|
263
|
-
});
|
|
264
|
-
if (end !== pEnd) subparts4(end + 1, pEnd, output);
|
|
265
220
|
}
|
|
266
221
|
function subparts6(pStart, pEnd, output) {
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
}, {
|
|
280
|
-
start: pEnd,
|
|
281
|
-
end: pEnd
|
|
282
|
-
});
|
|
283
|
-
else output.push({
|
|
284
|
-
start: pStart,
|
|
285
|
-
end: pEnd
|
|
286
|
-
});
|
|
287
|
-
return;
|
|
288
|
-
}
|
|
289
|
-
const size = pEnd - pStart + 1n;
|
|
290
|
-
if ((size & size - 1n) === 0n && (pStart & size - 1n) === 0n) {
|
|
222
|
+
let start = pStart;
|
|
223
|
+
while (start <= pEnd) {
|
|
224
|
+
const size = pEnd - start + 1n;
|
|
225
|
+
const lowBit = start & -start;
|
|
226
|
+
if ((size & size - 1n) === 0n && (lowBit === 0n || lowBit >= size)) {
|
|
227
|
+
output.push({
|
|
228
|
+
start,
|
|
229
|
+
end: pEnd
|
|
230
|
+
});
|
|
231
|
+
return;
|
|
232
|
+
}
|
|
233
|
+
const blockSize = lowBit !== 0n && lowBit <= size ? lowBit : biggestPowerOfTwo(size);
|
|
291
234
|
output.push({
|
|
292
|
-
start
|
|
293
|
-
end:
|
|
235
|
+
start,
|
|
236
|
+
end: start + blockSize - 1n
|
|
294
237
|
});
|
|
295
|
-
|
|
296
|
-
}
|
|
297
|
-
let biggest = biggestPowerOfTwo(size);
|
|
298
|
-
let start;
|
|
299
|
-
let end;
|
|
300
|
-
if ((pStart & biggest - 1n) === 0n) {
|
|
301
|
-
start = pStart;
|
|
302
|
-
end = start + biggest - 1n;
|
|
303
|
-
} else {
|
|
304
|
-
start = pEnd & -biggest;
|
|
305
|
-
if (start + biggest - 1n > pEnd) {
|
|
306
|
-
start = (pEnd & -biggest) - biggest;
|
|
307
|
-
while (start < pStart) {
|
|
308
|
-
biggest >>= 1n;
|
|
309
|
-
start = (pEnd & -biggest) - biggest;
|
|
310
|
-
}
|
|
311
|
-
end = start + biggest - 1n;
|
|
312
|
-
} else {
|
|
313
|
-
start = pEnd & -biggest;
|
|
314
|
-
end = start + biggest - 1n;
|
|
315
|
-
}
|
|
238
|
+
start += blockSize;
|
|
316
239
|
}
|
|
317
|
-
if (start !== pStart) subparts6(pStart, start - 1n, output);
|
|
318
|
-
output.push({
|
|
319
|
-
start,
|
|
320
|
-
end
|
|
321
|
-
});
|
|
322
|
-
if (end !== pEnd) subparts6(end + 1n, pEnd, output);
|
|
323
240
|
}
|
|
324
241
|
function formatPart4(part) {
|
|
325
242
|
return formatIPv4Fast(part.start) + prefixStrings[Math.clz32(part.end - part.start)];
|
|
@@ -486,6 +403,7 @@ function excludeCidr(base, excl) {
|
|
|
486
403
|
}
|
|
487
404
|
return result;
|
|
488
405
|
}
|
|
406
|
+
/** Returns a generator for individual IPs contained in the networks. */
|
|
489
407
|
function* expandCidr(nets) {
|
|
490
408
|
const arr = Array.isArray(nets) ? nets : [nets];
|
|
491
409
|
const v4 = [];
|
|
@@ -498,13 +416,13 @@ function* expandCidr(nets) {
|
|
|
498
416
|
if (v4.length > 0) for (const part of mergeIntervalsRaw4(v4)) {
|
|
499
417
|
let prevHigh = -1;
|
|
500
418
|
let prefix = "";
|
|
501
|
-
for (let
|
|
502
|
-
const high =
|
|
419
|
+
for (let num = part.start; num <= part.end; num++) {
|
|
420
|
+
const high = num >>> 8;
|
|
503
421
|
if (high !== prevHigh) {
|
|
504
|
-
prefix = octetDotStrings[
|
|
422
|
+
prefix = octetDotStrings[num >>> 24 & 255] + octetDotStrings[num >>> 16 & 255] + octetDotStrings[num >>> 8 & 255];
|
|
505
423
|
prevHigh = high;
|
|
506
424
|
}
|
|
507
|
-
yield prefix + octetStrings[
|
|
425
|
+
yield prefix + octetStrings[num & 255];
|
|
508
426
|
}
|
|
509
427
|
}
|
|
510
428
|
if (v6.length > 0) {
|
|
@@ -524,6 +442,9 @@ function overlapCidr(a, b) {
|
|
|
524
442
|
if (parseIPv4Range(a)) {
|
|
525
443
|
const startA = rangeV4Start, endA = rangeV4End;
|
|
526
444
|
if (parseIPv4Range(b)) return startA <= rangeV4End && rangeV4Start <= endA;
|
|
445
|
+
const pb = parseCidrLean(b);
|
|
446
|
+
if (pb.version !== 4) return false;
|
|
447
|
+
return startA <= pb.end && pb.start <= endA;
|
|
527
448
|
}
|
|
528
449
|
const pa = parseCidrLean(a);
|
|
529
450
|
const pb = parseCidrLean(b);
|
|
@@ -584,6 +505,9 @@ function containsCidr(a, b) {
|
|
|
584
505
|
if (parseIPv4Range(a)) {
|
|
585
506
|
const startA = rangeV4Start, endA = rangeV4End;
|
|
586
507
|
if (parseIPv4Range(b)) return startA <= rangeV4Start && endA >= rangeV4End;
|
|
508
|
+
const pb = parseCidrLean(b);
|
|
509
|
+
if (pb.version !== 4) return false;
|
|
510
|
+
return startA <= pb.start && endA >= pb.end;
|
|
587
511
|
}
|
|
588
512
|
const pa = parseCidrLean(a);
|
|
589
513
|
const pb = parseCidrLean(b);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "cidr-tools",
|
|
3
|
-
"version": "12.0.
|
|
3
|
+
"version": "12.0.2",
|
|
4
4
|
"author": "silverwind <me@silverwind.io>",
|
|
5
5
|
"description": "Tools to work with IPv4 and IPv6 CIDR",
|
|
6
6
|
"keywords": [
|
|
@@ -26,23 +26,23 @@
|
|
|
26
26
|
"bun": "*"
|
|
27
27
|
},
|
|
28
28
|
"dependencies": {
|
|
29
|
-
"ip-bigint": "^9.0.
|
|
29
|
+
"ip-bigint": "^9.0.5"
|
|
30
30
|
},
|
|
31
31
|
"devDependencies": {
|
|
32
|
-
"@types/node": "25.
|
|
33
|
-
"@typescript/native-preview": "7.0.0-dev.
|
|
34
|
-
"@vitest/coverage-v8": "4.1.
|
|
35
|
-
"eslint": "10.
|
|
36
|
-
"eslint-config-silverwind": "133.0.
|
|
32
|
+
"@types/node": "25.9.1",
|
|
33
|
+
"@typescript/native-preview": "7.0.0-dev.20260527.2",
|
|
34
|
+
"@vitest/coverage-v8": "4.1.7",
|
|
35
|
+
"eslint": "10.4.0",
|
|
36
|
+
"eslint-config-silverwind": "133.0.5",
|
|
37
37
|
"jest-extended": "7.0.0",
|
|
38
|
-
"tsdown": "0.
|
|
39
|
-
"tsdown-config-silverwind": "3.0.
|
|
38
|
+
"tsdown": "0.22.1",
|
|
39
|
+
"tsdown-config-silverwind": "3.0.2",
|
|
40
40
|
"typescript": "6.0.3",
|
|
41
41
|
"typescript-config-silverwind": "18.0.0",
|
|
42
|
-
"updates": "17.
|
|
43
|
-
"updates-config-silverwind": "3.0.
|
|
44
|
-
"versions": "15.0
|
|
45
|
-
"vitest": "4.1.
|
|
46
|
-
"vitest-config-silverwind": "11.3.
|
|
42
|
+
"updates": "17.17.3",
|
|
43
|
+
"updates-config-silverwind": "3.0.2",
|
|
44
|
+
"versions": "15.1.0",
|
|
45
|
+
"vitest": "4.1.7",
|
|
46
|
+
"vitest-config-silverwind": "11.3.5"
|
|
47
47
|
}
|
|
48
48
|
}
|