From 7c57ab82a47349fd3b73b4b421039d7994497269 Mon Sep 17 00:00:00 2001 From: Alexandre Hamez Date: Thu, 27 Feb 2025 15:57:26 +0100 Subject: [PATCH] docs: add a migration guide --- CHANGELOG.md | 31 ++++++------- README.md | 5 ++- documentation/v1_to_v2_migration.md | 67 +++++++++++++++++++++++++++++ 3 files changed, 87 insertions(+), 16 deletions(-) create mode 100644 documentation/v1_to_v2_migration.md diff --git a/CHANGELOG.md b/CHANGELOG.md index 32bc1cc1..8f9d3e33 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -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 diff --git a/README.md b/README.md index b1cd6ab4..40383f56 100644 --- a/README.md +++ b/README.md @@ -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: @@ -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 ``` diff --git a/documentation/v1_to_v2_migration.md b/documentation/v1_to_v2_migration.md new file mode 100644 index 00000000..9bbe0eed --- /dev/null +++ b/documentation/v1_to_v2_migration.md @@ -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 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 +```