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