github.com/lzy4123/fabric@v2.1.1+incompatible/common/tools/protolator/dynamic.go (about)

     1  /*
     2  Copyright IBM Corp. 2017 All Rights Reserved.
     3  
     4  Licensed under the Apache License, Version 2.0 (the "License");
     5  you may not use this file except in compliance with the License.
     6  You may obtain a copy of the License at
     7  
     8                   http://www.apache.org/licenses/LICENSE-2.0
     9  
    10  Unless required by applicable law or agreed to in writing, software
    11  distributed under the License is distributed on an "AS IS" BASIS,
    12  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13  See the License for the specific language governing permissions and
    14  limitations under the License.
    15  */
    16  
    17  package protolator
    18  
    19  import (
    20  	"reflect"
    21  
    22  	"github.com/golang/protobuf/proto"
    23  )
    24  
    25  func dynamicFrom(dynamicMsg func(underlying proto.Message) (proto.Message, error), value interface{}, destType reflect.Type) (reflect.Value, error) {
    26  	tree := value.(map[string]interface{}) // Safe, already checked
    27  	uMsg := reflect.New(destType.Elem())
    28  	nMsg, err := dynamicMsg(uMsg.Interface().(proto.Message)) // Safe, already checked
    29  	if err != nil {
    30  		return reflect.Value{}, err
    31  	}
    32  	if err := recursivelyPopulateMessageFromTree(tree, nMsg); err != nil {
    33  		return reflect.Value{}, err
    34  	}
    35  	return uMsg, nil
    36  }
    37  
    38  func dynamicTo(dynamicMsg func(underlying proto.Message) (proto.Message, error), value reflect.Value) (interface{}, error) {
    39  	nMsg, err := dynamicMsg(value.Interface().(proto.Message)) // Safe, already checked
    40  	if err != nil {
    41  		return nil, err
    42  	}
    43  	return recursivelyCreateTreeFromMessage(nMsg)
    44  }
    45  
    46  type dynamicFieldFactory struct{}
    47  
    48  func (dff dynamicFieldFactory) Handles(msg proto.Message, fieldName string, fieldType reflect.Type, fieldValue reflect.Value) bool {
    49  	dynamicProto, ok := msg.(DynamicFieldProto)
    50  	if !ok {
    51  		return false
    52  	}
    53  
    54  	return stringInSlice(fieldName, dynamicProto.DynamicFields())
    55  }
    56  
    57  func (dff dynamicFieldFactory) NewProtoField(msg proto.Message, fieldName string, fieldType reflect.Type, fieldValue reflect.Value) (protoField, error) {
    58  	dynamicProto, _ := msg.(DynamicFieldProto) // Type checked in Handles
    59  
    60  	return &plainField{
    61  		baseField: baseField{
    62  			msg:   msg,
    63  			name:  fieldName,
    64  			fType: mapStringInterfaceType,
    65  			vType: fieldType,
    66  			value: fieldValue,
    67  		},
    68  		populateFrom: func(v interface{}, dT reflect.Type) (reflect.Value, error) {
    69  			return dynamicFrom(func(underlying proto.Message) (proto.Message, error) {
    70  				return dynamicProto.DynamicFieldProto(fieldName, underlying)
    71  			}, v, dT)
    72  		},
    73  		populateTo: func(v reflect.Value) (interface{}, error) {
    74  			return dynamicTo(func(underlying proto.Message) (proto.Message, error) {
    75  				return dynamicProto.DynamicFieldProto(fieldName, underlying)
    76  			}, v)
    77  		},
    78  	}, nil
    79  }
    80  
    81  type dynamicMapFieldFactory struct{}
    82  
    83  func (dmff dynamicMapFieldFactory) Handles(msg proto.Message, fieldName string, fieldType reflect.Type, fieldValue reflect.Value) bool {
    84  	dynamicProto, ok := msg.(DynamicMapFieldProto)
    85  	if !ok {
    86  		return false
    87  	}
    88  
    89  	return stringInSlice(fieldName, dynamicProto.DynamicMapFields())
    90  }
    91  
    92  func (dmff dynamicMapFieldFactory) NewProtoField(msg proto.Message, fieldName string, fieldType reflect.Type, fieldValue reflect.Value) (protoField, error) {
    93  	dynamicProto := msg.(DynamicMapFieldProto) // Type checked by Handles
    94  
    95  	return &mapField{
    96  		baseField: baseField{
    97  			msg:   msg,
    98  			name:  fieldName,
    99  			fType: mapStringInterfaceType,
   100  			vType: fieldType,
   101  			value: fieldValue,
   102  		},
   103  		populateFrom: func(k string, v interface{}, dT reflect.Type) (reflect.Value, error) {
   104  			return dynamicFrom(func(underlying proto.Message) (proto.Message, error) {
   105  				return dynamicProto.DynamicMapFieldProto(fieldName, k, underlying)
   106  			}, v, dT)
   107  		},
   108  		populateTo: func(k string, v reflect.Value) (interface{}, error) {
   109  			return dynamicTo(func(underlying proto.Message) (proto.Message, error) {
   110  				return dynamicProto.DynamicMapFieldProto(fieldName, k, underlying)
   111  			}, v)
   112  		},
   113  	}, nil
   114  }
   115  
   116  type dynamicSliceFieldFactory struct{}
   117  
   118  func (dmff dynamicSliceFieldFactory) Handles(msg proto.Message, fieldName string, fieldType reflect.Type, fieldValue reflect.Value) bool {
   119  	dynamicProto, ok := msg.(DynamicSliceFieldProto)
   120  	if !ok {
   121  		return false
   122  	}
   123  
   124  	return stringInSlice(fieldName, dynamicProto.DynamicSliceFields())
   125  }
   126  
   127  func (dmff dynamicSliceFieldFactory) NewProtoField(msg proto.Message, fieldName string, fieldType reflect.Type, fieldValue reflect.Value) (protoField, error) {
   128  	dynamicProto := msg.(DynamicSliceFieldProto) // Type checked by Handles
   129  
   130  	return &sliceField{
   131  		baseField: baseField{
   132  			msg:   msg,
   133  			name:  fieldName,
   134  			fType: mapStringInterfaceType,
   135  			vType: fieldType,
   136  			value: fieldValue,
   137  		},
   138  		populateFrom: func(i int, v interface{}, dT reflect.Type) (reflect.Value, error) {
   139  			return dynamicFrom(func(underlying proto.Message) (proto.Message, error) {
   140  				return dynamicProto.DynamicSliceFieldProto(fieldName, i, underlying)
   141  			}, v, dT)
   142  		},
   143  		populateTo: func(i int, v reflect.Value) (interface{}, error) {
   144  			return dynamicTo(func(underlying proto.Message) (proto.Message, error) {
   145  				return dynamicProto.DynamicSliceFieldProto(fieldName, i, underlying)
   146  			}, v)
   147  		},
   148  	}, nil
   149  }