property_parser.gno
1.93 Kb · 73 lines
1package user
2
3import "net/url"
4
5// parsePropertiesCSV accepts comma-separated keys and comma-separated values.
6// Each value must be URL-encoded so commas and other separators can be carried
7// safely; this parser URL-decodes values before returning the map.
8//
9// Empty key lists and empty keys are rejected because keys define the map
10// shape. Empty values are policy-dependent, so the parser preserves them for
11// the create/update validator.
12//
13// Valid examples:
14//
15// keys="nickname,introduction" values="Alice,hello%2C%20world"
16// keys="nickname,introduction" values="Alice," # introduction is preserved as an empty value.
17// keys="nickname,introduction" values="," # both values are preserved as empty values.
18//
19// Invalid examples:
20//
21// keys="" values=""
22// keys="nickname," values="Alice,"
23// keys="nickname,introduction" values="Alice"
24// keys="nickname,introduction" values="" # key/value count mismatch.
25// keys="nickname,introduction" values="Alice,%zz"
26func parsePropertiesCSV(keys, values string) map[string]string {
27 if keys == "" {
28 panic("properties keys must be not empty")
29 }
30
31 result := map[string]string{}
32 keyStart, valStart := 0, 0
33 keyIdx, valIdx := 0, 0
34
35 for {
36 for keyIdx < len(keys) && keys[keyIdx] != ',' {
37 keyIdx++
38 }
39 for valIdx < len(values) && values[valIdx] != ',' {
40 valIdx++
41 }
42
43 key := keys[keyStart:keyIdx]
44 if key == "" {
45 panic("properties key must be not empty")
46 }
47 if _, found := result[key]; found {
48 panic("properties key duplicated: " + key)
49 }
50
51 value, err := url.PathUnescape(values[valStart:valIdx])
52 if err != nil {
53 panic("properties value URL decode failed: " + key)
54 }
55 result[key] = value
56
57 keyEnd := keyIdx >= len(keys)
58 valEnd := valIdx >= len(values)
59 if keyEnd != valEnd {
60 panic("properties keys and values count mismatch")
61 }
62 if keyEnd {
63 break
64 }
65
66 keyIdx++
67 valIdx++
68 keyStart = keyIdx
69 valStart = valIdx
70 }
71
72 return result
73}