Thrift has two components, the compiler and the libraries. The compiler is used to generate serialization and server/client code for the services you define in your Thrift files. The generated code depends on the Thrift libraries for networking and serialization primitives.
The first step to using Thrift is to write some Thrift code in a source file. You can start by defining some simple structs and enums:
user.thrift
enum Pet {
Dog = 0,
Cat = 1,
}
struct User {
0: string name,
1: Pet pet,
}
Each named enum value must have a unique 32-bit integer value associated with it and each struct field must have a unique 16-bit integer ID. These are used in the serialization protocol. Now that you have some Thrift code, you can use your new data structure in Haskell by invoking the Thrift Compiler:
$ thrift-compiler user.thrift
This will generate a Haskell source file called User/Types.hs
which contains the Haskell definitions of the data structures you defined as well as the code to serialize and deserialize those data structures. While the real generated code is somewhat complicated, it would look roughly like this for the above example:
data Pet = Pet_Dog | Pet_Cat
data User = User
{ user_name :: Text
, user_pet :: Pet
}
You can use these data types like any other Haskell data types by importing User.Types
. In addition, you can serialize then to ByteString
s using one of the Thrift serialization formats. For example, if you wanted to serialize a User
to JSON, you could do it like this:
import Thrift.Protocol.JSON
userBytes :: ByteString
userBytes = serializeJSON $ User "Joe" Pet_Dog
The serialized bytes can then be deserialized into structured data in any other Thrift-supported language such as C++, Python, or Java.
In addition to data structures, you can also define services and remote procedure calls in a Thrift file. Consider the following code that we will add to user.thrift
:
service UserFetcher {
User getUser(0: i64 id)
}
This defines a service called UserFetcher
with a single RPC what takes in a 64-bit integer user ID and returns information about the user. Running the Thrift Compiler in the same way as we did above will now result in two additonal files getting create called User.UserFetcher.Client
and User.UserFetcher.Server
. The client contains all the code that you need to make RPC calls to a running UserFetcher
server. The server file contains stubs so that you can create your own implementation of the server functions.
For more detailed examples of how to create servers and clients, see the code in lib/test/SocketChannelTest.hs
.
In this directory, you will find information on how to work with the code that gets generated by the Thrift compiler. This includes:
- Types: How Thrift types map to Haskell types
- Names: How Thrift named types and fields in Thrift map to Haskell data types
- Annotation: Special ways to customize the generated code
- Options: Thrift compiler flags to alter the generated code
- Serialization: Which serialization formats are available and how to use them