...
1 package ini
2
3 import (
4 "bytes"
5 "sort"
6 "strings"
7
8 "github.com/spf13/cast"
9 "gopkg.in/ini.v1"
10 )
11
12
13
14 type LoadOptions = ini.LoadOptions
15
16
17 type Codec struct {
18 KeyDelimiter string
19 LoadOptions LoadOptions
20 }
21
22 func (c Codec) Encode(v map[string]any) ([]byte, error) {
23 cfg := ini.Empty()
24 ini.PrettyFormat = false
25
26 flattened := map[string]any{}
27
28 flattened = flattenAndMergeMap(flattened, v, "", c.keyDelimiter())
29
30 keys := make([]string, 0, len(flattened))
31
32 for key := range flattened {
33 keys = append(keys, key)
34 }
35
36 sort.Strings(keys)
37
38 for _, key := range keys {
39 sectionName, keyName := "", key
40
41 lastSep := strings.LastIndex(key, ".")
42 if lastSep != -1 {
43 sectionName = key[:(lastSep)]
44 keyName = key[(lastSep + 1):]
45 }
46
47
48 if sectionName == "default" {
49 sectionName = ""
50 }
51
52 cfg.Section(sectionName).Key(keyName).SetValue(cast.ToString(flattened[key]))
53 }
54
55 var buf bytes.Buffer
56
57 _, err := cfg.WriteTo(&buf)
58 if err != nil {
59 return nil, err
60 }
61
62 return buf.Bytes(), nil
63 }
64
65 func (c Codec) Decode(b []byte, v map[string]any) error {
66 cfg := ini.Empty(c.LoadOptions)
67
68 err := cfg.Append(b)
69 if err != nil {
70 return err
71 }
72
73 sections := cfg.Sections()
74
75 for i := 0; i < len(sections); i++ {
76 section := sections[i]
77 keys := section.Keys()
78
79 for j := 0; j < len(keys); j++ {
80 key := keys[j]
81 value := cfg.Section(section.Name()).Key(key.Name()).String()
82
83 deepestMap := deepSearch(v, strings.Split(section.Name(), c.keyDelimiter()))
84
85
86 deepestMap[key.Name()] = value
87 }
88 }
89
90 return nil
91 }
92
93 func (c Codec) keyDelimiter() string {
94 if c.KeyDelimiter == "" {
95 return "."
96 }
97
98 return c.KeyDelimiter
99 }
100
View as plain text