thrift-iterator / Go

Licence: apache-2.0
decode/encode thrift message without IDL

Programming Languages

go
31211 projects - #10 most used programming language

Projects that are alternatives of or similar to Go

Cyberchef
The Cyber Swiss Army Knife - a web app for encryption, encoding, compression and data analysis
Stars: ✭ 13,674 (+6143.84%)
Mutual labels:  encoding
Finatra
Fast, testable, Scala services built on TwitterServer and Finagle
Stars: ✭ 2,126 (+870.78%)
Mutual labels:  thrift
Rust Lexical
Lexical, to- and from-string conversion routines.
Stars: ✭ 192 (-12.33%)
Mutual labels:  encoding
Mini Svg Data Uri
Small, efficient encoding of SVG data URIs for CSS, HTML, etc.
Stars: ✭ 158 (-27.85%)
Mutual labels:  encoding
Packetserial
An Arduino Library that facilitates packet-based serial communication using COBS or SLIP encoding.
Stars: ✭ 177 (-19.18%)
Mutual labels:  encoding
Convertzz
繼承自convertz,但更好用的簡繁轉換工具
Stars: ✭ 181 (-17.35%)
Mutual labels:  encoding
Spring Thrift Starter
Set of cool annotations that helps you building Thrift applications with Spring Boot
Stars: ✭ 151 (-31.05%)
Mutual labels:  thrift
Jsonlab
JSONLab: a native JSON/UBJSON/MassagePack encoder/decoder for MATLAB/Octave
Stars: ✭ 202 (-7.76%)
Mutual labels:  encoding
Encoding
Encoding Standard
Stars: ✭ 176 (-19.63%)
Mutual labels:  encoding
Base X
Encode/decode any base
Stars: ✭ 191 (-12.79%)
Mutual labels:  encoding
Xssor2
XSS'OR - Hack with JavaScript.
Stars: ✭ 1,969 (+799.09%)
Mutual labels:  encoding
Go.geojson
Encoding and decoding GeoJSON <-> Go
Stars: ✭ 172 (-21.46%)
Mutual labels:  encoding
Elixir Thrift
A Pure Elixir Thrift Implementation
Stars: ✭ 182 (-16.89%)
Mutual labels:  thrift
Img Encode
Encode an image to sound and view it as a spectrogram - turn your images into music
Stars: ✭ 157 (-28.31%)
Mutual labels:  encoding
Gunicorn thrift
Thrift app and worker for gunicorn!
Stars: ✭ 193 (-11.87%)
Mutual labels:  thrift
Datagene
DataGene - Identify How Similar TS Datasets Are to One Another (by @firmai)
Stars: ✭ 156 (-28.77%)
Mutual labels:  encoding
Libchef
🍀 c++ standalone header-only basic library. || c++头文件实现无第三方依赖基础库
Stars: ✭ 178 (-18.72%)
Mutual labels:  encoding
Elixir Json
Native JSON library for Elixir
Stars: ✭ 216 (-1.37%)
Mutual labels:  encoding
Encoding rs
A Gecko-oriented implementation of the Encoding Standard in Rust
Stars: ✭ 196 (-10.5%)
Mutual labels:  encoding
Thrift Tools
thrift-tools is a library and a set of tools to introspect Apache Thrift traffic.
Stars: ✭ 189 (-13.7%)
Mutual labels:  thrift

thrifter

decode/encode thrift message without IDL

Why?

  • because IDL generated model is ugly and inflexible, it is seldom used in application directly. instead we define another model, which leads to bad performance.
    • bytes need to be copied twice
    • more objects to gc
  • thrift proxy can not know all possible IDL in advance, in scenarios like api gateway, we need to decode/encode in a generic way to modify embedded header.
  • official thrift library for go is slow, verified in several benchmarks. It is even slower than json-iterator

works like encoding/json

encoding/json has a super simple api to encode/decode json. thrifter mimic the same api.

import "github.com/thrift-iterator/go"
// marshal to thrift
thriftEncodedBytes, err := thrifter.Marshal([]int{1, 2, 3})
// unmarshal back
var val []int
err = thrifter.Unmarshal(thriftEncodedBytes, &val)

even struct data binding is supported

import "github.com/thrift-iterator/go"

type NewOrderRequest struct {
    Lines []NewOrderLine `thrift:",1"`
}

type NewOrderLine struct {
    ProductId string `thrift:",1"`
    Quantity int `thrift:",2"`
}

// marshal to thrift
thriftEncodedBytes, err := thrifter.Marshal(NewOrderRequest{
	Lines: []NewOrderLine{
		{"apple", 1},
		{"orange", 2},
	}
})
// unmarshal back
var val NewOrderRequest
err = thrifter.Unmarshal(thriftEncodedBytes, &val)

without IDL

you do not need to define IDL. you do not need to use static code generation. you do not event need to define struct.

import "github.com/thrift-iterator/go"
import "github.com/thrift-iterator/go/general"

var msg general.Message
err := thrifter.Unmarshal(thriftEncodedBytes, &msg)
// the RPC call method name, type is string
fmt.Println(msg.MessageName)
// the RPC call arguments, type is general.Struct
fmt.Println(msg.Arguments)

what is general.Struct, it is defined as a map

type FieldId int16
type Struct map[FieldId]interface{}

we can extract out specific argument from deeply nested arguments using one line

productId := msg.MessageArgs.Get(
	protocol.FieldId(1), // lines of request
	0, // the first line
	protocol.FieldId(1), // product id
).(string)

You can unmarshal any thrift bytes into general objects. And you can marshal them back.

Partial decoding

fully decoding into a go struct consumes substantial resources. thrifter provide option to do partial decoding. You can modify part of the message, with untouched parts in []byte form.

import "github.com/thrift-iterator/go"
import "github.com/thrift-iterator/go/protocol"
import "github.com/thrift-iterator/go/raw"

// partial decoding
decoder := thrifter.NewDecoder(reader)
var msgHeader protocol.MessageHeader
decoder.Decode(&msgHeader)
var msgArgs raw.Struct
decoder.Decode(&msgArgs)

// modify...

// encode back
encoder := thrifter.NewEncoder(writer)
encoder.Encode(msgHeader)
encoder.Encode(msgArgs)

the definition of raw.Struct is

type StructField struct {
	Buffer []byte
	Type protocol.TType
}

type Struct map[protocol.FieldId]StructField

Performance

thrifter does not compromise performance.

gogoprotobuf

5000000	       366 ns/op	     144 B/op	      12 allocs/op

thrift

1000000	      1549 ns/op	     528 B/op	       9 allocs/op

thrifter by static codegen

5000000	       389 ns/op	     192 B/op	       6 allocs/op

thrifter by reflection

2000000	       585 ns/op	     192 B/op	       6 allocs/op

You can see the reflection implementation is not bad, much faster than the static code generated by thrift original implementation.

To have best performance, you can choose to use static code generation. The api is unchanged, just need to add extra static codegen in your build steps, and include the generated code in your package. The runtime will automatically use the generated encoder/decoder instead of reflection.

For example of static codegen, checkout https://github.com/thrift-iterator/go/blob/master/test/api/init.go

Sync IDL and Go Struct

Keep IDL and your object model is challenging. We do not always like the code generated from thrift IDL. But manually keeping the IDL and model in sync is tedious and error prone.

A separate toolchain to manipulate thrift IDL file, and keeping them bidirectionally in sync will be provided in another project.

Note that the project description data, including the texts, logos, images, and/or trademarks, for each open source project belongs to its rightful owner. If you wish to add or remove any projects, please contact us at [email protected].