Files
any2anexoj/internal/selectors.go
Natercio Moniz adcd192cb9
All checks were successful
Generate check / check-changes (pull_request) Successful in 28s
Quality / check-changes (pull_request) Successful in 3s
Generate check / verify-generate (pull_request) Has been skipped
Quality / run-tests (pull_request) Successful in 58s
support some filtering
2026-05-16 09:09:39 +01:00

115 lines
2.6 KiB
Go

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
}