feat(encoding)!: accept a map in the encoder interface

This interface is specific to encoding data from Viper's internal,
so it's okay to make it Viper specific.

BREAKING CHANGE: the encoder interface now accepts a map instead of an interface

Signed-off-by: Mark Sagi-Kazar <mark.sagikazar@gmail.com>
This commit is contained in:
Mark Sagi-Kazar 2021-07-16 00:26:30 +02:00 committed by Márk Sági-Kazár
parent e54e7a53a5
commit 4b307cc0f3
6 changed files with 21 additions and 25 deletions

View file

@ -7,7 +7,7 @@ import (
// Encoder encodes the contents of v into a byte representation. // Encoder encodes the contents of v into a byte representation.
// It's primarily used for encoding a map[string]interface{} into a file format. // It's primarily used for encoding a map[string]interface{} into a file format.
type Encoder interface { type Encoder interface {
Encode(v interface{}) ([]byte, error) Encode(v map[string]interface{}) ([]byte, error)
} }
const ( const (
@ -47,7 +47,7 @@ func (e *EncoderRegistry) RegisterEncoder(format string, enc Encoder) error {
return nil return nil
} }
func (e *EncoderRegistry) Encode(format string, v interface{}) ([]byte, error) { func (e *EncoderRegistry) Encode(format string, v map[string]interface{}) ([]byte, error) {
e.mu.RLock() e.mu.RLock()
encoder, ok := e.encoders[format] encoder, ok := e.encoders[format]
e.mu.RUnlock() e.mu.RUnlock()

View file

@ -8,7 +8,7 @@ type encoder struct {
b []byte b []byte
} }
func (e encoder) Encode(_ interface{}) ([]byte, error) { func (e encoder) Encode(_ map[string]interface{}) ([]byte, error) {
return e.b, nil return e.b, nil
} }
@ -41,7 +41,7 @@ func TestEncoderRegistry_Decode(t *testing.T) {
t.Run("OK", func(t *testing.T) { t.Run("OK", func(t *testing.T) {
registry := NewEncoderRegistry() registry := NewEncoderRegistry()
encoder := encoder{ encoder := encoder{
b: []byte("encoded value"), b: []byte("key: value"),
} }
err := registry.RegisterEncoder("myformat", encoder) err := registry.RegisterEncoder("myformat", encoder)
@ -49,20 +49,20 @@ func TestEncoderRegistry_Decode(t *testing.T) {
t.Fatal(err) t.Fatal(err)
} }
b, err := registry.Encode("myformat", "some value") b, err := registry.Encode("myformat", map[string]interface{}{"key": "value"})
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
if string(b) != "encoded value" { if string(b) != "key: value" {
t.Fatalf("expected 'encoded value', got: %#v", string(b)) t.Fatalf("expected 'key: value', got: %#v", string(b))
} }
}) })
t.Run("EncoderNotFound", func(t *testing.T) { t.Run("EncoderNotFound", func(t *testing.T) {
registry := NewEncoderRegistry() registry := NewEncoderRegistry()
_, err := registry.Encode("myformat", "some value") _, err := registry.Encode("myformat", map[string]interface{}{"key": "value"})
if err != ErrEncoderNotFound { if err != ErrEncoderNotFound {
t.Fatalf("expected ErrEncoderNotFound, got: %v", err) t.Fatalf("expected ErrEncoderNotFound, got: %v", err)
} }

View file

@ -12,7 +12,7 @@ import (
// TODO: add printer config to the codec? // TODO: add printer config to the codec?
type Codec struct{} type Codec struct{}
func (Codec) Encode(v interface{}) ([]byte, error) { func (Codec) Encode(v map[string]interface{}) ([]byte, error) {
b, err := json.Marshal(v) b, err := json.Marshal(v)
if err != nil { if err != nil {
return nil, err return nil, err

View file

@ -7,7 +7,7 @@ import (
// Codec implements the encoding.Encoder and encoding.Decoder interfaces for JSON encoding. // Codec implements the encoding.Encoder and encoding.Decoder interfaces for JSON encoding.
type Codec struct{} type Codec struct{}
func (Codec) Encode(v interface{}) ([]byte, error) { func (Codec) Encode(v map[string]interface{}) ([]byte, error) {
// TODO: expose prefix and indent in the Codec as setting? // TODO: expose prefix and indent in the Codec as setting?
return json.MarshalIndent(v, "", " ") return json.MarshalIndent(v, "", " ")
} }

View file

@ -7,22 +7,18 @@ import (
// Codec implements the encoding.Encoder and encoding.Decoder interfaces for TOML encoding. // Codec implements the encoding.Encoder and encoding.Decoder interfaces for TOML encoding.
type Codec struct{} type Codec struct{}
func (Codec) Encode(v interface{}) ([]byte, error) { func (Codec) Encode(v map[string]interface{}) ([]byte, error) {
if m, ok := v.(map[string]interface{}); ok { t, err := toml.TreeFromMap(v)
t, err := toml.TreeFromMap(m) if err != nil {
if err != nil { return nil, err
return nil, err
}
s, err := t.ToTomlString()
if err != nil {
return nil, err
}
return []byte(s), nil
} }
return toml.Marshal(v) s, err := t.ToTomlString()
if err != nil {
return nil, err
}
return []byte(s), nil
} }
func (Codec) Decode(b []byte, v map[string]interface{}) error { func (Codec) Decode(b []byte, v map[string]interface{}) error {

View file

@ -5,7 +5,7 @@ import "gopkg.in/yaml.v2"
// Codec implements the encoding.Encoder and encoding.Decoder interfaces for YAML encoding. // Codec implements the encoding.Encoder and encoding.Decoder interfaces for YAML encoding.
type Codec struct{} type Codec struct{}
func (Codec) Encode(v interface{}) ([]byte, error) { func (Codec) Encode(v map[string]interface{}) ([]byte, error) {
return yaml.Marshal(v) return yaml.Marshal(v)
} }