Skip to content

Commit 871327c

Browse files
✨ Add support for parsing a comma separated string list as a map of key-value pairs (#495)
<!-- Copyright (C) 2020-2022 Arm Limited or its affiliates and Contributors. All rights reserved. SPDX-License-Identifier: Apache-2.0 --> ### Description <!-- Please add any detail or context that would be useful to a reviewer. --> Add support for parsing a comma separated string list as a map of key-value pairs ### Test Coverage <!-- Please put an `x` in the correct box e.g. `[x]` to indicate the testing coverage of this change. --> - [x] This change is covered by existing or additional automated tests. - [ ] Manual testing has been performed (and evidence provided) as automated testing was not feasible. - [ ] Additional tests are not required for this change (e.g. documentation update). --------- Co-authored-by: Adrien CABARBAYE <adrien.cabarbaye@arm.com>
1 parent e6a5027 commit 871327c

File tree

3 files changed

+61
-0
lines changed

3 files changed

+61
-0
lines changed

changes/20240827111953.feature

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
:sparkles: Add support for parsing a comma separated string list as a map of key-value pairs

utils/collection/parseLists.go

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,11 @@
55
package collection
66

77
import (
8+
"fmt"
89
"strings"
910
"unicode"
11+
12+
"github.com/ARM-software/golang-utils/utils/commonerrors"
1013
)
1114

1215
func lineIsOnlyWhitespace(line string) bool {
@@ -52,3 +55,22 @@ func ParseListWithCleanupKeepBlankLines(input string, sep string) (newS []string
5255
func ParseCommaSeparatedList(input string) []string {
5356
return ParseListWithCleanup(input, ",")
5457
}
58+
59+
// ParseCommaSeparatedListToMap returns a map of key value pairs from a string containing a comma separated list
60+
func ParseCommaSeparatedListToMap(input string) (pairs map[string]string, err error) {
61+
inputSplit := ParseCommaSeparatedList(input)
62+
numElements := len(inputSplit)
63+
64+
if numElements%2 != 0 {
65+
err = fmt.Errorf("%w: could not parse comma separated list '%v' into map as it did not have an even number of elements", commonerrors.ErrInvalid, input)
66+
return
67+
}
68+
69+
pairs = make(map[string]string, numElements/2)
70+
// TODO use slices.Chunk introduced in go 23 when library is upgraded
71+
for i := 0; i < numElements; i += 2 {
72+
pairs[inputSplit[i]] = inputSplit[i+1]
73+
}
74+
75+
return
76+
}

utils/collection/parseLists_test.go

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,12 @@ import (
1010
"time"
1111

1212
"github.com/go-faker/faker/v4"
13+
"github.com/stretchr/testify/assert"
1314
"github.com/stretchr/testify/require"
15+
"golang.org/x/exp/maps"
16+
17+
"github.com/ARM-software/golang-utils/utils/commonerrors"
18+
"github.com/ARM-software/golang-utils/utils/commonerrors/errortest"
1419
)
1520

1621
var (
@@ -87,3 +92,36 @@ func TestParseCommaSeparatedListWithSpacesBetweenWordsKeepBlanks(t *testing.T) {
8792
finalList2 := ParseListWithCleanupKeepBlankLines(stringList, ",")
8893
require.Equal(t, stringArray, finalList2)
8994
}
95+
96+
func TestParseCommaSeparatedListToMap(t *testing.T) {
97+
for _, test := range []struct {
98+
Name string
99+
Input string
100+
Expected map[string]string
101+
Err error
102+
}{
103+
{"Normal 1", "hello,world", map[string]string{"hello": "world"}, nil},
104+
{"Normal 2", "hello,world,adrien,cabarbaye", map[string]string{"hello": "world", "adrien": "cabarbaye"}, nil},
105+
{"Normal 2.5", "hello, world, adrien, cabarbaye", map[string]string{"hello": "world", "adrien": "cabarbaye"}, nil},
106+
{"Normal 3", "hello,world,adrien,cabarbaye,", map[string]string{"hello": "world", "adrien": "cabarbaye"}, nil},
107+
{"Normal 4", "hello,,world,adrien,,,cabarbaye,,,", map[string]string{"hello": "world", "adrien": "cabarbaye"}, nil},
108+
{"Normal 5", "hello,world,this,value has spaces", map[string]string{"hello": "world", "this": "value has spaces"}, nil},
109+
{"Normal 6", "hello,,world,this,,,value has spaces,,,", map[string]string{"hello": "world", "this": "value has spaces"}, nil},
110+
{"Normal 7", "", map[string]string{}, nil},
111+
{"Normal 8", ",", map[string]string{}, nil},
112+
{"Normal 9", ",,,,,", map[string]string{}, nil},
113+
{"Normal 10", ",, ,, ,", map[string]string{}, nil},
114+
{"Bad 1", "one", nil, commonerrors.ErrInvalid},
115+
{"Bad 1", "one, two, three", nil, commonerrors.ErrInvalid},
116+
{"Bad 2", "one element with spaces", nil, commonerrors.ErrInvalid},
117+
{"Bad 3", "one element with spaces and end comma,", nil, commonerrors.ErrInvalid},
118+
{"Bad 4", "one element with spaces and multiple end commas,,,", nil, commonerrors.ErrInvalid},
119+
{"Bad 5", ",,,one element with spaces and multiple end/beginning commas,,,", nil, commonerrors.ErrInvalid},
120+
} {
121+
t.Run(test.Name, func(t *testing.T) {
122+
pairs, err := ParseCommaSeparatedListToMap(test.Input)
123+
errortest.AssertError(t, err, test.Err)
124+
assert.True(t, maps.Equal(test.Expected, pairs))
125+
})
126+
}
127+
}

0 commit comments

Comments
 (0)