From 9a2345dbcd08d53f7b2867097eb1f31121e76aec Mon Sep 17 00:00:00 2001 From: Nabil Abdel-Hafeez <7283535+987Nabil@users.noreply.github.com> Date: Tue, 30 Jan 2024 21:08:14 +0100 Subject: [PATCH] Extract common code for annotation based information (#650) --- .../zio/schema/codec/BsonSchemaCodec.scala | 13 +- .../scala/zio/schema/codec/JsonCodec.scala | 163 ++---- .../scala/zio/schema/codec/ThriftCodec.scala | 11 +- .../main/scala/zio/schema/StandardType.scala | 40 +- .../MutableSchemaBasedValueProcessor.scala | 463 +----------------- .../src/main/scala/zio/schema/Schema.scala | 28 +- 6 files changed, 108 insertions(+), 610 deletions(-) diff --git a/zio-schema-bson/src/main/scala/zio/schema/codec/BsonSchemaCodec.scala b/zio-schema-bson/src/main/scala/zio/schema/codec/BsonSchemaCodec.scala index fcfd78ac9..0166a26ff 100644 --- a/zio-schema-bson/src/main/scala/zio/schema/codec/BsonSchemaCodec.scala +++ b/zio-schema-bson/src/main/scala/zio/schema/codec/BsonSchemaCodec.scala @@ -30,7 +30,6 @@ import zio.schema.annotation.{ caseNameAliases, directDynamicMapping, discriminatorName, - fieldDefaultValue, fieldNameAliases, noDiscriminator, rejectExtraFields, @@ -605,12 +604,12 @@ object BsonSchemaCodec { // if all cases are CaseClass0, encode as a String if (cases.forall(_.schema.isInstanceOf[Schema.CaseClass0[_]])) { val caseMap: Map[Z, String] = cases - .filterNot(_.annotations.exists(_.isInstanceOf[transientCase])) + .filterNot(_.transient) .map { case_ => val manualBsonHint = case_.annotations.collectFirst { case bsonHint(name) => name } - val manualCaseName = case_.annotations.collectFirst { case caseName(name) => name } + val caseName = case_.caseName case_.schema.asInstanceOf[Schema.CaseClass0[Z]].defaultConstruct() -> - manualBsonHint.orElse(manualCaseName).getOrElse(case_.id) + manualBsonHint.getOrElse(caseName) } .toMap BsonEncoder.string.contramap(caseMap(_)) @@ -621,8 +620,8 @@ object BsonSchemaCodec { def getCaseName(case_ : Schema.Case[Z, _]) = { val manualBsonHint = case_.annotations.collectFirst { case bsonHint(name) => name } - val manualCaseName = case_.annotations.collectFirst { case caseName(name) => name } - manualBsonHint.orElse(manualCaseName).getOrElse(case_.id) + val caseName = case_.caseName + manualBsonHint.getOrElse(caseName) } val noDiscriminators = parentSchema.annotations.exists { @@ -1208,7 +1207,7 @@ object BsonSchemaCodec { case _: bsonNoExtraFields => () }.isDefined lazy val tcs: Array[BsonDecoder[Any]] = schemas.map(s => schemaDecoder(s).asInstanceOf[BsonDecoder[Any]]) - lazy val defaults: Array[Option[Any]] = fields.map(_.annotations.collectFirst { case a: fieldDefaultValue[_] => a.value }).toArray + lazy val defaults: Array[Option[Any]] = fields.map(_.defaultValue).toArray new BsonDecoder[Z] { def decodeUnsafe(reader: BsonReader, trace: List[BsonTrace], ctx: BsonDecoder.BsonDecoderContext): Z = unsafeCall(trace) { diff --git a/zio-schema-json/shared/src/main/scala/zio/schema/codec/JsonCodec.scala b/zio-schema-json/shared/src/main/scala/zio/schema/codec/JsonCodec.scala index 49bc02e7d..1b5d0ce69 100644 --- a/zio-schema-json/shared/src/main/scala/zio/schema/codec/JsonCodec.scala +++ b/zio-schema-json/shared/src/main/scala/zio/schema/codec/JsonCodec.scala @@ -188,57 +188,15 @@ object JsonCodec { case Schema.Map(ks, vs, _) => mapEncoder(ks, vs, discriminatorTuple, cfg) case Schema.Set(s, _) => ZJsonEncoder.chunk(schemaEncoder(s, cfg, discriminatorTuple)).contramap(m => Chunk.fromIterable(m)) - case Schema.Transform(c, _, g, a, _) => transformEncoder(a.foldLeft(c)((s, a) => s.annotate(a)), g, cfg) - case Schema.Tuple2(l, r, _) => ZJsonEncoder.tuple2(schemaEncoder(l, cfg, discriminatorTuple), schemaEncoder(r, cfg, discriminatorTuple)) - case Schema.Optional(schema, _) => ZJsonEncoder.option(schemaEncoder(schema, cfg, discriminatorTuple)) - case Schema.Fail(_, _) => unitEncoder.contramap(_ => ()) - case Schema.GenericRecord(_, structure, _) => recordEncoder(structure.toChunk, cfg) - case Schema.Either(left, right, _) => ZJsonEncoder.either(schemaEncoder(left, cfg, discriminatorTuple), schemaEncoder(right, cfg, discriminatorTuple)) - case Schema.Fallback(left, right, _, _) => fallbackEncoder(schemaEncoder(left, cfg, discriminatorTuple), schemaEncoder(right, cfg, discriminatorTuple)) - case l @ Schema.Lazy(_) => schemaEncoder(l.schema, cfg, discriminatorTuple) - case Schema.CaseClass0(_, _, _) => caseClassEncoder(schema, discriminatorTuple, cfg) - case Schema.CaseClass1(_, f, _, _) => caseClassEncoder(schema, discriminatorTuple, cfg, f) - case Schema.CaseClass2(_, f1, f2, _, _) => caseClassEncoder(schema, discriminatorTuple, cfg, f1, f2) - case Schema.CaseClass3(_, f1, f2, f3, _, _) => caseClassEncoder(schema, discriminatorTuple, cfg, f1, f2, f3) - case Schema.CaseClass4(_, f1, f2, f3, f4, _, _) => - caseClassEncoder(schema, discriminatorTuple, cfg, f1, f2, f3, f4) - case Schema.CaseClass5(_, f1, f2, f3, f4, f5, _, _) => - caseClassEncoder(schema, discriminatorTuple, cfg, f1, f2, f3, f4, f5) - case Schema.CaseClass6(_, f1, f2, f3, f4, f5, f6, _, _) => - caseClassEncoder(schema, discriminatorTuple, cfg, f1, f2, f3, f4, f5, f6) - case Schema.CaseClass7(_, f1, f2, f3, f4, f5, f6, f7, _, _) => - caseClassEncoder(schema, discriminatorTuple, cfg, f1, f2, f3, f4, f5, f6, f7) - case Schema.CaseClass8(_, f1, f2, f3, f4, f5, f6, f7, f8, _, _) => - caseClassEncoder(schema, discriminatorTuple, cfg, f1, f2, f3, f4, f5, f6, f7, f8) - case Schema - .CaseClass9(_, f1, f2, f3, f4, f5, f6, f7, f8, f9, _, _) => - caseClassEncoder(schema, discriminatorTuple, cfg, f1, f2, f3, f4, f5, f6, f7, f8, f9) - case Schema.CaseClass10(_, f1, f2, f3, f4, f5, f6, f7, f8, f9, f10, _, _) => - caseClassEncoder(schema, discriminatorTuple, cfg, f1, f2, f3, f4, f5, f6, f7, f8, f9, f10) - case Schema.CaseClass11(_, f1, f2, f3, f4, f5, f6, f7, f8, f9, f10, f11, _, _) => - caseClassEncoder(schema, discriminatorTuple, cfg, f1, f2, f3, f4, f5, f6, f7, f8, f9, f10, f11) - case Schema.CaseClass12(_, f1, f2, f3, f4, f5, f6, f7, f8, f9, f10, f11, f12, _, _) => - caseClassEncoder(schema, discriminatorTuple, cfg, f1, f2, f3, f4, f5, f6, f7, f8, f9, f10, f11, f12) - case Schema.CaseClass13(_, f1, f2, f3, f4, f5, f6, f7, f8, f9, f10, f11, f12, f13, _, _) => - caseClassEncoder(schema, discriminatorTuple, cfg, f1, f2, f3, f4, f5, f6, f7, f8, f9, f10, f11, f12, f13) - case Schema.CaseClass14(_, f1, f2, f3, f4, f5, f6, f7, f8, f9, f10, f11, f12, f13, f14, _, _) => - caseClassEncoder(schema, discriminatorTuple, cfg, f1, f2, f3, f4, f5, f6, f7, f8, f9, f10, f11, f12, f13, f14) - case Schema.CaseClass15(_, f1, f2, f3, f4, f5, f6, f7, f8, f9, f10, f11, f12, f13, f14, f15, _, _) => - caseClassEncoder(schema, discriminatorTuple, cfg, f1, f2, f3, f4, f5, f6, f7, f8, f9, f10, f11, f12, f13, f14, f15) - case Schema.CaseClass16(_, f1, f2, f3, f4, f5, f6, f7, f8, f9, f10, f11, f12, f13, f14, f15, f16, _, _) => - caseClassEncoder(schema, discriminatorTuple, cfg, f1, f2, f3, f4, f5, f6, f7, f8, f9, f10, f11, f12, f13, f14, f15, f16) - case Schema.CaseClass17(_, f1, f2, f3, f4, f5, f6, f7, f8, f9, f10, f11, f12, f13, f14, f15, f16, f17, _, _) => - caseClassEncoder(schema, discriminatorTuple, cfg, f1, f2, f3, f4, f5, f6, f7, f8, f9, f10, f11, f12, f13, f14, f15, f16, f17) - case Schema.CaseClass18(_, f1, f2, f3, f4, f5, f6, f7, f8, f9, f10, f11, f12, f13, f14, f15, f16, f17, f18, _, _) => - caseClassEncoder(schema, discriminatorTuple, cfg, f1, f2, f3, f4, f5, f6, f7, f8, f9, f10, f11, f12, f13, f14, f15, f16, f17, f18) - case Schema.CaseClass19(_, f1, f2, f3, f4, f5, f6, f7, f8, f9, f10, f11, f12, f13, f14, f15, f16, f17, f18, f19, _, _) => - caseClassEncoder(schema, discriminatorTuple, cfg, f1, f2, f3, f4, f5, f6, f7, f8, f9, f10, f11, f12, f13, f14, f15, f16, f17, f18, f19) - case Schema.CaseClass20(_, f1, f2, f3, f4, f5, f6, f7, f8, f9, f10, f11, f12, f13, f14, f15, f16, f17, f18, f19, f20, _) => - caseClassEncoder(schema, discriminatorTuple, cfg, f1, f2, f3, f4, f5, f6, f7, f8, f9, f10, f11, f12, f13, f14, f15, f16, f17, f18, f19, f20) - case Schema.CaseClass21(_, f1, f2, f3, f4, f5, f6, f7, f8, f9, f10, f11, f12, f13, f14, f15, f16, f17, f18, f19, f20, tail) => - caseClassEncoder(schema, discriminatorTuple, cfg, f1, f2, f3, f4, f5, f6, f7, f8, f9, f10, f11, f12, f13, f14, f15, f16, f17, f18, f19, f20, tail._1) - case Schema.CaseClass22(_, f1, f2, f3, f4, f5, f6, f7, f8, f9, f10, f11, f12, f13, f14, f15, f16, f17, f18, f19, f20, tail) => - caseClassEncoder(schema, discriminatorTuple, cfg, f1, f2, f3, f4, f5, f6, f7, f8, f9, f10, f11, f12, f13, f14, f15, f16, f17, f18, f19, f20, tail._1, tail._2) + case Schema.Transform(c, _, g, a, _) => transformEncoder(a.foldLeft(c)((s, a) => s.annotate(a)), g, cfg) + case Schema.Tuple2(l, r, _) => ZJsonEncoder.tuple2(schemaEncoder(l, cfg, discriminatorTuple), schemaEncoder(r, cfg, discriminatorTuple)) + case Schema.Optional(schema, _) => ZJsonEncoder.option(schemaEncoder(schema, cfg, discriminatorTuple)) + case Schema.Fail(_, _) => unitEncoder.contramap(_ => ()) + case Schema.GenericRecord(_, structure, _) => recordEncoder(structure.toChunk, cfg) + case Schema.Either(left, right, _) => ZJsonEncoder.either(schemaEncoder(left, cfg, discriminatorTuple), schemaEncoder(right, cfg, discriminatorTuple)) + case Schema.Fallback(left, right, _, _) => fallbackEncoder(schemaEncoder(left, cfg, discriminatorTuple), schemaEncoder(right, cfg, discriminatorTuple)) + case l @ Schema.Lazy(_) => schemaEncoder(l.schema, cfg, discriminatorTuple) + case s: Schema.Record[A] => caseClassEncoder(s, discriminatorTuple, cfg) case e @ Schema.Enum1(_, c, _) => enumEncoder(e, cfg, c) case e @ Schema.Enum2(_, c1, c2, _) => enumEncoder(e, cfg, c1, c2) case e @ Schema.Enum3(_, c1, c2, c3, _) => enumEncoder(e, cfg, c1, c2, c3) @@ -448,17 +406,12 @@ object JsonCodec { nonTransientCase match { case Some(case_) => - val caseName = case_.annotations.collectFirst { - case name: caseName => name.name - }.getOrElse(case_.id) + val caseName = case_.caseName val discriminatorChunk = parentSchema.annotations.collect { case d: discriminatorName => (d, caseName) } - val noDiscriminators = parentSchema.annotations.exists { - case noDiscriminator() => true - case _ => false - } + val noDiscriminators = parentSchema.noDiscriminator if (discriminatorChunk.isEmpty && !noDiscriminators) out.write('{') val indent_ = bump(indent) @@ -954,7 +907,7 @@ object JsonCodec { private[codec] def isEmptyOptionalValue(schema: Schema.Field[_, _], value: Any, cfg: Config) = { val ignoreEmptyCollections = - cfg.ignoreEmptyCollections || schema.annotations.contains(optionalField()) + cfg.ignoreEmptyCollections || schema.optional val isEmptyCollection = value match { case _: Iterable[_] => value.asInstanceOf[Iterable[_]].isEmpty @@ -964,7 +917,7 @@ object JsonCodec { ignoreEmptyCollections && isEmptyCollection } - private[codec] def caseClassEncoder[Z](parentSchema: Schema[_], discriminatorTuple: DiscriminatorTuple, cfg: Config, fields: Schema.Field[Z, _]*): ZJsonEncoder[Z] = { (a: Z, indent: Option[Int], out: Write) => + private[codec] def caseClassEncoder[Z](schema: Schema.Record[Z], discriminatorTuple: DiscriminatorTuple, cfg: Config): ZJsonEncoder[Z] = { (a: Z, indent: Option[Int], out: Write) => { out.write('{') val indent_ = bump(indent) @@ -978,17 +931,13 @@ object JsonCodec { else out.write(" : ") string.encoder.unsafeEncode(JsonFieldEncoder.string.unsafeEncodeField(caseTpeName), indent_, out) } - val nonTransientFields = fields.filter { - case Schema.Field(_, _, annotations, _, _, _) if annotations.collectFirst { case a: transientField => a }.isDefined => false - case _ => true - } - nonTransientFields.foreach { + schema.nonTransientFields.foreach { case s: Schema.Field[Z, _] => val enc = try { JsonEncoder.schemaEncoder(s.schema, cfg) } catch { - case e: Throwable => throw new RuntimeException(s"Failed to encode field '${s.name}' in $parentSchema'", e) + case e: Throwable => throw new RuntimeException(s"Failed to encode field '${s.name}' in $schema'", e) } val value = s.get(a) if (!enc.isNothing(value) && !isEmptyOptionalValue(s, value, cfg)) { @@ -1023,21 +972,21 @@ object JsonCodec { private[codec] def caseClass1Decoder[A, Z](discriminator: Int, schema: Schema.CaseClass1[A, Z]): ZJsonDecoder[Z] = { (trace: List[JsonError], in: RetractReader) => { - val buffer: Array[Any] = unsafeDecodeFields(discriminator, trace, in, schema, schema.field) + val buffer: Array[Any] = unsafeDecodeFields(discriminator, trace, in, schema) schema.defaultConstruct(buffer(0).asInstanceOf[A]) } } private[codec] def caseClass2Decoder[A1, A2, Z](discriminator: Int, schema: Schema.CaseClass2[A1, A2, Z]): ZJsonDecoder[Z] = { (trace: List[JsonError], in: RetractReader) => { - val buffer: Array[Any] = unsafeDecodeFields(discriminator, trace, in, schema, schema.field1, schema.field2) + val buffer: Array[Any] = unsafeDecodeFields(discriminator, trace, in, schema) schema.construct(buffer(0).asInstanceOf[A1], buffer(1).asInstanceOf[A2]) } } private[codec] def caseClass3Decoder[A1, A2, A3, Z](discriminator: Int, schema: Schema.CaseClass3[A1, A2, A3, Z]): ZJsonDecoder[Z] = { (trace: List[JsonError], in: RetractReader) => { - val buffer: Array[Any] = unsafeDecodeFields(discriminator, trace, in, schema, schema.field1, schema.field2, schema.field3) + val buffer: Array[Any] = unsafeDecodeFields(discriminator, trace, in, schema) schema.construct(buffer(0).asInstanceOf[A1], buffer(1).asInstanceOf[A2], buffer(2).asInstanceOf[A3]) } } @@ -1045,7 +994,7 @@ object JsonCodec { private[codec] def caseClass4Decoder[A1, A2, A3, A4, Z](discriminator: Int, schema: Schema.CaseClass4[A1, A2, A3, A4, Z]): ZJsonDecoder[Z] = { (trace: List[JsonError], in: RetractReader) => { val buffer: Array[Any] = - unsafeDecodeFields(discriminator, trace, in, schema, schema.field1, schema.field2, schema.field3, schema.field4) + unsafeDecodeFields(discriminator, trace, in, schema) schema.construct(buffer(0).asInstanceOf[A1], buffer(1).asInstanceOf[A2], buffer(2).asInstanceOf[A3], buffer(3).asInstanceOf[A4]) } } @@ -1053,70 +1002,70 @@ object JsonCodec { private[codec] def caseClass5Decoder[A1, A2, A3, A4, A5, Z](discriminator: Int, schema: Schema.CaseClass5[A1, A2, A3, A4, A5, Z]): ZJsonDecoder[Z] = { (trace: List[JsonError], in: RetractReader) => { val buffer: Array[Any] = - unsafeDecodeFields(discriminator, trace, in, schema, schema.field1, schema.field2, schema.field3, schema.field4, schema.field5) + unsafeDecodeFields(discriminator, trace, in, schema) schema.construct(buffer(0).asInstanceOf[A1], buffer(1).asInstanceOf[A2], buffer(2).asInstanceOf[A3], buffer(3).asInstanceOf[A4], buffer(4).asInstanceOf[A5]) } } private[codec] def caseClass6Decoder[A1, A2, A3, A4, A5, A6, Z](discriminator: Int, schema: Schema.CaseClass6[A1, A2, A3, A4, A5, A6, Z]): ZJsonDecoder[Z] = { (trace: List[JsonError], in: RetractReader) => { - val buffer: Array[Any] = unsafeDecodeFields(discriminator, trace, in, schema, schema.field1, schema.field2, schema.field3, schema.field4, schema.field5, schema.field6) + val buffer: Array[Any] = unsafeDecodeFields(discriminator, trace, in, schema) schema.construct(buffer(0).asInstanceOf[A1], buffer(1).asInstanceOf[A2], buffer(2).asInstanceOf[A3], buffer(3).asInstanceOf[A4], buffer(4).asInstanceOf[A5], buffer(5).asInstanceOf[A6]) } } private[codec] def caseClass7Decoder[A1, A2, A3, A4, A5, A6, A7, Z](discriminator: Int, schema: Schema.CaseClass7[A1, A2, A3, A4, A5, A6, A7, Z]): ZJsonDecoder[Z] = { (trace: List[JsonError], in: RetractReader) => { - val buffer: Array[Any] = unsafeDecodeFields(discriminator, trace, in, schema, schema.field1, schema.field2, schema.field3, schema.field4, schema.field5, schema.field6, schema.field7) + val buffer: Array[Any] = unsafeDecodeFields(discriminator, trace, in, schema) schema.construct(buffer(0).asInstanceOf[A1], buffer(1).asInstanceOf[A2], buffer(2).asInstanceOf[A3], buffer(3).asInstanceOf[A4], buffer(4).asInstanceOf[A5], buffer(5).asInstanceOf[A6], buffer(6).asInstanceOf[A7]) } } private[codec] def caseClass8Decoder[A1, A2, A3, A4, A5, A6, A7, A8, Z](discriminator: Int, schema: Schema.CaseClass8[A1, A2, A3, A4, A5, A6, A7, A8, Z]): ZJsonDecoder[Z] = { (trace: List[JsonError], in: RetractReader) => { - val buffer: Array[Any] = unsafeDecodeFields(discriminator, trace, in, schema, schema.field1, schema.field2, schema.field3, schema.field4, schema.field5, schema.field6, schema.field7, schema.field8) + val buffer: Array[Any] = unsafeDecodeFields(discriminator, trace, in, schema) schema.construct(buffer(0).asInstanceOf[A1], buffer(1).asInstanceOf[A2], buffer(2).asInstanceOf[A3], buffer(3).asInstanceOf[A4], buffer(4).asInstanceOf[A5], buffer(5).asInstanceOf[A6], buffer(6).asInstanceOf[A7], buffer(7).asInstanceOf[A8]) } } private[codec] def caseClass9Decoder[A1, A2, A3, A4, A5, A6, A7, A8, A9, Z](discriminator: Int, schema: Schema.CaseClass9[A1, A2, A3, A4, A5, A6, A7, A8, A9, Z]): ZJsonDecoder[Z] = { (trace: List[JsonError], in: RetractReader) => { - val buffer: Array[Any] = unsafeDecodeFields(discriminator, trace, in, schema, schema.field1, schema.field2, schema.field3, schema.field4, schema.field5, schema.field6, schema.field7, schema.field8, schema.field9) + val buffer: Array[Any] = unsafeDecodeFields(discriminator, trace, in, schema) schema.construct(buffer(0).asInstanceOf[A1], buffer(1).asInstanceOf[A2], buffer(2).asInstanceOf[A3], buffer(3).asInstanceOf[A4], buffer(4).asInstanceOf[A5], buffer(5).asInstanceOf[A6], buffer(6).asInstanceOf[A7], buffer(7).asInstanceOf[A8], buffer(8).asInstanceOf[A9]) } } private[codec] def caseClass10Decoder[A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, Z](discriminator: Int, schema: Schema.CaseClass10[A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, Z]): ZJsonDecoder[Z] = { (trace: List[JsonError], in: RetractReader) => { - val buffer: Array[Any] = unsafeDecodeFields(discriminator, trace, in, schema, schema.field1, schema.field2, schema.field3, schema.field4, schema.field5, schema.field6, schema.field7, schema.field8, schema.field9, schema.field10) + val buffer: Array[Any] = unsafeDecodeFields(discriminator, trace, in, schema) schema.construct(buffer(0).asInstanceOf[A1], buffer(1).asInstanceOf[A2], buffer(2).asInstanceOf[A3], buffer(3).asInstanceOf[A4], buffer(4).asInstanceOf[A5], buffer(5).asInstanceOf[A6], buffer(6).asInstanceOf[A7], buffer(7).asInstanceOf[A8], buffer(8).asInstanceOf[A9], buffer(9).asInstanceOf[A10]) } } private[codec] def caseClass11Decoder[A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, Z](discriminator: Int, schema: Schema.CaseClass11[A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, Z]): ZJsonDecoder[Z] = { (trace: List[JsonError], in: RetractReader) => { - val buffer: Array[Any] = unsafeDecodeFields(discriminator, trace, in, schema, schema.field1, schema.field2, schema.field3, schema.field4, schema.field5, schema.field6, schema.field7, schema.field8, schema.field9, schema.field10, schema.field11) + val buffer: Array[Any] = unsafeDecodeFields(discriminator, trace, in, schema) schema.construct(buffer(0).asInstanceOf[A1], buffer(1).asInstanceOf[A2], buffer(2).asInstanceOf[A3], buffer(3).asInstanceOf[A4], buffer(4).asInstanceOf[A5], buffer(5).asInstanceOf[A6], buffer(6).asInstanceOf[A7], buffer(7).asInstanceOf[A8], buffer(8).asInstanceOf[A9], buffer(9).asInstanceOf[A10], buffer(10).asInstanceOf[A11]) } } private[codec] def caseClass12Decoder[A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, Z](discriminator: Int, schema: Schema.CaseClass12[A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, Z]): ZJsonDecoder[Z] = { (trace: List[JsonError], in: RetractReader) => { - val buffer: Array[Any] = unsafeDecodeFields(discriminator, trace, in, schema, schema.field1, schema.field2, schema.field3, schema.field4, schema.field5, schema.field6, schema.field7, schema.field8, schema.field9, schema.field10, schema.field11, schema.field12) + val buffer: Array[Any] = unsafeDecodeFields(discriminator, trace, in, schema) schema.construct(buffer(0).asInstanceOf[A1], buffer(1).asInstanceOf[A2], buffer(2).asInstanceOf[A3], buffer(3).asInstanceOf[A4], buffer(4).asInstanceOf[A5], buffer(5).asInstanceOf[A6], buffer(6).asInstanceOf[A7], buffer(7).asInstanceOf[A8], buffer(8).asInstanceOf[A9], buffer(9).asInstanceOf[A10], buffer(10).asInstanceOf[A11], buffer(11).asInstanceOf[A12]) } } private[codec] def caseClass13Decoder[A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13, Z](discriminator: Int, schema: Schema.CaseClass13[A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13, Z]): ZJsonDecoder[Z] = { (trace: List[JsonError], in: RetractReader) => { - val buffer: Array[Any] = unsafeDecodeFields(discriminator, trace, in, schema, schema.field1, schema.field2, schema.field3, schema.field4, schema.field5, schema.field6, schema.field7, schema.field8, schema.field9, schema.field10, schema.field11, schema.field12, schema.field13) + val buffer: Array[Any] = unsafeDecodeFields(discriminator, trace, in, schema) schema.construct(buffer(0).asInstanceOf[A1], buffer(1).asInstanceOf[A2], buffer(2).asInstanceOf[A3], buffer(3).asInstanceOf[A4], buffer(4).asInstanceOf[A5], buffer(5).asInstanceOf[A6], buffer(6).asInstanceOf[A7], buffer(7).asInstanceOf[A8], buffer(8).asInstanceOf[A9], buffer(9).asInstanceOf[A10], buffer(10).asInstanceOf[A11], buffer(11).asInstanceOf[A12], buffer(12).asInstanceOf[A13]) } } private[codec] def caseClass14Decoder[A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13, A14, Z](discriminator: Int, schema: Schema.CaseClass14[A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13, A14, Z]): ZJsonDecoder[Z] = { (trace: List[JsonError], in: RetractReader) => { - val buffer: Array[Any] = unsafeDecodeFields(discriminator, trace, in, schema, schema.field1, schema.field2, schema.field3, schema.field4, schema.field5, schema.field6, schema.field7, schema.field8, schema.field9, schema.field10, schema.field11, schema.field12, schema.field13, schema.field14) + val buffer: Array[Any] = unsafeDecodeFields(discriminator, trace, in, schema) schema.construct( buffer(0).asInstanceOf[A1], buffer(1).asInstanceOf[A2], @@ -1138,7 +1087,7 @@ object JsonCodec { private[codec] def caseClass15Decoder[A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13, A14, A15, Z](discriminator: Int, schema: Schema.CaseClass15[A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13, A14, A15, Z]): ZJsonDecoder[Z] = { (trace: List[JsonError], in: RetractReader) => { - val buffer: Array[Any] = unsafeDecodeFields(discriminator, trace, in, schema, schema.field1, schema.field2, schema.field3, schema.field4, schema.field5, schema.field6, schema.field7, schema.field8, schema.field9, schema.field10, schema.field11, schema.field12, schema.field13, schema.field14, schema.field15) + val buffer: Array[Any] = unsafeDecodeFields(discriminator, trace, in, schema) schema.construct( buffer(0).asInstanceOf[A1], buffer(1).asInstanceOf[A2], @@ -1161,7 +1110,7 @@ object JsonCodec { private[codec] def caseClass16Decoder[A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13, A14, A15, A16, Z](discriminator: Int, schema: Schema.CaseClass16[A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13, A14, A15, A16, Z]): ZJsonDecoder[Z] = { (trace: List[JsonError], in: RetractReader) => { - val buffer: Array[Any] = unsafeDecodeFields(discriminator, trace, in, schema, schema.field1, schema.field2, schema.field3, schema.field4, schema.field5, schema.field6, schema.field7, schema.field8, schema.field9, schema.field10, schema.field11, schema.field12, schema.field13, schema.field14, schema.field15, schema.field16) + val buffer: Array[Any] = unsafeDecodeFields(discriminator, trace, in, schema) schema.construct( buffer(0).asInstanceOf[A1], buffer(1).asInstanceOf[A2], @@ -1185,7 +1134,7 @@ object JsonCodec { private[codec] def caseClass17Decoder[A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13, A14, A15, A16, A17, Z](discriminator: Int, schema: Schema.CaseClass17[A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13, A14, A15, A16, A17, Z]): ZJsonDecoder[Z] = { (trace: List[JsonError], in: RetractReader) => { - val buffer: Array[Any] = unsafeDecodeFields(discriminator, trace, in, schema, schema.field1, schema.field2, schema.field3, schema.field4, schema.field5, schema.field6, schema.field7, schema.field8, schema.field9, schema.field10, schema.field11, schema.field12, schema.field13, schema.field14, schema.field15, schema.field16, schema.field17) + val buffer: Array[Any] = unsafeDecodeFields(discriminator, trace, in, schema) schema.construct( buffer(0).asInstanceOf[A1], buffer(1).asInstanceOf[A2], @@ -1210,7 +1159,7 @@ object JsonCodec { private[codec] def caseClass18Decoder[A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13, A14, A15, A16, A17, A18, Z](discriminator: Int, schema: Schema.CaseClass18[A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13, A14, A15, A16, A17, A18, Z]): ZJsonDecoder[Z] = { (trace: List[JsonError], in: RetractReader) => { - val buffer: Array[Any] = unsafeDecodeFields(discriminator, trace, in, schema, schema.field1, schema.field2, schema.field3, schema.field4, schema.field5, schema.field6, schema.field7, schema.field8, schema.field9, schema.field10, schema.field11, schema.field12, schema.field13, schema.field14, schema.field15, schema.field16, schema.field17, schema.field18) + val buffer: Array[Any] = unsafeDecodeFields(discriminator, trace, in, schema) schema.construct( buffer(0).asInstanceOf[A1], buffer(1).asInstanceOf[A2], @@ -1236,7 +1185,7 @@ object JsonCodec { private[codec] def caseClass19Decoder[A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13, A14, A15, A16, A17, A18, A19, Z](discriminator: Int, schema: Schema.CaseClass19[A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13, A14, A15, A16, A17, A18, A19, Z]): ZJsonDecoder[Z] = { (trace: List[JsonError], in: RetractReader) => { - val buffer: Array[Any] = unsafeDecodeFields(discriminator, trace, in, schema, schema.field1, schema.field2, schema.field3, schema.field4, schema.field5, schema.field6, schema.field7, schema.field8, schema.field9, schema.field10, schema.field11, schema.field12, schema.field13, schema.field14, schema.field15, schema.field16, schema.field17, schema.field18, schema.field19) + val buffer: Array[Any] = unsafeDecodeFields(discriminator, trace, in, schema) schema.construct( buffer(0).asInstanceOf[A1], buffer(1).asInstanceOf[A2], @@ -1263,7 +1212,7 @@ object JsonCodec { private[codec] def caseClass20Decoder[A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13, A14, A15, A16, A17, A18, A19, A20, Z](discriminator: Int, schema: Schema.CaseClass20[A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13, A14, A15, A16, A17, A18, A19, A20, Z]): ZJsonDecoder[Z] = { (trace: List[JsonError], in: RetractReader) => { - val buffer: Array[Any] = unsafeDecodeFields(discriminator, trace, in, schema, schema.field1, schema.field2, schema.field3, schema.field4, schema.field5, schema.field6, schema.field7, schema.field8, schema.field9, schema.field10, schema.field11, schema.field12, schema.field13, schema.field14, schema.field15, schema.field16, schema.field17, schema.field18, schema.field19, schema.field20) + val buffer: Array[Any] = unsafeDecodeFields(discriminator, trace, in, schema) schema.construct( buffer(0).asInstanceOf[A1], buffer(1).asInstanceOf[A2], @@ -1292,7 +1241,7 @@ object JsonCodec { private[codec] def caseClass21Decoder[A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13, A14, A15, A16, A17, A18, A19, A20, A21, Z](discriminator: Int, 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]): ZJsonDecoder[Z] = { (trace: List[JsonError], in: RetractReader) => { val buffer: Array[Any] = - unsafeDecodeFields(discriminator, trace, in, schema, schema.field1, schema.field2, schema.field3, schema.field4, schema.field5, schema.field6, schema.field7, schema.field8, schema.field9, schema.field10, schema.field11, schema.field12, schema.field13, schema.field14, schema.field15, schema.field16, schema.field17, schema.field18, schema.field19, schema.field20, schema.field21) + unsafeDecodeFields(discriminator, trace, in, schema) schema.construct( buffer(0).asInstanceOf[A1], buffer(1).asInstanceOf[A2], @@ -1322,34 +1271,7 @@ object JsonCodec { private[codec] def caseClass22Decoder[A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13, A14, A15, A16, A17, A18, A19, A20, A21, A22, Z](discriminator: Int, 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]): ZJsonDecoder[Z] = { (trace: List[JsonError], in: RetractReader) => { val buffer: Array[Any] = - unsafeDecodeFields( - discriminator, - trace, - in, - schema, - schema.field1, - schema.field2, - schema.field3, - schema.field4, - schema.field5, - schema.field6, - schema.field7, - schema.field8, - schema.field9, - schema.field10, - schema.field11, - schema.field12, - schema.field13, - schema.field14, - schema.field15, - schema.field16, - schema.field17, - schema.field18, - schema.field19, - schema.field20, - schema.field21, - schema.field22 - ) + unsafeDecodeFields(discriminator, trace, in, schema) schema.construct( buffer(0).asInstanceOf[A1], buffer(1).asInstanceOf[A2], @@ -1377,7 +1299,8 @@ object JsonCodec { } } - private def unsafeDecodeFields[Z](discriminator: Int, trace: List[JsonError], in: RetractReader, caseClassSchema: Schema[Z], fields: Schema.Field[Z, _]*): Array[Any] = { + private def unsafeDecodeFields[Z](discriminator: Int, trace: List[JsonError], in: RetractReader, caseClassSchema: Schema.Record[Z]) = { + val fields = caseClassSchema.fields val len: Int = fields.length val buffer = Array.ofDim[Any](len) val fieldNames = fields.map(_.name.asInstanceOf[String]).toArray @@ -1425,14 +1348,12 @@ object JsonCodec { var i = 0 while (i < len) { if (buffer(i) == null) { - val optionalAnnotation = fields(i).annotations.collectFirst { case a: optionalField => a } - val transientFieldAnnotation = fields(i).annotations.collectFirst { case a: transientField => a } - val fieldDefaultValueAnnotation = fields(i).annotations.collectFirst { case a: fieldDefaultValue[_] => a } + val fieldDefaultValueAnnotation = fields(i).defaultValue - if (optionalAnnotation.isDefined || transientFieldAnnotation.isDefined) + if (fields(i).optional || fields(i).transient) buffer(i) = schemas(i).defaultValue.toOption.get else if (fieldDefaultValueAnnotation.isDefined) - buffer(i) = fieldDefaultValueAnnotation.get.value + buffer(i) = fieldDefaultValueAnnotation.get else buffer(i) = schemaDecoder(schemas(i)).unsafeDecodeMissing(spans(i) :: trace) diff --git a/zio-schema-thrift/src/main/scala/zio/schema/codec/ThriftCodec.scala b/zio-schema-thrift/src/main/scala/zio/schema/codec/ThriftCodec.scala index bae352447..e9a8e73c4 100644 --- a/zio-schema-thrift/src/main/scala/zio/schema/codec/ThriftCodec.scala +++ b/zio-schema-thrift/src/main/scala/zio/schema/codec/ThriftCodec.scala @@ -12,7 +12,6 @@ import org.apache.thrift.protocol._ import zio.schema.MutableSchemaBasedValueBuilder.{ CreateValueFromSchemaError, ReadingFieldResult } import zio.schema._ -import zio.schema.annotation.{ fieldDefaultValue, optionalField, transientField } import zio.schema.codec.DecodeError.{ EmptyContent, MalformedFieldWithPath, ReadError, ReadErrorWithPath } import zio.stream.ZPipeline import zio.{ Cause, Chunk, Unsafe, ZIO } @@ -626,15 +625,11 @@ object ThriftCodec { case Some(value) => value case None => - val optionalFieldAnnotation = field.annotations.collectFirst({ case a: optionalField => a }) - val transientFieldAnnotation = field.annotations.collectFirst({ case a: transientField => a }) - val fieldDefaultValueAnnotation = field.annotations.collectFirst { - case a: fieldDefaultValue[_] => a - } - if (optionalFieldAnnotation.isDefined || transientFieldAnnotation.isDefined) { + val fieldDefaultValueAnnotation = field.defaultValue + if (field.optional || field.transient) { field.schema.defaultValue.toOption.get } else if (fieldDefaultValueAnnotation.isDefined) { - fieldDefaultValueAnnotation.get.value + fieldDefaultValueAnnotation.get } else { fail(context.copy(path = context.path :+ field.name), s"Missing value") } diff --git a/zio-schema/jvm/src/main/scala/zio/schema/StandardType.scala b/zio-schema/jvm/src/main/scala/zio/schema/StandardType.scala index b65a46ee5..b3f39fc43 100644 --- a/zio-schema/jvm/src/main/scala/zio/schema/StandardType.scala +++ b/zio-schema/jvm/src/main/scala/zio/schema/StandardType.scala @@ -92,61 +92,61 @@ object StandardType { implicit object UnitType extends StandardType[Unit] { override def tag: String = Tags.UNIT override def compare(x: Unit, y: Unit): Int = 0 - override def defaultValue: Either[String, Unit] = Right(()) + override val defaultValue: Either[String, Unit] = Right(()) } implicit object StringType extends StandardType[String] { override def tag: String = Tags.STRING override def compare(x: String, y: String): Int = x.compareTo(y) - override def defaultValue: Either[String, String] = Right("") + override val defaultValue: Either[String, String] = Right("") } implicit object BoolType extends StandardType[Boolean] { override def tag: String = Tags.BOOL override def compare(x: Boolean, y: Boolean): Int = x.compareTo(y) - override def defaultValue: Either[String, Boolean] = Right(false) + override val defaultValue: Either[String, Boolean] = Right(false) } implicit object ByteType extends StandardType[Byte] { override def tag: String = Tags.BYTE override def compare(x: Byte, y: Byte): Int = x.compareTo(y) - override def defaultValue: Either[String, Byte] = Right(0.toByte) + override val defaultValue: Either[String, Byte] = Right(0.toByte) } implicit object ShortType extends StandardType[Short] { override def tag: String = Tags.SHORT override def compare(x: Short, y: Short): Int = x.compareTo(y) - override def defaultValue: Either[String, Short] = Right(0.asInstanceOf[Short]) + override val defaultValue: Either[String, Short] = Right(0.asInstanceOf[Short]) } implicit object IntType extends StandardType[Int] { override def tag: String = Tags.INT override def compare(x: Int, y: Int): Int = x.compareTo(y) - override def defaultValue: Either[String, Int] = Right(0) + override val defaultValue: Either[String, Int] = Right(0) } implicit object LongType extends StandardType[Long] { override def tag: String = Tags.LONG override def compare(x: Long, y: Long): Int = x.compareTo(y) - override def defaultValue: Either[String, Long] = Right(0.asInstanceOf[Long]) + override val defaultValue: Either[String, Long] = Right(0L) } implicit object FloatType extends StandardType[Float] { override def tag: String = Tags.FLOAT override def compare(x: Float, y: Float): Int = x.compareTo(y) - override def defaultValue: Either[String, Float] = Right(0.0.asInstanceOf[Float]) + override val defaultValue: Either[String, Float] = Right(0.0f) } implicit object DoubleType extends StandardType[Double] { override def tag: String = Tags.DOUBLE override def compare(x: Double, y: Double): Int = x.compareTo(y) - override def defaultValue: Either[String, Double] = Right(0.0) + override val defaultValue: Either[String, Double] = Right(0.0) } implicit object BinaryType extends StandardType[Chunk[Byte]] { override def tag: String = Tags.BINARY override def compare(x: Chunk[Byte], y: Chunk[Byte]): Int = x.sum.compare(y.sum) - override def defaultValue: Either[String, Chunk[Byte]] = Right(Chunk.empty) + override val defaultValue: Either[String, Chunk[Byte]] = Right(Chunk.empty) } implicit object CharType extends StandardType[Char] { @@ -154,7 +154,7 @@ object StandardType { override def compare(x: Char, y: Char): Int = x.compareTo(y) // The NUL Unicode character is used as the default value for // `StandardType[Char]` because the empty Char '' does not compile - override def defaultValue: Either[String, Char] = Right('\u0000') + override val defaultValue: Either[String, Char] = Right('\u0000') } implicit object UUIDType extends StandardType[java.util.UUID] { @@ -166,13 +166,13 @@ object StandardType { implicit object BigDecimalType extends StandardType[java.math.BigDecimal] { override def tag: String = Tags.BIG_DECIMAL override def compare(x: java.math.BigDecimal, y: java.math.BigDecimal): Int = x.compareTo(y) - override def defaultValue: Either[String, java.math.BigDecimal] = Right(java.math.BigDecimal.ZERO) + override val defaultValue: Either[String, java.math.BigDecimal] = Right(java.math.BigDecimal.ZERO) } implicit object BigIntegerType extends StandardType[java.math.BigInteger] { override def tag: String = Tags.BIG_INTEGER override def compare(x: BigInteger, y: BigInteger): Int = x.compareTo(y) - override def defaultValue: Either[String, java.math.BigInteger] = Right(java.math.BigInteger.ZERO) + override val defaultValue: Either[String, java.math.BigInteger] = Right(java.math.BigInteger.ZERO) } //java.time specific types @@ -186,13 +186,13 @@ object StandardType { implicit object MonthType extends StandardType[java.time.Month] { override def tag: String = Tags.MONTH override def compare(x: Month, y: Month): Int = x.getValue.compareTo(y.getValue) - override def defaultValue: Either[String, java.time.Month] = Right(java.time.Month.JANUARY) + override val defaultValue: Either[String, java.time.Month] = Right(java.time.Month.JANUARY) } implicit object MonthDayType extends StandardType[java.time.MonthDay] { override def tag: String = Tags.MONTH_DAY override def compare(x: MonthDay, y: MonthDay): Int = x.compareTo(y) - override def defaultValue: Either[String, java.time.MonthDay] = + override val defaultValue: Either[String, java.time.MonthDay] = Right(java.time.MonthDay.of(java.time.Month.JANUARY, 1)) } @@ -202,7 +202,7 @@ object StandardType { val startDate = time.LocalDate.of(0, 1, 1) startDate.plus(x).compareTo(startDate.plus(y)) } - override def defaultValue: Either[String, java.time.Period] = Right(java.time.Period.ZERO) + override val defaultValue: Either[String, java.time.Period] = Right(java.time.Period.ZERO) } implicit object YearType extends StandardType[java.time.Year] { @@ -226,19 +226,19 @@ object StandardType { implicit object ZoneOffsetType extends StandardType[java.time.ZoneOffset] { override def tag: String = Tags.ZONE_OFFSET override def compare(x: ZoneOffset, y: ZoneOffset): Int = x.compareTo(y) - override def defaultValue: Either[String, java.time.ZoneOffset] = Right(java.time.ZoneOffset.UTC) + override val defaultValue: Either[String, java.time.ZoneOffset] = Right(java.time.ZoneOffset.UTC) } implicit object DurationType extends StandardType[java.time.Duration] { override def tag: String = Tags.DURATION override def compare(x: time.Duration, y: time.Duration): Int = x.compareTo(y) - override def defaultValue: Either[String, java.time.Duration] = Right(java.time.Duration.ZERO) + override val defaultValue: Either[String, java.time.Duration] = Right(java.time.Duration.ZERO) } implicit object InstantType extends StandardType[java.time.Instant] { override def tag: String = Tags.INSTANT - override def defaultValue: Either[String, Instant] = Right(java.time.Instant.EPOCH) + override val defaultValue: Either[String, Instant] = Right(java.time.Instant.EPOCH) override def compare(x: Instant, y: Instant): Int = x.compareTo(y) } @@ -254,7 +254,7 @@ object StandardType { implicit object LocalTimeType extends StandardType[java.time.LocalTime] { override def tag: String = Tags.LOCAL_TIME - override def defaultValue: Either[String, LocalTime] = Right(java.time.LocalTime.MIDNIGHT) + override val defaultValue: Either[String, LocalTime] = Right(java.time.LocalTime.MIDNIGHT) override def compare(x: LocalTime, y: LocalTime): Int = x.compareTo(y) } diff --git a/zio-schema/shared/src/main/scala/zio/schema/MutableSchemaBasedValueProcessor.scala b/zio-schema/shared/src/main/scala/zio/schema/MutableSchemaBasedValueProcessor.scala index 432c1fecf..e036630e9 100644 --- a/zio-schema/shared/src/main/scala/zio/schema/MutableSchemaBasedValueProcessor.scala +++ b/zio-schema/shared/src/main/scala/zio/schema/MutableSchemaBasedValueProcessor.scala @@ -2,7 +2,6 @@ package zio.schema import scala.collection.immutable.ListMap -import zio.schema.annotation.transientField import zio.{ Chunk, ChunkBuilder } /** Base trait for mutable value processors, processing a value with a known schema. An example @@ -142,9 +141,8 @@ trait MutableSchemaBasedValueProcessor[Target, Context] { result = Some(resultValue) } - def fields(s: Schema.Record[_], record: Any, fs: Schema.Field[_, _]*): Unit = { - val nonTransientFields = fs.filterNot(_.annotations.exists(_.isInstanceOf[transientField])) - val values = ChunkBuilder.make[Target](nonTransientFields.size) + def fields(s: Schema.Record[_], record: Any): Unit = { + val values = ChunkBuilder.make[Target](s.nonTransientFields.size) def processNext(index: Int, remaining: Seq[Schema.Field[_, _]]): Unit = if (remaining.isEmpty) { @@ -152,7 +150,7 @@ trait MutableSchemaBasedValueProcessor[Target, Context] { processRecord( contextStack.head, s, - nonTransientFields.map(_.name).zip(values.result()).foldLeft(ListMap.empty[String, Target]) { + s.nonTransientFields.map(_.name).zip(values.result()).foldLeft(ListMap.empty[String, Target]) { case (lm, pair) => lm.updated(pair._1, pair._2) } @@ -174,7 +172,7 @@ trait MutableSchemaBasedValueProcessor[Target, Context] { } startProcessingRecord(contextStack.head, s) - processNext(0, nonTransientFields) + processNext(0, s.nonTransientFields) } def enumCases(s: Schema.Enum[_], cs: Schema.Case[_, _]*): Unit = { @@ -217,10 +215,9 @@ trait MutableSchemaBasedValueProcessor[Target, Context] { case Schema.Primitive(p, _) => finishWith(processPrimitive(currentContext, currentValue, p.asInstanceOf[StandardType[Any]])) - case s @ Schema.GenericRecord(_, structure, _) => - val map = currentValue.asInstanceOf[ListMap[String, _]] - val nonTransientFields = structure.toChunk.filterNot(_.annotations.exists(_.isInstanceOf[transientField])) - val values = ChunkBuilder.make[Target](nonTransientFields.size) + case s @ Schema.GenericRecord(_, _, _) => + val map = currentValue.asInstanceOf[ListMap[String, _]] + val values = ChunkBuilder.make[Target](s.nonTransientFields.size) def processNext(index: Int, remaining: Seq[Schema.Field[ListMap[String, _], _]]): Unit = if (remaining.isEmpty) { @@ -228,7 +225,7 @@ trait MutableSchemaBasedValueProcessor[Target, Context] { processRecord( currentContext, s, - nonTransientFields.map(_.name).zip(values.result()).foldLeft(ListMap.empty[String, Target]) { + s.nonTransientFields.map(_.name).zip(values.result()).foldLeft(ListMap.empty[String, Target]) { case (lm, pair) => lm.updated(pair._1, pair._2) } @@ -254,7 +251,7 @@ trait MutableSchemaBasedValueProcessor[Target, Context] { } startProcessingRecord(currentContext, s) - processNext(0, nonTransientFields) + processNext(0, s.nonTransientFields) case s @ Schema.Enum1(_, case1, _) => enumCases(s, case1) @@ -918,448 +915,8 @@ trait MutableSchemaBasedValueProcessor[Target, Context] { currentSchema = schema } - case s @ Schema.CaseClass0(_, _, _) => + case s: Schema.Record[_] => fields(s, currentValue) - - case s @ Schema.CaseClass1(_, f, _, _) => - fields(s, currentValue, f) - - case s @ Schema.CaseClass2(_, f1, f2, _, _) => - fields(s, currentValue, f1, f2) - case s @ Schema.CaseClass3(_, f1, f2, f3, _, _) => - fields(s, currentValue, f1, f2, f3) - case s @ Schema.CaseClass4(_, f1, f2, f3, f4, _, _) => - fields(s, currentValue, f1, f2, f3, f4) - case s @ Schema.CaseClass5(_, f1, f2, f3, f4, f5, _, _) => - fields(s, currentValue, f1, f2, f3, f4, f5) - case s @ Schema.CaseClass6(_, f1, f2, f3, f4, f5, f6, _, _) => - fields(s, currentValue, f1, f2, f3, f4, f5, f6) - case s @ Schema.CaseClass7(_, f1, f2, f3, f4, f5, f6, f7, _, _) => - fields(s, currentValue, f1, f2, f3, f4, f5, f6, f7) - case s @ Schema.CaseClass8( - _, - f1, - f2, - f3, - f4, - f5, - f6, - f7, - f8, - _, - _ - ) => - fields(s, currentValue, f1, f2, f3, f4, f5, f6, f7, f8) - case s @ Schema.CaseClass9( - _, - f1, - f2, - f3, - f4, - f5, - f6, - f7, - f8, - f9, - _, - _ - ) => - fields(s, currentValue, f1, f2, f3, f4, f5, f6, f7, f8, f9) - case s @ Schema.CaseClass10( - _, - f1, - f2, - f3, - f4, - f5, - f6, - f7, - f8, - f9, - f10, - _, - _ - ) => - fields(s, currentValue, f1, f2, f3, f4, f5, f6, f7, f8, f9, f10) - case s @ Schema.CaseClass11( - _, - f1, - f2, - f3, - f4, - f5, - f6, - f7, - f8, - f9, - f10, - f11, - _, - _ - ) => - fields(s, currentValue, f1, f2, f3, f4, f5, f6, f7, f8, f9, f10, f11) - case s @ Schema.CaseClass12( - _, - f1, - f2, - f3, - f4, - f5, - f6, - f7, - f8, - f9, - f10, - f11, - f12, - _, - _ - ) => - fields(s, currentValue, f1, f2, f3, f4, f5, f6, f7, f8, f9, f10, f11, f12) - case s @ Schema.CaseClass13( - _, - f1, - f2, - f3, - f4, - f5, - f6, - f7, - f8, - f9, - f10, - f11, - f12, - f13, - _, - _ - ) => - fields(s, currentValue, f1, f2, f3, f4, f5, f6, f7, f8, f9, f10, f11, f12, f13) - case s @ Schema.CaseClass14( - _, - f1, - f2, - f3, - f4, - f5, - f6, - f7, - f8, - f9, - f10, - f11, - f12, - f13, - f14, - _, - _ - ) => - fields(s, currentValue, f1, f2, f3, f4, f5, f6, f7, f8, f9, f10, f11, f12, f13, f14) - case s @ Schema.CaseClass15( - _, - f1, - f2, - f3, - f4, - f5, - f6, - f7, - f8, - f9, - f10, - f11, - f12, - f13, - f14, - f15, - _, - _ - ) => - fields(s, currentValue, f1, f2, f3, f4, f5, f6, f7, f8, f9, f10, f11, f12, f13, f14, f15) - case s @ Schema.CaseClass16( - _, - f1, - f2, - f3, - f4, - f5, - f6, - f7, - f8, - f9, - f10, - f11, - f12, - f13, - f14, - f15, - f16, - _, - _ - ) => - fields(s, currentValue, f1, f2, f3, f4, f5, f6, f7, f8, f9, f10, f11, f12, f13, f14, f15, f16) - case s @ Schema.CaseClass17( - _, - f1, - f2, - f3, - f4, - f5, - f6, - f7, - f8, - f9, - f10, - f11, - f12, - f13, - f14, - f15, - f16, - f17, - _, - _ - ) => - fields(s, currentValue, f1, f2, f3, f4, f5, f6, f7, f8, f9, f10, f11, f12, f13, f14, f15, f16, f17) - case s @ Schema.CaseClass18( - _, - f1, - f2, - f3, - f4, - f5, - f6, - f7, - f8, - f9, - f10, - f11, - f12, - f13, - f14, - f15, - f16, - f17, - f18, - _, - _ - ) => - fields( - s, - currentValue, - f1, - f2, - f3, - f4, - f5, - f6, - f7, - f8, - f9, - f10, - f11, - f12, - f13, - f14, - f15, - f16, - f17, - f18 - ) - case s @ Schema.CaseClass19( - _, - f1, - f2, - f3, - f4, - f5, - f6, - f7, - f8, - f9, - f10, - f11, - f12, - f13, - f14, - f15, - f16, - f17, - f18, - f19, - _, - _ - ) => - fields( - s, - currentValue, - f1, - f2, - f3, - f4, - f5, - f6, - f7, - f8, - f9, - f10, - f11, - f12, - f13, - f14, - f15, - f16, - f17, - f18, - f19 - ) - case s @ Schema.CaseClass20( - _, - f1, - f2, - f3, - f4, - f5, - f6, - f7, - f8, - f9, - f10, - f11, - f12, - f13, - f14, - f15, - f16, - f17, - f18, - f19, - f20, - _ - ) => - fields( - s, - currentValue, - f1, - f2, - f3, - f4, - f5, - f6, - f7, - f8, - f9, - f10, - f11, - f12, - f13, - f14, - f15, - f16, - f17, - f18, - f19, - f20 - ) - case s @ Schema.CaseClass21( - _, - f1, - f2, - f3, - f4, - f5, - f6, - f7, - f8, - f9, - f10, - f11, - f12, - f13, - f14, - f15, - f16, - f17, - f18, - f19, - f20, - tail - ) => - fields( - s, - currentValue, - f1, - f2, - f3, - f4, - f5, - f6, - f7, - f8, - f9, - f10, - f11, - f12, - f13, - f14, - f15, - f16, - f17, - f18, - f19, - f20, - tail._1 - ) - case s @ Schema.CaseClass22( - _, - f1, - f2, - f3, - f4, - f5, - f6, - f7, - f8, - f9, - f10, - f11, - f12, - f13, - f14, - f15, - f16, - f17, - f18, - f19, - f20, - tail - ) => - fields( - s, - currentValue, - f1, - f2, - f3, - f4, - f5, - f6, - f7, - f8, - f9, - f10, - f11, - f12, - f13, - f14, - f15, - f16, - f17, - f18, - f19, - f20, - tail._1, - tail._2 - ) case Schema.Dynamic(_) => processDynamic(currentContext, currentValue.asInstanceOf[DynamicValue]) match { case Some(target) => finishWith(target) diff --git a/zio-schema/shared/src/main/scala/zio/schema/Schema.scala b/zio-schema/shared/src/main/scala/zio/schema/Schema.scala index fefd1aae5..79f53a811 100644 --- a/zio-schema/shared/src/main/scala/zio/schema/Schema.scala +++ b/zio-schema/shared/src/main/scala/zio/schema/Schema.scala @@ -6,7 +6,7 @@ import java.time.temporal.ChronoUnit import scala.annotation.tailrec import scala.collection.immutable.ListMap -import zio.schema.annotation.fieldDefaultValue +import zio.schema.annotation.{ caseNameAliases, _ } import zio.schema.internal.SourceLocation import zio.schema.meta._ import zio.schema.validation._ @@ -362,6 +362,9 @@ object Schema extends SchemaPlatformSpecific with SchemaEquality { def caseOf(z: Z): Option[Case[Z, _]] = cases.find(_.isCase(z)) + val noDiscriminator: Boolean = + annotations.exists(_.isInstanceOf[noDiscriminator]) + override def toString: String = s"${this.getClass.getSimpleName}($id)" } @@ -375,6 +378,17 @@ object Schema extends SchemaPlatformSpecific with SchemaEquality { def get: R => A def set: (R, A) => R + val defaultValue: Option[A] = + annotations.collectFirst { + case a if a.isInstanceOf[fieldDefaultValue[A]] => a.asInstanceOf[fieldDefaultValue[A]].value + }.orElse(schema.defaultValue.toOption) + + val optional: Boolean = + annotations.exists(_.isInstanceOf[optionalField]) + + val transient: Boolean = + annotations.exists(_.isInstanceOf[transientField]) + override def toString: String = s"Field($name,$schema)" } @@ -417,6 +431,9 @@ object Schema extends SchemaPlatformSpecific with SchemaEquality { val fields: Chunk[Field[R, _]] + val nonTransientFields: Chunk[Field[R, _]] = + fields.filterNot(_.transient) + def construct(fieldValues: Chunk[Any])(implicit unsafe: Unsafe): scala.util.Either[String, R] def deconstruct(value: R)(implicit unsafe: Unsafe): Chunk[Option[Any]] @@ -801,11 +818,20 @@ object Schema extends SchemaPlatformSpecific with SchemaEquality { annotations: Chunk[Any] = Chunk.empty ) { self => + val caseName: String = + annotations.collectFirst { case name: caseName => name.name }.getOrElse(id) + + val caseNameAliases: Seq[String] = + annotations.collect { case aliases: caseNameAliases => aliases.aliases }.flatten + def deconstruct(r: R): A = unsafeDeconstruct(r) def deconstructOption(r: R): Option[A] = if (isCase(r)) Some(unsafeDeconstruct(r)) else None + val transient: Boolean = + annotations.exists(_.isInstanceOf[transientCase]) + override def toString: String = s"Case($id,$schema,$annotations)" }