diff --git a/pkg/ottl/functions.go b/pkg/ottl/functions.go index 4b48a1f6d176..483f205eec17 100644 --- a/pkg/ottl/functions.go +++ b/pkg/ottl/functions.go @@ -4,6 +4,7 @@ package ottl // import "github.com/open-telemetry/opentelemetry-collector-contrib/pkg/ottl" import ( + "context" "errors" "fmt" "reflect" @@ -18,15 +19,15 @@ type EnumParser func(*EnumSymbol) (*Enum, error) type Enum int64 -func newPath(fields []Field) *basePath { +func newPath[K any](fields []Field) *basePath[K] { if len(fields) == 0 { return nil } - var current *basePath + var current *basePath[K] for i := len(fields) - 1; i >= 0; i-- { - current = &basePath{ + current = &basePath[K]{ name: fields[i].Name, - key: newKey(fields[i].Keys), + key: newKey[K](fields[i].Keys), nextPath: current, } } @@ -34,26 +35,26 @@ func newPath(fields []Field) *basePath { return current } -type path interface { +type path[K any] interface { Name() string - Next() path - Key() key + Next() path[K] + Key() key[K] } -var _ path = &basePath{} +var _ path[any] = &basePath[any]{} -type basePath struct { +type basePath[K any] struct { name string - key key - nextPath *basePath + key key[K] + nextPath *basePath[K] fetched bool } -func (p *basePath) Name() string { +func (p *basePath[K]) Name() string { return p.name } -func (p *basePath) Next() path { +func (p *basePath[K]) Next() path[K] { if p.nextPath == nil { return nil } @@ -61,11 +62,11 @@ func (p *basePath) Next() path { return p.nextPath } -func (p *basePath) Key() key { +func (p *basePath[K]) Key() key[K] { return p.key } -func (p *basePath) isComplete() error { +func (p *basePath[K]) isComplete() error { if !p.fetched { return fmt.Errorf("the path section %q was not used by the context - this likely means you are using extra path sections", p.name) } @@ -75,13 +76,13 @@ func (p *basePath) isComplete() error { return p.nextPath.isComplete() } -func newKey(keys []Key) *baseKey { +func newKey[K any](keys []Key) *baseKey[K] { if len(keys) == 0 { return nil } - var current *baseKey + var current *baseKey[K] for i := len(keys) - 1; i >= 0; i-- { - current = &baseKey{ + current = &baseKey[K]{ s: keys[i].String, i: keys[i].Int, nextKey: current, @@ -91,30 +92,30 @@ func newKey(keys []Key) *baseKey { return current } -type key interface { - String() *string - Int() *int64 - Next() key +type key[K any] interface { + String(context.Context, K) (*string, error) + Int(context.Context, K) (*int64, error) + Next() key[K] } -var _ key = &baseKey{} +var _ key[any] = &baseKey[any]{} -type baseKey struct { +type baseKey[K any] struct { s *string i *int64 - nextKey *baseKey + nextKey *baseKey[K] fetched bool } -func (k *baseKey) String() *string { - return k.s +func (k *baseKey[K]) String(_ context.Context, _ K) (*string, error) { + return k.s, nil } -func (k *baseKey) Int() *int64 { - return k.i +func (k *baseKey[K]) Int(_ context.Context, _ K) (*int64, error) { + return k.i, nil } -func (k *baseKey) Next() key { +func (k *baseKey[K]) Next() key[K] { if k.nextKey == nil { return nil } @@ -122,7 +123,7 @@ func (k *baseKey) Next() key { return k.nextKey } -func (k *baseKey) isComplete() error { +func (k *baseKey[K]) isComplete() error { if !k.fetched { var val any if k.s != nil { diff --git a/pkg/ottl/functions_test.go b/pkg/ottl/functions_test.go index c03f207f9ef9..8327396403e7 100644 --- a/pkg/ottl/functions_test.go +++ b/pkg/ottl/functions_test.go @@ -2095,15 +2095,16 @@ func defaultFunctionsForTests() map[string]Factory[any] { } func Test_basePath_Name(t *testing.T) { - bp := basePath{ + bp := basePath[any]{ name: "test", } - assert.Equal(t, "test", bp.Name()) + n := bp.Name() + assert.Equal(t, "test", n) } func Test_basePath_Next(t *testing.T) { - bp := basePath{ - nextPath: &basePath{}, + bp := basePath[any]{ + nextPath: &basePath[any]{}, } next := bp.Next() assert.NotNil(t, next) @@ -2111,8 +2112,8 @@ func Test_basePath_Next(t *testing.T) { } func Test_basePath_Key(t *testing.T) { - k := &baseKey{} - bp := basePath{ + k := &baseKey[any]{} + bp := basePath[any]{ key: k, } assert.Equal(t, k, bp.Key()) @@ -2121,36 +2122,36 @@ func Test_basePath_Key(t *testing.T) { func Test_basePath_isComplete(t *testing.T) { tests := []struct { name string - p basePath + p basePath[any] expectedError bool }{ { name: "fetched no next", - p: basePath{ + p: basePath[any]{ fetched: true, }, }, { name: "fetched with next", - p: basePath{ + p: basePath[any]{ fetched: true, - nextPath: &basePath{ + nextPath: &basePath[any]{ fetched: true, }, }, }, { name: "not fetched no next", - p: basePath{ + p: basePath[any]{ fetched: false, }, expectedError: true, }, { name: "not fetched with next", - p: basePath{ + p: basePath[any]{ fetched: true, - nextPath: &basePath{ + nextPath: &basePath[any]{ fetched: false, }, }, @@ -2172,15 +2173,15 @@ func Test_basePath_isComplete(t *testing.T) { func Test_basePath_NextWithIsComplete(t *testing.T) { tests := []struct { name string - pathFunc func() *basePath + pathFunc func() *basePath[any] expectedError bool }{ { name: "fetched", - pathFunc: func() *basePath { - bp := basePath{ + pathFunc: func() *basePath[any] { + bp := basePath[any]{ fetched: true, - nextPath: &basePath{ + nextPath: &basePath[any]{ fetched: false, }, } @@ -2190,12 +2191,12 @@ func Test_basePath_NextWithIsComplete(t *testing.T) { }, { name: "not fetched enough", - pathFunc: func() *basePath { - bp := basePath{ + pathFunc: func() *basePath[any] { + bp := basePath[any]{ fetched: true, - nextPath: &basePath{ + nextPath: &basePath[any]{ fetched: false, - nextPath: &basePath{ + nextPath: &basePath[any]{ fetched: false, }, }, @@ -2227,7 +2228,7 @@ func Test_newPath(t *testing.T) { Name: "string", }, } - p := newPath(fields) + p := newPath[any](fields) assert.Equal(t, "body", p.name) p = p.nextPath assert.Equal(t, "string", p.name) @@ -2235,22 +2236,28 @@ func Test_newPath(t *testing.T) { } func Test_baseKey_String(t *testing.T) { - bp := baseKey{ + bp := baseKey[any]{ s: ottltest.Strp("test"), } - assert.Equal(t, "test", *bp.String()) + s, err := bp.String(context.Background(), nil) + assert.NoError(t, err) + assert.NotNil(t, s) + assert.Equal(t, "test", *s) } func Test_baseKey_Int(t *testing.T) { - bp := baseKey{ + bp := baseKey[any]{ i: ottltest.Intp(1), } - assert.Equal(t, int64(1), *bp.Int()) + i, err := bp.Int(context.Background(), nil) + assert.NoError(t, err) + assert.NotNil(t, i) + assert.Equal(t, int64(1), *i) } func Test_baseKey_Next(t *testing.T) { - bp := baseKey{ - nextKey: &baseKey{}, + bp := baseKey[any]{ + nextKey: &baseKey[any]{}, } next := bp.Next() assert.NotNil(t, next) @@ -2260,36 +2267,36 @@ func Test_baseKey_Next(t *testing.T) { func Test_baseKey_isComplete(t *testing.T) { tests := []struct { name string - p baseKey + p baseKey[any] expectedError bool }{ { name: "fetched no next", - p: baseKey{ + p: baseKey[any]{ fetched: true, }, }, { name: "fetched with next", - p: baseKey{ + p: baseKey[any]{ fetched: true, - nextKey: &baseKey{ + nextKey: &baseKey[any]{ fetched: true, }, }, }, { name: "not fetched no next", - p: baseKey{ + p: baseKey[any]{ fetched: false, }, expectedError: true, }, { name: "not fetched with next", - p: baseKey{ + p: baseKey[any]{ fetched: true, - nextKey: &baseKey{ + nextKey: &baseKey[any]{ fetched: false, }, }, @@ -2311,15 +2318,15 @@ func Test_baseKey_isComplete(t *testing.T) { func Test_baseKey_NextWithIsComplete(t *testing.T) { tests := []struct { name string - keyFunc func() *baseKey + keyFunc func() *baseKey[any] expectedError bool }{ { name: "fetched", - keyFunc: func() *baseKey { - bk := baseKey{ + keyFunc: func() *baseKey[any] { + bk := baseKey[any]{ fetched: true, - nextKey: &baseKey{ + nextKey: &baseKey[any]{ fetched: false, }, } @@ -2329,12 +2336,12 @@ func Test_baseKey_NextWithIsComplete(t *testing.T) { }, { name: "not fetched enough", - keyFunc: func() *baseKey { - bk := baseKey{ + keyFunc: func() *baseKey[any] { + bk := baseKey[any]{ fetched: true, - nextKey: &baseKey{ + nextKey: &baseKey[any]{ fetched: false, - nextKey: &baseKey{ + nextKey: &baseKey[any]{ fetched: false, }, }, @@ -2366,7 +2373,7 @@ func Test_newKey(t *testing.T) { String: ottltest.Strp("bar"), }, } - k := newKey(keys) + k := newKey[any](keys) assert.Equal(t, "foo", *k.s) k = k.nextKey assert.Equal(t, "bar", *k.s)