package util import ( "encoding/binary" "fmt" "os" "unicode/utf8" bolt "go.etcd.io/bbolt" ) func ToJsonString(b *bolt.Bucket) string { // TODO: Escape any double quotes inside // TODO: Deal with empty buckets ret := "{" b.ForEach(func(k, v []byte) error { ret = fmt.Sprintf("%s\"%s\":", ret, string(k)) if v == nil { ret = fmt.Sprintf("%s%s,", ret, ToJsonString(b.Bucket(k))) } else { ret = fmt.Sprintf("%s\"%s\",", ret, string(v)) } return nil }) ret = fmt.Sprintf("%s}", ret[:len(ret)-1]) return ret } func LogToFile(s string) error { return WriteToFile("bolt-log", s+"\n", os.O_RDWR|os.O_APPEND) } func WriteToFile(fn, s string, mode int) error { var f *os.File var err error if f == nil { f, err = os.OpenFile(fn, mode, 0660) } defer f.Close() if err != nil { return err } if _, err = f.WriteString(s); err != nil { return err } if err = f.Sync(); err != nil { return err } return nil } // stringify ensures that we can print only valid characters. // It's wrong to assume that everything is a string, since BoltDB is typeless. func Stringify(v []byte) string { if utf8.Valid(v) { ok := true for _, r := range string(v) { if r < 0x20 { ok = false break } else if r >= 0x7f && r <= 0x9f { ok = false break } } if ok { return string(v) } } if len(v) == 8 { return fmt.Sprintf("%v", binary.BigEndian.Uint64(v)) } return fmt.Sprintf("%x", v) } func StringifyPath(path []string) []string { for k, v := range path { path[k] = Stringify([]byte(v)) } return path }