UNPKG

the-moby-effect

Version:
326 lines (324 loc) 12 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.tail = exports.splitLiteral = exports.IPv6CidrBlockFromString = exports.IPv6CidrBlock = exports.IPv4CidrBlockFromString = exports.IPv4CidrBlock = exports.CidrBlockFromString = exports.CidrBlockBase = exports.CidrBlock = void 0; var Array = _interopRequireWildcard(require("effect/Array")); var Effect = _interopRequireWildcard(require("effect/Effect")); var Function = _interopRequireWildcard(require("effect/Function")); var ParseResult = _interopRequireWildcard(require("effect/ParseResult")); var Schema = _interopRequireWildcard(require("effect/Schema")); var Stream = _interopRequireWildcard(require("effect/Stream")); var Address = _interopRequireWildcard(require("./address.js")); var CidrBlockMask = _interopRequireWildcard(require("./cidrBlockMask.js")); var IPv4 = _interopRequireWildcard(require("./ipv4.js")); var IPv6 = _interopRequireWildcard(require("./ipv6.js")); function _getRequireWildcardCache(e) { if ("function" != typeof WeakMap) return null; var r = new WeakMap(), t = new WeakMap(); return (_getRequireWildcardCache = function (e) { return e ? t : r; })(e); } function _interopRequireWildcard(e, r) { if (!r && e && e.__esModule) return e; if (null === e || "object" != typeof e && "function" != typeof e) return { default: e }; var t = _getRequireWildcardCache(r); if (t && t.has(e)) return t.get(e); var n = { __proto__: null }, a = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var u in e) if ("default" !== u && {}.hasOwnProperty.call(e, u)) { var i = a ? Object.getOwnPropertyDescriptor(e, u) : null; i && (i.get || i.set) ? Object.defineProperty(n, u, i) : n[u] = e[u]; } return n.default = e, t && t.set(e, n), n; } /** * IPv4 or IPv6 cidr block schemas. * * @since 1.0.0 */ /** @internal */ const tail = elements => elements.slice(1); /** @internal */ exports.tail = tail; const splitLiteral = (str, delimiter) => str.split(delimiter); /** * @since 1.0.0 * @category Api interface */ exports.splitLiteral = splitLiteral; class CidrBlockBase extends /*#__PURE__*/Schema.Class("CidrBlockMixin")({ address: Address.Address, mask: /*#__PURE__*/Schema.Union(CidrBlockMask.IPv4CidrMask, CidrBlockMask.IPv6CidrMask) }) { /** @since 1.0.0 */ family = this.address.family; /** @internal */ onFamily({ onIPv4, onIPv6 }) { const isIPv4 = () => this.family === "ipv4"; const isIPv6 = () => this.family === "ipv6"; if (isIPv4()) { return onIPv4(this); } else if (isIPv6()) { return onIPv6(this); } else { return Function.absurd(this.family); } } /** * The first address in the range given by this address' subnet, often * referred to as the Network Address. * * @since 1.0.0 */ get networkAddressAsBigint() { return Effect.gen(this, function* () { const bits = this.family === "ipv4" ? 32 : 128; const bigIntegerAddress = yield* this.onFamily({ onIPv4: self => Schema.decode(IPv4.IPv4Bigint)(self.address.ip), onIPv6: self => Schema.decode(IPv6.IPv6Bigint)(self.address.ip) }); const intermediate = bigIntegerAddress.value.toString(2).padStart(bits, "0").slice(0, this.mask); const networkAddressString = intermediate + "0".repeat(bits - this.mask); const networkAddressBigInt = BigInt(`0b${networkAddressString}`); return this.onFamily({ onIPv4: _self => IPv4.IPv4BigintBrand(networkAddressBigInt), onIPv6: _self => IPv6.IPv6BigintBrand(networkAddressBigInt) }); }); } /** * The first address in the range given by this address' subnet, often * referred to as the Network Address. * * @since 1.0.0 */ networkAddress() { return this.onFamily({ onIPv4: self => Function.pipe(self.networkAddressAsBigint, Effect.flatMap(value => Schema.encode(IPv4.IPv4Bigint)({ value, family: "ipv4" })), Effect.flatMap(Schema.decode(IPv4.IPv4))), onIPv6: self => Function.pipe(self.networkAddressAsBigint, Effect.flatMap(value => Schema.encode(IPv6.IPv6Bigint)({ value, family: "ipv6" })), Effect.flatMap(Schema.decode(IPv6.IPv6))) }); } /** * The last address in the range given by this address' subnet, often * referred to as the Broadcast Address. * * @since 1.0.0 */ get broadcastAddressAsBigint() { return Effect.gen(this, function* () { const bits = this.family === "ipv4" ? 32 : 128; const bigIntegerAddress = yield* this.onFamily({ onIPv4: self => Schema.decode(IPv4.IPv4Bigint)(self.address.ip), onIPv6: self => Schema.decode(IPv6.IPv6Bigint)(self.address.ip) }); const intermediate = bigIntegerAddress.value.toString(2).padStart(bits, "0").slice(0, this.mask); const broadcastAddressString = intermediate + "1".repeat(bits - this.mask); const broadcastAddressBigInt = BigInt(`0b${broadcastAddressString}`); return this.onFamily({ onIPv4: _self => IPv4.IPv4BigintBrand(broadcastAddressBigInt), onIPv6: _self => IPv6.IPv6BigintBrand(broadcastAddressBigInt) }); }); } /** * The last address in the range given by this address' subnet, often * referred to as the Broadcast Address. * * @since 1.0.0 */ broadcastAddress() { return this.onFamily({ onIPv4: self => Function.pipe(self.broadcastAddressAsBigint, Effect.flatMap(value => Schema.encode(IPv4.IPv4Bigint)({ value, family: "ipv4" })), Effect.flatMap(Schema.decode(IPv4.IPv4))), onIPv6: self => Function.pipe(self.broadcastAddressAsBigint, Effect.flatMap(value => Schema.encode(IPv6.IPv6Bigint)({ value, family: "ipv6" })), Effect.flatMap(Schema.decode(IPv6.IPv6))) }); } /** * A stream of all addresses in the range given by this address' subnet. * * @since 1.0.0 */ get range() { return this.onFamily({ onIPv4: self => Effect.gen(function* () { const minValue = yield* self.networkAddressAsBigint; const maxValue = yield* self.broadcastAddressAsBigint; return Function.pipe(Stream.iterate(minValue, x => IPv4.IPv4BigintBrand(x + 1n)), Stream.takeWhile(n => n <= maxValue), Stream.flatMap(value => Schema.encode(IPv4.IPv4Bigint)({ value, family: "ipv4" })), Stream.mapEffect(Schema.decode(IPv4.IPv4))); }).pipe(Stream.unwrap), onIPv6: self => Effect.gen(function* () { const minValue = yield* self.networkAddressAsBigint; const maxValue = yield* self.broadcastAddressAsBigint; return Function.pipe(Stream.iterate(minValue, x => IPv6.IPv6BigintBrand(x + 1n)), Stream.takeWhile(n => n <= maxValue), Stream.flatMap(value => Schema.encode(IPv6.IPv6Bigint)({ value, family: "ipv6" })), Stream.mapEffect(Schema.decode(IPv6.IPv6))); }).pipe(Stream.unwrap) }); } /** * The total number of addresses in the range given by this address' subnet. * * @since 1.0.0 */ get total() { return Effect.gen(this, function* () { const minValue = yield* this.networkAddressAsBigint; const maxValue = yield* this.broadcastAddressAsBigint; return maxValue - minValue + 1n; }); } /** * Finds the smallest CIDR block that contains all the given IP addresses. * * @since 1.0.0 */ static cidrBlockForRange = inputs => Effect.gen(function* () { const bigIntMinAndMax = args => { return args.reduce(([min, max], e) => { return [e < min ? e : min, e > max ? e : max]; }, [args[0], args[0]]); }; const bigints = yield* Function.pipe(inputs, Array.map(address => address.family === "ipv4" ? Schema.decode(IPv4.IPv4Bigint)(address.ip) : Schema.decode(IPv6.IPv6Bigint)(address.ip)), Array.map(x => x), Array.map(Effect.map(({ value }) => value)), Effect.all); const bits = inputs[0].family === "ipv4" ? 32 : 128; const [min, max] = bigIntMinAndMax(bigints); const leadingZerosInMin = bits - min.toString(2).length; const leadingZerosInMax = bits - max.toString(2).length; const cidrMask = Math.min(leadingZerosInMin, leadingZerosInMax); const cidrAddress = inputs[0].family === "ipv4" ? yield* Schema.encode(IPv4.IPv4Bigint)({ value: IPv4.IPv4BigintBrand(min), family: "ipv4" }) : yield* Schema.encode(IPv6.IPv6Bigint)({ value: IPv6.IPv6BigintBrand(min), family: "ipv6" }); return yield* Schema.decode(CidrBlockFromString)(`${cidrAddress}/${cidrMask}`); }); } /** * @since 1.0.0 * @category Schemas */ exports.CidrBlockBase = CidrBlockBase; const IPv4CidrBlock = exports.IPv4CidrBlock = /*#__PURE__*/Schema.transformOrFail(Schema.Struct({ address: IPv4.IPv4, mask: CidrBlockMask.IPv4CidrMask }), CidrBlockBase, { encode: data => Effect.gen(function* () { const address = yield* Schema.decode(IPv4.IPv4)(data.address); const mask = yield* Schema.decode(CidrBlockMask.IPv4CidrMask)(data.mask); return { address, mask }; }).pipe(Effect.mapError(({ issue }) => issue)), decode: data => ParseResult.succeed({ address: data.address.ip, mask: data.mask }) }).annotations({ identifier: "IPv4CidrBlock", description: "An ipv4 cidr block" }); /** * A schema that transforms a `string` into a `CidrBlock`. * * @since 1.0.0 * @category Schemas */ const IPv4CidrBlockFromString = exports.IPv4CidrBlockFromString = /*#__PURE__*/Schema.transform(Schema.TemplateLiteral(Schema.String, Schema.Literal("/"), Schema.Number), IPv4CidrBlock, { decode: str => { const [address, mask] = splitLiteral(str, "/"); return { address, mask: Number.parseInt(mask, 10) }; }, encode: ({ address, mask }) => `${address}/${mask}` }).annotations({ identifier: "IPv4CidrBlockFromString", description: "An ipv4 cidr block from string" }); /** * @since 1.0.0 * @category Schemas */ const IPv6CidrBlock = exports.IPv6CidrBlock = /*#__PURE__*/Schema.transformOrFail(Schema.Struct({ address: IPv6.IPv6, mask: CidrBlockMask.IPv6CidrMask }), CidrBlockBase, { encode: data => Effect.gen(function* () { const address = yield* Schema.decode(IPv6.IPv6)(data.address); const mask = yield* Schema.decode(CidrBlockMask.IPv6CidrMask)(data.mask); return { address, mask }; }).pipe(Effect.mapError(({ issue }) => issue)), decode: data => ParseResult.succeed({ address: data.address.ip, mask: data.mask }) }).annotations({ identifier: "IPv6CidrBlock", description: "An ipv6 cidr block" }); /** * A schema that transforms a `string` into a `CidrBlock`. * * @since 1.0.0 * @category Schemas */ const IPv6CidrBlockFromString = exports.IPv6CidrBlockFromString = /*#__PURE__*/Schema.transform(Schema.TemplateLiteral(Schema.String, Schema.Literal("/"), Schema.Number), IPv6CidrBlock, { decode: str => { const [address, mask] = splitLiteral(str, "/"); return { address, mask: Number.parseInt(mask, 10) }; }, encode: ({ address, mask }) => `${address}/${mask}` }).annotations({ identifier: "IPv6CidrBlockFromString", description: "An ipv6 cidr block from string" }); /** * @since 1.0.0 * @category Schemas */ const CidrBlock = exports.CidrBlock = /*#__PURE__*/Schema.Union(IPv4CidrBlock, IPv6CidrBlock); /** * A schema that transforms a `string` into a `CidrBlock`. * * @since 1.0.0 * @category Schemas */ const CidrBlockFromString = exports.CidrBlockFromString = /*#__PURE__*/Schema.transform(Schema.TemplateLiteral(Schema.String, Schema.Literal("/"), Schema.Number), CidrBlock, { decode: str => { const [address, mask] = splitLiteral(str, "/"); return { address, mask: Number.parseInt(mask, 10) }; }, encode: ({ address, mask }) => `${address}/${mask}` }).annotations({ identifier: "CidrBlockFromString", description: "A cidr block" }); //# sourceMappingURL=cidrBlock.js.map