cidr-tools 12.1.2 → 12.1.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.
Files changed (2) hide show
  1. package/dist/index.js +57 -100
  2. package/package.json +15 -15
package/dist/index.js CHANGED
@@ -38,6 +38,7 @@ function parseIPv4Fast(s, end) {
38
38
  if (dots !== 3 || digits === 0 || octet > 255) return -1;
39
39
  return (num << 8 | octet) >>> 0;
40
40
  }
41
+ const hostMasks4 = Int32Array.from({ length: 33 }, (_, i) => i === 32 ? -1 : (1 << i) - 1);
41
42
  function formatIPv4Fast(n) {
42
43
  return octetDotStrings[n >>> 24 & 255] + octetDotStrings[n >>> 16 & 255] + octetDotStrings[n >>> 8 & 255] + octetStrings[n & 255];
43
44
  }
@@ -61,15 +62,9 @@ function parseIPv4Range(str) {
61
62
  const v4num = parseIPv4Fast(str, rangeSlashIndex !== -1 ? rangeSlashIndex : str.length);
62
63
  if (v4num === -1) return false;
63
64
  rangeV4Prefix = rangeSlashIndex !== -1 ? parsePrefixNum(str, rangeSlashIndex) : 32;
64
- const hostBits = 32 - rangeV4Prefix;
65
- if (hostBits >= 32) {
66
- rangeV4Start = 0;
67
- rangeV4End = 4294967295;
68
- } else {
69
- const mask = hostBits > 0 ? (1 << hostBits >>> 0) - 1 : 0;
70
- rangeV4Start = (v4num & ~mask) >>> 0;
71
- rangeV4End = (v4num | mask) >>> 0;
72
- }
65
+ const mask = hostMasks4[Math.max(32 - rangeV4Prefix, 0)];
66
+ rangeV4Start = (v4num & ~mask) >>> 0;
67
+ rangeV4End = (v4num | mask) >>> 0;
73
68
  return true;
74
69
  }
75
70
  function doNormalize(cidr, opts) {
@@ -84,10 +79,8 @@ function doNormalize(cidr, opts) {
84
79
  if (prefixNum === -1) prefixNum = bits[version];
85
80
  if (version === 4) {
86
81
  const hostBits = 32 - prefixNum;
87
- let startNum = Number(number);
88
- if (hostBits >= 32) startNum = 0;
89
- else if (hostBits > 0) startNum = (startNum & ~((1 << hostBits >>> 0) - 1)) >>> 0;
90
- const ip = formatIPv4Fast(startNum);
82
+ const mask = hostMasks4[Math.max(hostBits, 0)];
83
+ const ip = formatIPv4Fast((Number(number) & ~mask) >>> 0);
91
84
  return hostBits > 0 || prefixPresent ? ip + prefixStrings[prefixNum] : ip;
92
85
  }
93
86
  const { compress = true, hexify = false } = opts || {};
@@ -122,24 +115,15 @@ function parseCidr(str) {
122
115
  const prefixNum = prefixPresent ? parsePrefixNum(str, slashIndex) : 32;
123
116
  const ip = formatIPv4Fast(v4num);
124
117
  const prefix = prefixNumStrings[prefixNum] ?? String(prefixNum);
125
- const hostBits = 32 - prefixNum;
126
- let startNum, endNum;
127
- if (hostBits >= 32) {
128
- startNum = 0;
129
- endNum = 4294967295;
130
- } else {
131
- const mask = hostBits > 0 ? (1 << hostBits >>> 0) - 1 : 0;
132
- startNum = (v4num & ~mask) >>> 0;
133
- endNum = (v4num | mask) >>> 0;
134
- }
118
+ const mask = hostMasks4[Math.max(32 - prefixNum, 0)];
135
119
  return {
136
120
  cidr: ip + prefixStrings[prefixNum],
137
121
  ip,
138
122
  version: 4,
139
123
  prefix,
140
124
  prefixPresent,
141
- start: BigInt(startNum),
142
- end: BigInt(endNum)
125
+ start: BigInt((v4num & ~mask) >>> 0),
126
+ end: BigInt((v4num | mask) >>> 0)
143
127
  };
144
128
  }
145
129
  const ipPart = prefixPresent ? str.substring(0, slashIndex) : str;
@@ -188,12 +172,7 @@ function parseCidrLean(str) {
188
172
  const hostBits = numBits - prefixNum;
189
173
  if (version === 4) {
190
174
  const num = Number(number);
191
- if (hostBits >= 32) return {
192
- start: 0,
193
- end: 4294967295,
194
- version: 4
195
- };
196
- const mask = hostBits > 0 ? (1 << hostBits >>> 0) - 1 : 0;
175
+ const mask = hostMasks4[Math.max(hostBits, 0)];
197
176
  return {
198
177
  start: (num & ~mask) >>> 0,
199
178
  end: (num | mask) >>> 0,
@@ -367,13 +346,11 @@ function subtractSorted6(bases, excls) {
367
346
  }
368
347
  /** Returns an array of merged networks */
369
348
  function mergeCidr(nets) {
370
- const arr = typeof nets === "string" ? [nets] : nets;
371
- const v4 = [];
372
- const v6 = [];
373
- for (const s of arr) {
374
- const n = parseCidrLean(s);
375
- if (n.version === 4) v4.push(n);
376
- else v6.push(n);
349
+ const v4 = [], v6 = [];
350
+ for (const str of typeof nets === "string" ? [nets] : nets) {
351
+ const net = parseCidrLean(str);
352
+ if (net.version === 4) v4.push(net);
353
+ else v6.push(net);
377
354
  }
378
355
  const merged = [];
379
356
  for (const part of mergeIntervalsRaw4(v4)) subparts4(part.start, part.end, merged);
@@ -382,42 +359,30 @@ function mergeCidr(nets) {
382
359
  }
383
360
  /** Returns an array of merged remaining networks of the subtraction of `excludeNetworks` from `baseNetworks`. */
384
361
  function excludeCidr(base, excl) {
385
- const baseArr = typeof base === "string" ? [base] : base;
386
- const exclArr = typeof excl === "string" ? [excl] : excl;
387
362
  const v4base = [], v6base = [];
388
363
  const v4excl = [], v6excl = [];
389
- for (const s of baseArr) {
390
- const n = parseCidrLean(s);
391
- if (n.version === 4) v4base.push(n);
392
- else v6base.push(n);
364
+ for (const str of typeof base === "string" ? [base] : base) {
365
+ const net = parseCidrLean(str);
366
+ if (net.version === 4) v4base.push(net);
367
+ else v6base.push(net);
393
368
  }
394
- for (const s of exclArr) {
395
- const n = parseCidrLean(s);
396
- if (n.version === 4) v4excl.push(n);
397
- else v6excl.push(n);
369
+ for (const str of typeof excl === "string" ? [excl] : excl) {
370
+ const net = parseCidrLean(str);
371
+ if (net.version === 4) v4excl.push(net);
372
+ else v6excl.push(net);
398
373
  }
399
374
  const result = [];
400
- {
401
- const baseParts = mergeIntervalsRaw4(v4base);
402
- const exclParts = mergeIntervalsRaw4(v4excl);
403
- for (const part of subtractSorted4(baseParts, exclParts)) subparts4(part.start, part.end, result);
404
- }
405
- {
406
- const baseParts = mergeIntervalsRaw6(v6base);
407
- const exclParts = mergeIntervalsRaw6(v6excl);
408
- for (const part of subtractSorted6(baseParts, exclParts)) subparts6(part.start, part.end, result);
409
- }
375
+ if (v4base.length > 0) for (const part of subtractSorted4(mergeIntervalsRaw4(v4base), mergeIntervalsRaw4(v4excl))) subparts4(part.start, part.end, result);
376
+ if (v6base.length > 0) for (const part of subtractSorted6(mergeIntervalsRaw6(v6base), mergeIntervalsRaw6(v6excl))) subparts6(part.start, part.end, result);
410
377
  return result;
411
378
  }
412
379
  /** Returns a generator for individual IPs contained in the networks. */
413
380
  function* expandCidr(nets) {
414
- const arr = typeof nets === "string" ? [nets] : nets;
415
- const v4 = [];
416
- const v6 = [];
417
- for (const s of arr) {
418
- const n = parseCidrLean(s);
419
- if (n.version === 4) v4.push(n);
420
- else v6.push(n);
381
+ const v4 = [], v6 = [];
382
+ for (const str of typeof nets === "string" ? [nets] : nets) {
383
+ const net = parseCidrLean(str);
384
+ if (net.version === 4) v4.push(net);
385
+ else v6.push(net);
421
386
  }
422
387
  if (v4.length > 0) for (const part of mergeIntervalsRaw4(v4)) {
423
388
  let prevHigh = -1;
@@ -473,26 +438,22 @@ function overlapCidr(a, b) {
473
438
  if (pa.version !== pb.version) return false;
474
439
  return pa.start <= pb.end && pb.start <= pa.end;
475
440
  }
476
- const aArr = typeof a === "string" ? [a] : a;
477
- const bArr = typeof b === "string" ? [b] : b;
478
441
  const v4a = [], v6a = [];
479
442
  const v4b = [], v6b = [];
480
- for (const s of aArr) {
481
- const n = parseCidrLean(s);
482
- if (n.version === 4) v4a.push(n);
483
- else v6a.push(n);
484
- }
485
- for (const s of bArr) {
486
- const n = parseCidrLean(s);
487
- if (n.version === 4) v4b.push(n);
488
- else v6b.push(n);
489
- }
490
- if (v4a.length > 0 && v4b.length > 0) if (v4b.length === 1) {
491
- const bs = v4b[0].start, be = v4b[0].end;
492
- for (const el of v4a) if (el.start <= be && bs <= el.end) return true;
493
- } else if (v4a.length === 1) {
494
- const as = v4a[0].start, ae = v4a[0].end;
495
- for (const el of v4b) if (as <= el.end && el.start <= ae) return true;
443
+ for (const str of typeof a === "string" ? [a] : a) {
444
+ const net = parseCidrLean(str);
445
+ if (net.version === 4) v4a.push(net);
446
+ else v6a.push(net);
447
+ }
448
+ for (const str of typeof b === "string" ? [b] : b) {
449
+ const net = parseCidrLean(str);
450
+ if (net.version === 4) v4b.push(net);
451
+ else v6b.push(net);
452
+ }
453
+ if (v4a.length > 0 && v4b.length > 0) if (v4a.length === 1 || v4b.length === 1) {
454
+ const bIsSingle = v4b.length === 1;
455
+ const one = bIsSingle ? v4b[0] : v4a[0];
456
+ for (const el of bIsSingle ? v4a : v4b) if (one.start <= el.end && el.start <= one.end) return true;
496
457
  } else {
497
458
  v4a.sort(cmpV4Start);
498
459
  v4b.sort(cmpV4Start);
@@ -503,12 +464,10 @@ function overlapCidr(a, b) {
503
464
  else j++;
504
465
  }
505
466
  }
506
- if (v6a.length > 0 && v6b.length > 0) if (v6b.length === 1) {
507
- const bs = v6b[0].start, be = v6b[0].end;
508
- for (const el of v6a) if (el.start <= be && bs <= el.end) return true;
509
- } else if (v6a.length === 1) {
510
- const as = v6a[0].start, ae = v6a[0].end;
511
- for (const el of v6b) if (as <= el.end && el.start <= ae) return true;
467
+ if (v6a.length > 0 && v6b.length > 0) if (v6a.length === 1 || v6b.length === 1) {
468
+ const bIsSingle = v6b.length === 1;
469
+ const one = bIsSingle ? v6b[0] : v6a[0];
470
+ for (const el of bIsSingle ? v6a : v6b) if (one.start <= el.end && el.start <= one.end) return true;
512
471
  } else {
513
472
  v6a.sort(cmpV6Start);
514
473
  v6b.sort(cmpV6Start);
@@ -536,19 +495,17 @@ function containsCidr(a, b) {
536
495
  if (pa.version !== pb.version) return false;
537
496
  return pa.start <= pb.start && pa.end >= pb.end;
538
497
  }
539
- const aArr = typeof a === "string" ? [a] : a;
540
- const bArr = typeof b === "string" ? [b] : b;
541
498
  const v4a = [], v6a = [];
542
499
  const v4b = [], v6b = [];
543
- for (const s of aArr) {
544
- const n = parseCidrLean(s);
545
- if (n.version === 4) v4a.push(n);
546
- else v6a.push(n);
547
- }
548
- for (const s of bArr) {
549
- const n = parseCidrLean(s);
550
- if (n.version === 4) v4b.push(n);
551
- else v6b.push(n);
500
+ for (const str of typeof a === "string" ? [a] : a) {
501
+ const net = parseCidrLean(str);
502
+ if (net.version === 4) v4a.push(net);
503
+ else v6a.push(net);
504
+ }
505
+ for (const str of typeof b === "string" ? [b] : b) {
506
+ const net = parseCidrLean(str);
507
+ if (net.version === 4) v4b.push(net);
508
+ else v6b.push(net);
552
509
  }
553
510
  if (v4b.length > 0) {
554
511
  if (v4a.length === 0) return false;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "cidr-tools",
3
- "version": "12.1.2",
3
+ "version": "12.1.3",
4
4
  "author": "silverwind <me@silverwind.io>",
5
5
  "description": "Tools to work with IPv4 and IPv6 CIDR",
6
6
  "keywords": [
@@ -29,23 +29,23 @@
29
29
  "bun": "*"
30
30
  },
31
31
  "dependencies": {
32
- "ip-bigint": "^9.0.6"
32
+ "ip-bigint": "^9.0.7"
33
33
  },
34
34
  "devDependencies": {
35
- "@types/node": "26.0.1",
36
- "@typescript/native-preview": "7.0.0-dev.20260627.2",
37
- "@vitest/coverage-v8": "4.1.9",
38
- "eslint": "10.6.0",
39
- "eslint-config-silverwind": "138.0.0",
35
+ "@types/node": "26.1.2",
36
+ "@typescript/native-preview": "7.0.0-dev.20260707.2",
37
+ "@vitest/coverage-v8": "4.1.10",
38
+ "eslint": "10.8.0",
39
+ "eslint-config-silverwind": "143.0.0",
40
40
  "jest-extended": "7.0.0",
41
- "tsdown": "0.22.3",
42
- "tsdown-config-silverwind": "3.0.4",
41
+ "tsdown": "0.22.14",
42
+ "tsdown-config-silverwind": "4.0.3",
43
43
  "typescript": "6.0.3",
44
- "typescript-config-silverwind": "20.0.0",
45
- "updates": "17.18.0",
46
- "updates-config-silverwind": "4.0.0",
47
- "versions": "15.1.1",
48
- "vitest": "4.1.9",
49
- "vitest-config-silverwind": "11.3.6"
44
+ "typescript-config-silverwind": "20.0.3",
45
+ "updates": "17.19.2",
46
+ "updates-config-silverwind": "4.0.4",
47
+ "versions": "15.1.4",
48
+ "vitest": "4.1.10",
49
+ "vitest-config-silverwind": "11.4.0"
50
50
  }
51
51
  }