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 }