View Source Protox (Protox v1.7.3)
Use this module to generate the Elixir structs corresponding to a set of protobuf definitions and to encode/decode instances of these structures.
Elixit structs generation examples
From a set of files:
defmodule Dummy do
use Protox,
files: [
"./defs/foo.proto",
"./defs/bar.proto",
"./defs/baz/fiz.proto",
]
end
From a string:
defmodule Dummy do
use Protox,
schema: """
syntax = "proto3";
package fiz;
message Baz {
}
message Foo {
map<int32, Baz> b = 2;
}
"""
end
The generated modules respect the package declaration. For instance, in the above example,
both the Fiz.Baz
and Fiz.Foo
modules will be generated.
Encoding/decoding
For the rest of this module documentation, we suppose the following protobuf messages are defined:
defmodule Dummy do
use Protox,
schema: """
syntax = "proto3";
package fiz;
message Baz {
}
enum Enum {
FOO = 0;
BAR = 1;
}
message Foo {
Enum a = 1;
map<int32, Baz> b = 2;
}
""",
namespace: Namespace
use Protox,
schema: """
syntax = "proto3";
message Msg {
map<int32, string> msg_k = 8;
}
"""
use Protox,
schema: """
syntax = "proto3";
message Sub {
int32 a = 1;
}
"""
end
See each function documentation to see how they are used to encode and decode protobuf messages.
Summary
Functions
Decode a binary into a protobuf message.
Throwing version of decode/2
.
Encode a protobuf message into IO data.
Throwing version of encode/1
.
Errors
This function returns a tuple {:error, reason}
if
Throwing version of json_decode/2
.
Export a proto3 message to JSON as IO data.
Throwing version of json_encode/1
.
Functions
Decode a binary into a protobuf message.
Examples
iex> binary = <<66, 7, 8, 1, 18, 3, 102, 111, 111, 66, 7, 8, 2, 18, 3, 98, 97, 114>>
iex> {:ok, msg} = Protox.decode(binary, Msg)
iex> msg
%Msg{msg_k: %{1 => "foo", 2 => "bar"}}
iex> binary = <<66, 7, 8, 1, 18, 3, 102, 111, 66, 7, 8, 2, 18, 3, 98, 97, 114>>
iex> {:error, reason} = Protox.decode(binary, Msg)
iex> reason
%Protox.IllegalTagError{message: "Field with illegal tag 0"}
Throwing version of decode/2
.
Encode a protobuf message into IO data.
Examples
iex> msg = %Namespace.Fiz.Foo{a: 3, b: %{1 => %Namespace.Fiz.Baz{}}}
iex> {:ok, iodata} = Protox.encode(msg)
iex> :binary.list_to_bin(iodata)
<<8, 3, 18, 4, 8, 1, 18, 0>>
iex> msg = %Namespace.Fiz.Foo{a: "should not be a string"}
iex> {:error, reason} = Protox.encode(msg)
iex> reason
%Protox.EncodingError{field: :a, message: "Could not encode field :a (invalid field value)"}
Throwing version of encode/1
.
Errors
This function returns a tuple {:error, reason}
if:
input
could not be decoded to JSON;reason
is aProtox.JsonDecodingError
error
JSON library configuration
The default library to decode JSON is Jason
.
However, you can chose to use Poison
:
iex> Protox.json_decode("{\"a\":\"BAR\"}", Namespace.Fiz.Foo, json_decoder: Poison)
{:ok, %Namespace.Fiz.Foo{__uf__: [], a: :BAR, b: %{}}}
You can also use another library as long as it exports an decode!
function. You can easily
create a module to wrap a library that would not have this interface (like jiffy
):
defmodule Jiffy do
def decode!(input) do
:jiffy.decode(input, [:return_maps, :use_nil])
end
end
Throwing version of json_decode/2
.
Export a proto3 message to JSON as IO data.
Errors
This function returns a tuple {:error, reason}
if:
msg
could not be encoded to JSON;reason
is aProtox.JsonEncodingError
error
Examples
iex> msg = %Namespace.Fiz.Foo{a: :BAR}
iex> {:ok, iodata} = Protox.json_encode(msg)
iex> iodata
["{", ["\"a\"", ":", "\"BAR\""], "}"]
iex> msg = %Sub{a: 42}
iex> {:ok, iodata} = Protox.json_encode(msg)
iex> iodata
["{", ["\"a\"", ":", "42"], "}"]
iex> msg = %Msg{msg_k: %{1 => "foo", 2 => "bar"}}
iex> {:ok, iodata} = msg |> Protox.json_encode()
iex> :binary.list_to_bin(iodata)
"{\"msgK\":{\"2\":\"bar\",\"1\":\"foo\"}}"
JSON library configuration
The default library to encode values (i.e. mostly to escape strings) to JSON is Jason
.
However, you can chose to use Poison
:
iex> msg = %Namespace.Fiz.Foo{a: :BAR}
iex> Protox.json_encode(msg, json_encoder: Poison)
{:ok, ["{", ["\"a\"", ":", "\"BAR\""], "}"]}
You can also use another library as long as it exports an encode!
function, which is expected to return objects as maps and nil
to represent null
.
You can easily create a module to wrap a library that would not have this interface (like jiffy
):
defmodule Jiffy do
defdelegate encode!(msg), to: :jiffy, as: :encode
end
Encoding specifications
See https://developers.google.com/protocol-buffers/docs/proto3#json for the specifications of the encoding.
Throwing version of json_encode/1
.