Skip to content

Commit e50c6df

Browse files
committed
More efficient serialization of named tuples
1 parent f05707e commit e50c6df

File tree

1 file changed

+32
-11
lines changed
  • jsoniter-scala-macros/shared/src/main/scala-3/com/github/plokhotnyuk/jsoniter_scala/macros

1 file changed

+32
-11
lines changed

jsoniter-scala-macros/shared/src/main/scala-3/com/github/plokhotnyuk/jsoniter_scala/macros/JsonCodecMaker.scala

Lines changed: 32 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -993,7 +993,7 @@ object JsonCodecMaker {
993993
tpe match {
994994
case AppliedType(_, List(nTpe, tTpe)) =>
995995
// Borrowed from an amazing work of Aleksander Rainko: https://github.com/arainko/ducktape/blob/8d779f0303c23fd45815d3574467ffc321a8db2b/ducktape/src/main/scala/io/github/arainko/ducktape/internal/Structure.scala#L188-L199
996-
val names = tupleTypeArgs(nTpe.dealias.asType).map { case ConstantType(StringConstant(n)) => n }
996+
val names = tupleTypeArgs(nTpe.dealias.asType).map { case ConstantType(StringConstant(name)) => name }
997997
val typeArgs = tupleTypeArgs(tTpe.dealias.asType)
998998
val size = typeArgs.size
999999
val tupleTpe =
@@ -1020,7 +1020,7 @@ object JsonCodecMaker {
10201020
val constructor =
10211021
if (tpeTypeArgs.isEmpty) constructorNoTypes
10221022
else TypeApply(constructorNoTypes, tpeTypeArgs.map(Inferred(_)))
1023-
argss.tail.foldLeft(Apply(constructor, argss.head))((acc, args) => Apply(acc, args))
1023+
argss.tail.foldLeft(Apply(constructor, argss.head))(Apply(_, _))
10241024
}
10251025

10261026
val classInfos = new mutable.LinkedHashMap[TypeRepr, ClassInfo]
@@ -2733,6 +2733,25 @@ object JsonCodecMaker {
27332733
optDiscriminator: Option[WriteDiscriminator],
27342734
out: Expr[JsonWriter])(using Quotes): Expr[Unit] =
27352735
val tpe = types.head
2736+
val (valDefs, valRef) =
2737+
typeInfo match
2738+
case namedTupleInfo: NamedTupleInfo =>
2739+
val valDef = ValDef(
2740+
Symbol.newVal(Symbol.spliceOwner, "t", namedTupleInfo.tupleTpe, Flags.EmptyFlags, Symbol.noSymbol),
2741+
Some(
2742+
Apply(
2743+
Select
2744+
.unique(Ref(Symbol.requiredModule("scala.NamedTuple")), "toTuple")
2745+
.appliedToTypeTrees(tpe.typeArgs.map { typeArg =>
2746+
typeArg.asType match
2747+
case '[t] => TypeTree.of[t]
2748+
}),
2749+
List(x.asTerm)
2750+
)
2751+
)
2752+
)
2753+
(List(valDef), Ref(valDef.symbol))
2754+
case _ => (Nil, x.asTerm)
27362755
val writeFields = typeInfo.fields.map { fieldInfo =>
27372756
val fDefault =
27382757
if (cfg.transientDefault) fieldInfo.defaultValue
@@ -2742,13 +2761,13 @@ object JsonCodecMaker {
27422761
case '[ft] =>
27432762
val getter = typeInfo match
27442763
case namedTupleInfo: NamedTupleInfo =>
2745-
val idx = fieldInfo.nonTransientFieldIndex
2746-
if (namedTupleInfo.isGeneric) {
2747-
'{ $x.asInstanceOf[Tuple].productElement(${Expr(idx)}).asInstanceOf[ft] }.asTerm
2748-
} else namedTupleInfo.tupleType match {
2749-
case '[tt] => Select.unique('{ $x.asInstanceOf[tt] }.asTerm, s"_${idx + 1}")
2750-
}
2751-
case _ => Select(x.asTerm, fieldInfo.getterOrField)
2764+
namedTupleInfo.tupleType match
2765+
case '[tt] =>
2766+
val idx = fieldInfo.nonTransientFieldIndex
2767+
if (namedTupleInfo.isGeneric) {
2768+
'{ ${valRef.asExprOf[tt & Tuple]}.productElement(${Expr(idx)}).asInstanceOf[ft] }.asTerm
2769+
} else Select.unique(valRef, s"_${idx + 1}")
2770+
case _ => Select(valRef, fieldInfo.getterOrField)
27522771
fDefault match {
27532772
case Some(d) =>
27542773
if (cfg.transientEmpty && fTpe <:< TypeRepr.of[Iterable[_]]) '{
@@ -2873,8 +2892,10 @@ object JsonCodecMaker {
28732892
}
28742893
}
28752894
val allWriteFields = optDiscriminator.fold(writeFields)(_.write(out) :: writeFields)
2876-
Block('{ $out.writeObjectStart() }.asTerm :: allWriteFields.map(_.asTerm.changeOwner(Symbol.spliceOwner)),
2877-
'{ $out.writeObjectEnd() }.asTerm).asExprOf[Unit]
2895+
Block(valDefs,
2896+
Block('{ $out.writeObjectStart() }.asTerm :: allWriteFields.map(_.asTerm.changeOwner(Symbol.spliceOwner)),
2897+
'{ $out.writeObjectEnd() }.asTerm)
2898+
).asExprOf[Unit]
28782899

28792900
def getWriteConstType(tpe: TypeRepr, isStringified: Boolean, out: Expr[JsonWriter])(using Quotes): Expr[Unit] =
28802901
tpe match

0 commit comments

Comments
 (0)