summaryrefslogtreecommitdiffstats
path: root/vendor/github.com/spf13/viper/internal/encoding/decoder.go
blob: 08b1bb66b5e2c9dbe090aca3439b9591df403f51 (plain) (blame)
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
package encoding

import (
	"sync"
)

// Decoder decodes the contents of b into a v representation.
// It's primarily used for decoding contents of a file into a map[string]interface{}.
type Decoder interface {
	Decode(b []byte, v interface{}) error
}

const (
	// ErrDecoderNotFound is returned when there is no decoder registered for a format.
	ErrDecoderNotFound = encodingError("decoder not found for this format")

	// ErrDecoderFormatAlreadyRegistered is returned when an decoder is already registered for a format.
	ErrDecoderFormatAlreadyRegistered = encodingError("decoder already registered for this format")
)

// DecoderRegistry can choose an appropriate Decoder based on the provided format.
type DecoderRegistry struct {
	decoders map[string]Decoder

	mu sync.RWMutex
}

// NewDecoderRegistry returns a new, initialized DecoderRegistry.
func NewDecoderRegistry() *DecoderRegistry {
	return &DecoderRegistry{
		decoders: make(map[string]Decoder),
	}
}

// RegisterDecoder registers a Decoder for a format.
// Registering a Decoder for an already existing format is not supported.
func (e *DecoderRegistry) RegisterDecoder(format string, enc Decoder) error {
	e.mu.Lock()
	defer e.mu.Unlock()

	if _, ok := e.decoders[format]; ok {
		return ErrDecoderFormatAlreadyRegistered
	}

	e.decoders[format] = enc

	return nil
}

// Decode calls the underlying Decoder based on the format.
func (e *DecoderRegistry) Decode(format string, b []byte, v interface{}) error {
	e.mu.RLock()
	decoder, ok := e.decoders[format]
	e.mu.RUnlock()

	if !ok {
		return ErrDecoderNotFound
	}

	return decoder.Decode(b, v)
}