wire: Adding special value UNRECOGNIZED to the enum type
Are there any plans for Wire to add an UNRECOGNIZED value to enums, similar to the functionality provided by the proto3 compiler for Java?
https://protobuf.dev/reference/java/java-generated/#enum
The protocol buffer compiler will generate a Java enum type called Foo with the same set of values. If you are using proto3, it also adds the special value UNRECOGNIZED to the enum type.
The context for my query is that I’m working on a project where we’re considering switching to Wire for generating Kotlin code from our proto3 schema. However, I’ve noticed that not all enums in our existing proto schema include a special type in the first position (value 0). This feature of handling unknown enum values automatically is important for our project’s compatibility and robustness, and I’m interested in knowing if Wire plans to support something similar for Kotlin. If this feature is not planned, is there a possibility for me to implement it myself using some custom handler or workaround?
Thank you in advance
About this issue
- Original URL
- State: open
- Created 7 months ago
- Reactions: 1
- Comments: 21 (11 by maintainers)
I think I’m starting to understand what’s happening. Protoc does generate the
UNRECOGNIZED
for Proto3 only (not on proto2).Why?
With the new no-label field in proto3, an enum cannot be null. It has to be of some value, defaulting to its identity value (
0
).The $10 question is: you receive the value
2
when your enum only accepts0
or1
, what value do you get when you read the value after decoding?0
(which I think is a bug)UNRECOGNIZED
constant:-1
. It exposes at the same time two methods: one which returns the constant, the other one returns the value. Here,myEnum()
would returnUNRECOGNIZED
andmyEnumValue()
returns2
.So how about this?
UNRECOGNIZED
for proto3 enum fields, both java & kotlin.UNRECOGNIZED
already exists? looks like protoc crashes.UNRECOGNIZED
like a special value: It is only ever assigned when decoding, should not be used when encoding. Can be manually set to a message, etc.I might have time to do that but that’ll be Feb 2024. @JurajBegovac if you’re willing to do it, why not? We could start on one language at first (the adapter code is shared anyway). I’ll be out for a few weeks so won’t be able to give feedback for a while.
@JurajBegovac We started work on it 2 weeks ago. Should be ready by the end of April, or early May at the latest. We update https://github.com/square/wire/issues/2725#issuecomment-1936321944 as we go
I guess only kotlin is fine but as you wish 😄
Summary of some digging:
kotlin {}
blocks.UNRECOGNIZED -1
only for proto3Steps (PR separation):
KotlinGenerator
, add an option defaulted to false which generatesUNRECOGNIZED(-1)
field for both constructor and builder. This only concerns proto3.private fun <M : Message<M, B>, B : Message.Builder<M, B>, P : Enum<P>> Message<M, B>.unknownEnumTag(property: KProperty1<M, P?>): Int? {
which at call site would look likemyMessage.unknownEnumTag(MyMessage::myEnumGetter)
. I’d like to have the same signature for native and JS if possible.UNRECOGNIZED(-1)
if an opt-in setting is true.It’s on my radar but other priorities right now. I don’t have a clear image yet as how to implement it. I don’t think the constant -1 makes sense with the current API offered by Wire.
Hi @oldergod,
I’ve forked the repository and submitted a pull request with my proposed solution to address the issue
https://github.com/JurajBegovac/wire/pull/1