-
Notifications
You must be signed in to change notification settings - Fork 143
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Inconsistent behaviour when encoding oneof #362
Comments
What happens if you use a struct instead of an empty map? %Foo{value: {:baz, %Foo.Baz{}}} The library should probably not accept maps in place of structs but it is possible that it sees the empty map as a default value which are not encoded and since it's not encoded no oneof field was selected. |
There's two issues here:
Foo.encode(%Foo{value: {:bar, %{value: "bar"}}}) because
We're investigating this! cc @savhappy |
Also, 1. above might be related to #365. |
It seems to me that oneofs are always sent over the wire, even if the value is default, both for proto 2 and proto 3. I'll double check this, but if I'm right here, I think my PR at #379 implements the correct behaviour. With regards to the 1st problem:
This may be a pretty big breaking change. We can afford to do it as we are pre-1.0, but it's probably worth it to at least add a deprecation warning first, etc. WDYT? |
@v0idpwn why a "big breaking change"? Isn't that the expected behavior rather? |
I may be overestimating it's prevalence, but in my experience, the following snippet is rather common: Protobuf.encode!(%StructA{inner_struct: %{b: 1}}) That is, the caller explicitly says what's the most external struct, but relies in the library to deal with the rest. This works for maps and keywords, currently. Making it an exception straight away might make it hard to update the library, hence I'd prefer the warning path (but honestly I wouldn't mind it staying this way 😄 ) |
But this way is semantically just wrong, isn't it? When encoding, you own the data you're encoding so I find it surprising that you'd need the flexibility. Do you have example use cases of this kind of patterns in real-world code that you could point me to to help me understand? Btw, @ericmj any opinions here? |
Originally, you'd have something like: StructA.new!(inner_struct: [b: 1]) Then, when |
I've myself relied on this, on APIs that accepted arbitrary keyword lists and transformed into the protobuf to send a request. Manually converting is... verbose. The following code is not very assertive, but generally works: def create_user(keyword) do
request = struct!(CreateUserRequest, keyword)
encoded_request = CreateUserRequest.encode!(request)
call_external_api(encoded_request)
end Before, you'd use |
Hi there,
We're seeing (what feels like) inconsistent behaviour when encoding oneof values.
Given the following protobuf:
Which compiles to the following elixir code:
When encoding/decoding a message that contains a map for
Foo.Bar
(not the struct) and it contains a value - things work as expected:But when encoding/decoding an empty map - it simply gets dropped entirely - even though we are passing the proper tuple for the oneof:
Since we've noted which oneof it is - it seems like it should be included.
Thanks
The text was updated successfully, but these errors were encountered: