1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81
|
package jen
import (
"bytes"
"io"
"sort"
)
// Dict renders as key/value pairs. Use with Values for map or composite
// literals.
type Dict map[Code]Code
// DictFunc executes a func(Dict) to generate the value. Use with Values for
// map or composite literals.
func DictFunc(f func(Dict)) Dict {
d := Dict{}
f(d)
return d
}
func (d Dict) render(f *File, w io.Writer, s *Statement) error {
first := true
// must order keys to ensure repeatable source
type kv struct {
k Code
v Code
}
lookup := map[string]kv{}
keys := []string{}
for k, v := range d {
if k.isNull(f) || v.isNull(f) {
continue
}
buf := &bytes.Buffer{}
if err := k.render(f, buf, nil); err != nil {
return err
}
keys = append(keys, buf.String())
lookup[buf.String()] = kv{k: k, v: v}
}
sort.Strings(keys)
for _, key := range keys {
k := lookup[key].k
v := lookup[key].v
if first && len(keys) > 1 {
if _, err := w.Write([]byte("\n")); err != nil {
return err
}
first = false
}
if err := k.render(f, w, nil); err != nil {
return err
}
if _, err := w.Write([]byte(":")); err != nil {
return err
}
if err := v.render(f, w, nil); err != nil {
return err
}
if len(keys) > 1 {
if _, err := w.Write([]byte(",\n")); err != nil {
return err
}
}
}
return nil
}
func (d Dict) isNull(f *File) bool {
if d == nil || len(d) == 0 {
return true
}
for k, v := range d {
if !k.isNull(f) && !v.isNull(f) {
// if any of the key/value pairs are both not null, the Dict is not
// null
return false
}
}
return true
}
|