Skip to content

Commit

Permalink
Merge pull request #48 from go-faster/fix/can-interface-check
Browse files Browse the repository at this point in the history
fix: check `CanInterface` before using `Interface`
  • Loading branch information
ernado authored Mar 22, 2023
2 parents f0025e9 + ec8a823 commit 953ced4
Show file tree
Hide file tree
Showing 3 changed files with 80 additions and 52 deletions.
33 changes: 18 additions & 15 deletions .golangci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -95,43 +95,46 @@ issues:
- scopelint
- lll
- path: _test\.go
text: 'structtag: struct field tag .* bad syntax for struct tag pair'
text: "structtag: struct field tag .* bad syntax for struct tag pair"

# Ignore shadowing of err.
- linters: [ govet ]
- linters: [govet]
text: 'declaration of "(err|ctx|log|c)"'

# Ignore linters in main packages.
- path: main\.go
linters: [ goconst, funlen, gocognit, gocyclo ]
linters: [goconst, funlen, gocognit, gocyclo]

- text: 'exported: exported .+ should have comment.*or be unexported'
linters: [ revive ]
- text: "exported: exported .+ should have comment.*or be unexported"
linters: [revive]

# Annoying and useless.
- linters: [revive, golint]
text: "unused-parameter"

- path: encode\.go
text: 'shadow: declaration of "tail" shadows declaration'
source: 'var tail string'
source: "var tail string"

# Disable some linters for translated C code.
- path: (apic|writerc|emitterc|parserc|scannerc|readerc|yamlh|yamlprivateh)\.go
linters: [ whitespace, deadcode, varcheck, ineffassign, unparam ]
linters: [whitespace, deadcode, varcheck, ineffassign, unparam]
- path: (apic|writerc|emitterc|parserc|scannerc|readerc|yamlh|yamlprivateh)\.go
linters: [ revive ]
text: "(var-naming: don't use underscores|increment-decrement:|indent-error-flow:)"
linters: [revive]
text: "(var-naming: don't use underscores|increment-decrement:|indent-error-flow:|empty-block:)"
# More precise matching:
- path: apic\.go
linters: [ gocritic ]
linters: [gocritic]
text: "commentFormatting"
- path: emitterc\.go
linters: [ gocritic ]
linters: [gocritic]
text: "(elseIf|ifElseChain)"
- path: parserc\.go
linters: [ govet, gocritic ]
linters: [govet, gocritic]
text: "(shadow|ifElseChain)"
- path: scannerc\.go
linters: [ gocritic ]
linters: [gocritic]
text: "(elseIf|ifElseChain|boolExprSimplify|commentFormatting|appendCombine)"
- path: readerc\.go
linters: [ gocritic ]
linters: [gocritic]
text: "(ifElseChain|paramTypeCombine)"

77 changes: 40 additions & 37 deletions encode.go
Original file line number Diff line number Diff line change
Expand Up @@ -116,45 +116,48 @@ func (e *encoder) marshal(tag string, in reflect.Value) {
e.nilv()
return
}
iface := in.Interface()
switch value := iface.(type) {
case Node:
if !in.CanAddr() {
n := reflect.New(in.Type()).Elem()
n.Set(in)
in = n
}
e.nodev(in.Addr())
return
case *Node:
e.nodev(in)
return
case time.Time:
e.timev(tag, in)
return
case *time.Time:
e.timev(tag, in.Elem())
return
case time.Duration:
e.stringv(tag, reflect.ValueOf(value.String()))
return
case Marshaler:
v, err := value.MarshalYAML()
if err != nil {
fail(err)
}
if v == nil {
e.nilv()
// FIXME(tdakkota): get rid of Interface use.
if in.CanInterface() {
iface := in.Interface()
switch value := iface.(type) {
case Node:
if !in.CanAddr() {
n := reflect.New(in.Type()).Elem()
n.Set(in)
in = n
}
e.nodev(in.Addr())
return
case *Node:
e.nodev(in)
return
case time.Time:
e.timev(tag, in)
return
case *time.Time:
e.timev(tag, in.Elem())
return
case time.Duration:
e.stringv(tag, reflect.ValueOf(value.String()))
return
case Marshaler:
v, err := value.MarshalYAML()
if err != nil {
fail(err)
}
if v == nil {
e.nilv()
return
}
e.marshal(tag, reflect.ValueOf(v))
return
case encoding.TextMarshaler:
text, err := value.MarshalText()
if err != nil {
fail(err)
}
in = reflect.ValueOf(string(text))
}
e.marshal(tag, reflect.ValueOf(v))
return
case encoding.TextMarshaler:
text, err := value.MarshalText()
if err != nil {
fail(err)
}
in = reflect.ValueOf(string(text))
}
switch in.Kind() {
case reflect.Map:
Expand Down
22 changes: 22 additions & 0 deletions encode_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,10 @@ import (

var marshalIntTest = 123

type embeddedType struct {
A string `yaml:"a"`
}

var marshalTests = []struct {
value any
data string
Expand Down Expand Up @@ -517,6 +521,24 @@ var marshalTests = []struct {
"a: 1\nc: 3\nd: 4\n",
},

// Embedded type.
//
// See https://github.com/go-yaml/yaml/issues/944.
{
struct {
embeddedType
B string `yaml:"b"`
}{embeddedType{A: "1"}, "2"},
"embeddedtype:\n a: \"1\"\nb: \"2\"\n",
},
{
struct {
*embeddedType
B string `yaml:"b"`
}{&embeddedType{A: "1"}, "2"},
"embeddedtype:\n a: \"1\"\nb: \"2\"\n",
},

// Map inlining
{
&struct {
Expand Down

0 comments on commit 953ced4

Please sign in to comment.