apply slice, map pointer wrapping to named types only

master
Felix Lange 7 years ago
parent cd4d995e32
commit 90983d99de
  1. 30
      internal/tests/mapconv/output.go
  2. 42
      internal/tests/sliceconv/output.go
  3. 10
      typeutil.go

@ -43,9 +43,9 @@ func (x X) MarshalJSON() ([]byte, error) {
func (x *X) UnmarshalJSON(input []byte) error { func (x *X) UnmarshalJSON(input []byte) error {
type X struct { type X struct {
Map *map[replacedString]replacedInt Map map[replacedString]replacedInt
Named *namedMap2 Named *namedMap2
NoConv *map[string]int NoConv map[string]int
NoConvNamed *namedMap NoConvNamed *namedMap
} }
var dec X var dec X
@ -53,8 +53,8 @@ func (x *X) UnmarshalJSON(input []byte) error {
return err return err
} }
if dec.Map != nil { if dec.Map != nil {
x.Map = make(map[string]int, len(*dec.Map)) x.Map = make(map[string]int, len(dec.Map))
for k, v := range *dec.Map { for k, v := range dec.Map {
x.Map[string(k)] = int(v) x.Map[string(k)] = int(v)
} }
} }
@ -65,7 +65,7 @@ func (x *X) UnmarshalJSON(input []byte) error {
} }
} }
if dec.NoConv != nil { if dec.NoConv != nil {
x.NoConv = *dec.NoConv x.NoConv = dec.NoConv
} }
if dec.NoConvNamed != nil { if dec.NoConvNamed != nil {
x.NoConvNamed = *dec.NoConvNamed x.NoConvNamed = *dec.NoConvNamed
@ -108,9 +108,9 @@ func (x X) MarshalYAML() (interface{}, error) {
func (x *X) UnmarshalYAML(unmarshal func(interface{}) error) error { func (x *X) UnmarshalYAML(unmarshal func(interface{}) error) error {
type X struct { type X struct {
Map *map[replacedString]replacedInt Map map[replacedString]replacedInt
Named *namedMap2 Named *namedMap2
NoConv *map[string]int NoConv map[string]int
NoConvNamed *namedMap NoConvNamed *namedMap
} }
var dec X var dec X
@ -118,8 +118,8 @@ func (x *X) UnmarshalYAML(unmarshal func(interface{}) error) error {
return err return err
} }
if dec.Map != nil { if dec.Map != nil {
x.Map = make(map[string]int, len(*dec.Map)) x.Map = make(map[string]int, len(dec.Map))
for k, v := range *dec.Map { for k, v := range dec.Map {
x.Map[string(k)] = int(v) x.Map[string(k)] = int(v)
} }
} }
@ -130,7 +130,7 @@ func (x *X) UnmarshalYAML(unmarshal func(interface{}) error) error {
} }
} }
if dec.NoConv != nil { if dec.NoConv != nil {
x.NoConv = *dec.NoConv x.NoConv = dec.NoConv
} }
if dec.NoConvNamed != nil { if dec.NoConvNamed != nil {
x.NoConvNamed = *dec.NoConvNamed x.NoConvNamed = *dec.NoConvNamed
@ -173,9 +173,9 @@ func (x X) MarshalTOML() (interface{}, error) {
func (x *X) UnmarshalTOML(unmarshal func(interface{}) error) error { func (x *X) UnmarshalTOML(unmarshal func(interface{}) error) error {
type X struct { type X struct {
Map *map[replacedString]replacedInt Map map[replacedString]replacedInt
Named *namedMap2 Named *namedMap2
NoConv *map[string]int NoConv map[string]int
NoConvNamed *namedMap NoConvNamed *namedMap
} }
var dec X var dec X
@ -183,8 +183,8 @@ func (x *X) UnmarshalTOML(unmarshal func(interface{}) error) error {
return err return err
} }
if dec.Map != nil { if dec.Map != nil {
x.Map = make(map[string]int, len(*dec.Map)) x.Map = make(map[string]int, len(dec.Map))
for k, v := range *dec.Map { for k, v := range dec.Map {
x.Map[string(k)] = int(v) x.Map[string(k)] = int(v)
} }
} }
@ -195,7 +195,7 @@ func (x *X) UnmarshalTOML(unmarshal func(interface{}) error) error {
} }
} }
if dec.NoConv != nil { if dec.NoConv != nil {
x.NoConv = *dec.NoConv x.NoConv = dec.NoConv
} }
if dec.NoConvNamed != nil { if dec.NoConvNamed != nil {
x.NoConvNamed = *dec.NoConvNamed x.NoConvNamed = *dec.NoConvNamed

@ -45,10 +45,10 @@ func (x X) MarshalJSON() ([]byte, error) {
func (x *X) UnmarshalJSON(input []byte) error { func (x *X) UnmarshalJSON(input []byte) error {
type X struct { type X struct {
Slice *[]replacedInt Slice []replacedInt
Named *namedSlice2 Named *namedSlice2
ByteString *[]byte ByteString []byte
NoConv *[]int NoConv []int
NoConvNamed *namedSlice NoConvNamed *namedSlice
} }
var dec X var dec X
@ -56,8 +56,8 @@ func (x *X) UnmarshalJSON(input []byte) error {
return err return err
} }
if dec.Slice != nil { if dec.Slice != nil {
x.Slice = make([]int, len(*dec.Slice)) x.Slice = make([]int, len(dec.Slice))
for k, v := range *dec.Slice { for k, v := range dec.Slice {
x.Slice[k] = int(v) x.Slice[k] = int(v)
} }
} }
@ -68,10 +68,10 @@ func (x *X) UnmarshalJSON(input []byte) error {
} }
} }
if dec.ByteString != nil { if dec.ByteString != nil {
x.ByteString = string(*dec.ByteString) x.ByteString = string(dec.ByteString)
} }
if dec.NoConv != nil { if dec.NoConv != nil {
x.NoConv = *dec.NoConv x.NoConv = dec.NoConv
} }
if dec.NoConvNamed != nil { if dec.NoConvNamed != nil {
x.NoConvNamed = *dec.NoConvNamed x.NoConvNamed = *dec.NoConvNamed
@ -116,10 +116,10 @@ func (x X) MarshalYAML() (interface{}, error) {
func (x *X) UnmarshalYAML(unmarshal func(interface{}) error) error { func (x *X) UnmarshalYAML(unmarshal func(interface{}) error) error {
type X struct { type X struct {
Slice *[]replacedInt Slice []replacedInt
Named *namedSlice2 Named *namedSlice2
ByteString *[]byte ByteString []byte
NoConv *[]int NoConv []int
NoConvNamed *namedSlice NoConvNamed *namedSlice
} }
var dec X var dec X
@ -127,8 +127,8 @@ func (x *X) UnmarshalYAML(unmarshal func(interface{}) error) error {
return err return err
} }
if dec.Slice != nil { if dec.Slice != nil {
x.Slice = make([]int, len(*dec.Slice)) x.Slice = make([]int, len(dec.Slice))
for k, v := range *dec.Slice { for k, v := range dec.Slice {
x.Slice[k] = int(v) x.Slice[k] = int(v)
} }
} }
@ -139,10 +139,10 @@ func (x *X) UnmarshalYAML(unmarshal func(interface{}) error) error {
} }
} }
if dec.ByteString != nil { if dec.ByteString != nil {
x.ByteString = string(*dec.ByteString) x.ByteString = string(dec.ByteString)
} }
if dec.NoConv != nil { if dec.NoConv != nil {
x.NoConv = *dec.NoConv x.NoConv = dec.NoConv
} }
if dec.NoConvNamed != nil { if dec.NoConvNamed != nil {
x.NoConvNamed = *dec.NoConvNamed x.NoConvNamed = *dec.NoConvNamed
@ -187,10 +187,10 @@ func (x X) MarshalTOML() (interface{}, error) {
func (x *X) UnmarshalTOML(unmarshal func(interface{}) error) error { func (x *X) UnmarshalTOML(unmarshal func(interface{}) error) error {
type X struct { type X struct {
Slice *[]replacedInt Slice []replacedInt
Named *namedSlice2 Named *namedSlice2
ByteString *[]byte ByteString []byte
NoConv *[]int NoConv []int
NoConvNamed *namedSlice NoConvNamed *namedSlice
} }
var dec X var dec X
@ -198,8 +198,8 @@ func (x *X) UnmarshalTOML(unmarshal func(interface{}) error) error {
return err return err
} }
if dec.Slice != nil { if dec.Slice != nil {
x.Slice = make([]int, len(*dec.Slice)) x.Slice = make([]int, len(dec.Slice))
for k, v := range *dec.Slice { for k, v := range dec.Slice {
x.Slice[k] = int(v) x.Slice[k] = int(v)
} }
} }
@ -210,10 +210,10 @@ func (x *X) UnmarshalTOML(unmarshal func(interface{}) error) error {
} }
} }
if dec.ByteString != nil { if dec.ByteString != nil {
x.ByteString = string(*dec.ByteString) x.ByteString = string(dec.ByteString)
} }
if dec.NoConv != nil { if dec.NoConv != nil {
x.NoConv = *dec.NoConv x.NoConv = dec.NoConv
} }
if dec.NoConvNamed != nil { if dec.NoConvNamed != nil {
x.NoConvNamed = *dec.NoConvNamed x.NoConvNamed = *dec.NoConvNamed

@ -98,10 +98,20 @@ func underlyingMap(typ types.Type) *types.Map {
func ensureNilCheckable(typ types.Type) types.Type { func ensureNilCheckable(typ types.Type) types.Type {
orig := typ orig := typ
named := false
for { for {
switch typ.(type) { switch typ.(type) {
case *types.Named: case *types.Named:
typ = typ.Underlying() typ = typ.Underlying()
named = true
case *types.Slice, *types.Map:
if named {
// Named slices, maps, etc. are special because they can have a custom
// decoder function that prevents the JSON null value. Wrap them with a
// pointer to allow null always so required/optional works as expected.
return types.NewPointer(orig)
}
return orig
case *types.Pointer, *types.Interface: case *types.Pointer, *types.Interface:
return orig return orig
default: default:

Loading…
Cancel
Save