cidr-tools 11.2.0 → 11.2.1

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 +61 -13
  2. package/package.json +9 -9
package/dist/index.js CHANGED
@@ -29,8 +29,23 @@ function parseIPv4Fast(s) {
29
29
  function formatIPv4Fast(n) {
30
30
  return `${n >>> 24 & 255}.${n >>> 16 & 255}.${n >>> 8 & 255}.${n & 255}`;
31
31
  }
32
+ function parsePrefixNum(str, slashIndex) {
33
+ if (slashIndex === -1) return -1;
34
+ if (slashIndex + 1 >= str.length) throw new Error(`Network is not a CIDR or IP: "${str}"`);
35
+ let prefixNum = 0;
36
+ for (let i = slashIndex + 1; i < str.length; i++) {
37
+ const c = str.charCodeAt(i);
38
+ if (c < 48 || c > 57) throw new Error(`Network is not a CIDR or IP: "${str}"`);
39
+ prefixNum = prefixNum * 10 + (c - 48);
40
+ }
41
+ return prefixNum;
42
+ }
32
43
  function doNormalize(cidr, { compress = true, hexify = false } = {}) {
33
44
  const { start, end, prefix, version, prefixPresent } = parseCidr(cidr);
45
+ if (version === 4) {
46
+ const ip = formatIPv4Fast(Number(start));
47
+ return start !== end || prefixPresent ? `${ip}/${prefix}` : ip;
48
+ }
34
49
  if (start !== end || prefixPresent) return `${normalizeIp(stringifyIp({
35
50
  number: start,
36
51
  version
@@ -52,28 +67,55 @@ function normalizeCidr(cidr, opts) {
52
67
  function parseCidr(str) {
53
68
  const slashIndex = str.indexOf("/");
54
69
  let ipPart;
55
- let prefix;
70
+ let prefixNum;
56
71
  let prefixPresent;
57
72
  if (slashIndex !== -1) {
58
73
  ipPart = str.substring(0, slashIndex);
59
- prefix = str.substring(slashIndex + 1);
60
- if (!/^[0-9]+$/.test(prefix)) throw new Error(`Network is not a CIDR or IP: "${str}"`);
74
+ prefixNum = parsePrefixNum(str, slashIndex);
61
75
  prefixPresent = true;
62
76
  } else {
63
77
  ipPart = str;
78
+ prefixNum = -1;
64
79
  prefixPresent = false;
65
- prefix = "";
80
+ }
81
+ if (!ipPart.includes(":")) {
82
+ const v4num = parseIPv4Fast(ipPart);
83
+ if (v4num !== -1) {
84
+ if (prefixNum === -1) prefixNum = 32;
85
+ const ip = formatIPv4Fast(v4num);
86
+ const prefix = String(prefixNum);
87
+ const hostBits = 32 - prefixNum;
88
+ let startNum, endNum;
89
+ if (hostBits >= 32) {
90
+ startNum = 0;
91
+ endNum = 4294967295;
92
+ } else {
93
+ const mask = hostBits > 0 ? (1 << hostBits >>> 0) - 1 : 0;
94
+ startNum = (v4num & ~mask) >>> 0;
95
+ endNum = (v4num | mask) >>> 0;
96
+ }
97
+ return {
98
+ cidr: `${ip}/${prefix}`,
99
+ ip,
100
+ version: 4,
101
+ prefix,
102
+ prefixPresent,
103
+ start: BigInt(startNum),
104
+ end: BigInt(endNum)
105
+ };
106
+ }
66
107
  }
67
108
  const { number, version, ipv4mapped, scopeid } = parseIp(ipPart);
68
109
  if (!version) throw new Error(`Network is not a CIDR or IP: "${str}"`);
69
- if (!prefixPresent) prefix = String(bits[version]);
110
+ if (prefixNum === -1) prefixNum = bits[version];
111
+ const prefix = String(prefixNum);
70
112
  const ip = stringifyIp({
71
113
  number,
72
114
  version,
73
115
  ipv4mapped,
74
116
  scopeid
75
117
  });
76
- const hostBits = bits[version] - Number(prefix);
118
+ const hostBits = bits[version] - prefixNum;
77
119
  const mask = hostBits > 0 ? (1n << BigInt(hostBits)) - 1n : 0n;
78
120
  return {
79
121
  cidr: `${ip}/${prefix}`,
@@ -91,13 +133,7 @@ function parseCidrLean(str) {
91
133
  let prefixNum;
92
134
  if (slashIndex !== -1) {
93
135
  ipPart = str.substring(0, slashIndex);
94
- if (slashIndex + 1 >= str.length) throw new Error(`Network is not a CIDR or IP: "${str}"`);
95
- prefixNum = 0;
96
- for (let i = slashIndex + 1; i < str.length; i++) {
97
- const c = str.charCodeAt(i);
98
- if (c < 48 || c > 57) throw new Error(`Network is not a CIDR or IP: "${str}"`);
99
- prefixNum = prefixNum * 10 + (c - 48);
100
- }
136
+ prefixNum = parsePrefixNum(str, slashIndex);
101
137
  } else {
102
138
  ipPart = str;
103
139
  prefixNum = -1;
@@ -481,6 +517,12 @@ function* expandCidr(nets) {
481
517
  }
482
518
  /** Returns a boolean that indicates if `networksA` overlap (intersect) with `networksB`. */
483
519
  function overlapCidr(a, b) {
520
+ if (!Array.isArray(a) && !Array.isArray(b)) {
521
+ const pa = parseCidrLean(a);
522
+ const pb = parseCidrLean(b);
523
+ if (pa.version !== pb.version) return false;
524
+ return pa.start <= pb.end && pb.start <= pa.end;
525
+ }
484
526
  const aArr = Array.isArray(a) ? a : [a];
485
527
  const bArr = Array.isArray(b) ? b : [b];
486
528
  const v4a = [], v6a = [];
@@ -519,6 +561,12 @@ function overlapCidr(a, b) {
519
561
  }
520
562
  /** Returns a boolean that indicates whether `networksA` fully contain all `networksB`. */
521
563
  function containsCidr(a, b) {
564
+ if (!Array.isArray(a) && !Array.isArray(b)) {
565
+ const pa = parseCidrLean(a);
566
+ const pb = parseCidrLean(b);
567
+ if (pa.version !== pb.version) return false;
568
+ return pa.start <= pb.start && pa.end >= pb.end;
569
+ }
522
570
  const aArr = Array.isArray(a) ? a : [a];
523
571
  const bArr = Array.isArray(b) ? b : [b];
524
572
  const v4a = [], v6a = [];
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "cidr-tools",
3
- "version": "11.2.0",
3
+ "version": "11.2.1",
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,19 +17,19 @@
17
17
  "node": ">=18"
18
18
  },
19
19
  "dependencies": {
20
- "ip-bigint": "^8.2.9"
20
+ "ip-bigint": "^8.2.12"
21
21
  },
22
22
  "devDependencies": {
23
- "@types/node": "25.3.3",
24
- "@typescript/native-preview": "7.0.0-dev.20260305.1",
25
- "eslint": "9.39.3",
26
- "eslint-config-silverwind": "121.2.0",
23
+ "@types/node": "25.4.0",
24
+ "@typescript/native-preview": "7.0.0-dev.20260311.1",
25
+ "eslint": "9.39.4",
26
+ "eslint-config-silverwind": "124.0.7",
27
27
  "jest-extended": "7.0.0",
28
- "tsdown": "0.21.0",
29
- "tsdown-config-silverwind": "2.0.0",
28
+ "tsdown": "0.21.2",
29
+ "tsdown-config-silverwind": "2.0.1",
30
30
  "typescript": "5.9.3",
31
31
  "typescript-config-silverwind": "15.0.0",
32
- "updates": "17.8.1",
32
+ "updates": "17.9.0",
33
33
  "updates-config-silverwind": "1.0.3",
34
34
  "versions": "14.2.1",
35
35
  "vitest": "4.0.18",