peridot/vendor/go.temporal.io/sdk/internal/encode_args.go

139 lines
4.5 KiB
Go
Raw Permalink Normal View History

2022-07-07 20:11:50 +00:00
// The MIT License
//
// Copyright (c) 2020 Temporal Technologies Inc. All rights reserved.
//
// Copyright (c) 2020 Uber Technologies, Inc.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
package internal
import (
"errors"
"fmt"
"reflect"
commonpb "go.temporal.io/api/common/v1"
"go.temporal.io/sdk/converter"
)
// encode multiple arguments(arguments to a function).
func encodeArgs(dc converter.DataConverter, args []interface{}) (*commonpb.Payloads, error) {
return dc.ToPayloads(args...)
}
// decode multiple arguments(arguments to a function).
func decodeArgs(dc converter.DataConverter, fnType reflect.Type, data *commonpb.Payloads) (result []reflect.Value, err error) {
r, err := decodeArgsToPointerValues(dc, fnType, data)
if err != nil {
return
}
for i := 0; i < len(r); i++ {
result = append(result, reflect.ValueOf(r[i]).Elem())
}
return
}
func decodeArgsToPointerValues(dc converter.DataConverter, fnType reflect.Type, data *commonpb.Payloads) (result []interface{}, err error) {
argsLoop:
for i := 0; i < fnType.NumIn(); i++ {
argT := fnType.In(i)
if i == 0 && (isActivityContext(argT) || isWorkflowContext(argT)) {
continue argsLoop
}
arg := reflect.New(argT).Interface()
result = append(result, arg)
}
err = dc.FromPayloads(data, result...)
if err != nil {
return
}
return
}
func decodeArgsToRawValues(dc converter.DataConverter, fnType reflect.Type, data *commonpb.Payloads) ([]interface{}, error) {
// Build pointers to results
var pointers []interface{}
for i := 0; i < fnType.NumIn(); i++ {
argT := fnType.In(i)
if i == 0 && (isActivityContext(argT) || isWorkflowContext(argT)) {
continue
}
pointers = append(pointers, reflect.New(argT).Interface())
}
// Unmarshal
if err := dc.FromPayloads(data, pointers...); err != nil {
return nil, err
}
// Convert results back to non-pointer versions
results := make([]interface{}, len(pointers))
for i, pointer := range pointers {
result := reflect.ValueOf(pointer).Elem()
// Do not set nil pointers
if result.Kind() != reflect.Ptr || !result.IsNil() {
results[i] = result.Interface()
}
}
return results, nil
}
// encode single value(like return parameter).
func encodeArg(dc converter.DataConverter, arg interface{}) (*commonpb.Payloads, error) {
return dc.ToPayloads(arg)
}
// decode single value(like return parameter).
func decodeArg(dc converter.DataConverter, data *commonpb.Payloads, valuePtr interface{}) error {
return dc.FromPayloads(data, valuePtr)
}
func decodeAndAssignValue(dc converter.DataConverter, from interface{}, toValuePtr interface{}) error {
if toValuePtr == nil {
return nil
}
if rf := reflect.ValueOf(toValuePtr); rf.Type().Kind() != reflect.Ptr {
return errors.New("value parameter provided is not a pointer")
}
if data, ok := from.(*commonpb.Payloads); ok {
if err := decodeArg(dc, data, toValuePtr); err != nil {
return err
}
} else if fv := reflect.ValueOf(from); fv.IsValid() {
fromType := fv.Type()
toType := reflect.TypeOf(toValuePtr).Elem()
// If the value set was a pointer and is the same type as the wanted result,
// instead of panicking because it is not a pointer to a pointer, we will
// just set the pointer
if fv.Kind() == reflect.Ptr && fromType.Elem() == toType {
reflect.ValueOf(toValuePtr).Elem().Set(fv.Elem())
} else {
assignable := fromType.AssignableTo(toType)
if !assignable {
return fmt.Errorf("%s is not assignable to %s", fromType.Name(), toType.Name())
}
reflect.ValueOf(toValuePtr).Elem().Set(fv)
}
}
return nil
}