github.com/cloudwego/dynamicgo@v0.2.6-0.20240519101509-707f41b6b834/conv/t2j/conv.go (about)

     1  /**
     2   * Copyright 2023 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 t2j
    18  
    19  import (
    20  	"context"
    21  
    22  	"github.com/cloudwego/dynamicgo/conv"
    23  	"github.com/cloudwego/dynamicgo/http"
    24  	"github.com/cloudwego/dynamicgo/meta"
    25  	"github.com/cloudwego/dynamicgo/thrift"
    26  	_ "github.com/cloudwego/dynamicgo/thrift/annotation"
    27  )
    28  
    29  // BinaryConv is a converter from thrift binary to json
    30  type BinaryConv struct {
    31  	opts conv.Options
    32  }
    33  
    34  // NewBinaryConv returns a new BinaryConv
    35  func NewBinaryConv(opts conv.Options) BinaryConv {
    36  	return BinaryConv{opts: opts}
    37  }
    38  
    39  // SetOptions sets options
    40  func (self *BinaryConv) SetOptions(opts conv.Options) {
    41  	self.opts = opts
    42  }
    43  
    44  // Do converts thrift binary (tbytes) to json bytes (jbytes)
    45  //
    46  // desc is the thrift type descriptor of the thrift binary, usually it is a response STRUCT type
    47  // ctx is the context, which can be used to pass arguments as below:
    48  //     - conv.CtxKeyHTTPResponse: http.ResponseSetter as http request
    49  //     - conv.CtxKeyThriftRespBase: thrift.Base as base metadata of thrift response
    50  func (self *BinaryConv) Do(ctx context.Context, desc *thrift.TypeDescriptor, tbytes []byte) (json []byte, err error) {
    51  	buf := conv.NewBytes()
    52  
    53  	var resp http.ResponseSetter
    54  	if self.opts.EnableHttpMapping {
    55  		respi := ctx.Value(conv.CtxKeyHTTPResponse)
    56  		if respi != nil {
    57  			respi, ok := respi.(http.ResponseSetter)
    58  			if !ok {
    59  				return nil, wrapError(meta.ErrInvalidParam, "invalid http.Response", nil)
    60  			}
    61  			resp = respi
    62  		} else {
    63  			return nil, wrapError(meta.ErrInvalidParam, "no http response in context", nil)
    64  		}
    65  	}
    66  
    67  	err = self.do(ctx, tbytes, desc, buf, resp)
    68  	if err == nil && len(*buf) > 0 {
    69  		json = make([]byte, len(*buf))
    70  		copy(json, *buf)
    71  	}
    72  
    73  	conv.FreeBytes(buf)
    74  	return
    75  }
    76  
    77  // DoInto behaves like Do, but it writes the result to buffer directly instead of returning a new buffer
    78  func (self *BinaryConv) DoInto(ctx context.Context, desc *thrift.TypeDescriptor, tbytes []byte, buf *[]byte) (err error) {
    79  	var resp http.ResponseSetter
    80  	if self.opts.EnableHttpMapping {
    81  		respi := ctx.Value(conv.CtxKeyHTTPResponse)
    82  		if respi != nil {
    83  			respi, ok := respi.(http.ResponseSetter)
    84  			if !ok {
    85  				return wrapError(meta.ErrInvalidParam, "invalid http.Response", nil)
    86  			}
    87  			resp = respi
    88  		} else {
    89  			return wrapError(meta.ErrInvalidParam, "no http response in context", nil)
    90  		}
    91  	}
    92  
    93  	return self.do(ctx, tbytes, desc, buf, resp)
    94  }