8000 fix: indirection of typed nils by sagikazarmark · Pull Request #273 · spf13/cast · GitHub
[go: up one dir, main page]
More Web Proxy on the site http://driver.im/
Skip to content

fix: indirection of typed nils #273

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Jun 1, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions basic_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@ import (
)

func TestBool(t *testing.T) {
var ptr *bool

testCases := []testCase{
{0, false, false},
{int(0), false, false},
Expand All @@ -36,6 +38,7 @@ func TestBool(t *testing.T) {
{json.Number("0"), false, false},

{nil, false, false},
{ptr, false, false},
{"false", false, false},
{"FALSE", false, false},
{"False", false, false},
Expand Down Expand Up @@ -103,6 +106,8 @@ func TestString(t *testing.T) {
}
key := &Key{"foo"}

var ptr *string

testCases := []testCase{
{int(8), "8", false},
{int8(8), "8", false},
Expand All @@ -120,6 +125,7 @@ func TestString(t *testing.T) {
{true, "true", false},
{false, "false", false},
{nil, "", false},
{ptr, "", false},
{[]byte("one time"), "one time", false},
{"one more time", "one more time", false},
{template.HTML("one time"), "one time", false},
Expand Down
7 changes: 6 additions & 1 deletion indirect.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,12 @@ func indirect(i any) (any, bool) {
}

v := reflect.ValueOf(i)
for v.Kind() == reflect.Ptr && !v.IsNil() {

for v.Kind() == reflect.Ptr || (v.Kind() == reflect.Interface && v.Elem().Kind() == reflect.Ptr) {
if v.IsNil() {
return nil, true
}

v = v.Elem()
}

Expand Down
49 changes: 46 additions & 3 deletions indirect_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,13 +11,56 @@ import (
qt "github.com/frankban/quicktest"
)

func TestIndirectPointers(t *testing.T) {
func TestIndirect(t *testing.T) {
c := qt.New(t)

x := 13
y := &x
z := &y

c.Assert(ToInt(y), qt.Equals, 13)
c.Assert(ToInt(z), qt.Equals, 13)
var ptr *string
var ptrptr **string

var i any

var n = int(13)
var i2 any = n

var i3 any = &n

var b *bool
var i4 any = b

testCases := []struct {
input any
expected any
expectedOk bool
}{
{x, 13, false},
{y, 13, true},
{z, 13, true},
{ptr, nil, true},
{ptrptr, nil, true},
{i, nil, false},
{&i, nil, true},
{i2, 13, false},
{&i2, 13, true},
{i3, 13, true},
{&i3, 13, true},
{i4, nil, true},
{&i4, nil, true},
{nil, nil, false},
}

for _, testCase := range testCases {
// TODO: remove after minimum Go version is >=1.22
testCase := testCase

t.Run("", func(t *testing.T) {
v, ok := indirect(testCase.input)

c.Assert(v, qt.Equals, testCase.expected)
c.Assert(ok, qt.Equals, testCase.expectedOk)
})
}
}
4 changes: 4 additions & 0 deletions time.go
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,8 @@ func ToTimeInDefaultLocationE(i any, location *time.Location) (tim time.Time, er
return time.Unix(int64(v), 0), nil
case uint64:
return time.Unix(int64(v), 0), nil
case nil:
return time.Time{}, nil
default:
return time.Time{}, fmt.Errorf(errorMsg, i, i, time.Time{})
}
Expand Down Expand Up @@ -87,6 +89,8 @@ func ToDurationE(i any) (time.Duration, error) {
}

return time.ParseDuration(s)
case nil:
return time.Duration(0), nil
default:
if i, ok := resolveAlias(i); ok {
return ToDurationE(i)
Expand Down
9 changes: 9 additions & 0 deletions time_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@ import (
)

func TestTime(t *testing.T) {
var ptr *time.Time

testCases := []testCase{
{"2009-11-10 23:00:00 +0000 UTC", time.Date(2009, 11, 10, 23, 0, 0, 0, time.UTC), false}, // Time.String()
{"Tue Nov 10 23:00:00 2009", time.Date(2009, 11, 10, 23, 0, 0, 0, time.UTC), false}, // ANSIC
Expand Down Expand Up @@ -56,6 +58,8 @@ func TestTime(t *testing.T) {
{json.Number("1234567890"), time.Date(2009, 2, 13, 23, 31, 30, 0, time.UTC), false},
{time.Date(2009, 2, 13, 23, 31, 30, 0, time.UTC), time.Date(2009, 2, 13, 23, 31, 30, 0, time.UTC), false},

{ptr, time.Time{}, false},

// Failure cases
{"2006", time.Time{}, true},
{json.Number("123.4567890"), time.Time{}, true},
Expand All @@ -68,6 +72,8 @@ func TestTime(t *testing.T) {
func TestDuration(t *testing.T) {
type MyDuration time.Duration

var ptr *time.Duration

var expected time.Duration = 5

testCases := []testCase{
Expand All @@ -94,6 +100,9 @@ func TestDuration(t *testing.T) {
{string("5m"), time.Minute * expected, false},
{string("5h"), time.Hour * expected, false},

{0, time.Duration(0), false},
{ptr, time.Duration(0), false},

// Aliases
{MyInt(5), expected, false},
{MyString("5"), expected, false},
Expand Down
0