in http-core/src/main/scala/org/apache/pekko/http/impl/engine/parsing/HttpHeaderParser.scala [334:386]
private def rowIx(msb: Int) = (msb - 1) * 3
private def nodeBits(rowIx: Int, char: Int) = (((rowIx / 3 + 1) << 8) | char).toChar
/**
* Renders the trie structure into an ASCII representation.
*/
def formatTrie: String = {
def recurse(nodeIx: Int = 0): (Seq[List[String]], Int) = {
def recurseAndPrefixLines(subNodeIx: Int, p1: String, p2: String, p3: String) = {
val (lines, mainIx) = recurse(subNodeIx)
val prefixedLines = lines.zipWithIndex.map {
case (line, ix) => (if (ix < mainIx) p1 else if (ix > mainIx) p3 else p2) :: line
}
prefixedLines -> mainIx
}
def branchLines(dataIx: Int, p1: String, p2: String, p3: String) = branchData(dataIx) match {
case 0 => Seq.empty
case subNodeIx => recurseAndPrefixLines(subNodeIx, p1, p2, p3)._1
}
val node = nodes(nodeIx)
val char = escape((node & 0xFF).toChar)
node >>> 8 match {
case 0 => recurseAndPrefixLines(nodeIx + 1, " ", char + "-", " ")
case msb => node & 0xFF match {
case 0 => values(msb - 1) match {
case ValueBranch(_, valueParser, branchRootNodeIx, _) =>
val pad = " " * (valueParser.headerName.length + 3)
recurseAndPrefixLines(branchRootNodeIx, pad, "(" + valueParser.headerName + ")-", pad)
case vp: HeaderValueParser => Seq(" (" :: vp.headerName :: ")" :: Nil) -> 0
case value: RawHeader => Seq(" *" :: value.toString :: Nil) -> 0
case value => Seq(" " :: value.toString :: Nil) -> 0
}
case nodeChar =>
val rix = rowIx(msb)
val preLines = branchLines(rix, " ", "┌─", "| ")
val postLines = branchLines(rix + 2, "| ", "└─", " ")
val p1 = if (preLines.nonEmpty) "| " else " "
val p3 = if (postLines.nonEmpty) "| " else " "
val (matchLines, mainLineIx) = recurseAndPrefixLines(branchData(rix + 1), p1, char + '-', p3)
(preLines ++ matchLines ++ postLines, mainLineIx + preLines.size)
}
}
}
val sb = new JStringBuilder()
val (lines, mainLineIx) = recurse()
lines.zipWithIndex.foreach {
case (line, ix) =>
sb.append(if (ix == mainLineIx) '-' else ' ')
line.foreach(s => sb.append(s))
sb.append('\n')
}
sb.toString
}