blob: 08a9239ace1849b07d9114f1fc8fc59def2ade26 [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You 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 triple
import (
"reflect"
)
import (
hessian "github.com/apache/dubbo-go-hessian2"
perrors "github.com/pkg/errors"
)
// ReflectResponse reflect return value
func ReflectResponse(in interface{}, out interface{}) error {
if in == nil {
return perrors.Errorf("@in is nil")
}
if out == nil {
return perrors.Errorf("@out is nil")
}
if reflect.TypeOf(out).Kind() != reflect.Ptr {
return perrors.Errorf("@out should be a pointer")
}
inValue := hessian.EnsurePackValue(in)
outValue := hessian.EnsurePackValue(out)
outType := outValue.Type().String()
if outType == "interface {}" || outType == "*interface {}" {
hessian.SetValue(outValue, inValue)
return nil
}
switch inValue.Type().Kind() {
case reflect.Slice, reflect.Array:
return CopySlice(inValue, outValue)
case reflect.Map:
return CopyMap(inValue, outValue)
default:
hessian.SetValue(outValue, inValue)
}
return nil
}
// CopySlice copy from inSlice to outSlice
func CopySlice(inSlice, outSlice reflect.Value) error {
if inSlice.IsNil() {
return perrors.New("@in is nil")
}
if inSlice.Kind() != reflect.Slice {
return perrors.Errorf("@in is not slice, but %v", inSlice.Kind())
}
for outSlice.Kind() == reflect.Ptr {
outSlice = outSlice.Elem()
}
size := inSlice.Len()
outSlice.Set(reflect.MakeSlice(outSlice.Type(), size, size))
for i := 0; i < size; i++ {
inSliceValue := inSlice.Index(i)
if !inSliceValue.Type().AssignableTo(outSlice.Index(i).Type()) {
return perrors.Errorf("in element type [%s] can not assign to out element type [%s]",
inSliceValue.Type().String(), outSlice.Type().String())
}
outSlice.Index(i).Set(inSliceValue)
}
return nil
}
// CopyMap copy from in map to out map
func CopyMap(inMapValue, outMapValue reflect.Value) error {
if inMapValue.IsNil() {
return perrors.New("@in is nil")
}
if !inMapValue.CanInterface() {
return perrors.New("@in's Interface can not be used.")
}
if inMapValue.Kind() != reflect.Map {
return perrors.Errorf("@in is not map, but %v", inMapValue.Kind())
}
outMapType := hessian.UnpackPtrType(outMapValue.Type())
hessian.SetValue(outMapValue, reflect.MakeMap(outMapType))
outKeyType := outMapType.Key()
outMapValue = hessian.UnpackPtrValue(outMapValue)
outValueType := outMapValue.Type().Elem()
for _, inKey := range inMapValue.MapKeys() {
inValue := inMapValue.MapIndex(inKey)
if !inKey.Type().AssignableTo(outKeyType) {
return perrors.Errorf("in Key:{type:%s, value:%#v} can not assign to out Key:{type:%s} ",
inKey.Type().String(), inKey, outKeyType.String())
}
if !inValue.Type().AssignableTo(outValueType) {
return perrors.Errorf("in Value:{type:%s, value:%#v} can not assign to out value:{type:%s}",
inValue.Type().String(), inValue, outValueType.String())
}
outMapValue.SetMapIndex(inKey, inValue)
}
return nil
}