Skip to content

Commit

Permalink
Merge pull request #235 from disneystreaming/proto-timestamp-format
Browse files Browse the repository at this point in the history
timestamp format for proto
  • Loading branch information
Baccata authored Mar 14, 2024
2 parents 2b8509a + a38f63d commit 105a990
Show file tree
Hide file tree
Showing 6 changed files with 69 additions and 22 deletions.
2 changes: 1 addition & 1 deletion buildDeps.sc
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import mill.define._
import mill.scalalib._

object alloy {
val alloyVersion = "0.3.0"
val alloyVersion = "0.3.3"
val core =
ivy"com.disneystreaming.alloy:alloy-core:$alloyVersion"
val protobuf =
Expand Down
30 changes: 16 additions & 14 deletions buildSetup.sc
Original file line number Diff line number Diff line change
Expand Up @@ -35,20 +35,22 @@ trait BaseModule extends Module with HeaderModule {
}

def includeFileExtensions: List[String] = List("scala", "java")
def license: HeaderLicense = HeaderLicense.Custom("""|Copyright 2022 Disney Streaming
|
|Licensed under the Tomorrow Open Source Technology License, Version 1.0 (the "License");
|you may not use this file except in compliance with the License.
|You may obtain a copy of the License at
|
| https://disneystreaming.github.io/TOST-1.0.txt
|
|Unless required by applicable law or agreed to in writing, software
|distributed under the License is distributed on an "AS IS" BASIS,
|WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|See the License for the specific language governing permissions and
|limitations under the License.
|""".stripMargin)
def license: HeaderLicense = HeaderLicense.Custom(
"""|Copyright 2022 Disney Streaming
|
|Licensed under the Tomorrow Open Source Technology License, Version 1.0 (the "License");
|you may not use this file except in compliance with the License.
|You may obtain a copy of the License at
|
| https://disneystreaming.github.io/TOST-1.0.txt
|
|Unless required by applicable law or agreed to in writing, software
|distributed under the License is distributed on an "AS IS" BASIS,
|WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|See the License for the specific language governing permissions and
|limitations under the License.
|""".stripMargin
)
}

trait BasePublishModule extends BaseModule with CiReleaseModule {
Expand Down
2 changes: 1 addition & 1 deletion modules/cli/src/runners/Proto.scala
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,7 @@ private object Deps {
val validDeps = DependencyParser
.dependencies(
dependencies,
defaultScalaVersion = "2.13.10"
defaultScalaVersion = "2.13.12"
)
.either
.getOrElse(sys.error("Invalid dependency."))
Expand Down
2 changes: 1 addition & 1 deletion modules/openapi/tests/src/DebugSpec.scala
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ final class DebugSpec extends munit.FunSuite {
}

test("load with debug leaves validation events untouched") {
testFilteredErrors(debug = true, expectedCount = 5)
testFilteredErrors(debug = true, expectedCount = 4)
}
test("load without debug filters validation events") {
testFilteredErrors(debug = false, expectedCount = 2)
Expand Down
45 changes: 40 additions & 5 deletions modules/proto/src/smithytranslate/proto3/internals/Compiler.scala
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ import software.amazon.smithy.model.neighbor.NeighborProvider
import software.amazon.smithy.model.neighbor.Walker
import alloy.OpenEnumTrait
import software.amazon.smithy.model.traits.EnumValueTrait
import alloy.proto.ProtoTimestampFormatTrait

private[proto3] class Compiler(model: Model, allShapes: Boolean) {

Expand Down Expand Up @@ -400,9 +401,16 @@ private[proto3] class Compiler(model: Model, allShapes: Boolean) {
Type.RefType(targetShape)
} else {
val numType = extractNumType(m)
val maybeTimestampFormat = extractTimestampFormat(m)
val wrapped = hasProtoWrapped(m)
targetShape
.accept(typeVisitor(wrapped, numType))
.accept(
typeVisitor(
isWrapped = wrapped,
numType = numType,
timestampFormat = maybeTimestampFormat
)
)
.get
}
val field = MessageElement.FieldElement(
Expand Down Expand Up @@ -507,6 +515,15 @@ private[proto3] class Compiler(model: Model, allShapes: Boolean) {
.map { _.getNumType() }
}

private def extractTimestampFormat(
shape: Shape
): Option[ProtoTimestampFormatTrait.TimestampFormat] = {
shape
.getTrait(classOf[ProtoTimestampFormatTrait])
.toScala
.map(_.getTimestampFormat())
}

private def isUnit(shape: StructureShape): Boolean = {
shape
.getTrait(classOf[UnitTypeTrait])
Expand All @@ -519,7 +536,8 @@ private[proto3] class Compiler(model: Model, allShapes: Boolean) {
// TODO: namespace in type?
private def typeVisitor(
isWrapped: Boolean = false,
numType: Option[ProtoNumTypeTrait.NumType] = None
numType: Option[ProtoNumTypeTrait.NumType] = None,
timestampFormat: Option[ProtoTimestampFormatTrait.TimestampFormat] = None
): ShapeVisitor[Option[Type]] =
new ShapeVisitor[Option[Type]] {
def bigDecimalShape(shape: BigDecimalShape): Option[Type] = Some {
Expand Down Expand Up @@ -591,8 +609,15 @@ private[proto3] class Compiler(model: Model, allShapes: Boolean) {
.or(() => target.getTrait(classOf[ProtoNumTypeTrait]))
.toScala
.map(_.getNumType())
val timestampFormatValue = extractTimestampFormat(shape)

target.accept(typeVisitor(isWrapped, numType))
target.accept(
typeVisitor(
isWrapped = isWrapped,
numType = numType,
timestampFormat = timestampFormatValue
)
)
}

def operationShape(shape: OperationShape): Option[Type] = None
Expand Down Expand Up @@ -630,8 +655,18 @@ private[proto3] class Compiler(model: Model, allShapes: Boolean) {
}

def timestampShape(shape: TimestampShape): Option[Type] = Some {
if (!isWrapped) Type.GoogleTimestamp
else Type.AlloyWrappers.Timestamp
val format =
extractTimestampFormat(shape)
.orElse(timestampFormat)
.getOrElse(ProtoTimestampFormatTrait.TimestampFormat.PROTOBUF)
val isEpochMillis =
(format == ProtoTimestampFormatTrait.TimestampFormat.EPOCH_MILLIS)
if (!isWrapped) {
if (isEpochMillis) Type.Int64 else Type.GoogleTimestamp
} else {
if (isEpochMillis) Type.GoogleWrappers.Int64
else Type.AlloyWrappers.Timestamp
}
}

def unionShape(shape: UnionShape): Option[Type] = Some(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -177,6 +177,8 @@ class CompilerRendererSuite extends FunSuite {

test("Primitive fields") {
val source = """|namespace com.example
|
|use alloy.proto#protoTimestampFormat
|
|structure Struct {
| boolean: Boolean
Expand All @@ -192,6 +194,8 @@ class CompilerRendererSuite extends FunSuite {
| document: Document
| string: String
| timestamp: Timestamp
| @protoTimestampFormat("EPOCH_MILLIS")
| epoch: Timestamp
|}
|""".stripMargin

Expand All @@ -217,6 +221,7 @@ class CompilerRendererSuite extends FunSuite {
| google.protobuf.Value document = 11;
| string string = 12;
| google.protobuf.Timestamp timestamp = 13;
| int64 epoch = 14;
|}
|""".stripMargin
convertCheck(source, Map("com/example/example.proto" -> expected))
Expand All @@ -226,6 +231,7 @@ class CompilerRendererSuite extends FunSuite {
val source = """|namespace com.example
|
|use alloy.proto#protoWrapped
|use alloy.proto#protoTimestampFormat
|
|structure Struct {
| @protoWrapped
Expand Down Expand Up @@ -254,6 +260,9 @@ class CompilerRendererSuite extends FunSuite {
| string: String
| @protoWrapped
| timestamp: Timestamp
| @protoWrapped
| @protoTimestampFormat("EPOCH_MILLIS")
| epoch: Timestamp
|}
|""".stripMargin

Expand All @@ -279,6 +288,7 @@ class CompilerRendererSuite extends FunSuite {
| alloy.protobuf.DocumentValue document = 11;
| google.protobuf.StringValue string = 12;
| alloy.protobuf.TimestampValue timestamp = 13;
| google.protobuf.Int64Value epoch = 14;
|}
|""".stripMargin
convertCheck(source, Map("com/example/example.proto" -> expected))
Expand Down

0 comments on commit 105a990

Please sign in to comment.