Skip to content
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

feat(next): add DerefOrEmpty func to client. #169

Closed
wants to merge 2 commits into from
Closed
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
25 changes: 25 additions & 0 deletions next/deref.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
package next

import "reflect"

// DerefOrEmpty returns the dereferenced value of the input pointer, or the zero
// value of the type if the input is nil.
func DerefOrEmpty[T any](in *T) T {
if in == nil {
tType := reflect.TypeOf(*new(T))

//nolint:exhaustive
switch tType.Kind() {
case reflect.Slice, reflect.Array:
return reflect.MakeSlice(tType, 0, 0).Interface().(T)
case reflect.Map:
return reflect.MakeMap(tType).Interface().(T)
default:
var empty T

return empty
}
}

return *in
}
167 changes: 167 additions & 0 deletions next/deref_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,167 @@
package next_test

import (
"testing"

"github.com/krystal/go-katapult/next"
"github.com/stretchr/testify/require"
)

func ptr[T any](v T) *T {
return &v
}

func TestDerefOrEmpty_string(t *testing.T) {
tests := []struct {
name string
in *string
want string
}{
{
name: "Nil input",
in: nil,
want: "",
},
{
name: "Non-nil input",
in: ptr("hello"),
want: "hello",
},
}

for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
require.Equal(t, tt.want, next.DerefOrEmpty(tt.in))
})
}
}

func TestDerefOrEmpty_int(t *testing.T) {
tests := []struct {
name string
in *int
want int
}{
{
name: "Nil input",
in: nil,
want: 0,
},
{
name: "Non-nil input",
in: ptr(22),
want: 22,
},
}

for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
require.Equal(t, tt.want, next.DerefOrEmpty(tt.in))
})
}
}

func TestDerefOrEmpty_float64(t *testing.T) {
tests := []struct {
name string
in *float64
want float64
}{
{
name: "Nil input",
in: nil,
want: 0.0,
},
{
name: "Non-nil input",
in: ptr(3.14),
want: 3.14,
},
}

for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
require.Equal(t, tt.want, next.DerefOrEmpty(tt.in))
})
}
}

func TestDerefOrEmpty_slice(t *testing.T) {
tests := []struct {
name string
in *[]string
want []string
}{
{
name: "Nil input",
in: nil,
want: []string{},
},
{
name: "Non-nil input",
in: ptr([]string{"hello", "world"}),
want: []string{"hello", "world"},
},
}

for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
require.Equal(t, tt.want, next.DerefOrEmpty(tt.in))
})
}
}

func TestDerefOrEmpty_map(t *testing.T) {
tests := []struct {
name string
in *map[string]int
want map[string]int
}{
{
name: "Nil input",
in: nil,
want: map[string]int{},
},
{
name: "Non-nil input",
in: ptr(map[string]int{"hello": 32}),
want: map[string]int{"hello": 32},
},
}

for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
require.Equal(t, tt.want, next.DerefOrEmpty(tt.in))
})
}
}

func TestDerefOrEmpty_struct(t *testing.T) {
type testStruct struct {
Name string
Age int
}

tests := []struct {
name string
in *testStruct
want testStruct
}{
{
name: "Nil input",
in: nil,
want: testStruct{},
},
{
name: "Non-nil input",
in: ptr(testStruct{Name: "Alice", Age: 22}),
want: testStruct{Name: "Alice", Age: 22},
},
}

for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
require.Equal(t, tt.want, next.DerefOrEmpty(tt.in))
})
}
}
Loading