diff --git a/pkg/stanza/operator/parser/keyvalue/keyvalue.go b/pkg/stanza/operator/parser/keyvalue/keyvalue.go index 7598aafdeb73..634965acc5b4 100644 --- a/pkg/stanza/operator/parser/keyvalue/keyvalue.go +++ b/pkg/stanza/operator/parser/keyvalue/keyvalue.go @@ -7,11 +7,10 @@ import ( "context" "errors" "fmt" - "strings" - "go.uber.org/multierr" "go.uber.org/zap" + "github.com/open-telemetry/opentelemetry-collector-contrib/internal/coreinternal/parseutils" "github.com/open-telemetry/opentelemetry-collector-contrib/pkg/stanza/entry" "github.com/open-telemetry/opentelemetry-collector-contrib/pkg/stanza/operator" "github.com/open-telemetry/opentelemetry-collector-contrib/pkg/stanza/operator/helper" @@ -98,67 +97,10 @@ func (kv *Parser) parser(input string, delimiter string, pairDelimiter string) ( return nil, fmt.Errorf("parse from field %s is empty", kv.ParseFrom.String()) } - pairs, err := splitPairs(input, pairDelimiter) + pairs, err := parseutils.SplitString(input, pairDelimiter) if err != nil { return nil, fmt.Errorf("failed to parse pairs from input: %w", err) } - parsed := make(map[string]any) - - for _, raw := range pairs { - m := strings.SplitN(raw, delimiter, 2) - if len(m) != 2 { - e := fmt.Errorf("expected '%s' to split by '%s' into two items, got %d", raw, delimiter, len(m)) - err = multierr.Append(err, e) - continue - } - - key := strings.TrimSpace(m[0]) - value := strings.TrimSpace(m[1]) - - parsed[key] = value - } - - return parsed, err -} - -// splitPairs will split the input on the pairDelimiter and return the resulting slice. -// `strings.Split` is not used because it does not respect quotes and will split if the delimiter appears in a quoted value -func splitPairs(input, pairDelimiter string) ([]string, error) { - var result []string - currentPair := "" - delimiterLength := len(pairDelimiter) - quoteChar := "" // "" means we are not in quotes - - for i := 0; i < len(input); i++ { - if quoteChar == "" && i+delimiterLength <= len(input) && input[i:i+delimiterLength] == pairDelimiter { // delimiter - if currentPair == "" { // leading || trailing delimiter; ignore - continue - } - result = append(result, currentPair) - currentPair = "" - i += delimiterLength - 1 - continue - } - - if quoteChar == "" && (input[i] == '"' || input[i] == '\'') { // start of quote - quoteChar = string(input[i]) - continue - } - if string(input[i]) == quoteChar { // end of quote - quoteChar = "" - continue - } - - currentPair += string(input[i]) - } - - if quoteChar != "" { // check for closed quotes - return nil, fmt.Errorf("never reached end of a quoted value") - } - if currentPair != "" { // avoid adding empty value bc of a trailing delimiter - return append(result, currentPair), nil - } - - return result, nil + return parseutils.ParseKeyValuePairs(pairs, delimiter) } diff --git a/pkg/stanza/operator/parser/keyvalue/keyvalue_test.go b/pkg/stanza/operator/parser/keyvalue/keyvalue_test.go index 41cf7593d577..4feefa2bb914 100644 --- a/pkg/stanza/operator/parser/keyvalue/keyvalue_test.go +++ b/pkg/stanza/operator/parser/keyvalue/keyvalue_test.go @@ -147,7 +147,7 @@ func TestParserStringFailure(t *testing.T) { parser := newTestParser(t) _, err := parser.parse("invalid") require.Error(t, err) - require.Contains(t, err.Error(), fmt.Sprintf("expected '%s' to split by '%s' into two items, got", "invalid", parser.delimiter)) + require.Contains(t, err.Error(), fmt.Sprintf("cannot split %q into 2 items, got 1 item(s)", "invalid")) } func TestParserInvalidType(t *testing.T) {