export class Cidr32Block { public readonly endIpAddressExclusive : number ; /** Do not call directly.  Use the static factory methods to generate a cidr block */ constructor ( public readonly startIpAddressInclusive , public readonly subnetMaskLeading1Bits ) { if ( subnetMaskLeading1Bits < 0 || subnetMaskLeading1Bits > 32 ) { throw new Error ( `Mask for a cidr block must be between "0" and "32", but was ${ subnetMaskLeading1Bits }` ) ; } getIPv4Address ( startIpAddressInclusive ) ; const trailing1Bits = 32 - subnetMaskLeading1Bits ; const ipAddressesInBlock = 2 ** trailing1Bits ; this . endIpAddressExclusive = startIpAddressInclusive + ipAddressesInBlock ; } /**
     * Returns a cidr block given notation like "a.b.c.d/n"
     */ public static fromCidrNotation ( cidr ) { const split = cidr . split ( "/" ) ; if ( split . length !== 2 ) { throw new Error ( `Cidr block notation not valid.  Expected "a.b.c.d/n", but got "${ cidr }"` ) ; } const subnetMaskLeading1Bits = parseInt ( split [ 1 ] , 10 ) ; if ( subnetMaskLeading1Bits < 0 || subnetMaskLeading1Bits > 32 ) { throw new Error ( `Cidr mask bit count must be between 0 and 32, but was "${ subnetMaskLeading1Bits }"` ) ; } const trailing1Bits = 32 - subnetMaskLeading1Bits ; const leadingMask = ( 2 ** 32 ) - ( 2 ** trailing1Bits ) ; const ipAddress = split [ 0 ] ; const ipAddressValue = getIPv4AddressValue ( ipAddress ) ; const startIpAddress = ipAddressValue & leadingMask ; return new Cidr32Block ( startIpAddress , subnetMaskLeading1Bits ) ; } public nextBlock ( ) { return new Cidr32Block ( this . endIpAddressExclusive , this . subnetMaskLeading1Bits ) ; } public toString ( ) { return `${ getIPv4Address ( this . startIpAddressInclusive ) }/${ this . subnetMaskLeading1Bits }` ; } } function getIPv4AddressValue ( address ) { const split = address . split ( "." ) ; if ( split . length !== 4 ) { throw new Error ( `Ip address must be in the form "a.b.c.d", but was "${ address }"` ) ; } const a = getOctet ( split [ 0 ] ) ; const b = getOctet ( split [ 1 ] ) ; const c = getOctet ( split [ 2 ] ) ; const d = getOctet ( split [ 3 ] ) ; const result = ( a << 24 ) | ( b << 16 ) | ( c << 8 ) | d ; return result ; function getOctet ( piece ) { const val = parseInt ( piece , 10 ) ; if ( val < 0 || val >= 256 ) { throw new Error ( `Each part of the ip address must be between 0 and 255. Parsed "${ val }" from "${ piece } in ${ address }"` ) ; } return val ; } } export function getIPv4Address ( value ) { const ipAddress = ( ( value >> 24 ) & 255 ) + "." + ( ( value >> 16 ) & 255 ) + "." + ( ( value >> 8 ) & 255 ) + "." + ( value & 255 ) ; if ( getIPv4AddressValue ( ipAddress ) !== value ) { throw new Error ( `Could not convert ${ value } into a valid ip address` ) ; } return ipAddress ; }