protobuf icon indicating copy to clipboard operation
protobuf copied to clipboard

Inconsistent behaviour when encoding oneof

Open nsweeting opened this issue 7 months ago • 3 comments

Hi there,

We're seeing (what feels like) inconsistent behaviour when encoding oneof values.

Given the following protobuf:

syntax = "proto3";

message Foo {
  message Bar {
    string value = 1;
  }

  message Baz {}

  oneof value {
    Bar bar = 1;
    Baz baz = 2;
  }
}

Which compiles to the following elixir code:

defmodule Foo.Bar do
  @moduledoc false

  use Protobuf, protoc_gen_elixir_version: "0.12.0", syntax: :proto3

  field(:value, 1, type: :string)
end

defmodule Foo.Baz do
  @moduledoc false

  use Protobuf, protoc_gen_elixir_version: "0.12.0", syntax: :proto3
end

defmodule Foo do
  @moduledoc false

  use Protobuf, protoc_gen_elixir_version: "0.12.0", syntax: :proto3

  oneof(:value, 0)

  field(:bar, 1, type: Foo.Bar, oneof: 0)
  field(:baz, 2, type: Foo.Baz, oneof: 0)
end

When encoding/decoding a message that contains a map for Foo.Bar (not the struct) and it contains a value - things work as expected:

foo = %Foo{value: {:bar, %{value: "bar"}}}
foo |> Foo.encode() |> Foo.decode()

%Foo{
  value: {:bar, %Foo.Bar{value: "bar", __unknown_fields__: []}},
  __unknown_fields__: []
}

But when encoding/decoding an empty map - it simply gets dropped entirely - even though we are passing the proper tuple for the oneof:

foo = %Foo{value: {:baz, %{}}}
foo |> Foo.encode() |> Foo.decode()

%Foo{value: nil, __unknown_fields__: []}

Since we've noted which oneof it is - it seems like it should be included.

Thanks

nsweeting avatar Nov 23 '23 22:11 nsweeting