github.com/pvitto98/fabric@v2.1.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  }