Ensure values aren't nil before decoding.

This commit is contained in:
Alec Thomas
2020-12-04 16:14:16 +11:00
parent 5a9b3ae012
commit 3d57e73d11
4 changed files with 43 additions and 3 deletions
+20 -2
View File
@@ -19,6 +19,7 @@ import (
var (
mapperValueType = reflect.TypeOf((*MapperValue)(nil)).Elem()
boolMapperType = reflect.TypeOf((*BoolMapper)(nil)).Elem()
jsonUnmarshalerType = reflect.TypeOf((*json.Unmarshaler)(nil)).Elem()
textUnmarshalerType = reflect.TypeOf((*encoding.TextUnmarshaler)(nil)).Elem()
binaryUnmarshalerType = reflect.TypeOf((*encoding.BinaryUnmarshaler)(nil)).Elem()
)
@@ -89,6 +90,20 @@ func (m *binaryUnmarshalerAdapter) Decode(ctx *DecodeContext, target reflect.Val
return target.Addr().Interface().(encoding.BinaryUnmarshaler).UnmarshalBinary([]byte(value))
}
type jsonUnmarshalerAdapter struct{}
func (j *jsonUnmarshalerAdapter) Decode(ctx *DecodeContext, target reflect.Value) error {
var value string
err := ctx.Scan.PopValueInto("value", &value)
if err != nil {
return err
}
if target.Type().Implements(jsonUnmarshalerType) {
return target.Interface().(json.Unmarshaler).UnmarshalJSON([]byte(value))
}
return target.Addr().Interface().(json.Unmarshaler).UnmarshalJSON([]byte(value))
}
// A Mapper represents how a field is mapped from command-line values to Go.
//
// Mappers can be associated with concrete fields via pointer, reflect.Type, reflect.Kind, or via a "type" tag.
@@ -177,10 +192,13 @@ func (r *Registry) ForType(typ reflect.Type) Mapper {
}
// Next try stdlib unmarshaler interfaces.
for _, impl := range []reflect.Type{typ, reflect.PtrTo(typ)} {
if impl.Implements(textUnmarshalerType) {
switch {
case impl.Implements(textUnmarshalerType):
return &textUnmarshalerAdapter{}
} else if impl.Implements(binaryUnmarshalerType) {
case impl.Implements(binaryUnmarshalerType):
return &binaryUnmarshalerAdapter{}
case impl.Implements(jsonUnmarshalerType):
return &jsonUnmarshalerAdapter{}
}
}
// Finally try registered kinds.