Optional enum values with proto3

2,179 views
Skip to first unread message

Eugene Zhoga

unread,
Feb 6, 2019, 5:35:23 AM2/6/19
to ScalaPB
Hi,

Is it possible to wrap somehow enum (like primitive type) to have Option[EnumType] as output (proto3 is used)?
The only possibility for now I see is to wrap it into message but in this case it looks a bit ugly, like value = Some(EnumWrapper(EnumValue))
Is it any technic how to eliminate this intermediate EnumWrapper?

Thank you.
Evgeny

Nadav Samet

unread,
Feb 6, 2019, 4:01:30 PM2/6/19
to Eugene Zhoga, ScalaPB
There isn't a generic way to do it. One option to consider would be to use Int32Value from wrappers.proto (https://scalapb.github.io/customizations.html#primitive-wrappers) and add a custom type that would convert between Int32Value and the enum (https://scalapb.github.io/customizations.html#custom-types).

You can also use your own message type (MyEnumValue) and use a type mapper to convert between MyEnumValue and the value that is inside, but that requires a message type for each enum. It's probably the preferred way because this is more type-safe for non-ScalaPB users (the proto would reference the enum type and not just an int32)

--
You received this message because you are subscribed to the Google Groups "ScalaPB" group.
To unsubscribe from this group and stop receiving emails from it, send an email to scalapb+u...@googlegroups.com.
To post to this group, send email to sca...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/scalapb/39215fac-778e-4fee-ac65-86fdb8183e08%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.


--
-Nadav

Eugene Zhoga

unread,
Feb 7, 2019, 3:19:30 AM2/7/19
to ScalaPB
@Nadav Samet: Once again, thank you!

To extend your reply with some code snippets (to cover both cases + mapping to string):

proto description

syntax = "proto3";

option java_package
= "com.example";

import "google/protobuf/wrappers.proto";
import "scalapb/scalapb.proto";

option
(scalapb.options) = {
   
import: "com.example.Converters._"
};

enum Error {
   
NoError = 0;

   
SomeEnumError = 999999;
}
message
EnumsHolder {
   
enum SomeEnum {
       
SomeValue = 0;

        reserved
999999; // error mapping
    }
    message
SomeEnumWrapper {
       
SomeEnum value = 1;
   
}
}

message
OptionalEnumUsage {
    int32 id
= 1;
   
EnumsHolder.SomeEnumWrapper enum1 = 2 [(scalapb.field).type="EnumsHolder.SomeEnum"];
    google
.protobuf.Int32Value enum2 = 3 [(scalapb.field).type="EnumsHolder.SomeEnum"];
    google
.protobuf.StringValue enum3 = 4 [(scalapb.field).type="EnumsHolder.SomeEnum"];
}

and Converters:

package com.example

import com.google.protobuf.wrappers.{Int32Value, StringValue}
import scalapb.TypeMapper

object Converters {
 
implicit val Int32Value2NezasaTouroperatorMapper: TypeMapper[Int32Value, EnumsHolder.SomeEnum] =
   
TypeMapper[Int32Value, EnumsHolder.SomeEnum](i => EnumsHolder.SomeEnum.fromValue(i.value))(e => Int32Value(e.value))

 
implicit val StringValue2NezasaTouroperatorMapper: TypeMapper[StringValue, EnumsHolder.SomeEnum] =
   
TypeMapper[StringValue, EnumsHolder.SomeEnum](i => EnumsHolder.SomeEnum.fromName(i.value).getOrElse(EnumsHolder.SomeEnum.Unrecognized(Error.SomeEnumError.value)))(e => StringValue(e.name))

 
implicit val SomeEnumWrapper2SomeEnumMapper: TypeMapper[EnumsHolder.SomeEnumWrapper, EnumsHolder.SomeEnum] =
   
TypeMapper[EnumsHolder.SomeEnumWrapper, EnumsHolder.SomeEnum](_.value)(EnumsHolder.SomeEnumWrapper().withValue)

}


Best regards,
Evgeny
Reply all
Reply to author
Forward
0 new messages