Skip to content

Commit

Permalink
fixes
Browse files Browse the repository at this point in the history
  • Loading branch information
goshacodes committed Jul 7, 2024
1 parent 30eb1a3 commit 65adcf7
Show file tree
Hide file tree
Showing 21 changed files with 461 additions and 209 deletions.
408 changes: 329 additions & 79 deletions README.md

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package json.bench.tethysjson

import json.bench.{DataReader, DataWriter}
import json.bench.model.Data
import tethys._
import tethys.jackson._

object TethysBench {

implicit val dataWriter: JsonWriter[Data] = tethys.derivation.semiauto.jsonWriter[Data]
implicit val dataReader: JsonReader[Data] = tethys.derivation.semiauto.jsonReader[Data]

object TethysJacksonDataProcessor extends DataWriter with DataReader {

override def write(seq: Seq[Data]): String = seq.asJson

override def read(json: String): Seq[Data] = json.jsonAs[Seq[Data]].toOption.get
}
}
Original file line number Diff line number Diff line change
@@ -1,10 +1,9 @@
package json.bench.tethysjson

import json.bench.model.Data
import tethys._
import tethys.jackson._
import tethys.derivation.semiauto._
import json.bench.{DataReader, DataWriter}
import tethys.*
import tethys.jackson.*

/**
* Created by eld0727 on 21.04.17.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,6 @@ object BenchMarkdown {
else Left(JsonReader.stringReader.read(it))
}
}

implicit val primaryMetricsReader: JsonReader[PrimaryMetrics] = jsonReader[PrimaryMetrics]
implicit val benchmarkReader: JsonReader[Benchmark] = jsonReader[Benchmark]

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ object CollectionBuilder {
}

implicit def iterableFactoryCollectionBuilder[A, C[X] <: IterableFactoryDefaults[X, C]]: IterableFactoryCollectionBuilder[A, C] = macro CollectionBuilderMacroImpl.fromIterableFactory[A, C]
implicit def mapFactoryCollectionBuilder[K, V, M[X, Y] <: Map[X, Y]]: MapFactoryCollectionBuilder[K, V, M] = macro CollectionBuilderMacroImpl.fromMapFactory[K, V, M]
implicit def mapFactoryCollectionBuilder[K, V, M[X, Y] <: scala.collection.Map[X, Y]]: CollectionBuilder[(K, V), M[K, V]] = macro CollectionBuilderMacroImpl.fromMapFactory[K, V, M]

private class CollectionBuilderMacroImpl(val c: blackbox.Context) {
import c.universe._
Expand All @@ -30,7 +30,7 @@ object CollectionBuilder {
q"new tethys.compat.CollectionBuilder.IterableFactoryCollectionBuilder[${A.tpe}, ${C.tpe}]($ref)"
}

def fromMapFactory[K, V, M[X, Y] <: Map[X, Y]](implicit
def fromMapFactory[K, V, M[X, Y] <: scala.collection.Map[X, Y]](implicit
K: WeakTypeTag[K],
V: WeakTypeTag[V],
M: WeakTypeTag[M[K, V]]): Tree = {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package tethys.derivation
package tethys

import tethys.{FieldStyle, JsonReader}

Expand Down
37 changes: 37 additions & 0 deletions modules/core/src/main/scala-3/tethys/WriterBuilder.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
package tethys

import tethys.FieldStyle

sealed trait WriterBuilder[A]:
import WriterBuilder.*

def add(name: String): FunApply0[A, A]

def remove[B](field: A => B): WriterBuilder[A]

def rename[B](field: A => B)(rename: String): WriterBuilder[A]

def update[B](field: A => B): FunApply[A, B] with WithRename[FunApply[A, B]]

@deprecated("Use 'update' instead.")
def updatePartial[B](field: A => B): FunApply[A, B] with WithRename[FunApply[A, B]]

def fieldStyle(style: FieldStyle): WriterBuilder[A]


object WriterBuilder:
def apply[A](using mirror: scala.deriving.Mirror.ProductOf[A]): WriterBuilder[A] =
throw IllegalStateException("Config must be an inlined given or provided directly to 'derived'")

sealed trait WithRename[Res]:
def withRename(rename: String): Res

sealed trait FunApply0[A, B]:
def apply[C](fun: B => C): WriterBuilder[A]

sealed trait FunApply[A, B] extends FunApply0[A, B]:
def fromRoot[C](fun: A => C): WriterBuilder[A]


sealed trait JsonWriterSumConfig[A]:
def fieldStyle(style: FieldStyle): JsonWriterSumConfig[A]
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ object CollectionBuilder {
inline given iterableFactoryCollectionBuilder[A, C[X] <: Iterable[X]]: CollectionBuilder[A, C[A]] =
${CollectionBuilderMacroImpl.fromIterableFactory[A, C]}

inline given mapFactoryCollectionBuilder[K, V, M[X, Y] <: Map[X, Y]]: MapFactoryCollectionBuilder[K, V, M] =
inline given mapFactoryCollectionBuilder[K, V, M[X, Y] <: scala.collection.Map[X, Y]]: CollectionBuilder[(K, V), M[K, V]] =
${CollectionBuilderMacroImpl.fromMapFactory[K, V, M]}

object CollectionBuilderMacroImpl {
Expand All @@ -30,7 +30,7 @@ object CollectionBuilder {
'{new tethys.compat.CollectionBuilder.IterableFactoryCollectionBuilder[A, C]($factory)}
}

def fromMapFactory[K: Type, V: Type, M[X, Y] <: Map[X, Y]: Type](using Quotes): Expr[MapFactoryCollectionBuilder[K, V, M]] = {
def fromMapFactory[K: Type, V: Type, M[X, Y] <: scala.collection.Map[X, Y]: Type](using Quotes): Expr[MapFactoryCollectionBuilder[K, V, M]] = {
import quotes.reflect.*

val factory = Ref(TypeRepr.of[M].typeSymbol.companionModule).asExprOf[MapFactory[M]]
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
package tethys.derivation

import tethys.{FieldStyle, JsonReader, JsonWriter, JsonObjectWriter, JsonConfig}
import tethys.*

import scala.annotation.tailrec
import scala.collection.mutable
Expand All @@ -12,9 +12,9 @@ class ConfigurationMacroUtils(using val quotes: Quotes):
import quotes.reflect.*

def prepareWriterProductFields[T: Type](
config: Expr[JsonWriter.ProductConfig[T]]
config: Expr[WriterBuilder[T]]
): List[WriterField] =
val macroConfig = parseWriterProductConfig[T](config)
val macroConfig = parseWriterBuilderMacroConfig[T](config)
val updates = macroConfig.update.map(it => it.name -> it).toMap
val tpe = TypeRepr.of[T]
tpe.typeSymbol.caseFields.zipWithIndex
Expand Down Expand Up @@ -42,9 +42,9 @@ class ConfigurationMacroUtils(using val quotes: Quotes):
)
} ::: macroConfig.add

private def parseWriterProductConfig[T: Type](
config: Expr[JsonWriter.ProductConfig[T]]
): WriterProductMacroConfig =
private def parseWriterBuilderMacroConfig[T: Type](
config: Expr[WriterBuilder[T]]
): WriterBuilderMacroConfig =
val fields = TypeRepr.of[T].typeSymbol.caseFields.map(_.name)

def exitFieldAlreadyUpdated(name: String) =
Expand All @@ -54,32 +54,32 @@ class ConfigurationMacroUtils(using val quotes: Quotes):

@tailrec
def loop(
config: Expr[JsonWriter.ProductConfig[T]],
acc: WriterProductMacroConfig = WriterProductMacroConfig(),
updatedFields: Set[String] = Set.empty
): (WriterProductMacroConfig, Set[String]) =
config: Expr[WriterBuilder[T]],
acc: WriterBuilderMacroConfig = WriterBuilderMacroConfig(),
updatedFields: Set[String] = Set.empty
): (WriterBuilderMacroConfig, Set[String]) =
config match
case '{
JsonWriter.configure[T](using ${ mirror }: Mirror.ProductOf[T])
WriterBuilder[T](using ${ mirror }: Mirror.ProductOf[T])
} =>
(acc, updatedFields)

case '{
JsonObjectWriter.configure[T](using
WriterBuilder[T](using
${ mirror }: Mirror.ProductOf[T]
)
} =>
(acc, updatedFields)

case '{
($rest: JsonWriter.ProductConfig[T]).fieldStyle(${
($rest: WriterBuilder[T]).fieldStyle(${
fieldStyle
}: FieldStyle)
} =>
(acc.copy(fieldStyle = Some(fieldStyle.valueOrAbort)), updatedFields)

case '{
($rest: JsonWriter.ProductConfig[T])
($rest: WriterBuilder[T])
.add($field: String)
.apply[to]($lambda)
} =>
Expand All @@ -105,7 +105,7 @@ class ConfigurationMacroUtils(using val quotes: Quotes):
)

case '{
($rest: JsonWriter.ProductConfig[T]).remove(${
($rest: WriterBuilder[T]).remove(${
SelectedField(field)
}: T => Any)
} =>
Expand All @@ -119,7 +119,7 @@ class ConfigurationMacroUtils(using val quotes: Quotes):
)

case '{
($rest: JsonWriter.ProductConfig[T]).rename[to](${
($rest: WriterBuilder[T]).rename[to](${
SelectedField(field)
})($rename: String)
} =>
Expand All @@ -141,7 +141,7 @@ class ConfigurationMacroUtils(using val quotes: Quotes):
)

case '{
($rest: JsonWriter.ProductConfig[T])
($rest: WriterBuilder[T])
.update[from](${ SelectedField(field) })
.apply[to]($updater)
} =>
Expand All @@ -163,7 +163,7 @@ class ConfigurationMacroUtils(using val quotes: Quotes):
)

case '{
($rest: JsonWriter.ProductConfig[T])
($rest: WriterBuilder[T])
.update[from](${ SelectedField(field) })
.withRename($rename)
.apply[to]($updater)
Expand All @@ -186,7 +186,7 @@ class ConfigurationMacroUtils(using val quotes: Quotes):
)

case '{
($rest: JsonWriter.ProductConfig[T])
($rest: WriterBuilder[T])
.update(${ SelectedField(field) })
.fromRoot[to](${ updater })
} =>
Expand All @@ -208,7 +208,7 @@ class ConfigurationMacroUtils(using val quotes: Quotes):
)

case '{
($rest: JsonWriter.ProductConfig[T])
($rest: WriterBuilder[T])
.update[from](${ SelectedField(field) })
.withRename($rename)
.fromRoot[to](${ updater })
Expand All @@ -230,7 +230,7 @@ class ConfigurationMacroUtils(using val quotes: Quotes):
updatedFields = updatedFields + field.name
)
case '{
($rest: JsonWriter.ProductConfig[T])
($rest: WriterBuilder[T])
.updatePartial[from](${ SelectedField(field) })
.apply[to]($updater)
} =>
Expand All @@ -252,7 +252,7 @@ class ConfigurationMacroUtils(using val quotes: Quotes):
)

case '{
($rest: JsonWriter.ProductConfig[T])
($rest: WriterBuilder[T])
.updatePartial[from](${ SelectedField(field) })
.withRename($rename)
.apply[to]($updater)
Expand All @@ -275,7 +275,7 @@ class ConfigurationMacroUtils(using val quotes: Quotes):
)

case '{
($rest: JsonWriter.ProductConfig[T])
($rest: WriterBuilder[T])
.updatePartial(${ SelectedField(field) })
.fromRoot[to](${ updater })
} =>
Expand All @@ -297,7 +297,7 @@ class ConfigurationMacroUtils(using val quotes: Quotes):
)

case '{
($rest: JsonWriter.ProductConfig[T])
($rest: WriterBuilder[T])
.updatePartial[from](${ SelectedField(field) })
.withRename($rename)
.fromRoot[to](${ updater })
Expand All @@ -322,21 +322,21 @@ class ConfigurationMacroUtils(using val quotes: Quotes):
case other =>
other.asTerm match
case Inlined(_, _, term) =>
loop(term.asExprOf[tethys.derivation.JsonWriterProductConfig[T]])
loop(term.asExprOf[WriterBuilder[T]])
case _ =>
report.errorAndAbort(
s"Unknown tree. Config must be an inlined given.\nTree: ${other.asTerm
.show(using Printer.TreeStructure)}"
)

loop(traverseTree(config.asTerm).asExprOf[JsonWriter.ProductConfig[T]])._1
loop(traverseTree(config.asTerm).asExprOf[WriterBuilder[T]])._1

end parseWriterProductConfig
end parseWriterBuilderMacroConfig

def prepareReaderProductFields[T: Type](
config: Expr[ReaderBuilder[T]]
): (List[ReaderField], IsStrict) =
val macroConfig = parseReaderProductConfig[T](config)
val macroConfig = parseReaderBuilderMacroConfig[T](config)
val tpe = TypeRepr.of[T]
val defaults = collectDefaults[T]
val fields = tpe.typeSymbol.caseFields.zipWithIndex
Expand Down Expand Up @@ -444,9 +444,9 @@ class ConfigurationMacroUtils(using val quotes: Quotes):
}
.toMap

private def parseReaderProductConfig[T: Type](
private def parseReaderBuilderMacroConfig[T: Type](
config: Expr[ReaderBuilder[T]]
): ReaderProductMacroConfig =
): ReaderBuilderMacroConfig =
val fields = TypeRepr.of[T].typeSymbol.caseFields.map(_.name)

def exitExtractionAlreadyDefined(name: String) =
Expand All @@ -459,8 +459,8 @@ class ConfigurationMacroUtils(using val quotes: Quotes):

def loop(
config: Expr[ReaderBuilder[T]],
acc: ReaderProductMacroConfig = ReaderProductMacroConfig(Map.empty)
): ReaderProductMacroConfig =
acc: ReaderBuilderMacroConfig = ReaderBuilderMacroConfig(Map.empty)
): ReaderBuilderMacroConfig =
config match
case '{
ReaderBuilder[T](using
Expand Down Expand Up @@ -506,7 +506,7 @@ class ConfigurationMacroUtils(using val quotes: Quotes):
term: Term,
extractors: List[(String, TypeRepr)] = Nil,
lambda: Expr[Any => Any] = '{ identity[Any] }
): ReaderProductMacroConfig =
): ReaderBuilderMacroConfig =
term match
case config @ Apply(
TypeApply(Select(term, "extract"), List(tpt)),
Expand Down Expand Up @@ -759,7 +759,7 @@ class ConfigurationMacroUtils(using val quotes: Quotes):
enum What:
case Root, Field

case class WriterProductMacroConfig(
case class WriterBuilderMacroConfig(
delete: Set[String] = Set.empty,
add: List[WriterField.Added] = Nil,
update: List[WriterFieldUpdate] = Nil,
Expand Down Expand Up @@ -865,12 +865,12 @@ class ConfigurationMacroUtils(using val quotes: Quotes):
default: Option[Expr[Any]] = None
) extends ReaderField

case class ReaderProductMacroConfig(
case class ReaderBuilderMacroConfig(
extracted: Map[String, ReaderField] = Map.empty,
fieldStyle: Option[FieldStyle] = None,
isStrict: IsStrict = false
):
def withExtracted(field: ReaderField): ReaderProductMacroConfig =
def withExtracted(field: ReaderField): ReaderBuilderMacroConfig =
copy(extracted = extracted.updated(field.name, field))

type IsStrict = Boolean
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ package tethys.derivation
import tethys.writers.tokens.TokenWriter
import tethys.readers.FieldName
import tethys.readers.ReaderError
import tethys.{JsonConfig, JsonReader, JsonWriter}
import tethys.{JsonConfig, JsonReader, JsonWriter, WriterBuilder, ReaderBuilder}

import scala.compiletime.{constValueTuple, summonInline}

Expand All @@ -13,10 +13,10 @@ object Derivation:
inline def fieldJsonWriter[T, F]: JsonWriter[F] =
${ DerivationMacro.fieldJsonWriter[T, F] }

inline def parseJsonWriterProductConfig[T](inline config: JsonWriter.ProductConfig[T]): WriterBuilderParsed[T] =
inline def parseWriterBuilder[T](inline config: WriterBuilder[T]): WriterBuilderParsed[T] =
${ DerivationMacro.parseWriterBuilder[T]('{config}) }

inline def parseJsonReaderProductConfig[T](inline config: ReaderBuilder[T]): ReaderBuilderParsed =
inline def parseReaderBuilder[T](inline config: ReaderBuilder[T]): ReaderBuilderParsed =
${ DerivationMacro.parseReaderBuilder[T]('{config})}

inline def writeDiscriminator[T](inline config: JsonConfig[T]): (T, TokenWriter) => Unit =
Expand All @@ -31,7 +31,7 @@ private[derivation]
object DerivationMacro:
import scala.quoted.*

def parseWriterBuilder[T: Type](config: Expr[JsonWriter.ProductConfig[T]])(using quotes: Quotes): Expr[WriterBuilderParsed[T]] =
def parseWriterBuilder[T: Type](config: Expr[WriterBuilder[T]])(using quotes: Quotes): Expr[WriterBuilderParsed[T]] =
val utils = new ConfigurationMacroUtils
import utils.quotes.reflect.*
'{
Expand Down
Loading

0 comments on commit 65adcf7

Please sign in to comment.