github.com/tickoalcantara12/micro/v3@v3.0.0-20221007104245-9d75b9bcbab9/service/client/grpc/codec.go (about)

     1  // Copyright 2020 Asim Aslam
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use this file except in compliance with the License.
     5  // You may obtain a copy of the License at
     6  //
     7  //     https://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS,
    11  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    12  // See the License for the specific language governing permissions and
    13  // limitations under the License.
    14  //
    15  // Original source: github.com/micro/go-micro/v3/client/grpc/codec.go
    16  
    17  package grpc
    18  
    19  import (
    20  	"encoding/json"
    21  	"fmt"
    22  	"strings"
    23  
    24  	b "bytes"
    25  
    26  	"github.com/golang/protobuf/jsonpb"
    27  	"github.com/golang/protobuf/proto"
    28  	"github.com/tickoalcantara12/micro/v3/util/codec"
    29  	"github.com/tickoalcantara12/micro/v3/util/codec/bytes"
    30  	"github.com/oxtoacart/bpool"
    31  	"google.golang.org/grpc"
    32  	"google.golang.org/grpc/encoding"
    33  )
    34  
    35  type jsonCodec struct{}
    36  type protoCodec struct{}
    37  type bytesCodec struct{}
    38  type wrapCodec struct{ encoding.Codec }
    39  
    40  var jsonpbMarshaler = &jsonpb.Marshaler{
    41  	EmitDefaults: true,
    42  }
    43  var useNumber bool
    44  
    45  // create buffer pool with 16 instances each preallocated with 256 bytes
    46  var bufferPool = bpool.NewSizedBufferPool(16, 256)
    47  
    48  var (
    49  	defaultGRPCCodecs = map[string]encoding.Codec{
    50  		"application/json":         jsonCodec{},
    51  		"application/proto":        protoCodec{},
    52  		"application/protobuf":     protoCodec{},
    53  		"application/octet-stream": protoCodec{},
    54  		"application/grpc":         protoCodec{},
    55  		"application/grpc+json":    jsonCodec{},
    56  		"application/grpc+proto":   protoCodec{},
    57  		"application/grpc+bytes":   bytesCodec{},
    58  		"multipart/form-data":      jsonCodec{},
    59  	}
    60  )
    61  
    62  // UseNumber fix unmarshal Number(8234567890123456789) to interface(8.234567890123457e+18)
    63  func UseNumber() {
    64  	useNumber = true
    65  }
    66  
    67  func (w wrapCodec) String() string {
    68  	return w.Codec.Name()
    69  }
    70  
    71  func (w wrapCodec) Marshal(v interface{}) ([]byte, error) {
    72  	b, ok := v.(*bytes.Frame)
    73  	if ok {
    74  		return b.Data, nil
    75  	}
    76  	return w.Codec.Marshal(v)
    77  }
    78  
    79  func (w wrapCodec) Unmarshal(data []byte, v interface{}) error {
    80  	b, ok := v.(*bytes.Frame)
    81  	if ok {
    82  		b.Data = data
    83  		return nil
    84  	}
    85  	return w.Codec.Unmarshal(data, v)
    86  }
    87  
    88  func (protoCodec) Marshal(v interface{}) ([]byte, error) {
    89  	switch m := v.(type) {
    90  	case *bytes.Frame:
    91  		return m.Data, nil
    92  	case proto.Message:
    93  		return proto.Marshal(m)
    94  	}
    95  	return nil, fmt.Errorf("failed to marshal: %v is not type of *bytes.Frame or proto.Message", v)
    96  }
    97  
    98  func (protoCodec) Unmarshal(data []byte, v interface{}) error {
    99  	m, ok := v.(proto.Message)
   100  	if !ok {
   101  		return fmt.Errorf("failed to unmarshal: %v is not type of proto.Message", v)
   102  	}
   103  	return proto.Unmarshal(data, m)
   104  }
   105  
   106  func (protoCodec) Name() string {
   107  	return "proto"
   108  }
   109  
   110  func (bytesCodec) Marshal(v interface{}) ([]byte, error) {
   111  	b, ok := v.(*[]byte)
   112  	if !ok {
   113  		return nil, fmt.Errorf("failed to marshal: %v is not type of *[]byte", v)
   114  	}
   115  	return *b, nil
   116  }
   117  
   118  func (bytesCodec) Unmarshal(data []byte, v interface{}) error {
   119  	b, ok := v.(*[]byte)
   120  	if !ok {
   121  		return fmt.Errorf("failed to unmarshal: %v is not type of *[]byte", v)
   122  	}
   123  	*b = data
   124  	return nil
   125  }
   126  
   127  func (bytesCodec) Name() string {
   128  	return "bytes"
   129  }
   130  
   131  func (jsonCodec) Marshal(v interface{}) ([]byte, error) {
   132  	if b, ok := v.(*bytes.Frame); ok {
   133  		return b.Data, nil
   134  	}
   135  
   136  	if pb, ok := v.(proto.Message); ok {
   137  		buf := bufferPool.Get()
   138  		defer bufferPool.Put(buf)
   139  		if err := jsonpbMarshaler.Marshal(buf, pb); err != nil {
   140  			return nil, err
   141  		}
   142  		return buf.Bytes(), nil
   143  	}
   144  
   145  	return json.Marshal(v)
   146  }
   147  
   148  func (jsonCodec) Unmarshal(data []byte, v interface{}) error {
   149  	if len(data) == 0 {
   150  		return nil
   151  	}
   152  	if b, ok := v.(*bytes.Frame); ok {
   153  		b.Data = data
   154  		return nil
   155  	}
   156  	if pb, ok := v.(proto.Message); ok {
   157  		return jsonpb.Unmarshal(b.NewReader(data), pb)
   158  	}
   159  
   160  	dec := json.NewDecoder(b.NewReader(data))
   161  	if useNumber {
   162  		dec.UseNumber()
   163  	}
   164  	return dec.Decode(v)
   165  }
   166  
   167  func (jsonCodec) Name() string {
   168  	return "json"
   169  }
   170  
   171  type grpcCodec struct {
   172  	// headers
   173  	id       string
   174  	target   string
   175  	method   string
   176  	endpoint string
   177  
   178  	s grpc.ClientStream
   179  	c encoding.Codec
   180  }
   181  
   182  func (g *grpcCodec) ReadHeader(m *codec.Message, mt codec.MessageType) error {
   183  	md, err := g.s.Header()
   184  	if err != nil {
   185  		return err
   186  	}
   187  	if m == nil {
   188  		m = new(codec.Message)
   189  	}
   190  	if m.Header == nil {
   191  		m.Header = make(map[string]string, len(md))
   192  	}
   193  	for k, v := range md {
   194  		m.Header[k] = strings.Join(v, ",")
   195  	}
   196  	m.Id = g.id
   197  	m.Target = g.target
   198  	m.Method = g.method
   199  	m.Endpoint = g.endpoint
   200  	return nil
   201  }
   202  
   203  func (g *grpcCodec) ReadBody(v interface{}) error {
   204  	if f, ok := v.(*bytes.Frame); ok {
   205  		return g.s.RecvMsg(f)
   206  	}
   207  	return g.s.RecvMsg(v)
   208  }
   209  
   210  func (g *grpcCodec) Write(m *codec.Message, v interface{}) error {
   211  	// if we don't have a body
   212  	if v != nil {
   213  		return g.s.SendMsg(v)
   214  	}
   215  	// write the body using the framing codec
   216  	return g.s.SendMsg(&bytes.Frame{Data: m.Body})
   217  }
   218  
   219  func (g *grpcCodec) Close() error {
   220  	return g.s.CloseSend()
   221  }
   222  
   223  func (g *grpcCodec) String() string {
   224  	return g.c.Name()
   225  }