codec.go (1978B)
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 // LoadOptions contains all customized options used for load data source(s). 13 // This type is added here for convenience: this way consumers can import a single package called "ini". 14 type LoadOptions = ini.LoadOptions 15 16 // Codec implements the encoding.Encoder and encoding.Decoder interfaces for INI encoding. 17 type Codec struct { 18 KeyDelimiter string 19 LoadOptions LoadOptions 20 } 21 22 func (c Codec) Encode(v map[string]interface{}) ([]byte, error) { 23 cfg := ini.Empty() 24 ini.PrettyFormat = false 25 26 flattened := map[string]interface{}{} 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 // TODO: is this a good idea? 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]interface{}) 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 // set innermost value 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 }