in scalding-serialization/src/main/scala/com/twitter/scalding/serialization/macros/impl/ordered_serialization/ProductLike.scala [87:160]
def length(c: Context)(element: c.Tree)(
elementData: List[(c.universe.Type, c.universe.TermName, TreeOrderedBuf[c.type])]
): CompileTimeLengthTypes[c.type] = {
import c.universe._
import CompileTimeLengthTypes._
val (constSize, dynamicFunctions, maybeLength, noLength) =
elementData.foldLeft((0, Vector[c.Tree](), Vector[c.Tree](), 0)) {
case ((constantLength, dynamicLength, maybeLength, noLength), (tpe, accessorSymbol, tBuf)) =>
tBuf.length(q"$element.$accessorSymbol") match {
case const: ConstantLengthCalculation[_] =>
(
constantLength + const.asInstanceOf[ConstantLengthCalculation[c.type]].toInt,
dynamicLength,
maybeLength,
noLength
)
case f: FastLengthCalculation[_] =>
(
constantLength,
dynamicLength :+ f.asInstanceOf[FastLengthCalculation[c.type]].t,
maybeLength,
noLength
)
case m: MaybeLengthCalculation[_] =>
(
constantLength,
dynamicLength,
maybeLength :+ m.asInstanceOf[MaybeLengthCalculation[c.type]].t,
noLength
)
case _: NoLengthCalculationAvailable[_] =>
(constantLength, dynamicLength, maybeLength, noLength + 1)
}
}
val combinedDynamic = dynamicFunctions.foldLeft(q"""$constSize""") { case (prev, t) =>
q"$prev + $t"
}
if (noLength > 0) {
NoLengthCalculationAvailable(c)
} else {
if (maybeLength.isEmpty && dynamicFunctions.isEmpty) {
ConstantLengthCalculation(c)(constSize)
} else {
if (maybeLength.isEmpty) {
FastLengthCalculation(c)(combinedDynamic)
} else {
val const =
q"_root_.com.twitter.scalding.serialization.macros.impl.ordered_serialization.runtime_helpers.ConstLen"
val dyn =
q"_root_.com.twitter.scalding.serialization.macros.impl.ordered_serialization.runtime_helpers.DynamicLen"
val noLen =
q"_root_.com.twitter.scalding.serialization.macros.impl.ordered_serialization.runtime_helpers.NoLengthCalculation"
// Contains an MaybeLength
val combinedMaybe: Tree = maybeLength.reduce { (hOpt, nxtOpt) =>
q"""$hOpt + $nxtOpt"""
}
if (dynamicFunctions.nonEmpty || constSize != 0) {
MaybeLengthCalculation(c)(q"""
$combinedMaybe match {
case $const(l) => $dyn(l + $combinedDynamic)
case $dyn(l) => $dyn(l + $combinedDynamic)
case $noLen => $noLen
}
""")
} else {
MaybeLengthCalculation(c)(combinedMaybe)
}
}
}
}
}