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

Refactor package internal/attribute to not use generics. #3725

Merged
merged 15 commits into from
Feb 15, 2023
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,10 @@ This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.htm
- `OtelLibraryVersion` -> `OTelLibraryVersion`
- `OtelStatusDescription` -> `OTelStatusDescription`

### Fixed

- Refactor package internal/attribute to not use generics. (#3725)

## [1.13.0/0.36.0] 2023-02-07

### Added
Expand Down
16 changes: 8 additions & 8 deletions attribute/value.go
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ func BoolValue(v bool) Value {

// BoolSliceValue creates a BOOLSLICE Value.
func BoolSliceValue(v []bool) Value {
return Value{vtype: BOOLSLICE, slice: attribute.SliceValue(v)}
return Value{vtype: BOOLSLICE, slice: attribute.BoolSliceValue(v)}
}

// IntValue creates an INT64 Value.
Expand Down Expand Up @@ -99,7 +99,7 @@ func Int64Value(v int64) Value {

// Int64SliceValue creates an INT64SLICE Value.
func Int64SliceValue(v []int64) Value {
return Value{vtype: INT64SLICE, slice: attribute.SliceValue(v)}
return Value{vtype: INT64SLICE, slice: attribute.Int64SliceValue(v)}
}

// Float64Value creates a FLOAT64 Value.
Expand All @@ -112,7 +112,7 @@ func Float64Value(v float64) Value {

// Float64SliceValue creates a FLOAT64SLICE Value.
func Float64SliceValue(v []float64) Value {
return Value{vtype: FLOAT64SLICE, slice: attribute.SliceValue(v)}
return Value{vtype: FLOAT64SLICE, slice: attribute.Float64SliceValue(v)}
}

// StringValue creates a STRING Value.
Expand All @@ -125,7 +125,7 @@ func StringValue(v string) Value {

// StringSliceValue creates a STRINGSLICE Value.
func StringSliceValue(v []string) Value {
return Value{vtype: STRINGSLICE, slice: attribute.SliceValue(v)}
return Value{vtype: STRINGSLICE, slice: attribute.StringSliceValue(v)}
}

// Type returns a type of the Value.
Expand All @@ -149,7 +149,7 @@ func (v Value) AsBoolSlice() []bool {
}

func (v Value) asBoolSlice() []bool {
return attribute.AsSlice[bool](v.slice)
return attribute.AsBoolSlice(v.slice)
}

// AsInt64 returns the int64 value. Make sure that the Value's type is
Expand All @@ -168,7 +168,7 @@ func (v Value) AsInt64Slice() []int64 {
}

func (v Value) asInt64Slice() []int64 {
return attribute.AsSlice[int64](v.slice)
return attribute.AsInt64Slice(v.slice)
}

// AsFloat64 returns the float64 value. Make sure that the Value's
Expand All @@ -187,7 +187,7 @@ func (v Value) AsFloat64Slice() []float64 {
}

func (v Value) asFloat64Slice() []float64 {
return attribute.AsSlice[float64](v.slice)
return attribute.AsFloat64Slice(v.slice)
}

// AsString returns the string value. Make sure that the Value's type
Expand All @@ -206,7 +206,7 @@ func (v Value) AsStringSlice() []string {
}

func (v Value) asStringSlice() []string {
return attribute.AsSlice[string](v.slice)
return attribute.AsStringSlice(v.slice)
}

type unknownValueType struct{}
Expand Down
82 changes: 74 additions & 8 deletions internal/attribute/attribute.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,24 +22,90 @@ import (
"reflect"
)

// SliceValue convert a slice into an array with same elements as slice.
func SliceValue[T bool | int64 | float64 | string](v []T) any {
var zero T
// BoolSliceValue converts a bool slice into an array with same elements as slice.
func BoolSliceValue(v []bool) any {
var zero bool
cp := reflect.New(reflect.ArrayOf(len(v), reflect.TypeOf(zero)))
copy(cp.Elem().Slice(0, len(v)).Interface().([]T), v)
copy(cp.Elem().Slice(0, len(v)).Interface().([]bool), v)
return cp.Elem().Interface()
}

// AsSlice convert an array into a slice into with same elements as array.
func AsSlice[T bool | int64 | float64 | string](v any) []T {
// Int64SliceValue converts a int64 slice into an array with same elements as slice.
Petrie marked this conversation as resolved.
Show resolved Hide resolved
func Int64SliceValue(v []int64) any {
var zero int64
cp := reflect.New(reflect.ArrayOf(len(v), reflect.TypeOf(zero)))
copy(cp.Elem().Slice(0, len(v)).Interface().([]int64), v)
return cp.Elem().Interface()
}

// Float64SliceValue converts a float64 slice into an array with same elements as slice.
func Float64SliceValue(v []float64) any {
var zero float64
cp := reflect.New(reflect.ArrayOf(len(v), reflect.TypeOf(zero)))
copy(cp.Elem().Slice(0, len(v)).Interface().([]float64), v)
return cp.Elem().Interface()
}

// StringSliceValue converts a string slice into an array with same elements as slice.
func StringSliceValue(v []string) any {
var zero string
cp := reflect.New(reflect.ArrayOf(len(v), reflect.TypeOf(zero)))
copy(cp.Elem().Slice(0, len(v)).Interface().([]string), v)
return cp.Elem().Interface()
}

// AsBoolSlice converts a bool array into a slice into with same elements as array.
func AsBoolSlice(v any) []bool {
rv := reflect.ValueOf(v)
if rv.Type().Kind() != reflect.Array {
return nil
}
var zero bool
correctLen := rv.Len()
correctType := reflect.ArrayOf(correctLen, reflect.TypeOf(zero))
cpy := reflect.New(correctType)
_ = reflect.Copy(cpy.Elem(), rv)
return cpy.Elem().Slice(0, correctLen).Interface().([]bool)
}

// AsInt64Slice converts an int64 array into a slice into with same elements as array.
func AsInt64Slice(v any) []int64 {
rv := reflect.ValueOf(v)
if rv.Type().Kind() != reflect.Array {
return nil
}
var zero int64
correctLen := rv.Len()
correctType := reflect.ArrayOf(correctLen, reflect.TypeOf(zero))
cpy := reflect.New(correctType)
_ = reflect.Copy(cpy.Elem(), rv)
return cpy.Elem().Slice(0, correctLen).Interface().([]int64)
}

// AsFloat64Slice converts a float64 array into a slice into with same elements as array.
func AsFloat64Slice(v any) []float64 {
rv := reflect.ValueOf(v)
if rv.Type().Kind() != reflect.Array {
return nil
}
var zero float64
correctLen := rv.Len()
correctType := reflect.ArrayOf(correctLen, reflect.TypeOf(zero))
cpy := reflect.New(correctType)
_ = reflect.Copy(cpy.Elem(), rv)
return cpy.Elem().Slice(0, correctLen).Interface().([]float64)
}

// AsStringSlice converts a string array into a slice into with same elements as array.
func AsStringSlice(v any) []string {
rv := reflect.ValueOf(v)
if rv.Type().Kind() != reflect.Array {
return nil
}
var zero T
var zero string
correctLen := rv.Len()
correctType := reflect.ArrayOf(correctLen, reflect.TypeOf(zero))
cpy := reflect.New(correctType)
_ = reflect.Copy(cpy.Elem(), rv)
return cpy.Elem().Slice(0, correctLen).Interface().([]T)
return cpy.Elem().Slice(0, correctLen).Interface().([]string)
}
103 changes: 103 additions & 0 deletions internal/attribute/attribute_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
// Copyright The OpenTelemetry Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package attribute

import (
"reflect"
"testing"
)

var wrapFloat64SliceValue = func(v any) any {
MrAlias marked this conversation as resolved.
Show resolved Hide resolved
if vi, ok := v.([]float64); ok {
return Float64SliceValue(vi)
}
return nil
}

var wrapInt64SliceValue = func(v any) any {
if vi, ok := v.([]int64); ok {
return Int64SliceValue(vi)
}
return nil
}

var wrapBoolSliceValue = func(v any) any {
if vi, ok := v.([]bool); ok {
return BoolSliceValue(vi)
}
return nil
}
var wrapStringSliceValue = func(v any) any {
if vi, ok := v.([]string); ok {
return StringSliceValue(vi)
}
return nil
}
var wrapAsBoolSlice = func(v any) any { return AsBoolSlice(v) }
var wrapAsInt64Slice = func(v any) any { return AsInt64Slice(v) }
var wrapAsFloat64Slice = func(v any) any { return AsFloat64Slice(v) }
var wrapAsStringSlice = func(v any) any { return AsStringSlice(v) }

func TestSliceValue(t *testing.T) {
type args struct {
v any
}
tests := []struct {
name string
args args
want any
fn func(any) any
}{
{
name: "Float64SliceValue() two items",
args: args{v: []float64{1, 2.3}}, want: [2]float64{1, 2.3}, fn: wrapFloat64SliceValue,
},
{
name: "Int64SliceValue() two items",
args: args{[]int64{1, 2}}, want: [2]int64{1, 2}, fn: wrapInt64SliceValue,
},
{
name: "BoolSliceValue() two items",
args: args{v: []bool{true, false}}, want: [2]bool{true, false}, fn: wrapBoolSliceValue,
},
{
name: "StringSliceValue() two items",
args: args{[]string{"123", "2"}}, want: [2]string{"123", "2"}, fn: wrapStringSliceValue,
},
{
name: "AsBoolSlice() two items",
args: args{[2]bool{true, false}}, want: []bool{true, false}, fn: wrapAsBoolSlice,
},
{
name: "AsInt64Slice() two items",
args: args{[2]int64{1, 3}}, want: []int64{1, 3}, fn: wrapAsInt64Slice,
},
{
name: "AsFloat64Slice() two items",
args: args{[2]float64{1.2, 3.1}}, want: []float64{1.2, 3.1}, fn: wrapAsFloat64Slice,
},
{
name: "AsStringSlice() two items",
args: args{[2]string{"1234", "12"}}, want: []string{"1234", "12"}, fn: wrapAsStringSlice,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
if got := tt.fn(tt.args.v); !reflect.DeepEqual(got, tt.want) {
t.Errorf("got %v, want %v", got, tt.want)
}
})
}
}