Skip to content

Commit

Permalink
docs: add a migration guide
Browse files Browse the repository at this point in the history
  • Loading branch information
ahamez committed Feb 27, 2025
1 parent 503b2c8 commit 7c57ab8
Show file tree
Hide file tree
Showing 3 changed files with 87 additions and 16 deletions.
31 changes: 16 additions & 15 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,30 +5,31 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## [Unreleased]
## Unreleased

### Added
- schema/0 to access the underlying definition of a message.
- `schema/0` to access the underlying definition of a message.

### Changed
- BREAKING CHANGE: Configuration of features to generate via the CLI mix task is done with the `--generate` argument.
- BREAKING CHANGE: encoding functions now return the size alongside iodata. Before that, one had to use :binary.list_to_bin/1 to flatten the iodata to then use byte_size, defeating the purpose of having an iodata.
- BREAKING CHANGE: `Protox.decode!` and `Protox.decode` no longer raise or return an error if a message with required fields don't have all said fields set. The rationale being that we should let the user decide if it's a problem or not.
- Minimal supported Elixir version is now 1.15.
- BREAKING CHANGE: encoding functions now return the size alongside iodata.
Previously, one had to use `:binary.list_to_bin/1` to flatten the iodata and then use `byte_size`, defeating the purpose of having an iodata. Furthermore, it provides a significant performance boost.
- BREAKING CHANGE: `Protox.decode!` and `Protox.decode` no longer raise or return an error if a message don't have all required fields set. We should let the user decide whether it's a problem.
- BREAKING CHANGE: Rename `InvalidFieldAttribute` to `InvalidFieldAttributeError` for consistency.

### Removed
- Drop support for Elixir < 1.15.
- BREAKING CHANGE: Drop support of JSON encoding and decoding.
- BREAKING CHANGE: Remove :path option in favor of :paths.
- BREAKING CHANGE: Remove :keep_unknown_fields option.
It added complexity to the generation logic while not providing any value as one can simply ignore those fields.
- BREAKING CHANGE: Remove generated `syntax/0` (functionality still available through schema/1).
- BREAKING CHANGE: Remove generated `file_options/0` (functionality still available through schema/1).
- BREAKING CHANGE: Remove generated `field_def/1` (functionality still available through schema/1).
- BREAKING CHANGE: Remove generated `defs/0` (functionality still available through schema/1).
- BREAKING CHANGE: Remove generated `required_fields/0` (functionality still available through schema/1).
The implementation was half-baked, it's preferable to have the library focused. Even [Google doesn't recommend](https://protobuf.dev/programming-guides/json/) using JSON: _"In short, there are many good reasons why Google prefers to use the standard wire format for virtually everything rather than ProtoJSON format"_.
- BREAKING CHANGE: Remove `:path` option in favor of the already existing `:paths` option, which covers the same functionality.
- BREAKING CHANGE: Remove `:keep_unknown_fields` option (the corresponding `--keep-unknown-fields` option for the mix task `protox.generate` is also removed). They are now always kept.
It added complexity to the generation logic while not providing any value as one can simply ignore those fields and as it's mandatory to parse them correctly.
- BREAKING CHANGE: Remove generated `defs/0` (functionality remains available through `schema/0`).
- BREAKING CHANGE: Remove generated `field_def/1` (functionality remains available through `schema/0`).
- BREAKING CHANGE: Remove generated `file_options/0` (functionality remains available through `schema/0`).
- BREAKING CHANGE: Remove generated `required_fields/0` (functionality remains available through `schema/0`).
- BREAKING CHANGE: Remove generated `syntax/0` (functionality remains available through `schema/0`).
- BREAKING CHANGE: Remove generated `encode/1` from strings for enums.
- BREAKING CHANGE: Remove `Protox.Encode.encode/1` and `Protox.Encode.encode!/1` (functionality is still available in generated modules and in `Protox`.).
- BREAKING CHANGE: Remove `Protox.Encode.encode/1` and `Protox.Encode.encode!/1` (functionality remains available in generated modules and in `Protox`).


## 1.7.8
Expand Down
5 changes: 4 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,9 @@
Protox is an Elixir library for working with [Google's Protocol Buffers](https://developers.google.com/protocol-buffers), versions 2 and 3, supporting
binary encoding and decoding.

> [!NOTE]
> If you're using version 1, please see how to migrate to version 2 [here](documentation/v1_to_v2_migration.md).
## Example

Given the following protobuf definition:
Expand Down Expand Up @@ -101,7 +104,7 @@ defmodule MyModule do
use Protox, files: [
"./defs/foo.proto",
"./defs/bar.proto",
"./defs/baz/fiz.proto",
"./defs/baz/fiz.proto"
]
end
```
Expand Down
67 changes: 67 additions & 0 deletions documentation/v1_to_v2_migration.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
# Migration Guide

This guide explains how to migrate from version 1 to version 2 of Protox.

> [!NOTE]
> You'll find the rationales behind the changes in the [changelog](../CHANGELOG.md).
## Encoding

Protox now returns the size of the encoded messages along with the encoded data. If you don't need the size, you can simply ignore it:

```elixir
iex> msg = %Foo{a: 3, b: %{1 => %Baz{}}}
{:ok, iodata, _iodata_size} = Protox.encode(msg)
```

## JSON support

It's no longer possible to encode or decode JSON data directly using Protox. If it's necessary, you can stick to version 1.7 or switch to [`protobuf`](https://hex.pm/packages/protobuf).

## `Protox` options

The `:path` option is removed in favor of the already existing `:paths` option, thus one just has to provide a list containing a single path.

Also, the `:keep_unknown_fields` option is no longer available. Thus, unknown fields are always kept. If you don't need them, you juste have to ignore them.

## Generated code

The following functions generated for messages are replaced by the function `schema/0`:

- `defs/0`
- `field_def/1`
- `file_options/0`
- `required_fields/0`
- `syntax/0`

`schema/0` returns a `%Protox.MessageSchema{}` struct which contains information about the message's fields, syntax, and file options.

### Example

```elixir
iex> defmodule MyModule do
use Protox, schema: """
syntax = "proto2";
message Foo {
required int32 a = 1;
map<int32, string> b = 2;
}
"""
end

iex> Foo.schema().syntax
:proto2

iex> Foo.schema().fields[:a]
%Protox.Field{
tag: 1,
label: :required,
name: :a,
kind: %Protox.Scalar{default_value: 0},
type: :int32
}

iex> Foo.schema().file_options
nil
```

0 comments on commit 7c57ab8

Please sign in to comment.