func ParseSetFilter()

in pkg/source/gcp/query/queryutil/set_filter.go [44:137]


func ParseSetFilter(filter string, aliases SetFilterAliasToItemsMap, allowAny bool, allowSubtract bool, convertToLowerCase bool) (*SetFilterParseResult, error) {
	filterElements := strings.Split(filter, " ")
	for i := 0; i < len(filterElements); i++ {
		filterElements[i] = strings.TrimSpace(filterElements[i])
		if filterElements[i] != "" && !validElementRegex.Match([]byte(filterElements[i])) {
			return &SetFilterParseResult{ValidationError: "filter value must be whitespace splitted series of [a-zA-Z0-9\\-_]+"}, nil
		}
	}

	additivesMap := map[string]struct{}{}
	subtractivesMap := map[string]struct{}{}
	containsAny := false
	for i := 0; i < len(filterElements); i++ {
		filterElement := filterElements[i]
		if filterElement == "" {
			continue
		}
		negated := false
		if filterElement[0] == '-' {
			if !allowSubtract {
				return &SetFilterParseResult{
					ValidationError: "Subtract filter is not supported in this filter",
				}, nil
			}
			negated = true
			filterElement = filterElement[1:]
			if len(filterElement) == 0 {
				return &SetFilterParseResult{
					ValidationError: "Unexpected filter element `-`. Expecting item or alias after `-`.",
				}, nil
			}
		}
		if filterElement[0] == '@' {
			aliasName := filterElement[1:]
			if allowAny && aliasName == "any" {
				if negated {
					return &SetFilterParseResult{
						ValidationError: "Unsupported filter element `-@any`",
					}, nil
				}
				containsAny = true
				continue
			}
			if aliasMembers, found := aliases[aliasName]; found {
				for _, aliasMember := range aliasMembers {
					if negated {
						subtractivesMap[aliasMember] = struct{}{}
					} else {
						additivesMap[aliasMember] = struct{}{}
					}
				}
			} else {
				return &SetFilterParseResult{
					ValidationError: fmt.Sprintf("alias `%s` was not found", aliasName),
				}, nil
			}
		} else {
			if negated {
				subtractivesMap[filterElement] = struct{}{}
			} else {
				additivesMap[filterElement] = struct{}{}
			}
		}
	}

	result := &SetFilterParseResult{}
	result.Additives = []string{}
	result.Subtractives = []string{}
	result.SubtractMode = containsAny
	if containsAny {
		// If this was in subtract mode, we should evaluate subtract first then add next.
		for addOperand := range additivesMap {
			delete(subtractivesMap, addOperand)
		}
		for subtract := range subtractivesMap {
			result.Subtractives = append(result.Subtractives, subtract)
		}
	} else {
		// If this was in non subtract mode, we should evaluate add first then subtract next.
		for subtractOperand := range subtractivesMap {
			delete(additivesMap, subtractOperand)
		}
		for add := range additivesMap {
			result.Additives = append(result.Additives, add)
		}
	}
	slices.SortFunc(result.Additives, strings.Compare)
	slices.SortFunc(result.Subtractives, strings.Compare)
	if convertToLowerCase {
		result.Additives = ToLowerForStringArray(result.Additives)
		result.Subtractives = ToLowerForStringArray(result.Subtractives)
	}
	return result, nil
}