import { Octet } from "./Octet" ; import { Validator } from "./Validator" ; import * as bigInt from "big-integer" ; import { dottedDecimalNotationToBinaryString } from "./BinaryUtils" ; import { bigIntegerNumberToBinaryString } from "./BinaryUtils" ; import { parseBinaryStringToBigInteger } from "./BinaryUtils" ; import { leftPadWithZeroBit } from "./BinaryUtils" ; import { IPNumType } from "./IPNumType" ; import { decimalNumberToBinaryString } from "./BinaryUtils" ; import { Hexadecatet } from "./Hexadecatet" ; import { binaryStringToHexadecimalString } from "./HexadecimalUtils" ; import { expandIPv6Number } from "./IPv6Utils" ; import { hexadectetNotationToBinaryString } from "./HexadecimalUtils" ; /**
 * Provides the implementation of functionality that are common
 * to  IPv4 ,  IPv6 ,  IPv4Mask and  IPv6Mask export abstract class AbstractIPNum { /**
     * The decimal value represented by the IP number in BigInteger
     */ abstract readonly value : bigInt . BigInteger ; /**
     * The number of bits needed to represents the value of the IP number
     */ abstract readonly bitSize : number ; /**
     * The maximum bit size (i.e. binary value) of the IP number in BigInteger
     */ abstract readonly maximumBitSize : bigInt . BigInteger ; abstract nextIPNumber ( ) ; abstract previousIPNumber ( ) ; /**
     * Gets the numeric value of an IP number as  BigInteger returns { bigInt . BigInteger } public getValue ( ) { return this . value ; } returns { string } public toBinaryString ( ) { return leftPadWithZeroBit ( this . value . toString ( 2 ) , this . bitSize ) ; } returns { boolean } hasNext ( ) { return this . value . lesser ( this . maximumBitSize ) ; } returns { boolean } hasPrevious ( ) { return this . value . greater ( bigInt . zero ) ; } param { AbstractIPNum } anotherIPNum returns { boolean } public isEquals ( anotherIPNum ) { return this . value . equals ( anotherIPNum . value ) ; } param { AbstractIPNum } anotherIPNum returns { boolean } public isLessThan ( anotherIPNum ) { return this . value . lt ( anotherIPNum . value ) ; } param { AbstractIPNum } anotherIPNum returns { boolean } public isGreaterThan ( anotherIPNum ) { return this . value . gt ( anotherIPNum . value ) ; } param { AbstractIPNum } anotherIPNum returns { boolean } public isLessThanOrEquals ( anotherIPNum ) { return this . value . lesserOrEquals ( anotherIPNum . value ) ; } param { AbstractIPNum } anotherIPNum returns { boolean } public isGreaterThanOrEquals ( anotherIPNum ) { return this . value . greaterOrEquals ( anotherIPNum . value ) ; } } see https see https export class IPv4 extends AbstractIPNum { /**
     * The decimal value represented by the IPv4 number in BigInteger
     */ readonly value : bigInt . BigInteger ; /**
     * The number of bits needed to represents the value of the IPv4 number
     */ readonly bitSize : number = 32 ; /**
     * The maximum bit size (i.e. binary value) of the IPv4 number in BigInteger
     */ readonly maximumBitSize : bigInt . BigInteger = Validator . THIRTY_TWO_BIT_SIZE ; /**
     * The type of IP number. Value is one of the values of the  IPNumType enum
     *  type { IPNumType } readonly type : IPNumType = IPNumType . IPv4 ; /**
     * An array of  Octet 's
     *
     *  type { Array } readonly octets : Array < Octet > = [ ] ; type { string } readonly separator : string = "." ; /**
     * A convenience method for creating an  IPv4 by providing the decimal value of the IP number in BigInteger
     *
     *  param { bigInt . BigInteger } bigIntValue returns { IPv4 } static fromBigInteger ( bigIntValue ) { return new IPv4 ( bigIntValue ) ; } /**
     * A convenience method for creating an  IPv4 by providing the IP number in dot-decimal notation. E.g
     * "10.1.1.10"
     *
     * {@see https://en.wikipedia.org/wiki/Dot-decimal_notation} for more information on dot-decimal notation.
     *
     *  param { string } ipString returns { IPv4 } static fromDecimalDottedString ( ipString ) { return new IPv4 ( ipString ) ; } param { string } ipString returns { IPv4 } static fromString ( ipString ) { return IPv4 . fromDecimalDottedString ( ipString ) ; } /**
     * A convenience method for creating an  IPv4 from binary string
     *
     *  param { string } ipBinaryString returns { IPv4 } static fromBinaryString ( ipBinaryString ) { let validationResult = Validator . isValidBinaryString ( ipBinaryString ) ; if ( validationResult [ 0 ] ) { return new IPv4 ( parseBinaryStringToBigInteger ( ipBinaryString ) ) ; } else { throw Error ( validationResult [ 1 ] . join ( ',' ) ) ; } } param { string | bigInt . BigInteger } ipValue constructor ( ipValue ) { super ( ) ; if ( typeof ipValue === "string" ) { let [ value , octets ] = this . constructFromDecimalDottedString ( ipValue ) ; this . value = value ; this . octets = octets ; } else { let [ value , octets ] = this . constructFromBigIntegerValue ( ipValue ) ; this . value = value ; this . octets = octets ; } } returns { string } public toString ( ) { return this . octets . map ( ( value ) => { return value . toString ( ) ; } ) . join ( this . separator ) ; } /**
     * Gets the individual  Octet that makes up the IPv4 number
     *
     *  returns { Array < Octet > } The individual  Octet that makes up the IPv4 number
      public getOctets ( ) { return this . octets ; } returns { IPv4 } public nextIPNumber ( ) { return IPv4 . fromBigInteger ( this . getValue ( ) . add ( 1 ) ) ; } returns { IPv4 } public previousIPNumber ( ) { return IPv4 . fromBigInteger ( this . getValue ( ) . minus ( 1 ) ) ; } returns { IPv6 } public toIPv4MappedIPv6 ( ) { let binary = '1' . repeat ( 16 ) + this . toBinaryString ( ) ; return IPv6 . fromBinaryString ( binary ) ; } private constructFromDecimalDottedString ( ipString ) { let octets ; let value ; let [ isValid , message ] = Validator . isValidIPv4String ( ipString ) ; if ( ! isValid ) { throw new Error ( message . filter ( msg => { return msg !== '' ; } ) . toString ( ) ) ; } let stringOctets = ipString . split ( "." ) ; octets = stringOctets . map ( ( rawOctet ) => { return Octet . fromString ( rawOctet ) ; } ) ; value = bigInt ( dottedDecimalNotationToBinaryString ( ipString ) , 2 ) ; return [ value , octets ] ; } private constructFromBigIntegerValue ( ipv4Number ) { let [ isValid , message ] = Validator . isValidIPv4Number ( ipv4Number ) ; if ( ! isValid ) { throw new Error ( message . filter ( msg => { return msg !== '' ; } ) . toString ( ) ) ; } let binaryString = bigIntegerNumberToBinaryString ( ipv4Number ) ; return [ ipv4Number , this . binaryStringToDecimalOctets ( binaryString ) ] ; } private binaryStringToDecimalOctets ( ipv4BinaryString ) { if ( ipv4BinaryString . length < 32 ) { ipv4BinaryString = leftPadWithZeroBit ( ipv4BinaryString , 32 ) ; } let octets = ipv4BinaryString . match ( /.{1,8}/g ) ! ; return octets . map ( ( octet ) => { return Octet . fromString ( parseBinaryStringToBigInteger ( octet ) . toString ( ) ) ; } ) ; } } see https see https export class Asn extends AbstractIPNum { /**
     * The decimal value represented by the ASN number in BigInteger
     */ readonly value : bigInt . BigInteger ; /**
     * The number of bits needed to represents the value of the ASN number
     */ bitSize : number = 32 ; /**
     * The maximum bit size (i.e. binary value) of the ASN number in BigInteger
     */ maximumBitSize : bigInt . BigInteger = Validator . THIRTY_TWO_BIT_SIZE ; type : IPNumType = IPNumType . ASN ; private static AS_PREFIX = "AS" ; /**
     * A convenience method for creating an instance of  Asn from a string
     *
     * The given string can be in asplain, asdot or asdot+ representation format.
     * {@see https://tools.ietf.org/html/rfc5396} for more information on
     * the different ASN string representation
     *
     *  param { string } rawValue returns { Asn } static fromString ( rawValue ) { return new Asn ( rawValue ) ; } ; /**
     * A convenience method for creating an instance of  Asn from a numeric value
     *
     *  param { number } rawValue returns { Asn } static fromNumber ( rawValue ) { return new Asn ( rawValue ) ; } ; /**
     * A convenience method for creating an instance of  Asn from a binary string
     *
     *  param { string } binaryString returns { Asn } static fromBinaryString ( binaryString ) { let validationResult = Validator . isValidBinaryString ( binaryString ) ; if ( validationResult [ 0 ] ) { return new Asn ( parseInt ( binaryString , 2 ) ) ; } else { throw Error ( validationResult [ 1 ] . join ( ',' ) ) ; } } /**
     * Constructor for an instance of  ASN param { string | number } rawValue constructor ( rawValue ) { super ( ) ; if ( typeof rawValue === 'string' ) { if ( Asn . startWithASprefix ( rawValue ) ) { this . value = bigInt ( parseInt ( rawValue . substring ( 2 ) ) ) ; } else if ( rawValue . indexOf ( "." ) != - 1 ) { this . value = bigInt ( this . parseFromDotNotation ( rawValue ) ) ; } else { this . value = bigInt ( parseInt ( rawValue ) ) ; } } else { let valueAsBigInt = bigInt ( rawValue ) ; let [ isValid , message ] = Validator . isValidAsnNumber ( valueAsBigInt ) ; if ( ! isValid ) { throw Error ( message . filter ( msg => { return msg !== '' ; } ) . toString ( ) ) ; } this . value = valueAsBigInt ; } } returns { string } toString ( ) { let stringValue = this . value . toString ( ) ; return `${ Asn . AS_PREFIX }${ stringValue }` ; } returns { string } toASPlain ( ) { return this . value . toString ( ) ; } returns { string } toASDot ( ) { if ( this . value . valueOf ( ) >= 65536 ) { return this . toASDotPlus ( ) ; } return this . toASPlain ( ) ; } returns { string } toASDotPlus ( ) { let high = Math . floor ( this . value . valueOf ( ) / 65535 ) ; let low = ( this . value . valueOf ( ) % 65535 ) - high ; return `${ high }.${ low }` ; } returns { string } toBinaryString ( ) { return decimalNumberToBinaryString ( this . value . valueOf ( ) ) ; } returns { boolean } is16Bit ( ) { let [ valid16BitAsnNumber , ] = Validator . isValid16BitAsnNumber ( this . value ) ; return valid16BitAsnNumber ; } returns { boolean } is32Bit ( ) { return ! this . is16Bit ( ) ; } returns { AbstractIPNum } nextIPNumber ( ) { return new Asn ( this . value . valueOf ( ) + 1 ) ; } returns { AbstractIPNum } previousIPNumber ( ) { return new Asn ( this . value . valueOf ( ) - 1 ) ; } private static startWithASprefix ( word ) { return word . indexOf ( Asn . AS_PREFIX ) === 0 ; } private parseFromDotNotation ( rawValue ) { let values = rawValue . split ( "." ) ; let high = parseInt ( values [ 0 ] ) ; let low = parseInt ( values [ 1 ] ) ; return ( high * 65535 ) + ( low + high ) ; } } see https see https export class IPv6 extends AbstractIPNum { /**
     * The decimal value represented by the IPv6 number in BigInteger
     */ readonly value : bigInt . BigInteger ; /**
     * The number of bits needed to represents the value of the IPv6 number
     */ readonly bitSize : number = 128 ; /**
     * The maximum bit size (i.e. binary value) of the IPv6 number in BigInteger
     */ readonly maximumBitSize : bigInt . BigInteger = Validator . ONE_HUNDRED_AND_TWENTY_EIGHT_BIT_SIZE ; /**
     * The type of IP number. Value is one of the values of the  IPNumType enum
     *  type { IPNumType } readonly type : IPNumType = IPNumType . IPv6 ; /**
     * An array of  Hexadecatet 's
     *
     *  type { Array } readonly hexadecatet : Array < Hexadecatet > = [ ] ; type { string } readonly separator : string = ":" ; /**
     * A convenience method for creating an  IPv6 by providing the decimal value of the IP number in BigInteger
     *
     *  param { bigInt . BigInteger } bigIntValue returns { IPv6 } static fromBigInteger ( bigIntValue ) { return new IPv6 ( bigIntValue ) ; } /**
     * A convenience method for creating an  IPv6 by providing the IP number in hexadecatet notation. E.g
     * "2001:800:0:0:0:0:0:2002"
     *
     * {@see https://en.wikipedia.org/wiki/IPv6_address#Representation} for more information on hexadecatet notation.
     *
     *  param { string } ipString returns { IPv6 } static fromHexadecimalString ( ipString ) { return new IPv6 ( ipString ) ; } param { string } ipString returns { IPv6 } static fromString ( ipString ) { return IPv6 . fromHexadecimalString ( ipString ) ; } /**
     * A convenience method for creating an  IPv6 from binary string
     *
     *  param { string } ipBinaryString returns { IPv6 } static fromBinaryString ( ipBinaryString ) { let validationResult = Validator . isValidBinaryString ( ipBinaryString ) ; if ( validationResult [ 0 ] ) { let paddedBinaryString = leftPadWithZeroBit ( ipBinaryString , 128 ) ; return new IPv6 ( parseBinaryStringToBigInteger ( paddedBinaryString ) ) ; } else { throw Error ( validationResult [ 1 ] . join ( ',' ) ) ; } } /**
     * A convenience method for creating an IPv4-Compatible  IPv6 Address from an instance of  IPv4 param { IPv4 } ipv4 to create an IPv4-Compatible  IPv6 Address
     *  returns { IPv6 } the IPv4-Compatible  IPv6 Address
      static fromIPv4 ( ipv4 ) { return ipv4 . toIPv4MappedIPv6 ( ) ; } /**
     * A convenience method for creating an IPv4-Compatible  IPv6 Address from a IPv4 represented in
     * dot-decimal notation i.e. 127.0.0.1
     *
     *  param { IPv4 } ip4DotDecimalString returns { IPv6 } the IPv4-Compatible  IPv6 Address
      static fromIPv4DotDecimalString ( ip4DotDecimalString ) { return new IPv4 ( ip4DotDecimalString ) . toIPv4MappedIPv6 ( ) ; } param { string | bigInt . BigInteger } ipValue constructor ( ipValue ) { super ( ) ; if ( typeof ipValue === "string" ) { let expandedIPv6 = expandIPv6Number ( ipValue ) ; let [ value , hexadecatet ] = this . constructFromHexadecimalDottedString ( expandedIPv6 ) ; this . value = value ; this . hexadecatet = hexadecatet ; } else { let [ value , hexadecatet ] = this . constructFromBigIntegerValue ( ipValue ) ; this . value = value ; this . hexadecatet = hexadecatet ; } } returns { string } public toString ( ) { let ipv6String = this . hexadecatet . map ( ( value ) => { return value . toString ( ) ; } ) . join ( ":" ) ; if ( this . hexadecatet . length < 8 ) { return "::" + ipv6String ; } else { return ipv6String ; } } /**
     * Gets the individual  Hexadecatet that makes up the IPv6 number
     *
     *  returns { Array < Hexadecatet > } The individual  Hexadecatet that makes up the IPv6 number
      public getHexadecatet ( ) { return this . hexadecatet ; } returns { IPv6 } public nextIPNumber ( ) { return IPv6 . fromBigInteger ( this . getValue ( ) . add ( 1 ) ) ; } returns { IPv6 } public previousIPNumber ( ) { return IPv6 . fromBigInteger ( this . getValue ( ) . minus ( 1 ) ) ; } private constructFromBigIntegerValue ( ipv6Number ) { let [ isValid , message ] = Validator . isValidIPv6Number ( ipv6Number ) ; if ( ! isValid ) { throw new Error ( message . filter ( msg => { return msg !== '' ; } ) . toString ( ) ) ; } let binaryString = bigIntegerNumberToBinaryString ( ipv6Number ) ; return [ ipv6Number , this . binaryStringToHexadecatets ( binaryString ) ] ; } private constructFromHexadecimalDottedString ( expandedIPv6 ) { let [ isValid , message ] = Validator . isValidIPv6String ( expandedIPv6 ) ; if ( ! isValid ) { throw new Error ( message . filter ( msg => { return msg !== '' ; } ) . toString ( ) ) ; } let stringHexadecimals = expandedIPv6 . split ( ":" ) ; let hexadecatet = stringHexadecimals . map ( ( stringHexadecatet ) => { return Hexadecatet . fromString ( stringHexadecatet ) ; } ) ; let value = bigInt ( hexadectetNotationToBinaryString ( expandedIPv6 ) , 2 ) ; return [ value , hexadecatet ] ; } private binaryStringToHexadecatets ( binaryString ) { let hexadecimalString = binaryStringToHexadecimalString ( binaryString ) ; while ( hexadecimalString . length % 4 != 0 ) { hexadecimalString = '0' + hexadecimalString ; } let hexadecimalStrings = hexadecimalString . match ( /.{1,4}/g ) ! ; return hexadecimalStrings . map ( ( stringHexadecatet ) => { return Hexadecatet . fromString ( stringHexadecatet ) ; } ) ; } } /**
 * The IPv4Mask can be seen as a specialized IPv4 number where, in a 32 bit number, starting from the left, you
 * have continuous bits turned on (with 1 value) followed by bits turned off (with 0 value). In networking, it is used
 * to demarcate which bits are used to identify a network, and the ones that are used to identify hosts on the network
 */ export class IPv4Mask extends IPv4 { /**
     * An array of  Octet 's
     *
     *  type { Array } readonly octets : Array < Octet > = [ ] ; /**
     * The decimal value represented by the IPv4 mask in BigInteger
     */ readonly value : bigInt . BigInteger ; /**
     * The cidr prefix represented by this mask
     */ readonly prefix : number ; param { string } rawValue returns { IPv4Mask } static fromDecimalDottedString ( rawValue ) { return new IPv4Mask ( rawValue ) ; } ; param { string } ipString constructor ( ipString ) { super ( ipString ) ; let isValid ; let message ; [ isValid , message ] = Validator . isValidIPv4Mask ( ipString ) ; if ( ! isValid ) { throw new Error ( message . filter ( msg => { return msg !== '' ; } ) . toString ( ) ) ; } let stringOctets = ipString . split ( "." ) ; this . octets = stringOctets . map ( ( rawOctet ) => { return Octet . fromString ( rawOctet ) ; } ) ; let binaryString = dottedDecimalNotationToBinaryString ( ipString ) ; this . prefix = ( binaryString . match ( /1/g ) || [ ] ) . length ; this . value = bigInt ( binaryString , 2 ) ; } } /**
 * The IPv6Mask can be seen as a specialized IPv4 number where, in a 128 bit number, starting from the left,
 * you have continuous bits turned on (with 1 value) followed by bits turned off (with 0 value). In networking, it
 * is used to to demarcate which bits are used to identify a network, and the ones that are used to identify hosts
 * on the network
 */ export class IPv6Mask extends IPv6 { /**
     * An array of  Hexadecatet 's
     *
     *  type { Array } readonly hexadecatet : Array < Hexadecatet > = [ ] ; /**
     * The decimal value represented by the IPv6 number in BigInteger
     */ readonly value : bigInt . BigInteger ; /**
     * The cidr prefix represented by this mask
     */ readonly prefix : number ; param { string } rawValue returns { IPv6Mask } static fromHexadecimalString ( rawValue ) { return new IPv6Mask ( rawValue ) ; } ; param { string } ipString constructor ( ipString ) { super ( ipString ) ; let isValid ; let message ; [ isValid , message ] = Validator . isValidIPv6Mask ( ipString ) ; if ( ! isValid ) { throw new Error ( message . filter ( msg => { return msg !== '' ; } ) . toString ( ) ) ; } let stringHexadecimals = ipString . split ( ":" ) ; this . hexadecatet = stringHexadecimals . map ( ( stringHexadecatet ) => { return Hexadecatet . fromString ( stringHexadecatet ) ; } ) ; let binaryString = hexadectetNotationToBinaryString ( ipString ) ; this . prefix = ( binaryString . match ( /1/g ) || [ ] ) . length ; this . value = bigInt ( binaryString , 2 ) ; this . value = bigInt ( hexadectetNotationToBinaryString ( ipString ) , 2 ) ; } } /**
 * Check is the given IP number is an  IPv4 or not
 *  param ip export function isIPv4 ( ip ) { return ip . bitSize === 32 ; }