Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 8 additions & 8 deletions core/src/main/scala/proteus/ProtobufCodec.scala
Original file line number Diff line number Diff line change
Expand Up @@ -365,12 +365,12 @@ object ProtobufCodec {
else CodedOutputStream.computeStringSize(id, value)
case _: PrimitiveType.Double =>
val value = register.asInstanceOf[Register.Double].get(registers, offset)
if (value == 0d && !alwaysEncode) 0
if (value == 0d && java.lang.Double.doubleToRawLongBits(value) == 0L && !alwaysEncode) 0
else if (id == -1) CodedOutputStream.computeDoubleSizeNoTag(value)
else CodedOutputStream.computeDoubleSize(id, value)
case _: PrimitiveType.Float =>
val value = register.asInstanceOf[Register.Float].get(registers, offset)
if (value == 0f && !alwaysEncode) 0
if (value == 0f && java.lang.Float.floatToRawIntBits(value) == 0 && !alwaysEncode) 0
else if (id == -1) CodedOutputStream.computeFloatSizeNoTag(value)
else CodedOutputStream.computeFloatSize(id, value)
case _ => throw new ProteusException(s"Unsupported primitive type: $primitiveType")
Expand Down Expand Up @@ -400,12 +400,12 @@ object ProtobufCodec {
else CodedOutputStream.computeStringSize(id, value)
case _: PrimitiveType.Double =>
val value: Double = a
if (value == 0d && !alwaysEncode) 0
if (value == 0d && java.lang.Double.doubleToRawLongBits(value) == 0L && !alwaysEncode) 0
else if (id == -1) CodedOutputStream.computeDoubleSizeNoTag(value)
else CodedOutputStream.computeDoubleSize(id, value)
case _: PrimitiveType.Float =>
val value: Float = a
if (value == 0f && !alwaysEncode) 0
if (value == 0f && java.lang.Float.floatToRawIntBits(value) == 0 && !alwaysEncode) 0
else if (id == -1) CodedOutputStream.computeFloatSizeNoTag(value)
else CodedOutputStream.computeFloatSize(id, value)
case _ => throw new ProteusException(s"Unsupported primitive type: $primitiveType")
Expand Down Expand Up @@ -437,12 +437,12 @@ object ProtobufCodec {
}
case _: PrimitiveType.Double =>
val value = register.asInstanceOf[Register.Double].get(registers, offset)
if (value != 0d || alwaysEncode) {
if (value != 0d || java.lang.Double.doubleToRawLongBits(value) != 0L || alwaysEncode) {
if (id == -1) output.writeDoubleNoTag(value) else output.writeDouble(id, value)
}
case _: PrimitiveType.Float =>
val value = register.asInstanceOf[Register.Float].get(registers, offset)
if (value != 0f || alwaysEncode) {
if (value != 0f || java.lang.Float.floatToRawIntBits(value) != 0 || alwaysEncode) {
if (id == -1) output.writeFloatNoTag(value) else output.writeFloat(id, value)
}
case _ => throw new ProteusException(s"Unsupported primitive type: $primitiveType")
Expand Down Expand Up @@ -472,12 +472,12 @@ object ProtobufCodec {
}
case _: PrimitiveType.Double =>
val value: Double = a
if (value != 0d || alwaysEncode) {
if (value != 0d || java.lang.Double.doubleToRawLongBits(value) != 0L || alwaysEncode) {
if (id == -1) output.writeDoubleNoTag(value) else output.writeDouble(id, value)
}
case _: PrimitiveType.Float =>
val value: Float = a
if (value != 0f || alwaysEncode) {
if (value != 0f || java.lang.Float.floatToRawIntBits(value) != 0 || alwaysEncode) {
if (id == -1) output.writeFloatNoTag(value) else output.writeFloat(id, value)
}
case _ => throw new ProteusException(s"Unsupported primitive type: $primitiveType")
Expand Down
8 changes: 6 additions & 2 deletions core/src/main/scala/proteus/ProtobufDeriver.scala
Original file line number Diff line number Diff line change
Expand Up @@ -271,7 +271,7 @@ case class ProtobufDeriver private (
getComment(field.modifiers)
)
case instance =>
val fieldId = getReservedIndex(field.modifiers) match {
val fieldId = getReservedIndex(field.modifiers) match {
case Some(reservedIndex) => reservedIndex
case None =>
getReservedFromIndex(field.modifiers) match {
Expand All @@ -284,12 +284,16 @@ case class ProtobufDeriver private (
id
}
}
val fieldDefault = instance match {
case _: ProtobufCodec.Primitive[?] => getDefaultValue(using instance)
case _ => field.value.getDefaultValue.getOrElse(getDefaultValue(using instance))
}
builder += SimpleField(
name,
fieldId,
instance,
register,
field.value.getDefaultValue.getOrElse(getDefaultValue(using instance)),
fieldDefault,
getComment(field.modifiers),
isDeprecated(field.modifiers)
)
Expand Down
19 changes: 19 additions & 0 deletions core/src/test/scala/proteus/ProtobufCodecSpec.scala
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,25 @@ object ProtobufCodecSpec extends ZIOSpecDefault {
val decoded = codec.decode(encoded)

assert(decoded)(equalTo(original))
},
test("primitive field with a non-zero default round-trips its zero value") {
case class WithDefault(count: Int = 5, label: String = "x") derives Schema
val codec = Schema[WithDefault].derive(deriver)

val original = WithDefault(0, "")
val decoded = codec.decode(codec.encode(original))

assert(decoded)(equalTo(original))
},
test("negative-zero double and float fields preserve their sign bit") {
case class Zeros(d: Double, f: Float) derives Schema
val codec = Schema[Zeros].derive(deriver)

val original = Zeros(-0.0, -0.0f)
val decoded = codec.decode(codec.encode(original))

assert(java.lang.Double.doubleToRawLongBits(decoded.d))(equalTo(java.lang.Double.doubleToRawLongBits(-0.0))) &&
assert(java.lang.Float.floatToRawIntBits(decoded.f))(equalTo(java.lang.Float.floatToRawIntBits(-0.0f)))
}
),
suite("Enum Tests")(
Expand Down