feat(encoding): add default codec registry

Signed-off-by: Mark Sagi-Kazar <mark.sagikazar@gmail.com>
This commit is contained in:
Mark Sagi-Kazar 2024-06-24 11:37:05 +02:00 committed by Márk Sági-Kazár
parent 29a215ca4e
commit 15ad72deb2
2 changed files with 123 additions and 0 deletions

View file

@ -1,6 +1,9 @@
package viper package viper
import ( import (
"strings"
"sync"
"github.com/spf13/viper/internal/encoding/dotenv" "github.com/spf13/viper/internal/encoding/dotenv"
"github.com/spf13/viper/internal/encoding/hcl" "github.com/spf13/viper/internal/encoding/hcl"
"github.com/spf13/viper/internal/encoding/ini" "github.com/spf13/viper/internal/encoding/ini"
@ -137,3 +140,84 @@ func (r codecRegistry) codec(format string) (Codec, bool) {
return nil, false return nil, false
} }
// DefaultCodecRegistry
type DefaultCodecRegistry struct {
codecs map[string]Codec
mu sync.RWMutex
once sync.Once
}
// NewCodecRegistry returns a new [CodecRegistry], ready to accept custom [Codec]s.
func NewCodecRegistry() *DefaultCodecRegistry {
r := &DefaultCodecRegistry{}
r.init()
return r
}
func (r *DefaultCodecRegistry) init() {
r.once.Do(func() {
r.codecs = map[string]Codec{}
})
}
// RegisterCodec registers a custom [Codec].
func (r *DefaultCodecRegistry) RegisterCodec(format string, codec Codec) error {
r.init()
r.mu.Lock()
defer r.mu.Unlock()
r.codecs[strings.ToLower(format)] = codec
return nil
}
func (r *DefaultCodecRegistry) Encoder(format string) (Encoder, error) {
encoder, ok := r.codec(format)
if !ok {
return nil, ErrEncoderNotFound
}
return encoder, nil
}
func (r *DefaultCodecRegistry) Decoder(format string) (Decoder, error) {
decoder, ok := r.codec(format)
if !ok {
return nil, ErrDecoderNotFound
}
return decoder, nil
}
func (r *DefaultCodecRegistry) codec(format string) (Codec, bool) {
r.mu.Lock()
defer r.mu.Unlock()
if r.codecs != nil {
codec, ok := r.codecs[format]
if ok {
return codec, true
}
}
switch format {
case "yaml", "yml":
return yaml.Codec{}, true
case "json":
return json.Codec{}, true
case "toml":
return toml.Codec{}, true
case "dotenv", "env":
return &dotenv.Codec{}, true
}
return nil, false
}

39
encoding_test.go Normal file
View file

@ -0,0 +1,39 @@
package viper
import (
"testing"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
type codec struct{}
func (codec) Encode(_ map[string]any) ([]byte, error) {
return nil, nil
}
func (codec) Decode(_ []byte, _ map[string]any) error {
return nil
}
func TestDefaultCodecRegistry(t *testing.T) {
t.Run("OK", func(t *testing.T) {
registry := NewCodecRegistry()
c := codec{}
err := registry.RegisterCodec("myformat", c)
require.NoError(t, err)
encoder, err := registry.Encoder("myformat")
require.NoError(t, err)
assert.Equal(t, c, encoder)
decoder, err := registry.Decoder("myformat")
require.NoError(t, err)
assert.Equal(t, c, decoder)
})
}