cidr-tools 7.0.4 → 7.0.6

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/README.md CHANGED
@@ -71,15 +71,14 @@ Returns a string or array (depending on input) with a normalized representation.
71
71
 
72
72
  - `network` *String*: A CIDR or IP address.
73
73
 
74
- 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 work with the BigInts directly.
74
+ 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.
75
75
 
76
76
  `parsed`: `Object`
77
77
  - `cidr` String: The CIDR of the network.
78
- - `version` Number: Either `4` or `6`.
78
+ - `version` Number: IP protocol version. Either `4` or `6`.
79
79
  - `prefix` String: The network prefix, e.g. `/64`.
80
- - `start` BigInt: Start of the network.
81
- - `end` BigInt: Start of the network.
82
- - `single` Boolean: `true` when is a single IP.
80
+ - `start` BigInt: Start number of the network.
81
+ - `end` BigInt: End number of the network.
83
82
 
84
83
  ## Related
85
84
 
package/index.d.ts CHANGED
@@ -2,7 +2,6 @@ type IPv4Address = string;
2
2
  type IPv4CIDR = string;
3
3
  type IPv6Address = string;
4
4
  type IPv6CIDR = string;
5
-
6
5
  type Network = IPv4Address | IPv4CIDR | IPv6Address | IPv6CIDR;
7
6
  type Networks = Network | Network[];
8
7
 
@@ -12,7 +11,6 @@ type Parsed = {
12
11
  prefix: string;
13
12
  start: bigint;
14
13
  end: bigint;
15
- single: boolean;
16
14
  };
17
15
 
18
16
  type NormalizeOpts = {
package/index.js CHANGED
@@ -1,10 +1,6 @@
1
1
  import {parseIp, stringifyIp, normalizeIp, ipVersion} from "ip-bigint";
2
2
 
3
- const bits = {
4
- 4: 32,
5
- 6: 128,
6
- };
7
-
3
+ const bits = {4: 32, 6: 128};
8
4
  const uniq = arr => Array.from(new Set(arr));
9
5
  const cidrVersion = cidr => cidr.includes("/") ? ipVersion(cidr) : 0;
10
6
 
@@ -20,8 +16,8 @@ function compare(a, b) {
20
16
  }
21
17
 
22
18
  function doNormalize(cidr, {compress = true, hexify = false} = {}) {
23
- const {start, prefix, single, version} = parse(cidr);
24
- if (!single) { // cidr
19
+ const {start, end, prefix, version} = parse(cidr);
20
+ if (start !== end) { // cidr
25
21
  // set network address to first address
26
22
  const ip = normalizeIp(stringifyIp({number: start, version}), {compress, hexify});
27
23
  return `${ip}/${prefix}`;
@@ -41,7 +37,6 @@ export function normalize(cidr, {compress = true, hexify = false} = {}) {
41
37
  export function parse(str) {
42
38
  const cidrVer = cidrVersion(str);
43
39
  const parsed = Object.create(null);
44
- parsed.single = false;
45
40
 
46
41
  if (cidrVer) {
47
42
  parsed.cidr = str;
@@ -51,13 +46,17 @@ export function parse(str) {
51
46
  if (version) {
52
47
  parsed.cidr = `${str}/${bits[version]}`;
53
48
  parsed.version = version;
54
- parsed.single = true;
55
49
  } else {
56
50
  throw new Error(`Network is not a CIDR or IP: ${str}`);
57
51
  }
58
52
  }
59
53
 
60
54
  const [ip, prefix] = parsed.cidr.split("/");
55
+
56
+ if (!/^[0-9]+$/.test(prefix)) {
57
+ throw new Error(`Network is not a CIDR or IP: ${str}`);
58
+ }
59
+
61
60
  parsed.prefix = prefix;
62
61
  const {number, version} = parseIp(ip);
63
62
  const numBits = bits[version];
@@ -223,75 +222,80 @@ function diff(a, b) {
223
222
  return a - b;
224
223
  }
225
224
 
226
- function formatPart(part, v) {
227
- const ip = normalize(stringifyIp({
228
- number: BigInt(part.start.toString()),
229
- version: v,
230
- }));
225
+ function formatPart(part, version) {
226
+ const ip = normalize(stringifyIp({number: BigInt(part.start.toString()), version}));
231
227
  const zeroes = diff(part.end, part.start).toString(2);
232
- const prefix = bits[v] - (zeroes.match(/0/g) || []).length;
228
+ const prefix = bits[version] - (zeroes.match(/0/g) || []).length;
233
229
  return `${ip}/${prefix}`;
234
230
  }
235
231
 
236
232
  function mapNets(nets) {
237
- const maps = {4: {}, 6: {}};
238
- for (const {start, end, version: v} of nets) {
239
- if (!maps[v][start]) maps[v][start] = {};
240
- if (!maps[v][end]) maps[v][end] = {};
233
+ const maps = {4: {}, 6: {}}; // TODO: use Map with BigInt key
234
+ for (const {start, end, version} of nets) {
235
+ if (!maps[version][start]) maps[version][start] = {};
236
+ if (!maps[version][end]) maps[version][end] = {};
241
237
 
242
- if (maps[v][start].start) {
243
- maps[v][start].start += 1;
238
+ if (maps[version][start].start) {
239
+ maps[version][start].start += 1;
244
240
  } else {
245
- maps[v][start].start = 1;
241
+ maps[version][start].start = 1;
246
242
  }
247
243
 
248
- if (maps[v][end].end) {
249
- maps[v][end].end += 1;
244
+ if (maps[version][end].end) {
245
+ maps[version][end].end += 1;
250
246
  } else {
251
- maps[v][end].end = 1;
247
+ maps[version][end].end = 1;
252
248
  }
253
249
  }
254
250
  return maps;
255
251
  }
256
252
 
257
- export function merge(nets) {
258
- // sort to workaround https://github.com/silverwind/cidr-tools/issues/17
259
- nets = uniq((Array.isArray(nets) ? nets : [nets]).sort(compare).map(parse));
260
- const maps = mapNets(nets);
253
+ function doMerge(maps, v) {
254
+ let start = null;
255
+ let end = null;
256
+ const numbers = Object.keys(maps);
257
+ let depth = 0;
258
+ const merged = [];
261
259
 
262
- const merged = {4: [], 6: []};
263
- const start = {4: null, 6: null};
264
- const end = {4: null, 6: null};
260
+ for (const [index, number] of numbers.entries()) {
261
+ const marker = maps[number];
265
262
 
266
- for (const v of [4, 6]) {
267
- const numbers = Object.keys(maps[v]);
268
- let depth = 0;
263
+ if (start === null && marker.start) {
264
+ start = BigInt(number);
265
+ }
266
+ if (marker.end) {
267
+ end = BigInt(number);
268
+ }
269
269
 
270
- for (const [index, number] of numbers.entries()) {
271
- const marker = maps[v][number];
270
+ if (marker.start) depth += marker.start;
271
+ if (marker.end) depth -= marker.end;
272
272
 
273
- if (start[v] === null && marker.start) {
274
- start[v] = BigInt(number);
273
+ const next = numbers[index + 1];
274
+ if (marker.end && depth === 0 && next && ((BigInt(next) - BigInt(number)) > 1)) {
275
+ // when there is a end and the next part is more than one number away, we cut a part
276
+ for (const sub of subparts({start, end})) {
277
+ merged.push(formatPart(sub, v));
275
278
  }
276
- if (marker.end) {
277
- end[v] = BigInt(number);
279
+ start = null;
280
+ end = null;
281
+ } else if (index === (numbers.length - 1)) {
282
+ // cut the final part
283
+ for (const sub of subparts({start, end})) {
284
+ merged.push(formatPart(sub, v));
278
285
  }
286
+ }
287
+ }
288
+ return merged;
289
+ }
279
290
 
280
- if (marker.start) depth += marker.start;
281
- if (marker.end) depth -= marker.end;
291
+ export function merge(nets) {
292
+ // sort to workaround https://github.com/silverwind/cidr-tools/issues/17
293
+ nets = uniq((Array.isArray(nets) ? nets : [nets]).sort(compare).map(parse));
294
+ const maps = mapNets(nets);
282
295
 
283
- if (marker.end && depth === 0 && ((numbers[index + 1] - numbers[index]) > 1)) {
284
- for (const sub of subparts({start: start[v], end: end[v]})) {
285
- merged[v].push(formatPart(sub, v));
286
- }
287
- start[v] = null;
288
- end[v] = null;
289
- } else if (index === (numbers.length - 1)) {
290
- for (const sub of subparts({start: start[v], end: end[v]})) {
291
- merged[v].push(formatPart(sub, v));
292
- }
293
- }
294
- }
296
+ const merged = {4: [], 6: []};
297
+ for (const v of [4, 6]) {
298
+ merged[v] = doMerge(maps[v], v);
295
299
  }
296
300
 
297
301
  return [...merged[4].sort(compare), ...merged[6].sort(compare)];
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "cidr-tools",
3
- "version": "7.0.4",
3
+ "version": "7.0.6",
4
4
  "author": "silverwind <me@silverwind.io>",
5
5
  "description": "Tools to work with IPv4 and IPv6 CIDR",
6
6
  "repository": "silverwind/cidr-tools",
@@ -18,15 +18,15 @@
18
18
  "./index.d.ts"
19
19
  ],
20
20
  "dependencies": {
21
- "ip-bigint": "^8.0.1"
21
+ "ip-bigint": "^8.0.2"
22
22
  },
23
23
  "devDependencies": {
24
- "eslint": "8.54.0",
25
- "eslint-config-silverwind": "79.3.5",
26
- "tsd": "0.29.0",
27
- "updates": "15.0.4",
28
- "versions": "12.0.0",
29
- "vitest": "0.34.6",
30
- "vitest-config-silverwind": "3.0.0"
24
+ "eslint": "8.56.0",
25
+ "eslint-config-silverwind": "80.0.3",
26
+ "tsd": "0.30.5",
27
+ "updates": "15.1.2",
28
+ "versions": "12.0.1",
29
+ "vitest": "1.3.1",
30
+ "vitest-config-silverwind": "5.1.1"
31
31
  }
32
32
  }