func testNumberLength()

in phonenumbers.go [2341:2413]


func testNumberLength(number string, metadata *PhoneMetadata, numberType PhoneNumberType) ValidationResult {
	desc := getNumberDescByType(metadata, numberType)

	// There should always be "possibleLengths" set for every element. This is declared in the XML
	// schema which is verified by PhoneNumberMetadataSchemaTest.
	// For size efficiency, where a sub-description (e.g. fixed-line) has the same possibleLengths
	// as the parent, this is missing, so we fall back to the general desc (where no numbers of the
	// type exist at all, there is one possible length (-1) which is guaranteed not to match the
	// length of any real phone number).
	possibleLengths := desc.PossibleLength
	if len(possibleLengths) == 0 {
		possibleLengths = metadata.GeneralDesc.PossibleLength
	}
	localLengths := desc.PossibleLengthLocalOnly

	if numberType == FIXED_LINE_OR_MOBILE {
		if !descHasPossibleNumberData(getNumberDescByType(metadata, FIXED_LINE)) {
			// The rare case has been encountered where no fixedLine data is available (true for some
			// non-geographical entities), so we just check mobile.
			return testNumberLength(number, metadata, MOBILE)
		} else {
			mobileDesc := getNumberDescByType(metadata, MOBILE)
			if descHasPossibleNumberData(mobileDesc) {
				// Note that when adding the possible lengths from mobile, we have to again check they
				// aren't empty since if they are this indicates they are the same as the general desc and
				// should be obtained from there.
				mobileLengths := mobileDesc.PossibleLength
				if len(mobileLengths) == 0 {
					mobileLengths = metadata.GeneralDesc.PossibleLength
				}
				possibleLengths = mergeLengths(possibleLengths, mobileLengths)

				if len(localLengths) == 0 {
					localLengths = mobileDesc.PossibleLengthLocalOnly
				} else {
					localLengths = mergeLengths(localLengths, mobileDesc.PossibleLengthLocalOnly)
				}
			}
		}
	}

	// If the type is not supported at all (indicated by the possible lengths containing -1 at this
	// point) we return invalid length.
	if possibleLengths[0] == -1 {
		return INVALID_LENGTH
	}

	actualLength := int32(len(number))

	// This is safe because there is never an overlap beween the possible lengths and the local-only
	// lengths; this is checked at build time.
	for _, l := range localLengths {
		if l == actualLength {
			return IS_POSSIBLE_LOCAL_ONLY
		}
	}
	minimumLength := possibleLengths[0]
	if minimumLength == actualLength {
		return IS_POSSIBLE
	} else if minimumLength > actualLength {
		return TOO_SHORT
	} else if possibleLengths[len(possibleLengths)-1] < actualLength {
		return TOO_LONG
	}

	// We skip the first element; we've already checked it.
	for _, l := range possibleLengths[1:] {
		if l == actualLength {
			return IS_POSSIBLE
		}
	}
	return INVALID_LENGTH
}