github.com/cloudwego/dynamicgo@v0.2.6-0.20240519101509-707f41b6b834/conv/t2j/impl.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  	"errors"
    22  	"fmt"
    23  
    24  	"github.com/cloudwego/dynamicgo/conv"
    25  	"github.com/cloudwego/dynamicgo/http"
    26  	"github.com/cloudwego/dynamicgo/internal/json"
    27  	"github.com/cloudwego/dynamicgo/internal/primitive"
    28  	"github.com/cloudwego/dynamicgo/internal/rt"
    29  	"github.com/cloudwego/dynamicgo/meta"
    30  	"github.com/cloudwego/dynamicgo/thrift"
    31  	"github.com/cloudwego/dynamicgo/thrift/base"
    32  )
    33  
    34  const (
    35  	_GUARD_SLICE_FACTOR = 2
    36  )
    37  
    38  //go:noinline
    39  func wrapError(code meta.ErrCode, msg string, err error) error {
    40  	// panic(meta.NewError(meta.NewErrorCode(code, meta.THRIFT2JSON), msg, err))
    41  	return meta.NewError(meta.NewErrorCode(code, meta.THRIFT2JSON), msg, err)
    42  }
    43  
    44  //go:noinline
    45  func unwrapError(msg string, err error) error {
    46  	if v, ok := err.(meta.Error); ok {
    47  		return wrapError(v.Code, msg, err)
    48  	} else {
    49  		return wrapError(meta.ErrConvert, msg, err)
    50  	}
    51  }
    52  
    53  func (self *BinaryConv) readResponseBase(ctx context.Context, p *thrift.BinaryProtocol) (bool, error) {
    54  	obj := ctx.Value(conv.CtxKeyThriftRespBase)
    55  	if obj == nil {
    56  		return false, nil
    57  	}
    58  	base, ok := obj.(*base.BaseResp)
    59  	if !ok || base == nil {
    60  		return false, wrapError(meta.ErrInvalidParam, "invalid response base", nil)
    61  	}
    62  	s := p.Read
    63  	if err := p.Skip(thrift.STRUCT, self.opts.UseNativeSkip); err != nil {
    64  		return false, wrapError(meta.ErrRead, "", err)
    65  	}
    66  	e := p.Read
    67  	if _, err := base.FastRead(p.Buf[s:e]); err != nil {
    68  		return false, wrapError(meta.ErrRead, "", err)
    69  	}
    70  	return true, nil
    71  }
    72  
    73  func (self *BinaryConv) do(ctx context.Context, src []byte, desc *thrift.TypeDescriptor, out *[]byte, resp http.ResponseSetter) (err error) {
    74  	//NOTICE: output buffer must be larger than src buffer
    75  	rt.GuardSlice(out, len(src)*_GUARD_SLICE_FACTOR)
    76  	
    77  	var p = thrift.BinaryProtocol{
    78  		Buf: src,
    79  	}
    80  
    81  	if desc.Type() != thrift.STRUCT {
    82  		return self.doRecurse(ctx, desc, out, resp, &p)
    83  	}
    84  
    85  	_, e := p.ReadStructBegin()
    86  	if e != nil {
    87  		return wrapError(meta.ErrRead, "", e)
    88  	}
    89  	*out = json.EncodeObjectBegin(*out)
    90  
    91  	r := thrift.NewRequiresBitmap()
    92  	desc.Struct().Requires().CopyTo(r)
    93  	comma := false
    94  
    95  	existExceptionField := false
    96  
    97  	for {
    98  		_, typeId, id, e := p.ReadFieldBegin()
    99  		if e != nil {
   100  			return wrapError(meta.ErrRead, "", e)
   101  		}
   102  		if typeId == thrift.STOP {
   103  			break
   104  		}
   105  
   106  		field := desc.Struct().FieldById(thrift.FieldID(id))
   107  		if field == nil {
   108  			if self.opts.DisallowUnknownField {
   109  				return wrapError(meta.ErrUnknownField, fmt.Sprintf("unknown field %d", id), nil)
   110  			}
   111  			if e := p.Skip(typeId, self.opts.UseNativeSkip); e != nil {
   112  				return wrapError(meta.ErrRead, "", e)
   113  			}
   114  			continue
   115  		}
   116  
   117  		r.Set(field.ID(), thrift.OptionalRequireness)
   118  
   119  		if self.opts.EnableThriftBase && field.IsResponseBase() {
   120  			skip, err := self.readResponseBase(ctx, &p)
   121  			if err != nil {
   122  				return err
   123  			}
   124  			if skip {
   125  				continue
   126  			}
   127  		}
   128  
   129  		restart := p.Read
   130  
   131  		if resp != nil && self.opts.EnableHttpMapping && field.HTTPMappings() != nil {
   132  			ok, err := self.writeHttpValue(ctx, resp, &p, field)
   133  			if err != nil {
   134  				return unwrapError(fmt.Sprintf("mapping field %s of STRUCT %s failed", field.Name(), desc.Name()), err)
   135  			}
   136  			// NOTICE: if option HttpMappingAsExtra is false and http-mapping failed,
   137  			// continue to write to json body
   138  			if !self.opts.WriteHttpValueFallback || ok {
   139  				continue
   140  			}
   141  		}
   142  
   143  		p.Read = restart
   144  		if comma {
   145  			*out = json.EncodeObjectComma(*out)
   146  		} else {
   147  			comma = true
   148  		}
   149  		// NOTICE: always use field.Alias() here, because alias equals to name by default
   150  		*out = json.EncodeString(*out, field.Alias())
   151  		*out = json.EncodeObjectColon(*out)
   152  
   153  		// handle a thrift exception field. the id of a thrift exception field is non-zero
   154  		if self.opts.ConvertException && id != 0 {
   155  			existExceptionField = true
   156  			// reset out to get only exception field data
   157  			*out = (*out)[:0]
   158  		}
   159  
   160  		if self.opts.EnableValueMapping && field.ValueMapping() != nil {
   161  			err = field.ValueMapping().Read(ctx, &p, field, out)
   162  			if err != nil {
   163  				return unwrapError(fmt.Sprintf("mapping field %s of STRUCT %s failed", field.Name(), desc.Type()), err)
   164  			}
   165  		} else {
   166  			err = self.doRecurse(ctx, field.Type(), out, resp, &p)
   167  			if err != nil {
   168  				return unwrapError(fmt.Sprintf("converting field %s of STRUCT %s failed", field.Name(), desc.Type()), err)
   169  			}
   170  		}
   171  
   172  		if existExceptionField {
   173  			break
   174  		}
   175  	}
   176  
   177  	if err = self.handleUnsets(r, desc.Struct(), out, comma, ctx, resp); err != nil {
   178  		return err
   179  	}
   180  
   181  	thrift.FreeRequiresBitmap(r)
   182  	if existExceptionField && err == nil {
   183  		err = errors.New(string(*out))
   184  	} else {
   185  		*out = json.EncodeObjectEnd(*out)
   186  	}
   187  	return err
   188  }
   189  
   190  func (self *BinaryConv) doRecurse(ctx context.Context, desc *thrift.TypeDescriptor, out *[]byte, resp http.ResponseSetter, p *thrift.BinaryProtocol) (err error) {
   191  	tt := desc.Type()
   192  	switch tt {
   193  	case thrift.BOOL:
   194  		v, e := p.ReadBool()
   195  		if e != nil {
   196  			return wrapError(meta.ErrRead, "", e)
   197  		}
   198  		*out = json.EncodeBool(*out, v)
   199  	case thrift.BYTE:
   200  		v, e := p.ReadByte()
   201  		if e != nil {
   202  			return wrapError(meta.ErrWrite, "", e)
   203  		}
   204  		if self.opts.ByteAsUint8 {
   205  			*out = json.EncodeInt64(*out, int64(uint8(v)))
   206  		} else {
   207  			*out = json.EncodeInt64(*out, int64(int8(v)))
   208  		}
   209  	case thrift.I16:
   210  		v, e := p.ReadI16()
   211  		if e != nil {
   212  			return wrapError(meta.ErrWrite, "", e)
   213  		}
   214  		*out = json.EncodeInt64(*out, int64(v))
   215  	case thrift.I32:
   216  		v, e := p.ReadI32()
   217  		if e != nil {
   218  			return wrapError(meta.ErrWrite, "", e)
   219  		}
   220  		*out = json.EncodeInt64(*out, int64(v))
   221  	case thrift.I64:
   222  		v, e := p.ReadI64()
   223  		if e != nil {
   224  			return wrapError(meta.ErrWrite, "", e)
   225  		}
   226  		if self.opts.Int642String {
   227  			*out = append(*out, '"')
   228  			*out = json.EncodeInt64(*out, int64(v))
   229  			*out = append(*out, '"')
   230  		} else {
   231  			*out = json.EncodeInt64(*out, int64(v))
   232  		}
   233  	case thrift.DOUBLE:
   234  		v, e := p.ReadDouble()
   235  		if e != nil {
   236  			return wrapError(meta.ErrWrite, "", e)
   237  		}
   238  		*out = json.EncodeFloat64(*out, float64(v))
   239  	case thrift.STRING:
   240  		if desc.IsBinary() && !self.opts.NoBase64Binary {
   241  			v, e := p.ReadBinary(false)
   242  			if e != nil {
   243  				return wrapError(meta.ErrRead, "", e)
   244  			}
   245  			*out = json.EncodeBaniry(*out, v)
   246  		} else {
   247  			v, e := p.ReadString(false)
   248  			if e != nil {
   249  				return wrapError(meta.ErrRead, "", e)
   250  			}
   251  			*out = json.EncodeString(*out, v)
   252  		}
   253  	case thrift.STRUCT:
   254  		_, e := p.ReadStructBegin()
   255  		if e != nil {
   256  			return wrapError(meta.ErrRead, "", e)
   257  		}
   258  		*out = json.EncodeObjectBegin(*out)
   259  
   260  		r := thrift.NewRequiresBitmap()
   261  		desc.Struct().Requires().CopyTo(r)
   262  		comma := false
   263  
   264  		for {
   265  			_, typeId, id, e := p.ReadFieldBegin()
   266  			if e != nil {
   267  				return wrapError(meta.ErrRead, "", e)
   268  			}
   269  			if typeId == 0 {
   270  				break
   271  			}
   272  
   273  			field := desc.Struct().FieldById(thrift.FieldID(id))
   274  			if field == nil {
   275  				if self.opts.DisallowUnknownField {
   276  					return wrapError(meta.ErrUnknownField, fmt.Sprintf("unknown field %d", id), nil)
   277  				}
   278  				if e := p.Skip(typeId, self.opts.UseNativeSkip); e != nil {
   279  					return wrapError(meta.ErrRead, "", e)
   280  				}
   281  				continue
   282  			}
   283  
   284  			r.Set(field.ID(), thrift.OptionalRequireness)
   285  			restart := p.Read
   286  
   287  			if resp != nil && self.opts.EnableHttpMapping && field.HTTPMappings() != nil {
   288  				ok, err := self.writeHttpValue(ctx, resp, p, field)
   289  				if err != nil {
   290  					return unwrapError(fmt.Sprintf("mapping field %s of STRUCT %s failed", field.Name(), desc.Name()), err)
   291  				}
   292  				// NOTICE: if option HttpMappingAsExtra is false and http-mapping failed,
   293  				// continue to write to json body
   294  				if !self.opts.WriteHttpValueFallback || ok {
   295  					continue
   296  				}
   297  			}
   298  
   299  			// HttpMappingAsExtra is true, return to begining and write json body
   300  			p.Read = restart
   301  			if comma {
   302  				*out = json.EncodeObjectComma(*out)
   303  				if err != nil {
   304  					return wrapError(meta.ErrWrite, "", err)
   305  				}
   306  			} else {
   307  				comma = true
   308  			}
   309  			// NOTICE: always use field.Alias() here, because alias equals to name by default
   310  			*out = json.EncodeString(*out, field.Alias())
   311  			*out = json.EncodeObjectColon(*out)
   312  
   313  			if self.opts.EnableValueMapping && field.ValueMapping() != nil {
   314  				if err = field.ValueMapping().Read(ctx, p, field, out); err != nil {
   315  					return unwrapError(fmt.Sprintf("mapping field %s of STRUCT %s failed", field.Name(), desc.Type()), err)
   316  				}
   317  			} else {
   318  				err = self.doRecurse(ctx, field.Type(), out, nil, p)
   319  				if err != nil {
   320  					return unwrapError(fmt.Sprintf("converting field %s of STRUCT %s failed", field.Name(), desc.Type()), err)
   321  				}
   322  			}
   323  		}
   324  
   325  		if err = self.handleUnsets(r, desc.Struct(), out, comma, ctx, resp); err != nil {
   326  			return err
   327  		}
   328  
   329  		thrift.FreeRequiresBitmap(r)
   330  		*out = json.EncodeObjectEnd(*out)
   331  	case thrift.MAP:
   332  		keyType, valueType, size, e := p.ReadMapBegin()
   333  		if e != nil {
   334  			return wrapError(meta.ErrRead, "", e)
   335  		}
   336  		if keyType != desc.Key().Type() {
   337  			return wrapError(meta.ErrDismatchType, fmt.Sprintf("expect type %s but got type %s", desc.Key().Type(), keyType), nil)
   338  		} else if valueType != desc.Elem().Type() {
   339  			return wrapError(meta.ErrDismatchType, fmt.Sprintf("expect type %s but got type %s", desc.Elem().Type(), valueType), nil)
   340  		}
   341  		*out = json.EncodeObjectBegin(*out)
   342  		for i := 0; i < size; i++ {
   343  			if i != 0 {
   344  				*out = json.EncodeObjectComma(*out)
   345  			}
   346  			err = self.buildinTypeToKey(p, desc.Key(), out)
   347  			if err != nil {
   348  				return wrapError(meta.ErrConvert, "", err)
   349  			}
   350  			*out = json.EncodeObjectColon(*out)
   351  			err = self.doRecurse(ctx, desc.Elem(), out, nil, p)
   352  			if err != nil {
   353  				return unwrapError(fmt.Sprintf("converting %dth element of MAP failed", i), err)
   354  			}
   355  		}
   356  		e = p.ReadMapEnd()
   357  		if e != nil {
   358  			return wrapError(meta.ErrRead, "", e)
   359  		}
   360  		*out = json.EncodeObjectEnd(*out)
   361  	case thrift.SET, thrift.LIST:
   362  		elemType, size, e := p.ReadSetBegin()
   363  		if e != nil {
   364  			return wrapError(meta.ErrRead, "", e)
   365  		}
   366  		if elemType != desc.Elem().Type() {
   367  			return wrapError(meta.ErrDismatchType, fmt.Sprintf("expect type %s but got type %s", desc.Elem().Type(), elemType), nil)
   368  		}
   369  		*out = json.EncodeArrayBegin(*out)
   370  		for i := 0; i < size; i++ {
   371  			if i != 0 {
   372  				*out = json.EncodeArrayComma(*out)
   373  			}
   374  			err = self.doRecurse(ctx, desc.Elem(), out, nil, p)
   375  			if err != nil {
   376  				return unwrapError(fmt.Sprintf("converting %dth element of SET failed", i), err)
   377  			}
   378  		}
   379  		e = p.ReadSetEnd()
   380  		if e != nil {
   381  			return wrapError(meta.ErrRead, "", e)
   382  		}
   383  		*out = json.EncodeArrayEnd(*out)
   384  
   385  	default:
   386  		return wrapError(meta.ErrUnsupportedType, fmt.Sprintf("unknown descriptor type %s", tt), nil)
   387  	}
   388  
   389  	return
   390  }
   391  
   392  func (self *BinaryConv) handleUnsets(b *thrift.RequiresBitmap, desc *thrift.StructDescriptor, out *[]byte, comma bool, ctx context.Context, resp http.ResponseSetter) error {
   393  	return b.HandleRequires(desc, self.opts.WriteRequireField, self.opts.WriteDefaultField, self.opts.WriteOptionalField, func(field *thrift.FieldDescriptor) error {
   394  		// check if field has http mapping
   395  		var ok = false
   396  		if hms := field.HTTPMappings(); self.opts.EnableHttpMapping && hms != nil {
   397  			// make a default thrift value
   398  			p := thrift.BinaryProtocol{Buf: make([]byte, 0, conv.DefaulHttpValueBufferSizeForJSON)};
   399  			if err := p.WriteDefaultOrEmpty(field); err != nil {
   400  				return wrapError(meta.ErrWrite, fmt.Sprintf("encoding field '%s' default value failed", field.Name()), err)
   401  			}
   402  			// convert it into http
   403  			var err error
   404  			ok, err = self.writeHttpValue(ctx, resp, &p, field)
   405  			if err != nil {
   406  				return err
   407  			}
   408  		}
   409  		if ok {
   410  			return nil
   411  		}
   412  		if !comma {
   413  			comma = true
   414  		} else {
   415  			*out = json.EncodeArrayComma(*out)
   416  		}
   417  		*out = json.EncodeString(*out, field.Name())
   418  		*out = json.EncodeObjectColon(*out)
   419  		return writeDefaultOrEmpty(field, out)
   420  	})
   421  }
   422  
   423  func writeDefaultOrEmpty(field *thrift.FieldDescriptor, out *[]byte) (err error) {
   424  	if dv := field.DefaultValue(); dv != nil {
   425  		*out = append(*out, dv.JSONValue()...)
   426  		return nil
   427  	}
   428  	switch t := field.Type().Type(); t {
   429  	case thrift.BOOL:
   430  		*out = json.EncodeBool(*out, false)
   431  	case thrift.BYTE, thrift.I16, thrift.I32, thrift.I64:
   432  		*out = json.EncodeInt64(*out, 0)
   433  	case thrift.DOUBLE:
   434  		*out = json.EncodeFloat64(*out, 0)
   435  	case thrift.STRING:
   436  		*out = json.EncodeString(*out, "")
   437  	case thrift.LIST, thrift.SET:
   438  		*out = json.EncodeEmptyArray(*out)
   439  	case thrift.MAP:
   440  		*out = json.EncodeEmptyObject(*out)
   441  	case thrift.STRUCT:
   442  		*out = json.EncodeObjectBegin(*out)
   443  		for i, field := range field.Type().Struct().Fields() {
   444  			if i != 0 {
   445  				*out = json.EncodeObjectComma(*out)
   446  			}
   447  			*out = json.EncodeString(*out, field.Alias())
   448  			*out = json.EncodeObjectColon(*out)
   449  			if err := writeDefaultOrEmpty(field, out); err != nil {
   450  				return err
   451  			}
   452  		}
   453  		*out = json.EncodeObjectEnd(*out)
   454  	default:
   455  		return wrapError(meta.ErrUnsupportedType, fmt.Sprintf("unknown descriptor type %s", t), nil)
   456  	}
   457  	return err
   458  }
   459  
   460  func (self *BinaryConv) buildinTypeToKey(p *thrift.BinaryProtocol, dest *thrift.TypeDescriptor, out *[]byte) error {
   461  	*out = append(*out, '"')
   462  	switch t := dest.Type(); t {
   463  	// case thrift.BOOL:
   464  	// 	v, err := p.ReadBool()
   465  	// 	if err != nil {
   466  	// 		return err
   467  	// 	}
   468  	// 	*out = json.EncodeBool(*out, v)
   469  	case thrift.I08:
   470  		v, err := p.ReadByte()
   471  		if err != nil {
   472  			return err
   473  		}
   474  		if self.opts.ByteAsUint8 {
   475  			*out = json.EncodeInt64(*out, int64(uint8(v)))
   476  		} else {
   477  			*out = json.EncodeInt64(*out, int64(int8(v)))
   478  		}
   479  	case thrift.I16:
   480  		v, err := p.ReadI16()
   481  		if err != nil {
   482  			return err
   483  		}
   484  		*out = json.EncodeInt64(*out, int64(v))
   485  	case thrift.I32:
   486  		v, err := p.ReadI32()
   487  		if err != nil {
   488  			return err
   489  		}
   490  		*out = json.EncodeInt64(*out, int64(v))
   491  	case thrift.I64:
   492  		v, err := p.ReadI64()
   493  		if err != nil {
   494  			return err
   495  		}
   496  		*out = json.EncodeInt64(*out, int64(v))
   497  	// case thrift.DOUBLE:
   498  	// 	v, err := p.ReadDouble()
   499  	// 	if err != nil {
   500  	// 		return err
   501  	// 	}
   502  	// 	*out, err = json.EncodeFloat64(*out, v)
   503  	case thrift.STRING:
   504  		v, err := p.ReadString(false)
   505  		if err != nil {
   506  			return err
   507  		}
   508  		json.NoQuote(out, v)
   509  	default:
   510  		return wrapError(meta.ErrUnsupportedType, fmt.Sprintf("unsupported descriptor type %s as MAP key", t), nil)
   511  	}
   512  	*out = append(*out, '"')
   513  	return nil
   514  }
   515  
   516  func (self *BinaryConv) writeHttpValue(ctx context.Context, resp http.ResponseSetter, p *thrift.BinaryProtocol, field *thrift.FieldDescriptor) (ok bool, err error) {
   517  	var thriftVal []byte
   518  	var jsonVal []byte
   519  	var textVal []byte
   520  	
   521  	for _, hm := range field.HTTPMappings() {
   522  		var val []byte
   523  		enc := hm.Encoding();
   524  
   525  		if enc == meta.EncodingThriftBinary {
   526  			// raw encoding, check if raw value is set
   527  			if thriftVal == nil {
   528  				var start = p.Read
   529  				if err := p.Skip(field.Type().Type(), self.opts.UseNativeSkip); err != nil {
   530  					return false, wrapError(meta.ErrRead, "", err)
   531  				}
   532  				val = p.Buf[start:p.Read]
   533  				thriftVal = val
   534  			} else {
   535  				val = thriftVal
   536  			}
   537  
   538  		} else if enc == meta.EncodingText || !field.Type().Type().IsComplex() { // not complex value, must use text encoding
   539  			if textVal == nil {
   540  				tmp := make([]byte, 0, conv.DefaulHttpValueBufferSizeForJSON)
   541  				err = p.ReadStringWithDesc(field.Type(), &tmp, self.opts.ByteAsUint8, self.opts.DisallowUnknownField, !self.opts.NoBase64Binary)
   542  				if err != nil {
   543  					return false, unwrapError(fmt.Sprintf("reading thrift value of '%s' failed, thrift pos:%d", field.Name(), p.Read), err)
   544  				}
   545  				val = tmp
   546  				textVal = val 
   547  			} else {
   548  				val = textVal
   549  			} 
   550  		} else if self.opts.UseKitexHttpEncoding {
   551  			// kitex http encoding fallback
   552  			if textVal == nil {
   553  				obj, err := p.ReadAnyWithDesc(field.Type(), self.opts.ByteAsUint8, !self.opts.NoCopyString, self.opts.DisallowUnknownField, true)
   554  				if err != nil {
   555  					return false, unwrapError(fmt.Sprintf("reading thrift value of '%s' failed, thrift pos:%d", field.Name(), p.Read), err)
   556  				}
   557  				textVal = rt.Str2Mem(primitive.KitexToString(obj))
   558  				val = textVal
   559  			} else {
   560  				val = textVal
   561  			} 
   562  		} else if enc == meta.EncodingJSON {
   563  			// for nested type, convert it to a new JSON string
   564  			if jsonVal == nil {
   565  				tmp := make([]byte, 0, conv.DefaulHttpValueBufferSizeForJSON)
   566  				err := self.doRecurse(ctx, field.Type(), &tmp, resp, p)
   567  				if err != nil {
   568  					return false, unwrapError(fmt.Sprintf("mapping field %s failed, thrift pos:%d", field.Name(), p.Read), err)
   569  				}
   570  				val = tmp
   571  				jsonVal = val
   572  			} else {
   573  				val = jsonVal
   574  			}
   575  			
   576  		} else {
   577  			return false, wrapError(meta.ErrConvert, fmt.Sprintf("unsuported http-value encoding %v of field '%s'", enc, field.Name()), nil)
   578  		}
   579  
   580  		// NOTICE: ignore error if the value is not set
   581  		if e := hm.Response(ctx, resp, field, rt.Mem2Str(val)); e == nil {
   582  			ok = true
   583  			break
   584  		} else if !self.opts.OmitHttpMappingErrors {
   585  			return false, e
   586  		}
   587  	}
   588  	return
   589  }
   590  
   591  // func setValueToHttp(resp http.ResponseSetter, typ thrift.AnnoType, key string, val string) error {
   592  // 	switch typ {
   593  // 	case annotation.APIHeader:
   594  // 		return resp.SetHeader(key, val)
   595  // 	case annotation.APIRawBody:
   596  // 		return resp.SetRawBody(rt.Str2Mem(val))
   597  // 	case annotation.APICookie:
   598  // 		return resp.SetCookie(key, val)
   599  // 	case annotation.APIHTTPCode:
   600  // 		code, err := strconv.Atoi(val)
   601  // 		if err != nil {
   602  // 			return err
   603  // 		}
   604  // 		return resp.SetStatusCode(code)
   605  // 	default:
   606  // 		return wrapError(meta.ErrUnsupportedType, fmt.Sprintf("unsupported annotation type %d", typ), nil)
   607  // 	}
   608  // }