feat(encoding): return an error when no codec is found

Signed-off-by: Mark Sagi-Kazar <mark.sagikazar@gmail.com>
This commit is contained in:
Mark Sagi-Kazar 2024-06-22 12:43:44 +02:00 committed by Márk Sági-Kazár
parent 3a285e0226
commit 29a215ca4e
2 changed files with 41 additions and 16 deletions

View file

@ -28,16 +28,32 @@ type Codec interface {
Decoder Decoder
} }
type encodingError string
func (e encodingError) Error() string {
return string(e)
}
const (
// ErrEncoderNotFound is returned when there is no encoder registered for a format.
ErrEncoderNotFound = encodingError("encoder not found for this format")
// ErrDecoderNotFound is returned when there is no decoder registered for a format.
ErrDecoderNotFound = encodingError("decoder not found for this format")
)
// EncoderRegistry returns an [Encoder] for a given format. // EncoderRegistry returns an [Encoder] for a given format.
// The second return value is false if no [Encoder] is registered for the format. //
// The error is [ErrEncoderNotFound] if no [Encoder] is registered for the format.
type EncoderRegistry interface { type EncoderRegistry interface {
Encoder(format string) (Encoder, bool) Encoder(format string) (Encoder, error)
} }
// DecoderRegistry returns an [Decoder] for a given format. // DecoderRegistry returns an [Decoder] for a given format.
// The second return value is false if no [Decoder] is registered for the format. //
// The error is [ErrDecoderNotFound] if no [Decoder] is registered for the format.
type DecoderRegistry interface { type DecoderRegistry interface {
Decoder(format string) (Decoder, bool) Decoder(format string) (Decoder, error)
} }
// [CodecRegistry] combines [EncoderRegistry] and [DecoderRegistry] interfaces. // [CodecRegistry] combines [EncoderRegistry] and [DecoderRegistry] interfaces.
@ -72,12 +88,22 @@ type codecRegistry struct {
v *Viper v *Viper
} }
func (r codecRegistry) Encoder(format string) (Encoder, bool) { func (r codecRegistry) Encoder(format string) (Encoder, error) {
return r.codec(format) encoder, ok := r.codec(format)
if !ok {
return nil, ErrEncoderNotFound
} }
func (r codecRegistry) Decoder(format string) (Decoder, bool) { return encoder, nil
return r.codec(format) }
func (r codecRegistry) Decoder(format string) (Decoder, error) {
decoder, ok := r.codec(format)
if !ok {
return nil, ErrDecoderNotFound
}
return decoder, nil
} }
func (r codecRegistry) codec(format string) (Codec, bool) { func (r codecRegistry) codec(format string) (Codec, bool) {

View file

@ -1723,12 +1723,12 @@ func (v *Viper) unmarshalReader(in io.Reader, c map[string]any) error {
switch format := strings.ToLower(v.getConfigType()); format { switch format := strings.ToLower(v.getConfigType()); format {
case "yaml", "yml", "json", "toml", "hcl", "tfvars", "ini", "properties", "props", "prop", "dotenv", "env": case "yaml", "yml", "json", "toml", "hcl", "tfvars", "ini", "properties", "props", "prop", "dotenv", "env":
decoder, ok := v.decoderRegistry2.Decoder(format) decoder, err := v.decoderRegistry2.Decoder(format)
if !ok { if err != nil {
return ConfigParseError{errors.New("decoder not found")} return ConfigParseError{err}
} }
err := decoder.Decode(buf.Bytes(), c) err = decoder.Decode(buf.Bytes(), c)
if err != nil { if err != nil {
return ConfigParseError{err} return ConfigParseError{err}
} }
@ -1743,10 +1743,9 @@ func (v *Viper) marshalWriter(f afero.File, configType string) error {
c := v.AllSettings() c := v.AllSettings()
switch configType { switch configType {
case "yaml", "yml", "json", "toml", "hcl", "tfvars", "ini", "prop", "props", "properties", "dotenv", "env": case "yaml", "yml", "json", "toml", "hcl", "tfvars", "ini", "prop", "props", "properties", "dotenv", "env":
encoder, ok := v.encoderRegistry2.Encoder(configType) encoder, err := v.encoderRegistry2.Encoder(configType)
if !ok { if err != nil {
// TODO: return a proper error return ConfigMarshalError{err}
return ConfigMarshalError{errors.New("encoder not found")}
} }
b, err := encoder.Encode(c) b, err := encoder.Encode(c)