Skip to content

Commit

Permalink
Add primitive uuid support (#91)
Browse files Browse the repository at this point in the history
* Add primitive uuid support

* Handle uuid decoding failure

* Run sbt prepare
  • Loading branch information
paulpdaniels committed Sep 27, 2021
1 parent e7d5032 commit 1615556
Show file tree
Hide file tree
Showing 7 changed files with 41 additions and 10 deletions.
1 change: 1 addition & 0 deletions zio-schema/shared/src/main/scala/zio/schema/Diff.scala
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,7 @@ object Differ {
case Schema.Primitive(StandardType.BigDecimalType) => bigDecimal
case Schema.Primitive(StandardType.BigIntegerType) => bigInt
case Schema.Primitive(StandardType.StringType) => string
case Schema.Primitive(StandardType.UUIDType) => string.transform(_.toString)
case Schema.Primitive(StandardType.DayOfWeekType) => dayOfWeek
case Schema.Primitive(StandardType.Month) => month
case Schema.Primitive(StandardType.MonthDay) => monthDay
Expand Down
24 changes: 14 additions & 10 deletions zio-schema/shared/src/main/scala/zio/schema/StandardType.scala
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ object StandardType {
final val OFFSET_TIME = "offsetTime"
final val OFFSET_DATE_TIME = "offsetDateTime"
final val ZONED_DATE_TIME = "zonedDateTime"
final val UUID = "uuid"
}

def fromString(tag: String): Option[StandardType[_]] =
Expand Down Expand Up @@ -73,6 +74,7 @@ object StandardType {
case Tags.OFFSET_TIME => Some(OffsetTime(DateTimeFormatter.ISO_OFFSET_TIME))
case Tags.OFFSET_DATE_TIME => Some(OffsetDateTime(DateTimeFormatter.ISO_OFFSET_DATE_TIME))
case Tags.ZONED_DATE_TIME => Some(ZonedDateTime(DateTimeFormatter.ISO_ZONED_DATE_TIME))
case Tags.UUID => Some(UUIDType)
case units =>
try {
Some(Duration(ChronoUnit.valueOf(units)))
Expand All @@ -82,16 +84,17 @@ object StandardType {
def fromTemporalUnits(units: String): Option[StandardType[java.time.Duration]] =
ChronoUnit.values().find(_.toString == units).map(Duration(_))

implicit object UnitType extends StandardType[Unit] { override def tag = Tags.UNIT }
implicit object StringType extends StandardType[String] { override def tag = Tags.STRING }
implicit object BoolType extends StandardType[Boolean] { override def tag = Tags.BOOL }
implicit object ShortType extends StandardType[Short] { override def tag = Tags.SHORT }
implicit object IntType extends StandardType[Int] { override def tag = Tags.INT }
implicit object LongType extends StandardType[Long] { override def tag = Tags.LONG }
implicit object FloatType extends StandardType[Float] { override def tag = Tags.FLOAT }
implicit object DoubleType extends StandardType[Double] { override def tag = Tags.DOUBLE }
implicit object BinaryType extends StandardType[Chunk[Byte]] { override def tag = Tags.BINARY }
implicit object CharType extends StandardType[Char] { override def tag = Tags.CHAR }
implicit object UnitType extends StandardType[Unit] { override def tag = Tags.UNIT }
implicit object StringType extends StandardType[String] { override def tag = Tags.STRING }
implicit object BoolType extends StandardType[Boolean] { override def tag = Tags.BOOL }
implicit object ShortType extends StandardType[Short] { override def tag = Tags.SHORT }
implicit object IntType extends StandardType[Int] { override def tag = Tags.INT }
implicit object LongType extends StandardType[Long] { override def tag = Tags.LONG }
implicit object FloatType extends StandardType[Float] { override def tag = Tags.FLOAT }
implicit object DoubleType extends StandardType[Double] { override def tag = Tags.DOUBLE }
implicit object BinaryType extends StandardType[Chunk[Byte]] { override def tag = Tags.BINARY }
implicit object CharType extends StandardType[Char] { override def tag = Tags.CHAR }
implicit object UUIDType extends StandardType[java.util.UUID] { override def tag = Tags.UUID }

implicit object BigDecimalType extends StandardType[java.math.BigDecimal] { override def tag = Tags.BIG_DECIMAL }
implicit object BigIntegerType extends StandardType[java.math.BigInteger] { override def tag = Tags.BIG_INTEGER }
Expand Down Expand Up @@ -129,4 +132,5 @@ object StandardType {
final case class ZonedDateTime(formatter: DateTimeFormatter) extends StandardType[java.time.ZonedDateTime] {
override def tag = Tags.ZONED_DATE_TIME
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@ object JsonCodec extends Codec {
case StandardType.CharType => ZJsonCodec.char
case StandardType.BigIntegerType => ZJsonCodec.bigInteger
case StandardType.BigDecimalType => ZJsonCodec.bigDecimal
case StandardType.UUIDType => ZJsonCodec.uuid
case StandardType.DayOfWeekType => ZJsonCodec.dayOfWeek // ZJsonCodec[java.time.DayOfWeek]
case StandardType.Duration(_) => ZJsonCodec.duration //ZJsonCodec[java.time.Duration]
case StandardType.Instant(_) => ZJsonCodec.instant //ZJsonCodec[java.time.Instant]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,11 @@ package zio.schema.codec
import java.nio.charset.StandardCharsets
import java.nio.{ ByteBuffer, ByteOrder }
import java.time._
import java.util.UUID

import scala.annotation.tailrec
import scala.collection.immutable.ListMap
import scala.util.control.NonFatal

import zio.schema._
import zio.schema.ast.SchemaAst
Expand Down Expand Up @@ -107,6 +109,7 @@ object ProtobufCodec extends Codec {
case StandardType.CharType => true
case StandardType.BigIntegerType => false
case StandardType.BigDecimalType => false
case StandardType.UUIDType => false
case StandardType.DayOfWeekType => true
case StandardType.Month => true
case StandardType.MonthDay => false
Expand Down Expand Up @@ -247,6 +250,8 @@ object ProtobufCodec extends Codec {
encodeKey(WireType.LengthDelimited(bytes.length), fieldNumber) ++ bytes
case (StandardType.CharType, c: Char) =>
encodePrimitive(fieldNumber, StandardType.StringType, c.toString)
case (StandardType.UUIDType, u: UUID) =>
encodePrimitive(fieldNumber, StandardType.StringType, u.toString)
case (StandardType.DayOfWeekType, v: DayOfWeek) =>
encodePrimitive(fieldNumber, StandardType.IntType, v.getValue)
case (StandardType.Month, v: Month) =>
Expand Down Expand Up @@ -413,6 +418,8 @@ object ProtobufCodec extends Codec {

def fail(failure: String): Decoder[Nothing] = Decoder(_ => Left(failure))

def succeedNow[A](a: A): Decoder[A] = Decoder(bytes => Right((bytes, a)))

def succeed[A](a: => A): Decoder[A] = Decoder(bytes => Right((bytes, a)))

def binaryDecoder: Decoder[Chunk[Byte]] = Decoder(bytes => Right((Chunk.empty, bytes)))
Expand Down Expand Up @@ -588,6 +595,13 @@ object ProtobufCodec extends Codec {
case StandardType.DoubleType => doubleDecoder
case StandardType.BinaryType => binaryDecoder
case StandardType.CharType => stringDecoder.map(_.charAt(0))
case StandardType.UUIDType =>
stringDecoder.flatMap { uuid =>
try succeedNow(UUID.fromString(uuid))
catch {
case NonFatal(_) => fail("Invalid UUID string")
}
}
case StandardType.DayOfWeekType =>
varIntDecoder.map(_.intValue).map(DayOfWeek.of)
case StandardType.Month =>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ object DynamicValueGen {
case typ: StandardType.ZoneId.type => gen(typ, JavaTimeGen.anyZoneId)
case typ: StandardType.ZoneOffset.type => gen(typ, JavaTimeGen.anyZoneOffset)
case typ: StandardType.UnitType.type => Gen.const(DynamicValue.Primitive((), typ))
case typ: StandardType.UUIDType.type => gen(typ, Gen.anyUUID)
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ object StandardTypeGen {
(StandardType.BigDecimalType),
(StandardType.BigIntegerType),
(StandardType.CharType),
(StandardType.UUIDType),
(StandardType.DayOfWeekType),
(StandardType.Duration(ChronoUnit.SECONDS)),
(StandardType.Instant(DateTimeFormatter.ISO_DATE_TIME)),
Expand Down Expand Up @@ -54,6 +55,7 @@ object StandardTypeGen {
case typ: StandardType.DoubleType.type => typ -> Gen.anyDouble
case typ: StandardType.BinaryType.type => typ -> Gen.chunkOf(Gen.anyByte)
case typ: StandardType.CharType.type => typ -> Gen.anyASCIIChar
case typ: StandardType.UUIDType.type => typ -> Gen.anyUUID
case typ: StandardType.BigDecimalType.type => typ -> Gen.anyDouble.map(d => java.math.BigDecimal.valueOf(d))
case typ: StandardType.BigIntegerType.type => typ -> Gen.anyLong.map(n => java.math.BigInteger.valueOf(n))
case typ: StandardType.DayOfWeekType.type => typ -> JavaTimeGen.anyDayOfWeek
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package zio.schema.codec
import java.time._
import java.time.format.DateTimeFormatter
import java.time.temporal.ChronoUnit
import java.util.UUID

import scala.collection.immutable.ListMap
import scala.util.Try
Expand Down Expand Up @@ -179,6 +180,13 @@ object ProtobufCodecSpec extends DefaultRunnableSpec {
ed2 <- encodeAndDecodeNS(Schema[Char], value)
} yield assert(ed)(equalTo(Chunk(value))) && assert(ed2)(equalTo(value))
},
testM("uuids") {
val value = UUID.randomUUID
for {
ed <- encodeAndDecode(Schema[UUID], value)
ed2 <- encodeAndDecodeNS(Schema[UUID], value)
} yield assert(ed)(equalTo(Chunk(value))) && assert(ed2)(equalTo(value))
},
testM("day of weeks") {
val value = DayOfWeek.of(3)
for {
Expand Down

0 comments on commit 1615556

Please sign in to comment.