github.com/cloudwego/kitex@v0.9.0/pkg/generic/generic.go (about)

     1  /*
     2   * Copyright 2021 CloudWeGo Authors
     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 generic ...
    18  package generic
    19  
    20  import (
    21  	"fmt"
    22  
    23  	"github.com/cloudwego/dynamicgo/conv"
    24  
    25  	"github.com/cloudwego/kitex/pkg/remote"
    26  	"github.com/cloudwego/kitex/pkg/remote/codec/protobuf"
    27  	"github.com/cloudwego/kitex/pkg/remote/codec/thrift"
    28  	"github.com/cloudwego/kitex/pkg/serviceinfo"
    29  )
    30  
    31  // Generic ...
    32  type Generic interface {
    33  	Closer
    34  	// PayloadCodec return codec implement
    35  	PayloadCodec() remote.PayloadCodec
    36  	// PayloadCodecType return the type of codec
    37  	PayloadCodecType() serviceinfo.PayloadCodec
    38  	// RawThriftBinaryGeneric must be framed
    39  	Framed() bool
    40  	// GetMethod to get method name if need
    41  	GetMethod(req interface{}, method string) (*Method, error)
    42  }
    43  
    44  // Method information
    45  type Method struct {
    46  	Name   string
    47  	Oneway bool
    48  }
    49  
    50  // BinaryThriftGeneric raw thrift binary Generic
    51  func BinaryThriftGeneric() Generic {
    52  	return &binaryThriftGeneric{}
    53  }
    54  
    55  // MapThriftGeneric map mapping generic
    56  // Base64 codec for binary field is disabled by default. You can change this option with SetBinaryWithBase64.
    57  // eg:
    58  //
    59  //	g, err := generic.MapThriftGeneric(p)
    60  //	SetBinaryWithBase64(g, true)
    61  //
    62  // String value is returned for binary field by default. You can change the return value to []byte for binary field with SetBinaryWithByteSlice.
    63  // eg:
    64  //
    65  //	SetBinaryWithByteSlice(g, true)
    66  func MapThriftGeneric(p DescriptorProvider) (Generic, error) {
    67  	codec, err := newMapThriftCodec(p, thriftCodec)
    68  	if err != nil {
    69  		return nil, err
    70  	}
    71  	return &mapThriftGeneric{
    72  		codec: codec,
    73  	}, nil
    74  }
    75  
    76  func MapThriftGenericForJSON(p DescriptorProvider) (Generic, error) {
    77  	codec, err := newMapThriftCodecForJSON(p, thriftCodec)
    78  	if err != nil {
    79  		return nil, err
    80  	}
    81  	return &mapThriftGeneric{
    82  		codec: codec,
    83  	}, nil
    84  }
    85  
    86  // HTTPThriftGeneric http mapping Generic.
    87  // Base64 codec for binary field is disabled by default. You can change this option with SetBinaryWithBase64.
    88  // eg:
    89  //
    90  //	g, err := generic.HTTPThriftGeneric(p)
    91  //	SetBinaryWithBase64(g, true)
    92  func HTTPThriftGeneric(p DescriptorProvider, opts ...Option) (Generic, error) {
    93  	gOpts := &Options{dynamicgoConvOpts: DefaultHTTPDynamicGoConvOpts}
    94  	gOpts.apply(opts)
    95  	codec, err := newHTTPThriftCodec(p, thriftCodec, gOpts)
    96  	if err != nil {
    97  		return nil, err
    98  	}
    99  	return &httpThriftGeneric{codec: codec}, nil
   100  }
   101  
   102  func HTTPPbThriftGeneric(p DescriptorProvider, pbp PbDescriptorProvider) (Generic, error) {
   103  	codec, err := newHTTPPbThriftCodec(p, pbp, thriftCodec)
   104  	if err != nil {
   105  		return nil, err
   106  	}
   107  	return &httpPbThriftGeneric{
   108  		codec: codec,
   109  	}, nil
   110  }
   111  
   112  // JSONThriftGeneric json mapping generic.
   113  // Base64 codec for binary field is enabled by default. You can change this option with SetBinaryWithBase64.
   114  // eg:
   115  //
   116  //	g, err := generic.JSONThriftGeneric(p)
   117  //	SetBinaryWithBase64(g, false)
   118  func JSONThriftGeneric(p DescriptorProvider, opts ...Option) (Generic, error) {
   119  	gOpts := &Options{dynamicgoConvOpts: DefaultJSONDynamicGoConvOpts}
   120  	gOpts.apply(opts)
   121  	codec, err := newJsonThriftCodec(p, thriftCodec, gOpts)
   122  	if err != nil {
   123  		return nil, err
   124  	}
   125  	return &jsonThriftGeneric{codec: codec}, nil
   126  }
   127  
   128  // JSONPbGeneric json mapping generic.
   129  // Uses dynamicgo for json to protobufs conversion, so DynamicGo field is true by default.
   130  func JSONPbGeneric(p PbDescriptorProviderDynamicGo, opts ...Option) (Generic, error) {
   131  	gOpts := &Options{dynamicgoConvOpts: conv.Options{}}
   132  	gOpts.apply(opts)
   133  
   134  	codec, err := newJsonPbCodec(p, pbCodec, gOpts)
   135  	if err != nil {
   136  		return nil, err
   137  	}
   138  	return &jsonPbGeneric{codec: codec}, nil
   139  }
   140  
   141  // SetBinaryWithBase64 enable/disable Base64 codec for binary field.
   142  func SetBinaryWithBase64(g Generic, enable bool) error {
   143  	switch c := g.(type) {
   144  	case *httpThriftGeneric:
   145  		if c.codec == nil {
   146  			return fmt.Errorf("empty codec for %#v", c)
   147  		}
   148  		c.codec.binaryWithBase64 = enable
   149  		if c.codec.dynamicgoEnabled {
   150  			c.codec.convOpts.NoBase64Binary = !enable
   151  			c.codec.convOptsWithThriftBase.NoBase64Binary = !enable
   152  		}
   153  	case *jsonThriftGeneric:
   154  		if c.codec == nil {
   155  			return fmt.Errorf("empty codec for %#v", c)
   156  		}
   157  		c.codec.binaryWithBase64 = enable
   158  		if c.codec.dynamicgoEnabled {
   159  			c.codec.convOpts.NoBase64Binary = !enable
   160  			c.codec.convOptsWithThriftBase.NoBase64Binary = !enable
   161  			c.codec.convOptsWithException.NoBase64Binary = !enable
   162  		}
   163  	case *mapThriftGeneric:
   164  		if c.codec == nil {
   165  			return fmt.Errorf("empty codec for %#v", c)
   166  		}
   167  		c.codec.binaryWithBase64 = enable
   168  	default:
   169  		return fmt.Errorf("Base64Binary is unavailable for %#v", g)
   170  	}
   171  	return nil
   172  }
   173  
   174  // SetBinaryWithByteSlice enable/disable returning []byte for binary field.
   175  func SetBinaryWithByteSlice(g Generic, enable bool) error {
   176  	switch c := g.(type) {
   177  	case *mapThriftGeneric:
   178  		if c.codec == nil {
   179  			return fmt.Errorf("empty codec for %#v", c)
   180  		}
   181  		c.codec.binaryWithByteSlice = enable
   182  	default:
   183  		return fmt.Errorf("returning []byte for binary fields is unavailable for %#v", g)
   184  	}
   185  	return nil
   186  }
   187  
   188  var thriftCodec = thrift.NewThriftCodec()
   189  
   190  var pbCodec = protobuf.NewProtobufCodec()
   191  
   192  type binaryThriftGeneric struct{}
   193  
   194  func (g *binaryThriftGeneric) Framed() bool {
   195  	return true
   196  }
   197  
   198  func (g *binaryThriftGeneric) PayloadCodecType() serviceinfo.PayloadCodec {
   199  	return serviceinfo.Thrift
   200  }
   201  
   202  func (g *binaryThriftGeneric) PayloadCodec() remote.PayloadCodec {
   203  	pc := &binaryThriftCodec{thriftCodec}
   204  	return pc
   205  }
   206  
   207  func (g *binaryThriftGeneric) GetMethod(req interface{}, method string) (*Method, error) {
   208  	return &Method{method, false}, nil
   209  }
   210  
   211  func (g *binaryThriftGeneric) Close() error {
   212  	return nil
   213  }
   214  
   215  type mapThriftGeneric struct {
   216  	codec *mapThriftCodec
   217  }
   218  
   219  func (g *mapThriftGeneric) Framed() bool {
   220  	return false
   221  }
   222  
   223  func (g *mapThriftGeneric) PayloadCodecType() serviceinfo.PayloadCodec {
   224  	return serviceinfo.Thrift
   225  }
   226  
   227  func (g *mapThriftGeneric) PayloadCodec() remote.PayloadCodec {
   228  	return g.codec
   229  }
   230  
   231  func (g *mapThriftGeneric) GetMethod(req interface{}, method string) (*Method, error) {
   232  	return g.codec.getMethod(req, method)
   233  }
   234  
   235  func (g *mapThriftGeneric) Close() error {
   236  	return g.codec.Close()
   237  }
   238  
   239  type jsonThriftGeneric struct {
   240  	codec *jsonThriftCodec
   241  }
   242  
   243  func (g *jsonThriftGeneric) Framed() bool {
   244  	return g.codec.dynamicgoEnabled
   245  }
   246  
   247  func (g *jsonThriftGeneric) PayloadCodecType() serviceinfo.PayloadCodec {
   248  	return serviceinfo.Thrift
   249  }
   250  
   251  func (g *jsonThriftGeneric) PayloadCodec() remote.PayloadCodec {
   252  	return g.codec
   253  }
   254  
   255  func (g *jsonThriftGeneric) GetMethod(req interface{}, method string) (*Method, error) {
   256  	return g.codec.getMethod(req, method)
   257  }
   258  
   259  func (g *jsonThriftGeneric) Close() error {
   260  	return g.codec.Close()
   261  }
   262  
   263  type jsonPbGeneric struct {
   264  	codec *jsonPbCodec
   265  }
   266  
   267  func (g *jsonPbGeneric) Framed() bool {
   268  	return false
   269  }
   270  
   271  func (g *jsonPbGeneric) PayloadCodecType() serviceinfo.PayloadCodec {
   272  	return serviceinfo.Protobuf
   273  }
   274  
   275  func (g *jsonPbGeneric) PayloadCodec() remote.PayloadCodec {
   276  	return g.codec
   277  }
   278  
   279  func (g *jsonPbGeneric) GetMethod(req interface{}, method string) (*Method, error) {
   280  	return g.codec.getMethod(req, method)
   281  }
   282  
   283  func (g *jsonPbGeneric) Close() error {
   284  	return g.codec.Close()
   285  }
   286  
   287  type httpThriftGeneric struct {
   288  	codec *httpThriftCodec
   289  }
   290  
   291  func (g *httpThriftGeneric) Framed() bool {
   292  	return g.codec.dynamicgoEnabled
   293  }
   294  
   295  func (g *httpThriftGeneric) PayloadCodecType() serviceinfo.PayloadCodec {
   296  	return serviceinfo.Thrift
   297  }
   298  
   299  func (g *httpThriftGeneric) PayloadCodec() remote.PayloadCodec {
   300  	return g.codec
   301  }
   302  
   303  func (g *httpThriftGeneric) GetMethod(req interface{}, method string) (*Method, error) {
   304  	return g.codec.getMethod(req)
   305  }
   306  
   307  func (g *httpThriftGeneric) Close() error {
   308  	return g.codec.Close()
   309  }
   310  
   311  type httpPbThriftGeneric struct {
   312  	codec *httpPbThriftCodec
   313  }
   314  
   315  func (g *httpPbThriftGeneric) Framed() bool {
   316  	return false
   317  }
   318  
   319  func (g *httpPbThriftGeneric) PayloadCodecType() serviceinfo.PayloadCodec {
   320  	return serviceinfo.Thrift
   321  }
   322  
   323  func (g *httpPbThriftGeneric) PayloadCodec() remote.PayloadCodec {
   324  	return g.codec
   325  }
   326  
   327  func (g *httpPbThriftGeneric) GetMethod(req interface{}, method string) (*Method, error) {
   328  	return g.codec.getMethod(req)
   329  }
   330  
   331  func (g *httpPbThriftGeneric) Close() error {
   332  	return g.codec.Close()
   333  }