diff --git a/protocol/thrift/base/README.md b/protocol/thrift/base/README.md new file mode 100644 index 0000000..82ea1fe --- /dev/null +++ b/protocol/thrift/base/README.md @@ -0,0 +1,11 @@ +# base + +`base` contains optimised generated code for kitex generic. +`base` is used widely in internal systems, so we expect to have a unified place for `base`. +It deprecates `Base` and `BaseResp` structs in `kitex` and `dynamicgo` + +Users should not use this package, it's only for cloudwego internals. + +The code under this package is generated by `fastgo` version of `thriftgo` which we haven't released yet and is only used in a few repos. You can find the code [here](https://github.com/cloudwego/thriftgo/tree/feat-fastcodec). + +Use `thriftgo` `fastgo` at your own risks. it's NOT fully tested and that's why we manually add test code in this package. diff --git a/protocol/thrift/base/base.go b/protocol/thrift/base/base.go new file mode 100644 index 0000000..d22c7a1 --- /dev/null +++ b/protocol/thrift/base/base.go @@ -0,0 +1,127 @@ +/* + * Copyright 2024 CloudWeGo Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// Code generated by thriftgo (0.3.15). DO NOT EDIT. + +package base + +import ( + "fmt" +) + +type TrafficEnv struct { + Open bool `thrift:"Open,1" json:"Open"` + Env string `thrift:"Env,2" json:"Env"` +} + +func NewTrafficEnv() *TrafficEnv { + return &TrafficEnv{ + + Open: false, + Env: "", + } +} + +func (p *TrafficEnv) InitDefault() { + p.Open = false + p.Env = "" +} + +func (p *TrafficEnv) String() string { + if p == nil { + return "" + } + return fmt.Sprintf("TrafficEnv(%+v)", *p) +} + +var fieldIDToName_TrafficEnv = map[int16]string{ + 1: "Open", + 2: "Env", +} + +type Base struct { + LogID string `thrift:"LogID,1" json:"LogID"` + Caller string `thrift:"Caller,2" json:"Caller"` + Addr string `thrift:"Addr,3" json:"Addr"` + Client string `thrift:"Client,4" json:"Client"` + TrafficEnv *TrafficEnv `thrift:"TrafficEnv,5,optional" json:"TrafficEnv,omitempty"` + Extra map[string]string `thrift:"Extra,6,optional" json:"Extra,omitempty"` +} + +func NewBase() *Base { + return &Base{ + + LogID: "", + Caller: "", + Addr: "", + Client: "", + } +} + +func (p *Base) InitDefault() { + p.LogID = "" + p.Caller = "" + p.Addr = "" + p.Client = "" +} + +func (p *Base) String() string { + if p == nil { + return "" + } + return fmt.Sprintf("Base(%+v)", *p) +} + +var fieldIDToName_Base = map[int16]string{ + 1: "LogID", + 2: "Caller", + 3: "Addr", + 4: "Client", + 5: "TrafficEnv", + 6: "Extra", +} + +type BaseResp struct { + StatusMessage string `thrift:"StatusMessage,1" json:"StatusMessage"` + StatusCode int32 `thrift:"StatusCode,2" json:"StatusCode"` + Extra map[string]string `thrift:"Extra,3,optional" json:"Extra,omitempty"` +} + +func NewBaseResp() *BaseResp { + return &BaseResp{ + + StatusMessage: "", + StatusCode: 0, + } +} + +func (p *BaseResp) InitDefault() { + p.StatusMessage = "" + p.StatusCode = 0 +} + +func (p *BaseResp) String() string { + if p == nil { + return "" + } + return fmt.Sprintf("BaseResp(%+v)", *p) +} + +var fieldIDToName_BaseResp = map[int16]string{ + 1: "StatusMessage", + 2: "StatusCode", + 3: "Extra", +} diff --git a/protocol/thrift/base/base.sh b/protocol/thrift/base/base.sh new file mode 100755 index 0000000..437b281 --- /dev/null +++ b/protocol/thrift/base/base.sh @@ -0,0 +1,19 @@ +#! /bin/bash + +set -e + +thriftgo -g fastgo:no_default_serdes=true -o=.. ./base.thrift + +mv base.go base_tmp.go # fix sed base.go > base.go +# rm unused funcs and vars, keep the file smaller: +# func GetXXX +# func IsSet +# multiline DEFAULT vars +# singleline DEFAULT vars +sed '/func.* Get.* {/,/^}/d' base_tmp.go |\ + sed '/func.* IsSet.* {/,/^}/d' |\ + sed '/DEFAULT.*{/,/^}/d' |\ + sed '/DEFAULT/d' > base.go + +gofmt -w base.go +rm base_tmp.go diff --git a/protocol/thrift/base/base.thrift b/protocol/thrift/base/base.thrift new file mode 100644 index 0000000..696033b --- /dev/null +++ b/protocol/thrift/base/base.thrift @@ -0,0 +1,23 @@ +namespace py base +namespace go base +namespace java com.bytedance.thrift.base + +struct TrafficEnv { + 1: bool Open = false, + 2: string Env = "", +} + +struct Base { + 1: string LogID = "", + 2: string Caller = "", + 3: string Addr = "", + 4: string Client = "", + 5: optional TrafficEnv TrafficEnv, + 6: optional map Extra, +} + +struct BaseResp { + 1: string StatusMessage = "", + 2: i32 StatusCode = 0, + 3: optional map Extra, +} diff --git a/protocol/thrift/base/base_test.go b/protocol/thrift/base/base_test.go new file mode 100644 index 0000000..c2c0eaf --- /dev/null +++ b/protocol/thrift/base/base_test.go @@ -0,0 +1,87 @@ +/* + * Copyright 2024 CloudWeGo Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package base + +import ( + "testing" + + "github.com/stretchr/testify/require" +) + +func TestBase(t *testing.T) { + var err error + + p := NewBase() + p.InitDefault() // for code coverage ... + p.LogID = "1" + p.Caller = "2" + p.Addr = "3" + p.Client = "4" + t.Log(p.String()) + + sz := p.BLength() + b := make([]byte, sz) + n := p.FastWrite(b) + require.Equal(t, sz, n) + + p2 := NewBase() + n, err = p2.FastRead(b) + require.Equal(t, len(b), n) + require.NoError(t, err) + require.Equal(t, p, p2) + + // optional fields + + p.TrafficEnv = NewTrafficEnv() + p.TrafficEnv.InitDefault() // for code coverage ... + p.Extra = map[string]string{"5": "6"} + t.Log(p.String()) + + sz = p.BLength() + b = make([]byte, sz) + n = p.FastWrite(b) + require.Equal(t, sz, n) + + p2 = NewBase() + n, err = p2.FastRead(b) + require.Equal(t, len(b), n) + require.NoError(t, err) + require.Equal(t, p, p2) + +} + +func TestBaseResp(t *testing.T) { + var err error + + p := NewBaseResp() + p.InitDefault() // for code coverage ... + p.StatusMessage = "msg" + p.StatusCode = 200 + p.Extra = map[string]string{"k": "v"} + t.Log(p.String()) + + sz := p.BLength() + b := make([]byte, sz) + n := p.FastWrite(b) + require.Equal(t, sz, n) + + p2 := NewBaseResp() + n, err = p2.FastRead(b) + require.Equal(t, len(b), n) + require.NoError(t, err) + require.Equal(t, p, p2) +} diff --git a/protocol/thrift/base/k-base.go b/protocol/thrift/base/k-base.go new file mode 100644 index 0000000..e6ad17e --- /dev/null +++ b/protocol/thrift/base/k-base.go @@ -0,0 +1,432 @@ +/* + * Copyright 2024 CloudWeGo Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// Code generated by thriftgo (0.3.15) (fastgo). DO NOT EDIT. +package base + +import ( + "encoding/binary" + "fmt" + "unsafe" + + "github.com/cloudwego/gopkg/protocol/thrift" +) + +func (p *TrafficEnv) BLength() int { + if p == nil { + return 1 + } + off := 0 + + // p.Open ID:1 thrift.BOOL + off += 3 + off += 1 + + // p.Env ID:2 thrift.STRING + off += 3 + off += 4 + len(p.Env) + return off + 1 +} + +func (p *TrafficEnv) FastWrite(b []byte) int { return p.FastWriteNocopy(b, nil) } + +func (p *TrafficEnv) FastWriteNocopy(b []byte, w thrift.NocopyWriter) int { + if p == nil { + b[0] = 0 + return 1 + } + off := 0 + + // p.Open ID:1 thrift.BOOL + b[off] = 2 + binary.BigEndian.PutUint16(b[off+1:], 1) + off += 3 + b[off] = *((*byte)(unsafe.Pointer(&p.Open))) + off++ + + // p.Env ID:2 thrift.STRING + b[off] = 11 + binary.BigEndian.PutUint16(b[off+1:], 2) + off += 3 + off += thrift.Binary.WriteStringNocopy(b[off:], w, p.Env) + + b[off] = 0 + return off + 1 +} + +func (p *TrafficEnv) FastRead(b []byte) (off int, err error) { + var ftyp thrift.TType + var fid int16 + var l int + x := thrift.BinaryProtocol{} + for { + ftyp, fid, l, err = x.ReadFieldBegin(b[off:]) + off += l + if err != nil { + goto ReadFieldBeginError + } + if ftyp == thrift.STOP { + break + } + switch uint32(fid)<<8 | uint32(ftyp) { + case 0x102: // p.Open ID:1 thrift.BOOL + p.Open, l, err = x.ReadBool(b[off:]) + off += l + if err != nil { + goto ReadFieldError + } + case 0x20b: // p.Env ID:2 thrift.STRING + p.Env, l, err = x.ReadString(b[off:]) + off += l + if err != nil { + goto ReadFieldError + } + default: + l, err = x.Skip(b[off:], ftyp) + off += l + if err != nil { + goto SkipFieldError + } + } + } + return +ReadFieldBeginError: + return off, thrift.PrependError(fmt.Sprintf("%T read field begin error: ", p), err) +ReadFieldError: + return off, thrift.PrependError(fmt.Sprintf("%T read field %d '%s' error: ", p, fid, fieldIDToName_TrafficEnv[fid]), err) +SkipFieldError: + return off, thrift.PrependError(fmt.Sprintf("%T skip field %d type %d error: ", p, fid, ftyp), err) +} + +func (p *Base) BLength() int { + if p == nil { + return 1 + } + off := 0 + + // p.LogID ID:1 thrift.STRING + off += 3 + off += 4 + len(p.LogID) + + // p.Caller ID:2 thrift.STRING + off += 3 + off += 4 + len(p.Caller) + + // p.Addr ID:3 thrift.STRING + off += 3 + off += 4 + len(p.Addr) + + // p.Client ID:4 thrift.STRING + off += 3 + off += 4 + len(p.Client) + + // p.TrafficEnv ID:5 thrift.STRUCT + if p.TrafficEnv != nil { + off += 3 + off += p.TrafficEnv.BLength() + } + + // p.Extra ID:6 thrift.MAP + if p.Extra != nil { + off += 3 + off += 6 + for k, v := range p.Extra { + off += 4 + len(k) + off += 4 + len(v) + } + } + return off + 1 +} + +func (p *Base) FastWrite(b []byte) int { return p.FastWriteNocopy(b, nil) } + +func (p *Base) FastWriteNocopy(b []byte, w thrift.NocopyWriter) int { + if p == nil { + b[0] = 0 + return 1 + } + off := 0 + + // p.LogID ID:1 thrift.STRING + b[off] = 11 + binary.BigEndian.PutUint16(b[off+1:], 1) + off += 3 + off += thrift.Binary.WriteStringNocopy(b[off:], w, p.LogID) + + // p.Caller ID:2 thrift.STRING + b[off] = 11 + binary.BigEndian.PutUint16(b[off+1:], 2) + off += 3 + off += thrift.Binary.WriteStringNocopy(b[off:], w, p.Caller) + + // p.Addr ID:3 thrift.STRING + b[off] = 11 + binary.BigEndian.PutUint16(b[off+1:], 3) + off += 3 + off += thrift.Binary.WriteStringNocopy(b[off:], w, p.Addr) + + // p.Client ID:4 thrift.STRING + b[off] = 11 + binary.BigEndian.PutUint16(b[off+1:], 4) + off += 3 + off += thrift.Binary.WriteStringNocopy(b[off:], w, p.Client) + + // p.TrafficEnv ID:5 thrift.STRUCT + if p.TrafficEnv != nil { + b[off] = 12 + binary.BigEndian.PutUint16(b[off+1:], 5) + off += 3 + off += p.TrafficEnv.FastWriteNocopy(b[off:], w) + } + + // p.Extra ID:6 thrift.MAP + if p.Extra != nil { + b[off] = 13 + binary.BigEndian.PutUint16(b[off+1:], 6) + off += 3 + b[off] = 11 + b[off+1] = 11 + binary.BigEndian.PutUint32(b[off+2:], uint32(len(p.Extra))) + off += 6 + for k, v := range p.Extra { + off += thrift.Binary.WriteStringNocopy(b[off:], w, k) + off += thrift.Binary.WriteStringNocopy(b[off:], w, v) + } + } + + b[off] = 0 + return off + 1 +} + +func (p *Base) FastRead(b []byte) (off int, err error) { + var ftyp thrift.TType + var fid int16 + var l int + x := thrift.BinaryProtocol{} + for { + ftyp, fid, l, err = x.ReadFieldBegin(b[off:]) + off += l + if err != nil { + goto ReadFieldBeginError + } + if ftyp == thrift.STOP { + break + } + switch uint32(fid)<<8 | uint32(ftyp) { + case 0x10b: // p.LogID ID:1 thrift.STRING + p.LogID, l, err = x.ReadString(b[off:]) + off += l + if err != nil { + goto ReadFieldError + } + case 0x20b: // p.Caller ID:2 thrift.STRING + p.Caller, l, err = x.ReadString(b[off:]) + off += l + if err != nil { + goto ReadFieldError + } + case 0x30b: // p.Addr ID:3 thrift.STRING + p.Addr, l, err = x.ReadString(b[off:]) + off += l + if err != nil { + goto ReadFieldError + } + case 0x40b: // p.Client ID:4 thrift.STRING + p.Client, l, err = x.ReadString(b[off:]) + off += l + if err != nil { + goto ReadFieldError + } + case 0x50c: // p.TrafficEnv ID:5 thrift.STRUCT + p.TrafficEnv = NewTrafficEnv() + l, err = p.TrafficEnv.FastRead(b[off:]) + off += l + if err != nil { + goto ReadFieldError + } + case 0x60d: // p.Extra ID:6 thrift.MAP + var sz int + _, _, sz, l, err = x.ReadMapBegin(b[off:]) + off += l + if err != nil { + goto ReadFieldError + } + p.Extra = make(map[string]string, sz) + for i := 0; i < sz; i++ { + var k string + var v string + k, l, err = x.ReadString(b[off:]) + off += l + if err != nil { + goto ReadFieldError + } + v, l, err = x.ReadString(b[off:]) + off += l + if err != nil { + goto ReadFieldError + } + p.Extra[k] = v + } + default: + l, err = x.Skip(b[off:], ftyp) + off += l + if err != nil { + goto SkipFieldError + } + } + } + return +ReadFieldBeginError: + return off, thrift.PrependError(fmt.Sprintf("%T read field begin error: ", p), err) +ReadFieldError: + return off, thrift.PrependError(fmt.Sprintf("%T read field %d '%s' error: ", p, fid, fieldIDToName_Base[fid]), err) +SkipFieldError: + return off, thrift.PrependError(fmt.Sprintf("%T skip field %d type %d error: ", p, fid, ftyp), err) +} + +func (p *BaseResp) BLength() int { + if p == nil { + return 1 + } + off := 0 + + // p.StatusMessage ID:1 thrift.STRING + off += 3 + off += 4 + len(p.StatusMessage) + + // p.StatusCode ID:2 thrift.I32 + off += 3 + off += 4 + + // p.Extra ID:3 thrift.MAP + if p.Extra != nil { + off += 3 + off += 6 + for k, v := range p.Extra { + off += 4 + len(k) + off += 4 + len(v) + } + } + return off + 1 +} + +func (p *BaseResp) FastWrite(b []byte) int { return p.FastWriteNocopy(b, nil) } + +func (p *BaseResp) FastWriteNocopy(b []byte, w thrift.NocopyWriter) int { + if p == nil { + b[0] = 0 + return 1 + } + off := 0 + + // p.StatusMessage ID:1 thrift.STRING + b[off] = 11 + binary.BigEndian.PutUint16(b[off+1:], 1) + off += 3 + off += thrift.Binary.WriteStringNocopy(b[off:], w, p.StatusMessage) + + // p.StatusCode ID:2 thrift.I32 + b[off] = 8 + binary.BigEndian.PutUint16(b[off+1:], 2) + off += 3 + binary.BigEndian.PutUint32(b[off:], uint32(p.StatusCode)) + off += 4 + + // p.Extra ID:3 thrift.MAP + if p.Extra != nil { + b[off] = 13 + binary.BigEndian.PutUint16(b[off+1:], 3) + off += 3 + b[off] = 11 + b[off+1] = 11 + binary.BigEndian.PutUint32(b[off+2:], uint32(len(p.Extra))) + off += 6 + for k, v := range p.Extra { + off += thrift.Binary.WriteStringNocopy(b[off:], w, k) + off += thrift.Binary.WriteStringNocopy(b[off:], w, v) + } + } + + b[off] = 0 + return off + 1 +} + +func (p *BaseResp) FastRead(b []byte) (off int, err error) { + var ftyp thrift.TType + var fid int16 + var l int + x := thrift.BinaryProtocol{} + for { + ftyp, fid, l, err = x.ReadFieldBegin(b[off:]) + off += l + if err != nil { + goto ReadFieldBeginError + } + if ftyp == thrift.STOP { + break + } + switch uint32(fid)<<8 | uint32(ftyp) { + case 0x10b: // p.StatusMessage ID:1 thrift.STRING + p.StatusMessage, l, err = x.ReadString(b[off:]) + off += l + if err != nil { + goto ReadFieldError + } + case 0x208: // p.StatusCode ID:2 thrift.I32 + p.StatusCode, l, err = x.ReadI32(b[off:]) + off += l + if err != nil { + goto ReadFieldError + } + case 0x30d: // p.Extra ID:3 thrift.MAP + var sz int + _, _, sz, l, err = x.ReadMapBegin(b[off:]) + off += l + if err != nil { + goto ReadFieldError + } + p.Extra = make(map[string]string, sz) + for i := 0; i < sz; i++ { + var k string + var v string + k, l, err = x.ReadString(b[off:]) + off += l + if err != nil { + goto ReadFieldError + } + v, l, err = x.ReadString(b[off:]) + off += l + if err != nil { + goto ReadFieldError + } + p.Extra[k] = v + } + default: + l, err = x.Skip(b[off:], ftyp) + off += l + if err != nil { + goto SkipFieldError + } + } + } + return +ReadFieldBeginError: + return off, thrift.PrependError(fmt.Sprintf("%T read field begin error: ", p), err) +ReadFieldError: + return off, thrift.PrependError(fmt.Sprintf("%T read field %d '%s' error: ", p, fid, fieldIDToName_BaseResp[fid]), err) +SkipFieldError: + return off, thrift.PrependError(fmt.Sprintf("%T skip field %d type %d error: ", p, fid, ftyp), err) +}