Skip to content

Commit

Permalink
Changes to tablewriter to support slices of interface
Browse files Browse the repository at this point in the history
  • Loading branch information
djthorpe committed Jun 18, 2024
1 parent 4425e0f commit 64a7e73
Showing 1 changed file with 32 additions and 2 deletions.
34 changes: 32 additions & 2 deletions pkg/meta/meta.go
Original file line number Diff line number Diff line change
Expand Up @@ -263,8 +263,12 @@ func typeOf(v any) (reflect.Type, bool, error) {
rt := reflect.TypeOf(v)
isSlice := false
if rt.Kind() == reflect.Slice || rt.Kind() == reflect.Array {
rt = rt.Elem()
isSlice = true
if t, err := sliceTypeOf(v); err != nil {
return nil, false, err
} else {
rt = t
isSlice = true
}
}
if rt.Kind() == reflect.Ptr {
rt = rt.Elem()
Expand All @@ -276,6 +280,32 @@ func typeOf(v any) (reflect.Type, bool, error) {
return rt, isSlice, nil
}

// Returns the type of a slice or array, given that the slice might be an
// interface to many different value types
func sliceTypeOf(v any) (reflect.Type, error) {
// If it's not an interface, just return the type
t := reflect.TypeOf(v).Elem()
if t.Kind() != reflect.Interface {
return t, nil
}

// If it's an interface make sure every element in the slice or array
// is the same type
rv := reflect.ValueOf(v)
if rv.Len() == 0 {
return nil, ErrBadParameter.With("NewTableMeta: empty []", rv.Type())
}
rt := rv.Index(0).Elem().Type()
for i := 1; i < rv.Len(); i++ {
if rt != rv.Index(i).Elem().Type() {
return nil, ErrBadParameter.With("NewTableMeta: []interface with different types")
}
}

// Return (hopefully) the struct type
return rt, nil
}

// asColumns returns a slice of field metadata for a struct type
func asColumns(rt reflect.Type, tag []string) []*fieldmeta {
cols := make([]*fieldmeta, 0, rt.NumField())
Expand Down

0 comments on commit 64a7e73

Please sign in to comment.