property_parser.gno
1.39 Kb · 59 lines
1package personal_world
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.
12func parsePropertiesCSV(keys, values string) map[string]string {
13 if keys == "" {
14 panic("properties keys must be not empty")
15 }
16
17 result := map[string]string{}
18 keyStart, valStart := 0, 0
19 keyIdx, valIdx := 0, 0
20
21 for {
22 for keyIdx < len(keys) && keys[keyIdx] != ',' {
23 keyIdx++
24 }
25 for valIdx < len(values) && values[valIdx] != ',' {
26 valIdx++
27 }
28
29 key := keys[keyStart:keyIdx]
30 if key == "" {
31 panic("properties key must be not empty")
32 }
33 if _, found := result[key]; found {
34 panic("properties key duplicated: " + key)
35 }
36
37 value, err := url.PathUnescape(values[valStart:valIdx])
38 if err != nil {
39 panic("properties value URL decode failed: " + key)
40 }
41 result[key] = value
42
43 keyEnd := keyIdx >= len(keys)
44 valEnd := valIdx >= len(values)
45 if keyEnd != valEnd {
46 panic("properties keys and values count mismatch")
47 }
48 if keyEnd {
49 break
50 }
51
52 keyIdx++
53 valIdx++
54 keyStart = keyIdx
55 valStart = valIdx
56 }
57
58 return result
59}