protobuf-elixir
A pure Elixir implementation of Google Protobuf
Why this instead of exprotobuf(gpb)?
It have some must-have and other cool features like:
- A protoc plugin to generate Elixir code just like what other official libs do, which is powerful and reliable.
- Generate simple and explicit code with the power of Macro. (see test/support/test_msg.ex)
- Plugins support. Only grpc is supported now.
- Use structs for messages instead of Erlang records.
- Support Typespec in generated code.
Installation
The package can be installed
by adding protobuf to your list of dependencies in mix.exs:
def deps do
[{:protobuf, "~> 0.3.1"}]
endFeatures
- Define messages with DSL
- Decode basic messages
- Skip unknown fields
- Decode embedded messages
- Decode packed and repeated fields
- Encode messages
- protoc plugin
- map
- Support default values
- Validate values
- Generate typespecs
- oneof
Usage
Generate Elixir code
-
Install
protochere -
Install protoc plugin
protoc-gen-elixirfor Elixir . NOTE: You have to make sureprotoc-gen-elixir(this name is important) is in your PATH.$ mix escript.install hex protobuf -
Generate Elixir code using protoc
$ protoc --elixir_out=./lib foo.proto -
Files
foo.pb.exwill be generated, like:
defmodule Foo.Bar do
use Protobuf
defstruct [:a, :b]
field :a, 1, optional: true, type: :int32
field :b, 2, optional: true, type: :string
end
defmodule Foo do
use Protobuf
defstruct [:a, :b, :c]
field :a, 1, required: true, type: :float
field :b, 2, optional: true, type: :fixed64, default: 5
field :e, 3, optional: true, type: Foo.Bar
endEncode and decode in your code
struct = Foo.new(a: 3.2, c: Foo.Bar.new())
encoded = Foo.encode(struct)
struct = Foo.decode(encoded)Note:
-
You should use
YourModule.newinstead of using the struct directly because default values will be set for all fields. -
Default values will be set by default in
decode, which can be changed by:use_defaultoption. -
Validation is done in
encode. An error will be raised if the struct is invalid(like type is not matched).
gRPC Support
If you write services in protobuf, you can generate gRPC code by passing plugins=grpc in --go_out:
$ protoc --elixir_out=plugins=grpc:./lib/ *.protoTips for protoc
-
Custom protoc-gen-elixir name or path using
--plugin$ protoc --elixir_out=./lib --plugin=./protoc-gen-elixir *.proto -
Pass
-Iargument if you import other protobuf files$ protoc -I protos --elixir_out=./lib protos/hello.proto
Acknowledgements
Many thanks to gpb and golang/protobuf as good examples of writing Protobuf decoder/encoder.