package internal import ( "fmt" "strconv" "strings" ) func Any() Selector { return func(r Record) bool { return true } } func And(a, b Selector) Selector { return func(r Record) bool { return a(r) && b(r) } } func OnlyNature(n Nature) Selector { return func(r Record) bool { return r.Nature() == n } } func OnlyAssetCountry(c int64) Selector { return func(r Record) bool { return r.AssetCountry() == c } } // selectorParser is a function that parses a selector value string into a Selector type selectorParser func(string) (Selector, error) // parsers maps selector keys to their parser functions var parsers = map[string]selectorParser{ "code": parseNature, "assetCountry": parseAssetCountry, } func parseNature(value string) (Selector, error) { if value == "" { return nil, fmt.Errorf("code selector requires a non-empty value") } nature := Nature(value) if !nature.Valid() { return nil, fmt.Errorf("invalid nature code %q", value) } return OnlyNature(nature), nil } func parseAssetCountry(value string) (Selector, error) { if value == "" { return nil, fmt.Errorf("assetCountry selector requires a non-empty value") } i, err := strconv.ParseInt(value, 10, 64) if err != nil { return nil, fmt.Errorf("assetCountry value must be a valid integer: %w", err) } return OnlyAssetCountry(i), nil } // ParseSelectors parses a list of selector strings into a composed Selector. // Each selector string must be in the format "key:value" where key is one of: // - code: filter by nature (e.g., "code:G01") // - assetCountry: filter by asset country code (e.g., "assetCountry:840") // // Multiple selectors are combined with AND logic. // If no selectors are provided, returns Any() which matches all records. func ParseSelectors(sl []string) (Selector, error) { if len(sl) == 0 { return Any(), nil } // Parse the first selector first, err := parseSingleSelector(sl[0]) if err != nil { return nil, err } // If there's only one, return it if len(sl) == 1 { return first, nil } // Recursively parse the rest and combine with AND rest, err := ParseSelectors(sl[1:]) if err != nil { return nil, err } return And(first, rest), nil } func parseSingleSelector(s string) (Selector, error) { key, value, found := strings.Cut(s, ":") if !found { return nil, fmt.Errorf("invalid selector format %q: must be 'key:value'", s) } parser, ok := parsers[key] if !ok { return nil, fmt.Errorf("unknown selector key %q: supported keys are %v", key, supportedKeys()) } return parser(value) } func supportedKeys() []string { keys := make([]string, 0, len(parsers)) for k := range parsers { keys = append(keys, k) } return keys }