github.com/myafeier/fabric@v1.0.1-0.20170722181825-3a4b1f2bce86/common/tools/protolator/api.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 "github.com/golang/protobuf/proto" 21 ) 22 23 /////////////////////////////////////////////////////////////////////////////////////////////////// 24 // 25 // This set of interfaces and methods is designed to allow protos to have Go methods attached 26 // to them, so that they may be automatically marshaled to human readable JSON (where the 27 // opaque byte fields are represented as their expanded proto contents) and back once again 28 // to standard proto messages. 29 // 30 // There are currently three different types of interfaces available for protos to implement: 31 // 32 // 1. StaticallyOpaque*FieldProto: These interfaces should be implemented by protos which have 33 // opaque byte fields whose marshaled type is known at compile time. This is mostly true 34 // for the signature oriented fields like the Envelope.Payload, or Header.ChannelHeader 35 // 36 // 2. VariablyOpaque*FieldProto: These interfaces are identical to the StaticallyOpaque*FieldProto 37 // definitions, with the exception that they are guaranteed to be evaluated after the 38 // StaticallyOpaque*FieldProto definitions. In particular, this allows for the type selection of 39 // a VariablyOpaque*FieldProto to depend on data populated by the StaticallyOpaque*FieldProtos. 40 // For example, the Payload.data field depends upon the Payload.Header.ChannelHeader.type field, 41 // which is along a statically marshaled path. 42 // 43 // 3. Dynamic*FieldProto: These interfaces are for messages which contain other messages whose 44 // attributes cannot be determined at compile time. For example, a ConfigValue message may evaluate 45 // the map field values["MSP"] successfully in an organization context, but not at all in a channel 46 // context. Because go is not a dynamic language, this dynamic behavior must be simulated by 47 // wrapping the underlying proto message in another type which can be configured at runtime with 48 // different contextual behavior. (See tests for examples) 49 // 50 /////////////////////////////////////////////////////////////////////////////////////////////////// 51 52 // StaticallyOpaqueFieldProto should be implemented by protos which have bytes fields which 53 // are the marshaled value of a fixed type 54 type StaticallyOpaqueFieldProto interface { 55 // StaticallyOpaqueFields returns the field names which contain opaque data 56 StaticallyOpaqueFields() []string 57 58 // StaticallyOpaqueFieldProto returns a newly allocated proto message of the correct 59 // type for the field name. 60 StaticallyOpaqueFieldProto(name string) (proto.Message, error) 61 } 62 63 // StaticallyOpaqueMapFieldProto should be implemented by protos which have maps to bytes fields 64 // which are the marshaled value of a fixed type 65 type StaticallyOpaqueMapFieldProto interface { 66 // StaticallyOpaqueFields returns the field names which contain opaque data 67 StaticallyOpaqueMapFields() []string 68 69 // StaticallyOpaqueFieldProto returns a newly allocated proto message of the correct 70 // type for the field name. 71 StaticallyOpaqueMapFieldProto(name string, key string) (proto.Message, error) 72 } 73 74 // StaticallyOpaqueSliceFieldProto should be implemented by protos which have maps to bytes fields 75 // which are the marshaled value of a fixed type 76 type StaticallyOpaqueSliceFieldProto interface { 77 // StaticallyOpaqueFields returns the field names which contain opaque data 78 StaticallyOpaqueSliceFields() []string 79 80 // StaticallyOpaqueFieldProto returns a newly allocated proto message of the correct 81 // type for the field name. 82 StaticallyOpaqueSliceFieldProto(name string, index int) (proto.Message, error) 83 } 84 85 // VariablyOpaqueFieldProto should be implemented by protos which have bytes fields which 86 // are the marshaled value depends upon the other contents of the proto 87 type VariablyOpaqueFieldProto interface { 88 // VariablyOpaqueFields returns the field names which contain opaque data 89 VariablyOpaqueFields() []string 90 91 // VariablyOpaqueFieldProto returns a newly allocated proto message of the correct 92 // type for the field name. 93 VariablyOpaqueFieldProto(name string) (proto.Message, error) 94 } 95 96 // VariablyOpaqueMapFieldProto should be implemented by protos which have maps to bytes fields 97 // which are the marshaled value of a a message type determined by the other contents of the proto 98 type VariablyOpaqueMapFieldProto interface { 99 // VariablyOpaqueFields returns the field names which contain opaque data 100 VariablyOpaqueMapFields() []string 101 102 // VariablyOpaqueFieldProto returns a newly allocated proto message of the correct 103 // type for the field name. 104 VariablyOpaqueMapFieldProto(name string, key string) (proto.Message, error) 105 } 106 107 // VariablyOpaqueSliceFieldProto should be implemented by protos which have maps to bytes fields 108 // which are the marshaled value of a a message type determined by the other contents of the proto 109 type VariablyOpaqueSliceFieldProto interface { 110 // VariablyOpaqueFields returns the field names which contain opaque data 111 VariablyOpaqueSliceFields() []string 112 113 // VariablyOpaqueFieldProto returns a newly allocated proto message of the correct 114 // type for the field name. 115 VariablyOpaqueSliceFieldProto(name string, index int) (proto.Message, error) 116 } 117 118 // DynamicFieldProto should be implemented by protos which have nested fields whose attributes 119 // (such as their opaque types) cannot be determined until runtime 120 type DynamicFieldProto interface { 121 // DynamicFields returns the field names which are dynamic 122 DynamicFields() []string 123 124 // DynamicFieldProto returns a newly allocated dynamic message, decorating an underlying 125 // proto message with the runtime determined function 126 DynamicFieldProto(name string, underlying proto.Message) (proto.Message, error) 127 } 128 129 // DynamicMapFieldProto should be implemented by protos which have maps to messages whose attributes 130 // (such as their opaque types) cannot be determined until runtime 131 type DynamicMapFieldProto interface { 132 // DynamicFields returns the field names which are dynamic 133 DynamicMapFields() []string 134 135 // DynamicMapFieldProto returns a newly allocated dynamic message, decorating an underlying 136 // proto message with the runtime determined function 137 DynamicMapFieldProto(name string, key string, underlying proto.Message) (proto.Message, error) 138 } 139 140 // DynamicSliceFieldProto should be implemented by protos which have slices of messages whose attributes 141 // (such as their opaque types) cannot be determined until runtime 142 type DynamicSliceFieldProto interface { 143 // DynamicFields returns the field names which are dynamic 144 DynamicSliceFields() []string 145 146 // DynamicSliceFieldProto returns a newly allocated dynamic message, decorating an underlying 147 // proto message with the runtime determined function 148 DynamicSliceFieldProto(name string, index int, underlying proto.Message) (proto.Message, error) 149 } 150 151 // DecoreatedProto should be implemented by the dynamic wrappers applied by the Dynamic*FieldProto interfaces 152 // This is necessary for the proto system to unmarshal, because it discovers proto message type by reflection 153 // (Rather than by interface definition as it probably should ( https://github.com/golang/protobuf/issues/291 ) 154 type DecoratedProto interface { 155 // Underlying returns the underlying proto message which is being dynamically decorated 156 Underlying() proto.Message 157 }