github.com/kaituanwang/hyperledger@v2.0.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 }