A pure Elixir implementation of Google Protobuf
It has 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.
The package can be installed by adding protobuf
to your list of dependencies in mix.exs
:
def deps do
[
{:protobuf, "~> 0.5.3"},
# Only for files generated from Google's protos.
# Can be ignored if you don't use Google's protos.
{:google_protos, "~> 0.1"}
]
end
- 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
- Install
protoc
(cpp) here orbrew install protobuf
on MacOS. - Install protoc plugin
protoc-gen-elixir
for 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 helloworld.proto
- Files
helloworld.pb.ex
will be generated, like:
defmodule Helloworld.HelloRequest do
use Protobuf, syntax: :proto3
@type t :: %__MODULE__{
name: String.t
}
defstruct [:name]
field :name, 1, type: :string
end
defmodule Helloworld.HelloReply do
use Protobuf, syntax: :proto3
@type t :: %__MODULE__{
message: String.t
}
defstruct [:message]
field :message, 1, type: :string
end
struct = Foo.new(a: 3.2, c: Foo.Bar.new())
encoded = Foo.encode(struct)
struct = Foo.decode(encoded)
Note:
- You should use
YourModule.new
instead 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_default
option. - Validation is done in
encode
. An error will be raised if the struct is invalid(like type is not matched).
If you write services in protobuf, you can generate gRPC code by passing plugins=grpc
in --elixir_out
:
$ protoc --elixir_out=plugins=grpc:./lib/ *.proto
- Custom protoc-gen-elixir name or path using
--plugin
$ protoc --elixir_out=./lib --plugin=./protoc-gen-elixir *.proto
- Pass
-I
argument if you import other protobuf files
$ protoc -I protos --elixir_out=./lib protos/hello.proto
This project is being sponsored by Tubi. Thank you!
Many thanks to gpb and golang/protobuf as good examples of writing Protobuf decoder/encoder.