Skip to content

Commit

Permalink
Fixes zio#12: Implement Schema.serializable (zio#83)
Browse files Browse the repository at this point in the history
* Remove setup gpg

* Update setup-java

* Test

* test2

* test 3

* Fixes zio#78: Implement diffing between instances described by a schema

* Specs and additional implementations

* Rename DiffAlgorithm to Differ

* Add diffs for product and sum types

* Copy Myers diff implementation from zio-test

* Implement binary diff and unit tests

* Fix various temporal diffs and add unit tests

* formatting

* Test coverage and tweaks

* Fixes zio#12: Implement Schema.serializable

* Formatting

* Remove commented code

* Refactoring for clarity and type safety

* Refactor for clarity

* Test coverage and (ignored) test cases for recursive data types

* linting

* Better encoding of serializable schema with an Abstract Syntax Tree.
This allows us to check for cyclic references while building the tree
and replace recursive references with pointers.

Also fixed a bug with JSON encoding/decoding of recursive data types and
fixed derivation of recursive ADTs by inserting laziness into the
implicit conversions.

* Fix bugs in protobuf decoding

* 2.12 does not suport by-name implicit parameters

* Re-enable dynamic value test for recursive data types

* AST materialization and unit tests

* Remove ref method from Schema

* Preserve ref map on recursive materializations

* Add multi-dimensionality to schema to account for sequences of sequences

* Do AST comparison on Lazy schemas by limiting stack depth to avoid infinite recurse

* Rename Ast to SchemaAst to avoid conflicts

* Appease the 2.12 compiler

Co-authored-by: thinkharder <thinkharderdev@users.noreply.github.com>
  • Loading branch information
2 people authored and landlockedsurfer committed May 28, 2022
1 parent 18fda4f commit 8510a6f
Show file tree
Hide file tree
Showing 17 changed files with 2,055 additions and 4,894 deletions.
8 changes: 5 additions & 3 deletions project/BuildHelper.scala
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,9 @@ object BuildHelper {

val zioVersion = "1.0.9"
val zioNioVersion = "1.0.0-RC9"
val zioJsonVersion = "0.1.2"
val zioJsonVersion = "0.1.5"
val silencerVersion = "1.7.1"
val magnoliaVersion = "0.16.0"
val magnoliaVersion = "0.17.0"

private val testDeps = Seq(
"dev.zio" %% "zio-test" % zioVersion % "test",
Expand Down Expand Up @@ -50,7 +50,9 @@ object BuildHelper {
"-Xsource:2.13",
"-Xlint:_,-type-parameter-shadow",
"-Ywarn-numeric-widen",
"-Ywarn-value-discard"
"-Ywarn-value-discard",
"-Ypatmat-exhaust-depth",
"off"
)

val optimizerOptions =
Expand Down
193 changes: 24 additions & 169 deletions zio-schema/shared/src/main/scala/zio/schema/Diff.scala
Original file line number Diff line number Diff line change
Expand Up @@ -350,10 +350,10 @@ object Diff {
}
}

//scalafmt: { maxColumn = 400, optIn.configStyleArguments = false }
object ProductDiffer {

def unapply[A](schema: Schema[A]): Option[Differ[A]] = schema match {
case Schema.CaseObject(_) => Some(Differ.identical[A])
case s: Schema.CaseClass1[_, A] => Some(product1(s))
case s: Schema.CaseClass2[_, _, A] => Some(product2(s))
case s: Schema.CaseClass3[_, _, _, A] => Some(product3(s))
Expand Down Expand Up @@ -383,97 +383,49 @@ object ProductDiffer {
def product1[A, Z](schema: Schema.CaseClass1[A, Z]): Differ[Z] =
(thisZ: Z, thatZ: Z) =>
Diff
.Record(
ListMap(
fieldDiffer(schema.field, schema.extractField)(thisZ, thatZ)
)
)
.Record(ListMap(fieldDiffer(schema.field, schema.extractField)(thisZ, thatZ)))
.orIdentical

def product2[A1, A2, Z](schema: Schema.CaseClass2[A1, A2, Z]): Differ[Z] =
(thisZ: Z, thatZ: Z) =>
Diff
.Record(
ListMap.empty ++ Chunk(
fieldDiffer(schema.field1, schema.extractField1),
fieldDiffer(schema.field2, schema.extractField2)
).map(_.apply(thisZ, thatZ))
)
.Record(ListMap.empty ++ Chunk(fieldDiffer(schema.field1, schema.extractField1), fieldDiffer(schema.field2, schema.extractField2)).map(_.apply(thisZ, thatZ)))
.orIdentical

def product3[A1, A2, A3, Z](schema: Schema.CaseClass3[A1, A2, A3, Z]): Differ[Z] =
(thisZ: Z, thatZ: Z) =>
Diff
.Record(
ListMap.empty ++ Chunk(
fieldDiffer(schema.field1, schema.extractField1),
fieldDiffer(schema.field2, schema.extractField2),
fieldDiffer(schema.field3, schema.extractField3)
).map(_.apply(thisZ, thatZ))
)
.Record(ListMap.empty ++ Chunk(fieldDiffer(schema.field1, schema.extractField1), fieldDiffer(schema.field2, schema.extractField2), fieldDiffer(schema.field3, schema.extractField3)).map(_.apply(thisZ, thatZ)))
.orIdentical

def product4[A1, A2, A3, A4, Z](schema: Schema.CaseClass4[A1, A2, A3, A4, Z]): Differ[Z] =
(thisZ: Z, thatZ: Z) =>
Diff
.Record(
ListMap.empty ++ Chunk(
fieldDiffer(schema.field1, schema.extractField1),
fieldDiffer(schema.field2, schema.extractField2),
fieldDiffer(schema.field3, schema.extractField3),
fieldDiffer(schema.field4, schema.extractField4)
).map(_.apply(thisZ, thatZ))
)
.Record(ListMap.empty ++ Chunk(fieldDiffer(schema.field1, schema.extractField1), fieldDiffer(schema.field2, schema.extractField2), fieldDiffer(schema.field3, schema.extractField3), fieldDiffer(schema.field4, schema.extractField4)).map(_.apply(thisZ, thatZ)))
.orIdentical

def product5[A1, A2, A3, A4, A5, Z](schema: Schema.CaseClass5[A1, A2, A3, A4, A5, Z]): Differ[Z] =
(thisZ: Z, thatZ: Z) =>
Diff
.Record(
ListMap.empty ++ Chunk(
fieldDiffer(schema.field1, schema.extractField1),
fieldDiffer(schema.field2, schema.extractField2),
fieldDiffer(schema.field3, schema.extractField3),
fieldDiffer(schema.field4, schema.extractField4),
fieldDiffer(schema.field5, schema.extractField5)
).map(_.apply(thisZ, thatZ))
)
.Record(ListMap.empty ++ Chunk(fieldDiffer(schema.field1, schema.extractField1), fieldDiffer(schema.field2, schema.extractField2), fieldDiffer(schema.field3, schema.extractField3), fieldDiffer(schema.field4, schema.extractField4), fieldDiffer(schema.field5, schema.extractField5)).map(_.apply(thisZ, thatZ)))
.orIdentical

def product6[A1, A2, A3, A4, A5, A6, Z](schema: Schema.CaseClass6[A1, A2, A3, A4, A5, A6, Z]): Differ[Z] =
(thisZ: Z, thatZ: Z) =>
Diff
.Record(
ListMap.empty ++ Chunk(
fieldDiffer(schema.field1, schema.extractField1),
fieldDiffer(schema.field2, schema.extractField2),
fieldDiffer(schema.field3, schema.extractField3),
fieldDiffer(schema.field4, schema.extractField4),
fieldDiffer(schema.field5, schema.extractField5),
fieldDiffer(schema.field6, schema.extractField6)
).map(_.apply(thisZ, thatZ))
)
.Record(ListMap.empty ++ Chunk(fieldDiffer(schema.field1, schema.extractField1), fieldDiffer(schema.field2, schema.extractField2), fieldDiffer(schema.field3, schema.extractField3), fieldDiffer(schema.field4, schema.extractField4), fieldDiffer(schema.field5, schema.extractField5), fieldDiffer(schema.field6, schema.extractField6)).map(_.apply(thisZ, thatZ)))
.orIdentical

def product7[A1, A2, A3, A4, A5, A6, A7, Z](schema: Schema.CaseClass7[A1, A2, A3, A4, A5, A6, A7, Z]): Differ[Z] =
(thisZ: Z, thatZ: Z) =>
Diff
.Record(
ListMap.empty ++ Chunk(
fieldDiffer(schema.field1, schema.extractField1),
fieldDiffer(schema.field2, schema.extractField2),
fieldDiffer(schema.field3, schema.extractField3),
fieldDiffer(schema.field4, schema.extractField4),
fieldDiffer(schema.field5, schema.extractField5),
fieldDiffer(schema.field6, schema.extractField6),
fieldDiffer(schema.field7, schema.extractField7)
).map(_.apply(thisZ, thatZ))
ListMap.empty ++ Chunk(fieldDiffer(schema.field1, schema.extractField1), fieldDiffer(schema.field2, schema.extractField2), fieldDiffer(schema.field3, schema.extractField3), fieldDiffer(schema.field4, schema.extractField4), fieldDiffer(schema.field5, schema.extractField5), fieldDiffer(schema.field6, schema.extractField6), fieldDiffer(schema.field7, schema.extractField7))
.map(_.apply(thisZ, thatZ))
)
.orIdentical

def product8[A1, A2, A3, A4, A5, A6, A7, A8, Z](
schema: Schema.CaseClass8[A1, A2, A3, A4, A5, A6, A7, A8, Z]
): Differ[Z] =
def product8[A1, A2, A3, A4, A5, A6, A7, A8, Z](schema: Schema.CaseClass8[A1, A2, A3, A4, A5, A6, A7, A8, Z]): Differ[Z] =
(thisZ: Z, thatZ: Z) =>
Diff
.Record(
Expand All @@ -490,9 +442,7 @@ object ProductDiffer {
)
.orIdentical

def product9[A1, A2, A3, A4, A5, A6, A7, A8, A9, Z](
schema: Schema.CaseClass9[A1, A2, A3, A4, A5, A6, A7, A8, A9, Z]
): Differ[Z] =
def product9[A1, A2, A3, A4, A5, A6, A7, A8, A9, Z](schema: Schema.CaseClass9[A1, A2, A3, A4, A5, A6, A7, A8, A9, Z]): Differ[Z] =
(thisZ: Z, thatZ: Z) =>
Diff
.Record(
Expand All @@ -510,9 +460,7 @@ object ProductDiffer {
)
.orIdentical

def product10[A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, Z](
schema: Schema.CaseClass10[A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, Z]
): Differ[Z] =
def product10[A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, Z](schema: Schema.CaseClass10[A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, Z]): Differ[Z] =
(thisZ: Z, thatZ: Z) =>
Diff
.Record(
Expand All @@ -531,9 +479,7 @@ object ProductDiffer {
)
.orIdentical

def product11[A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, Z](
schema: Schema.CaseClass11[A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, Z]
): Differ[Z] =
def product11[A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, Z](schema: Schema.CaseClass11[A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, Z]): Differ[Z] =
(thisZ: Z, thatZ: Z) =>
Diff
.Record(
Expand All @@ -553,9 +499,7 @@ object ProductDiffer {
)
.orIdentical

def product12[A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, Z](
schema: Schema.CaseClass12[A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, Z]
): Differ[Z] =
def product12[A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, Z](schema: Schema.CaseClass12[A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, Z]): Differ[Z] =
(thisZ: Z, thatZ: Z) =>
Diff
.Record(
Expand All @@ -576,9 +520,7 @@ object ProductDiffer {
)
.orIdentical

def product13[A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13, Z](
schema: Schema.CaseClass13[A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13, Z]
): Differ[Z] =
def product13[A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13, Z](schema: Schema.CaseClass13[A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13, Z]): Differ[Z] =
(thisZ: Z, thatZ: Z) =>
Diff
.Record(
Expand All @@ -600,9 +542,7 @@ object ProductDiffer {
)
.orIdentical

def product14[A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13, A14, Z](
schema: Schema.CaseClass14[A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13, A14, Z]
): Differ[Z] =
def product14[A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13, A14, Z](schema: Schema.CaseClass14[A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13, A14, Z]): Differ[Z] =
(thisZ: Z, thatZ: Z) =>
Diff
.Record(
Expand All @@ -625,9 +565,7 @@ object ProductDiffer {
)
.orIdentical

def product15[A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13, A14, A15, Z](
schema: Schema.CaseClass15[A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13, A14, A15, Z]
): Differ[Z] =
def product15[A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13, A14, A15, Z](schema: Schema.CaseClass15[A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13, A14, A15, Z]): Differ[Z] =
(thisZ: Z, thatZ: Z) =>
Diff
.Record(
Expand All @@ -651,9 +589,7 @@ object ProductDiffer {
)
.orIdentical

def product16[A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13, A14, A15, A16, Z](
schema: Schema.CaseClass16[A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13, A14, A15, A16, Z]
): Differ[Z] =
def product16[A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13, A14, A15, A16, Z](schema: Schema.CaseClass16[A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13, A14, A15, A16, Z]): Differ[Z] =
(thisZ: Z, thatZ: Z) =>
Diff
.Record(
Expand All @@ -678,9 +614,7 @@ object ProductDiffer {
)
.orIdentical

def product17[A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13, A14, A15, A16, A17, Z](
schema: Schema.CaseClass17[A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13, A14, A15, A16, A17, Z]
): Differ[Z] =
def product17[A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13, A14, A15, A16, A17, Z](schema: Schema.CaseClass17[A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13, A14, A15, A16, A17, Z]): Differ[Z] =
(thisZ: Z, thatZ: Z) =>
Diff
.Record(
Expand All @@ -706,9 +640,7 @@ object ProductDiffer {
)
.orIdentical

def product18[A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13, A14, A15, A16, A17, A18, Z](
schema: Schema.CaseClass18[A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13, A14, A15, A16, A17, A18, Z]
): Differ[Z] =
def product18[A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13, A14, A15, A16, A17, A18, Z](schema: Schema.CaseClass18[A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13, A14, A15, A16, A17, A18, Z]): Differ[Z] =
(thisZ: Z, thatZ: Z) =>
Diff
.Record(
Expand All @@ -735,9 +667,7 @@ object ProductDiffer {
)
.orIdentical

def product19[A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13, A14, A15, A16, A17, A18, A19, Z](
schema: Schema.CaseClass19[A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13, A14, A15, A16, A17, A18, A19, Z]
): Differ[Z] =
def product19[A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13, A14, A15, A16, A17, A18, A19, Z](schema: Schema.CaseClass19[A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13, A14, A15, A16, A17, A18, A19, Z]): Differ[Z] =
(thisZ: Z, thatZ: Z) =>
Diff
.Record(
Expand Down Expand Up @@ -765,31 +695,7 @@ object ProductDiffer {
)
.orIdentical

def product20[A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13, A14, A15, A16, A17, A18, A19, A20, Z](
schema: Schema.CaseClass20[
A1,
A2,
A3,
A4,
A5,
A6,
A7,
A8,
A9,
A10,
A11,
A12,
A13,
A14,
A15,
A16,
A17,
A18,
A19,
A20,
Z
]
): Differ[Z] =
def product20[A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13, A14, A15, A16, A17, A18, A19, A20, Z](schema: Schema.CaseClass20[A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13, A14, A15, A16, A17, A18, A19, A20, Z]): Differ[Z] =
(thisZ: Z, thatZ: Z) =>
Diff
.Record(
Expand Down Expand Up @@ -818,32 +724,7 @@ object ProductDiffer {
)
.orIdentical

def product21[A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13, A14, A15, A16, A17, A18, A19, A20, A21, Z](
schema: Schema.CaseClass21[
A1,
A2,
A3,
A4,
A5,
A6,
A7,
A8,
A9,
A10,
A11,
A12,
A13,
A14,
A15,
A16,
A17,
A18,
A19,
A20,
A21,
Z
]
): Differ[Z] =
def product21[A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13, A14, A15, A16, A17, A18, A19, A20, A21, Z](schema: Schema.CaseClass21[A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13, A14, A15, A16, A17, A18, A19, A20, A21, Z]): Differ[Z] =
(thisZ: Z, thatZ: Z) =>
Diff
.Record(
Expand Down Expand Up @@ -873,33 +754,7 @@ object ProductDiffer {
)
.orIdentical

def product22[A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13, A14, A15, A16, A17, A18, A19, A20, A21, A22, Z](
schema: Schema.CaseClass22[
A1,
A2,
A3,
A4,
A5,
A6,
A7,
A8,
A9,
A10,
A11,
A12,
A13,
A14,
A15,
A16,
A17,
A18,
A19,
A20,
A21,
A22,
Z
]
): Differ[Z] =
def product22[A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13, A14, A15, A16, A17, A18, A19, A20, A21, A22, Z](schema: Schema.CaseClass22[A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13, A14, A15, A16, A17, A18, A19, A20, A21, A22, Z]): Differ[Z] =
(thisZ: Z, thatZ: Z) =>
Diff
.Record(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,6 @@ trait DynamicValue { self =>
case (DynamicValue.Record(values), s: Schema.Record[A]) =>
DynamicValue.decodeStructure(values, s.structure).map(m => Chunk.fromIterable(m.values)).flatMap(s.rawConstruct)

case (DynamicValue.Singleton(l), Schema.CaseObject(r)) if l == r =>
Right(r)

case (DynamicValue.Enumeration((key, value)), Schema.Enumeration(cases)) =>
cases.get(key) match {
case Some(schema) =>
Expand Down Expand Up @@ -186,7 +183,7 @@ object DynamicValue {
case Right(a) => DynamicValue.Transform(fromSchemaAndValue(schema, a))
}

case Schema.CaseObject(instance) => DynamicValue.Singleton(instance)
case Schema.Meta(ast) => DynamicValue.DynamicAst(ast)

case Schema.CaseClass1(_, f, _, ext) =>
DynamicValue.Record(ListMap(f.label -> fromSchemaAndValue(f.schema, ext(value))))
Expand Down Expand Up @@ -1067,5 +1064,7 @@ object DynamicValue {

final case class RightValue(value: DynamicValue) extends DynamicValue

final case class DynamicAst(ast: SchemaAst) extends DynamicValue

final case class Error(message: String) extends DynamicValue
}
Loading

0 comments on commit 8510a6f

Please sign in to comment.