Search Apps Documentation Source Content File Folder Download Copy Actions Download

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}