decoder.go raw

   1  package encoding
   2  
   3  import (
   4  	"sync"
   5  )
   6  
   7  // Decoder decodes the contents of b into v.
   8  // It's primarily used for decoding contents of a file into a map[string]any.
   9  type Decoder interface {
  10  	Decode(b []byte, v map[string]any) error
  11  }
  12  
  13  const (
  14  	// ErrDecoderNotFound is returned when there is no decoder registered for a format.
  15  	ErrDecoderNotFound = encodingError("decoder not found for this format")
  16  
  17  	// ErrDecoderFormatAlreadyRegistered is returned when an decoder is already registered for a format.
  18  	ErrDecoderFormatAlreadyRegistered = encodingError("decoder already registered for this format")
  19  )
  20  
  21  // DecoderRegistry can choose an appropriate Decoder based on the provided format.
  22  type DecoderRegistry struct {
  23  	decoders map[string]Decoder
  24  
  25  	mu sync.RWMutex
  26  }
  27  
  28  // NewDecoderRegistry returns a new, initialized DecoderRegistry.
  29  func NewDecoderRegistry() *DecoderRegistry {
  30  	return &DecoderRegistry{
  31  		decoders: make(map[string]Decoder),
  32  	}
  33  }
  34  
  35  // RegisterDecoder registers a Decoder for a format.
  36  // Registering a Decoder for an already existing format is not supported.
  37  func (e *DecoderRegistry) RegisterDecoder(format string, enc Decoder) error {
  38  	e.mu.Lock()
  39  	defer e.mu.Unlock()
  40  
  41  	if _, ok := e.decoders[format]; ok {
  42  		return ErrDecoderFormatAlreadyRegistered
  43  	}
  44  
  45  	e.decoders[format] = enc
  46  
  47  	return nil
  48  }
  49  
  50  // Decode calls the underlying Decoder based on the format.
  51  func (e *DecoderRegistry) Decode(format string, b []byte, v map[string]any) error {
  52  	e.mu.RLock()
  53  	decoder, ok := e.decoders[format]
  54  	e.mu.RUnlock()
  55  
  56  	if !ok {
  57  		return ErrDecoderNotFound
  58  	}
  59  
  60  	return decoder.Decode(b, v)
  61  }
  62