/**
        * Parses a string and fills up the phoneNumber. This method is the same as the public
        * parse() method, with the exception that it allows the default region to be null, for use by
        * isNumberMatch(). checkRegion should be set to false if it is permitted for the default region
        * to be null or unknown ("ZZ").
        */
        private void ParseHelper(String numberToParse, String defaultRegion, bool keepRawInput,
            bool checkRegion, PhoneNumber.Builder phoneNumber)
        {
            if (numberToParse == null)
                throw new NumberParseException(ErrorType.NOT_A_NUMBER,
                    "The phone number supplied was null.");
            else if (numberToParse.Length > MAX_INPUT_STRING_LENGTH)
                throw new NumberParseException(ErrorType.TOO_LONG,
                    "The string supplied was too long to parse.");

            StringBuilder nationalNumber = new StringBuilder();
            BuildNationalNumberForParsing(numberToParse, nationalNumber);

            if (!IsViablePhoneNumber(nationalNumber.ToString()))
                throw new NumberParseException(ErrorType.NOT_A_NUMBER,
                    "The string supplied did not seem to be a phone number.");

            // Check the region supplied is valid, or that the extracted number starts with some sort of +
            // sign so the number's region can be determined.
            if (checkRegion && !CheckRegionForParsing(nationalNumber.ToString(), defaultRegion))
                throw new NumberParseException(ErrorType.INVALID_COUNTRY_CODE,
                    "Missing or invalid default region.");

            if (keepRawInput)
                phoneNumber.SetRawInput(numberToParse);

            // Attempt to parse extension first, since it doesn't require region-specific data and we want
            // to have the non-normalised number here.
            String extension = MaybeStripExtension(nationalNumber);
            if (extension.Length > 0)
                phoneNumber.SetExtension(extension);

            PhoneMetadata regionMetadata = GetMetadataForRegion(defaultRegion);
            // Check to see if the number is given in international format so we know whether this number is
            // from the default region or not.
            StringBuilder normalizedNationalNumber = new StringBuilder();
            int countryCode = 0;
            try
            {
                // TODO: This method should really just take in the string buffer that has already
                // been created, and just remove the prefix, rather than taking in a string and then
                // outputting a string buffer.
                countryCode = MaybeExtractCountryCode(nationalNumber.ToString(), regionMetadata,
                    normalizedNationalNumber, keepRawInput, phoneNumber);
            }
            catch (NumberParseException e)
            {
                var m = PLUS_CHARS_PATTERN.MatchBeginning(nationalNumber.ToString());
                if (e.ErrorType == ErrorType.INVALID_COUNTRY_CODE &&
                    m.Success)
                {
                    // Strip the plus-char, and try again.
                    countryCode = MaybeExtractCountryCode(
                        nationalNumber.ToString().Substring(m.Index + m.Length),
                        regionMetadata, normalizedNationalNumber,
                        keepRawInput, phoneNumber);
                    if (countryCode == 0)
                    {
                        throw new NumberParseException(ErrorType.INVALID_COUNTRY_CODE,
                            "Could not interpret numbers after plus-sign.");
                    }
                }
                else
                {
                    throw new NumberParseException(e.ErrorType, e.Message);
                }
            }
            if (countryCode != 0)
            {
                String phoneNumberRegion = GetRegionCodeForCountryCode(countryCode);
                if (phoneNumberRegion != defaultRegion)
                    regionMetadata = GetMetadataForRegionOrCallingCode(countryCode, phoneNumberRegion);
            }
            else
            {
                // If no extracted country calling code, use the region supplied instead. The national number
                // is just the normalized version of the number we were given to parse.
                Normalize(nationalNumber);
                normalizedNationalNumber.Append(nationalNumber);
                if (defaultRegion != null)
                {
                    countryCode = regionMetadata.CountryCode;
                    phoneNumber.SetCountryCode(countryCode);
                }
                else if (keepRawInput)
                {
                    phoneNumber.ClearCountryCode();
                }
            }
            if (normalizedNationalNumber.Length < MIN_LENGTH_FOR_NSN)
                throw new NumberParseException(ErrorType.TOO_SHORT_NSN,
                    "The string supplied is too short to be a phone number.");

            if (regionMetadata != null)
            {
                StringBuilder carrierCode = new StringBuilder();
                MaybeStripNationalPrefixAndCarrierCode(normalizedNationalNumber, regionMetadata, carrierCode);
                if (keepRawInput)
                    phoneNumber.SetPreferredDomesticCarrierCode(carrierCode.ToString());
            }
            int lengthOfNationalNumber = normalizedNationalNumber.Length;
            if (lengthOfNationalNumber < MIN_LENGTH_FOR_NSN)
                throw new NumberParseException(ErrorType.TOO_SHORT_NSN,
                    "The string supplied is too short to be a phone number.");

            if (lengthOfNationalNumber > MAX_LENGTH_FOR_NSN)
                throw new NumberParseException(ErrorType.TOO_LONG,
                    "The string supplied is too long to be a phone number.");

            if (normalizedNationalNumber[0] == '0')
                phoneNumber.SetItalianLeadingZero(true);
            phoneNumber.SetNationalNumber(ulong.Parse(normalizedNationalNumber.ToString()));
        }
 /**
 * Attempts to extract a valid number from a phone number that is too long to be valid, and resets
 * the PhoneNumber object passed in to that valid version. If no valid number could be extracted,
 * the PhoneNumber object passed in will not be modified.
 * @param number a PhoneNumber object which contains a number that is too long to be valid.
 * @return  true if a valid phone number can be successfully extracted.
 */
 public bool TruncateTooLongNumber(PhoneNumber.Builder number)
 {
     if (IsValidNumber(number.Clone().Build()))
         return true;
     PhoneNumber copy = null;
     ulong nationalNumber = number.NationalNumber;
     do
     {
         nationalNumber /= 10;
         PhoneNumber.Builder numberCopy = number.Clone();
         numberCopy.SetNationalNumber(nationalNumber);
         copy = numberCopy.Build();
         if (IsPossibleNumberWithReason(copy) == ValidationResult.TOO_SHORT ||
           nationalNumber == 0)
             return false;
     }
     while (!IsValidNumber(copy));
     number.SetNationalNumber(nationalNumber);
     return true;
 }