encoder.go raw

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