Skip to content

Commit

Permalink
✨ feat: reflects - add new func TypeReal, TypeElem, MakeSliceByElem
Browse files Browse the repository at this point in the history
  • Loading branch information
inhere committed Jul 24, 2023
1 parent 8690507 commit f8b93a0
Show file tree
Hide file tree
Showing 6 changed files with 72 additions and 9 deletions.
4 changes: 4 additions & 0 deletions reflects/check_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,10 @@ func TestIsEqual(t *testing.T) {
is.True(reflects.IsEqual([]byte{}, []byte{}))
is.True(reflects.IsEqual([]byte("abc"), []byte("abc")))
is.False(reflects.IsEqual([]byte("abc"), 123))

var data []string
// fmt.Printf("%+v %+v\n", data, []string{})
is.False(reflects.IsEqual([]string{}, data))
}

func TestIsEmpty(t *testing.T) {
Expand Down
18 changes: 18 additions & 0 deletions reflects/reflects.go
Original file line number Diff line number Diff line change
@@ -1,2 +1,20 @@
// Package reflects Provide extends reflect util functions.
package reflects

import "reflect"

// MakeSliceByElem create a new slice by the element type.
//
// - elType: the type of the element.
// - returns: the new slice.
//
// Usage:
//
// sl := MakeSliceByElem(reflect.TypeOf(1), 10, 20)
// sl.Index(0).SetInt(10)
//
// // Or use reflect.AppendSlice() merge two slice
// // Or use `for` with `reflect.Append()` add elements
func MakeSliceByElem(elTyp reflect.Type, len, cap int) reflect.Value {
return reflect.MakeSlice(reflect.SliceOf(elTyp), len, cap)
}
20 changes: 20 additions & 0 deletions reflects/type.go
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,8 @@ type Type interface {
reflect.Type
// BaseKind value
BaseKind() BKind
// SafeElem returns a type's element type. otherwise, will return self.
SafeElem() reflect.Type
}

type xType struct {
Expand All @@ -76,3 +78,21 @@ func TypeOf(v any) Type {
func (t *xType) BaseKind() BKind {
return t.baseKind
}

// RealType returns a ptr type's real type. otherwise, will return self.
func (t *xType) RealType() reflect.Type {
if t.Kind() == reflect.Pointer {
return t.Type.Elem()
}
return t.Type
}

// SafeElem returns the array, slice, chan, map type's element type. otherwise, will return self.
func (t *xType) SafeElem() reflect.Type {
switch t.Kind() {
case reflect.Array, reflect.Chan, reflect.Map, reflect.Slice:
return t.Type.Elem()
default:
return t.Type
}
}
30 changes: 22 additions & 8 deletions reflects/util.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,26 +8,40 @@ import (
)

// Elem returns the value that the interface v contains
// or that the pointer v points to.
// or that the pointer v points to. otherwise, will return self
func Elem(v reflect.Value) reflect.Value {
if v.Kind() == reflect.Ptr || v.Kind() == reflect.Interface {
if v.Kind() == reflect.Pointer || v.Kind() == reflect.Interface {
return v.Elem()
}

// otherwise, will return self
return v
}

// Indirect like reflect.Indirect(), but can also indirect reflect.Interface
// Indirect like reflect.Indirect(), but can also indirect reflect.Interface. otherwise, will return self
func Indirect(v reflect.Value) reflect.Value {
if v.Kind() == reflect.Ptr || v.Kind() == reflect.Interface {
if v.Kind() == reflect.Pointer || v.Kind() == reflect.Interface {
return v.Elem()
}

// otherwise, will return self
return v
}

// TypeReal returns a ptr type's real type. otherwise, will return self.
func TypeReal(t reflect.Type) reflect.Type {
if t.Kind() == reflect.Pointer {
return t.Elem()
}
return t
}

// TypeElem returns the array, slice, chan, map type's element type. otherwise, will return self.
func TypeElem(t reflect.Type) reflect.Type {
switch t.Kind() {
case reflect.Array, reflect.Chan, reflect.Map, reflect.Slice:
return t.Elem()
default:
return t
}
}

// Len get reflect value length
func Len(v reflect.Value) int {
v = reflect.Indirect(v)
Expand Down
7 changes: 7 additions & 0 deletions reflects/util_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -104,8 +104,15 @@ func TestSliceAddItem_ok(t *testing.T) {
assert.Len(t, sl, 2)

rv.Index(1).Set(reflect.ValueOf("def"))
dump.P(sl)

slv := reflects.MakeSliceByElem(reflect.TypeOf("str"), 0, 2)
slv = reflect.Append(slv, reflect.ValueOf("a"))
slv = reflect.Append(slv, reflect.ValueOf("b"))
sl = slv.Interface().([]string)
dump.P(sl)
assert.Len(t, sl, 2)
assert.Eq(t, "a", sl[0])
}

func TestSlice_subMap_addItem(t *testing.T) {
Expand Down
2 changes: 1 addition & 1 deletion reflects/value.go
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ func (v Value) Indirect() Value {
//
// TIP: not like reflect.Value.Elem. otherwise, will return self.
func (v Value) Elem() Value {
if v.Kind() == reflect.Ptr || v.Kind() == reflect.Interface {
if v.Kind() == reflect.Pointer || v.Kind() == reflect.Interface {
elem := v.Value.Elem()

return Value{
Expand Down

0 comments on commit f8b93a0

Please sign in to comment.