package etcdb import ( "encoding/hex" "fmt" ) type HexDB struct { WrappedDB DB } var _ DB = HexDB{} func (h HexDB) Get(key string) (value []byte, ok bool, err error) { encodedValue, ok, err := h.WrappedDB.Get(key) if !ok || err != nil { return } value = make([]byte, hex.DecodedLen(len(encodedValue))) _, err = hex.Decode(value, encodedValue) if err != nil { err = fmt.Errorf("invalid hex-encoded value: %w", err) ok = false } return } func (h HexDB) Put(key string, value []byte) (err error) { encodedValue := make([]byte, hex.EncodedLen(len(value))) hex.Encode(encodedValue, value) return h.WrappedDB.Put(key, encodedValue) } func (h HexDB) Del(key string) error { return h.WrappedDB.Del(key) } func (h HexDB) ForEach(callback func(key string, value []byte) (cont bool)) (err error) { forEachErr := h.WrappedDB.ForEach(func(key string, encodedValue []byte) (cont bool) { value := make([]byte, hex.DecodedLen(len(encodedValue))) _, err = hex.Decode(value, encodedValue) if err != nil { err = fmt.Errorf("invalid hex-encoded value under %q: %w", key, err) return false } return callback(key, value) }) if err == nil && forEachErr != nil { err = forEachErr } return } func (h HexDB) Watch(rev int64) <-chan WatchEvent { ch := make(chan WatchEvent, 1) go func() { defer close(ch) inCh := h.WrappedDB.Watch(rev) for evt := range inCh { if len(evt.Value) == 0 { ch <- evt continue } value := make([]byte, hex.DecodedLen(len(evt.Value))) _, err := hex.Decode(value, evt.Value) if err != nil { ch <- WatchEvent{ Key: evt.Key, Err: fmt.Errorf("invalid hex-encoded value: %w", err), } continue } evt.Value = value ch <- evt } }() return ch }