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  }