github.com/lzy4123/fabric@v2.1.1+incompatible/common/tools/protolator/statically_opaque.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 opaqueFrom(opaqueType func() (proto.Message, error), value interface{}, destType reflect.Type) (reflect.Value, error) {
    26  	tree := value.(map[string]interface{}) // Safe, already checked
    27  	nMsg, err := opaqueType()
    28  	if err != nil {
    29  		return reflect.Value{}, err
    30  	}
    31  	if err := recursivelyPopulateMessageFromTree(tree, nMsg); err != nil {
    32  		return reflect.Value{}, err
    33  	}
    34  	mMsg, err := MostlyDeterministicMarshal(nMsg)
    35  	if err != nil {
    36  		return reflect.Value{}, err
    37  	}
    38  	return reflect.ValueOf(mMsg), nil
    39  }
    40  
    41  func opaqueTo(opaqueType func() (proto.Message, error), value reflect.Value) (interface{}, error) {
    42  	nMsg, err := opaqueType()
    43  	if err != nil {
    44  		return nil, err
    45  	}
    46  	mMsg := value.Interface().([]byte) // Safe, already checked
    47  	if err = proto.Unmarshal(mMsg, nMsg); err != nil {
    48  		return nil, err
    49  	}
    50  	return recursivelyCreateTreeFromMessage(nMsg)
    51  }
    52  
    53  type staticallyOpaqueFieldFactory struct{}
    54  
    55  func (soff staticallyOpaqueFieldFactory) Handles(msg proto.Message, fieldName string, fieldType reflect.Type, fieldValue reflect.Value) bool {
    56  	opaqueProto, ok := msg.(StaticallyOpaqueFieldProto)
    57  	if !ok {
    58  		return false
    59  	}
    60  
    61  	return stringInSlice(fieldName, opaqueProto.StaticallyOpaqueFields())
    62  }
    63  
    64  func (soff staticallyOpaqueFieldFactory) NewProtoField(msg proto.Message, fieldName string, fieldType reflect.Type, fieldValue reflect.Value) (protoField, error) {
    65  	opaqueProto := msg.(StaticallyOpaqueFieldProto) // Type checked in Handles
    66  
    67  	return &plainField{
    68  		baseField: baseField{
    69  			msg:   msg,
    70  			name:  fieldName,
    71  			fType: mapStringInterfaceType,
    72  			vType: bytesType,
    73  			value: fieldValue,
    74  		},
    75  		populateFrom: func(v interface{}, dT reflect.Type) (reflect.Value, error) {
    76  			return opaqueFrom(func() (proto.Message, error) { return opaqueProto.StaticallyOpaqueFieldProto(fieldName) }, v, dT)
    77  		},
    78  		populateTo: func(v reflect.Value) (interface{}, error) {
    79  			return opaqueTo(func() (proto.Message, error) { return opaqueProto.StaticallyOpaqueFieldProto(fieldName) }, v)
    80  		},
    81  	}, nil
    82  }
    83  
    84  type staticallyOpaqueMapFieldFactory struct{}
    85  
    86  func (soff staticallyOpaqueMapFieldFactory) Handles(msg proto.Message, fieldName string, fieldType reflect.Type, fieldValue reflect.Value) bool {
    87  	opaqueProto, ok := msg.(StaticallyOpaqueMapFieldProto)
    88  	if !ok {
    89  		return false
    90  	}
    91  
    92  	return stringInSlice(fieldName, opaqueProto.StaticallyOpaqueMapFields())
    93  }
    94  
    95  func (soff staticallyOpaqueMapFieldFactory) NewProtoField(msg proto.Message, fieldName string, fieldType reflect.Type, fieldValue reflect.Value) (protoField, error) {
    96  	opaqueProto := msg.(StaticallyOpaqueMapFieldProto) // Type checked in Handles
    97  
    98  	return &mapField{
    99  		baseField: baseField{
   100  			msg:   msg,
   101  			name:  fieldName,
   102  			fType: mapStringInterfaceType,
   103  			vType: fieldType,
   104  			value: fieldValue,
   105  		},
   106  		populateFrom: func(key string, v interface{}, dT reflect.Type) (reflect.Value, error) {
   107  			return opaqueFrom(func() (proto.Message, error) {
   108  				return opaqueProto.StaticallyOpaqueMapFieldProto(fieldName, key)
   109  			}, v, dT)
   110  		},
   111  		populateTo: func(key string, v reflect.Value) (interface{}, error) {
   112  			return opaqueTo(func() (proto.Message, error) {
   113  				return opaqueProto.StaticallyOpaqueMapFieldProto(fieldName, key)
   114  			}, v)
   115  		},
   116  	}, nil
   117  }
   118  
   119  type staticallyOpaqueSliceFieldFactory struct{}
   120  
   121  func (soff staticallyOpaqueSliceFieldFactory) Handles(msg proto.Message, fieldName string, fieldType reflect.Type, fieldValue reflect.Value) bool {
   122  	opaqueProto, ok := msg.(StaticallyOpaqueSliceFieldProto)
   123  	if !ok {
   124  		return false
   125  	}
   126  
   127  	return stringInSlice(fieldName, opaqueProto.StaticallyOpaqueSliceFields())
   128  }
   129  
   130  func (soff staticallyOpaqueSliceFieldFactory) NewProtoField(msg proto.Message, fieldName string, fieldType reflect.Type, fieldValue reflect.Value) (protoField, error) {
   131  	opaqueProto := msg.(StaticallyOpaqueSliceFieldProto) // Type checked in Handles
   132  
   133  	return &sliceField{
   134  		baseField: baseField{
   135  			msg:   msg,
   136  			name:  fieldName,
   137  			fType: mapStringInterfaceType,
   138  			vType: fieldType,
   139  			value: fieldValue,
   140  		},
   141  		populateFrom: func(index int, v interface{}, dT reflect.Type) (reflect.Value, error) {
   142  			return opaqueFrom(func() (proto.Message, error) {
   143  				return opaqueProto.StaticallyOpaqueSliceFieldProto(fieldName, index)
   144  			}, v, dT)
   145  		},
   146  		populateTo: func(index int, v reflect.Value) (interface{}, error) {
   147  			return opaqueTo(func() (proto.Message, error) {
   148  				return opaqueProto.StaticallyOpaqueSliceFieldProto(fieldName, index)
   149  			}, v)
   150  		},
   151  	}, nil
   152  }