-
Notifications
You must be signed in to change notification settings - Fork 15
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
Protobuf compilation: schema and protocol #66
Conversation
…ing protoc-jar maven plugin
…orking through coalgebra implementation
…eam help/feedback
…e working just yet
…ess/skeuomorph into protobuf_compilation # Conflicts: # src/main/scala/protobuf/schema.scala
…tor code still failing
…into protobuf_compilation
…ess/skeuomorph into protobuf_compilation
Few questions:
Why not use scala enum instead? How do you define an option on proto3? Should the scala generated code have some imports? Is this supporting bigdecimal? |
@juanpedromoreno Interesting. I barely haven't changed the printer, but yes, I should have detected this issue. I'm on it. |
def dependency: Printer[String] = konst("import ") *< string >* konst("._")
|
@rafaparadela I know all fields in |
@juanpedromoreno Solved printer of the operations at 769ff31 |
@AdrianRaFo The long debate about the lack of |
Thanks, rafa just make sure to include into the doc 😉👏 |
I'd avoid the Enum, I prefer having a proper ADT. @rafaparadela |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Awesome work @rafaparadela, thank you very much to push this forward! Also, thanks to all other people involved, @rlmark @oli-kitty, you rock!
@rafaparadela , I added a couple of comments and suggestions, none of them are a blocker though. If you prefer merging & addressing those later on, I'm OK with that too!
fields | ||
.filter(t => t.hasOneofIndex && t.getOneofIndex == index) | ||
.map(fromFieldDescriptorProto(_, source, files)) | ||
.collect { case b: NativeField => b }) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I believe this b: NativeField
is doing a ClassTag
check at runtime. Can you change it with a pattern match like:
.collect { case b: NativeField => b }) | |
.collect { case b@NativeField(_, _, _, _, _, _) => b }) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Solved at 78581e0
.map(_.msg) | ||
} | ||
|
||
implicit class LabelOps(self: Label) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can we make this implicit class private? I'd like to avoid polluting the namespace in case someone imports NativeField._
.
implicit class LabelOps(self: Label) { | |
private implicit class LabelOps(self: Label) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Solved at 78581e0
def isRepeated: Boolean = self.name() == "LABEL_REPEATED" | ||
} | ||
|
||
implicit class JavaListOps[B](self: util.List[B]) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
same here
implicit class JavaListOps[B](self: util.List[B]) { | |
private implicit class JavaListOps[B](self: util.List[B]) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Solved at 78581e0
|
||
final case class NativeOneOfField(name: String, tpe: NativeOneOf) extends NativeFieldF | ||
|
||
sealed trait NativeDescriptor |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Following with the conversation in #64 (comment),
What's the use of this ADT? Is it just intermediate representation that will not be exposed to the user? If we want to keep it, can we make it non-recursive at least? We can throw more recursion schemes if so! 😋
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
+1
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I was probably wrong, but I assumed that if I need to define a Coalgebra[ProtobufF, A]
to go from A
to ProtobufF[A]
, then A
needs to be recursive. At least, I couldn't express Coalgebra[ProtobufF, FileDescriptorSet]
<- being FileDescriptorSet
the original Java descriptor for the schema of protobuf.
Actually, NativeDescriptor
is not a 1-to-1 representation of FileDescriptorSet
, but contains a lot of business logic to aggregate data, and to discard unnecessary fields down the road.
Frankly, I'd love to try Coalgebra[ProtobufF, FileDescriptorSet]
again with your help.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Solved at 7ce48d6
def toTOption(no: NativeOption): ProtobufF.Option = | ||
ProtobufF.Option(no.name, no.value) | ||
|
||
def toJson: Algebra[ProtobufF, Json] = Algebra { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What are we using this for? Is there a JSON representation for Protobuf?
If we're using this to translate to Avro, I believe that the correct path would be:
Trans[ProtobufF, AvroF]
and then Algebra[AvroF, Json]
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We can tackle this in a different PR, I have removed the Algebra[ProtobufF, Json]
, since is not being used so far.
| def GetBooks(req: Stream[F, GetBookRequest]): Stream[F, Book] | ||
|} | ||
| | ||
|}""".stripMargin |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
👏 👏 👏 👏 👏 !!!!!! 🎉 🎉 🎈 🎉!!!
THIS IS AWESOME
|
||
final case class NativeOneOfField(name: String, tpe: NativeOneOf) extends NativeFieldF | ||
|
||
sealed trait NativeDescriptor |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
+1
file.getServiceList.j2s.map(s => toNativeService(s, files)) | ||
) | ||
} | ||
.getOrElse(throw new Exception(s"Could not find descriptors for: $descriptorFileName")) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could we use some of the defined errors here, rather than Exception
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Solved at 78581e0
val (hasAlias, noAlias) = valuesAndAliases.groupBy(_.getNumber).values.partition(_.lengthCompare(1) > 0) | ||
val separateValueFromAliases: Iterable[(EnumValueDescriptorProto, List[EnumValueDescriptorProto])] = hasAlias.map { | ||
case h :: t => (h, t) | ||
case _ => throw new Exception(s"Wrong number of aliases") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same here: Could we use some of the defined errors here, rather than Exception
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Solved at 78581e0
maybeKey <- getMapField(maybeMsg, "key") | ||
maybeValue <- getMapField(maybeMsg, "value") | ||
} yield NativeMap(fromFieldType(maybeKey, files), fromFieldType(maybeValue, files))) | ||
.getOrElse(throw new Exception(s"Could not find map entry for: $name")) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
and here: Could we use some of the defined errors here, rather than Exception
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Solved at 78581e0
.filter(t => t.hasOneofIndex && t.getOneofIndex == index) | ||
.map(fromFieldDescriptorProto(_, source, files)) | ||
.collect { case b: NativeField => b }) | ||
.getOrElse(throw new Exception(s"Empty set of fields in OneOf: ${oneof.getName}")) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
and here: Could we use some of the defined errors here, rather than Exception
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Solved at 78581e0
Regarding #66 (comment), I'd prefer ADT for enums too. |
# Conflicts: # src/main/scala/higherkindness/skeuomorph/protobuf/Native.scala # src/main/scala/higherkindness/skeuomorph/protobuf/ParseProto.scala # src/main/scala/higherkindness/skeuomorph/protobuf/schema.scala
@juanpedromoreno Finally the intermediate NativeDescriptor has been removed with the great help of @pepegar . I think this is ready to be merged (once we got a green from CI) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks awesome to me! 👍
Given a proto file, we wanted to generate of Scala code, and this PR does this.
Included goodness:
This is the example:
Protobuf
Parsing nested
.proto
files and converting into Scala codeGiven these proto files below:
author.proto
book.proto
We can parse and convert them into Scala code as:
It would generate: