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

     1  package p2j
     2  
     3  import (
     4  	"context"
     5  
     6  	"github.com/cloudwego/dynamicgo/conv"
     7  	"github.com/cloudwego/dynamicgo/http"
     8  	"github.com/cloudwego/dynamicgo/meta"
     9  	"github.com/cloudwego/dynamicgo/proto"
    10  )
    11  
    12  type BinaryConv struct {
    13  	opts conv.Options
    14  }
    15  
    16  // NewBinaryConv returns a new BinaryConv
    17  func NewBinaryConv(opts conv.Options) BinaryConv {
    18  	return BinaryConv{opts: opts}
    19  }
    20  
    21  // SetOptions sets options
    22  func (self *BinaryConv) SetOptions(opts conv.Options) {
    23  	self.opts = opts
    24  }
    25  
    26  // Do converts protobuf binary (pbytes) to json bytes (jbytes)
    27  // desc is the protobuf type descriptor of the protobuf binary, usually it is a response Message type
    28  func (self *BinaryConv) Do(ctx context.Context, desc *proto.TypeDescriptor, pbytes []byte) (json []byte, err error) {
    29  	buf := conv.NewBytes()
    30  
    31  	// resp alloc but not use
    32  	var resp http.ResponseSetter
    33  	if self.opts.EnableHttpMapping {
    34  		respi := ctx.Value(conv.CtxKeyHTTPResponse)
    35  		if respi != nil {
    36  			respi, ok := respi.(http.ResponseSetter)
    37  			if !ok {
    38  				return nil, wrapError(meta.ErrInvalidParam, "invalid http.Response", nil)
    39  			}
    40  			resp = respi
    41  		} else {
    42  			return nil, wrapError(meta.ErrInvalidParam, "no http response in context", nil)
    43  		}
    44  	}
    45  
    46  	err = self.do(ctx, pbytes, desc, buf, resp)
    47  	if err == nil && len(*buf) > 0 {
    48  		json = make([]byte, len(*buf))
    49  		copy(json, *buf)
    50  	}
    51  
    52  	conv.FreeBytes(buf)
    53  	return
    54  }
    55  
    56  // DoInto behaves like Do, but it writes the result to buffer directly instead of returning a new buffer
    57  func (self *BinaryConv) DoInto(ctx context.Context, desc *proto.TypeDescriptor, pbytes []byte, buf *[]byte) (err error) {
    58  	// resp alloc but not use
    59  	var resp http.ResponseSetter
    60  	if self.opts.EnableHttpMapping {
    61  		respi := ctx.Value(conv.CtxKeyHTTPResponse)
    62  		if respi != nil {
    63  			respi, ok := respi.(http.ResponseSetter)
    64  			if !ok {
    65  				return wrapError(meta.ErrInvalidParam, "invalid http.Response", nil)
    66  			}
    67  			resp = respi
    68  		} else {
    69  			return wrapError(meta.ErrInvalidParam, "no http response in context", nil)
    70  		}
    71  	}
    72  
    73  	return self.do(ctx, pbytes, desc, buf, resp)
    74  }