# `Protox`
[🔗](https://github.com/ahamez/protox/blob/main/lib/protox.ex#L1)

Use this module to generate the Elixir structs corresponding to a set of protobuf definitions
and to encode/decode instances of these structures.

## Elixir 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.

# `check_generator_version`

# `decode`
*since 1.6.0* 

```elixir
@spec decode(binary(), atom()) :: {:ok, struct()} | {:error, any()}
```

Decode a binary into a protobuf message.

## Examples
    iex> binary = <<8, 42, 18, 7, 8, 1, 18, 3, 102, 111, 111>>
    iex> {:ok, msg} = Protox.decode(binary, ProtoxExample)
    iex> msg
    %ProtoxExample{a: 42, b: %{1 => "foo"}}

    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, ProtoxExample)
    iex> reason
    %Protox.DecodingError{
                  message: "Could not decode data (invalid wire type 7)",
                  binary: <<7, 8, 2, 18, 3, 98, 97, 114>>
                }

# `decode!`
*since 1.6.0* 

```elixir
@spec decode!(binary(), atom()) :: struct() | no_return()
```

Throwing version of `decode/2`.

# `encode`
*since 1.6.0* 

```elixir
@spec encode(struct()) :: {:ok, iodata(), non_neg_integer()} | {:error, any()}
```

Encode a protobuf message into IO data.

## Examples
    iex> msg = %ProtoxExample{a: 3, b: %{1 => "some string"}}
    iex> {:ok, iodata, _iodata_size} = Protox.encode(msg)
    iex> IO.iodata_to_binary(iodata)
    <<8, 3, 18, 15, 8, 1, 18, 11, 115, 111, 109, 101, 32, 115, 116, 114, 105, 110, 103>>

    iex> msg = %ProtoxExample{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)"}

# `encode!`
*since 1.6.0* 

```elixir
@spec encode!(struct()) :: {iodata(), non_neg_integer()} | no_return()
```

Throwing version of `encode/1`.

# `generator_version`

---

*Consult [api-reference.md](api-reference.md) for complete listing*
