/// <summary>
        /// Gets the length of the prefix.
        /// </summary>
        /// <returns>The length of the prefix.</returns>
        public int GetPrefixLength()
        {
            byte[] byteBegin = this.Begin.GetAddressBytes();
            byte[] byteEnd   = this.End.GetAddressBytes();

            if (this.Begin.Equals(this.End))
            {
                return(byteBegin.Length * 8);
            }

            int length = byteBegin.Length * 8;

            for (int i = 0; i < length; i++)
            {
                byte[] mask = Bitwise.GetBitMask(byteBegin.Length, i);

                if (new IPAddress(Bitwise.And(byteBegin, mask)).Equals(this.Begin))
                {
                    if (new IPAddress(Bitwise.Or(byteBegin, Bitwise.Not(mask))).Equals(this.End))
                    {
                        return(i);
                    }
                }
            }

            throw new FormatException(string.Format("{0} is not a CIDR Subnet", this.ToString()));
        }
        /// <summary>
        /// Parses the specified ip range string.
        /// </summary>
        /// <param name="ipRangeString">The ip range string.</param>
        /// <returns>IPAddressRange instance.</returns>
        public static IPAddressRange Parse(string ipRangeString)
        {
            if (ipRangeString == null)
            {
                throw new ArgumentNullException("ipRangeString");
            }

            ipRangeString = ipRangeString.Replace(" ", string.Empty);

            var matchCidrRange = RegexCidrRange.Match(ipRangeString);

            if (matchCidrRange.Success)
            {
                var baseAdrBytes = IPAddress.Parse(matchCidrRange.Groups["adr"].Value).GetAddressBytes();
                var maskLength   = int.Parse(matchCidrRange.Groups["maskLen"].Value);

                if (baseAdrBytes.Length * 8 < maskLength)
                {
                    throw new FormatException();
                }

                var maskBytes = Bitwise.GetBitMask(baseAdrBytes.Length, maskLength);
                baseAdrBytes = Bitwise.And(baseAdrBytes, maskBytes);

                return(new IPAddressRange(new IPAddress(baseAdrBytes), new IPAddress(Bitwise.Or(baseAdrBytes, Bitwise.Not(maskBytes)))));
            }

            var matchSingleAddress = RegexSingleAddress.Match(ipRangeString);

            if (matchSingleAddress.Success)
            {
                return(new IPAddressRange(IPAddress.Parse(ipRangeString)));
            }

            var matchAddressRange = RegexAddressRange.Match(ipRangeString);

            if (matchAddressRange.Success)
            {
                return(new IPAddressRange(IPAddress.Parse(matchAddressRange.Groups["begin"].Value), IPAddress.Parse(matchAddressRange.Groups["end"].Value)));
            }

            var matchBitMaskRange = RegexBitMaskRange.Match(ipRangeString);

            if (matchBitMaskRange.Success)
            {
                var baseAdrBytes = IPAddress.Parse(matchBitMaskRange.Groups["adr"].Value).GetAddressBytes();
                var maskBytes    = IPAddress.Parse(matchBitMaskRange.Groups["bitmask"].Value).GetAddressBytes();
                baseAdrBytes = Bitwise.And(baseAdrBytes, maskBytes);

                return(new IPAddressRange(new IPAddress(baseAdrBytes), new IPAddress(Bitwise.Or(baseAdrBytes, Bitwise.Not(maskBytes)))));
            }

            throw new FormatException("Unknown IP range string.");
        }
        /// <summary>
        /// Initializes a new instance of the <see cref="IPAddressRange"/> class.
        /// Creates a range from a base address and mask bits. This can also be used with <see cref="GetSubnetMaskLength"/> to create a range based on a subnet mask.
        /// </summary>
        /// <param name="baseAddress">The base address.</param>
        /// <param name="maskLength">Length of the mask.</param>
        public IPAddressRange(IPAddress baseAddress, int maskLength)
        {
            if (baseAddress == null)
            {
                throw new ArgumentNullException("baseAddress");
            }

            var baseAdrBytes = baseAddress.GetAddressBytes();

            if (baseAdrBytes.Length * 8 < maskLength)
            {
                throw new FormatException();
            }

            var maskBytes = Bitwise.GetBitMask(baseAdrBytes.Length, maskLength);

            baseAdrBytes = Bitwise.And(baseAdrBytes, maskBytes);

            this.Begin = new IPAddress(baseAdrBytes);
            this.End   = new IPAddress(Bitwise.Or(baseAdrBytes, Bitwise.Not(maskBytes)));
        }