1+ package scala .typelevel
2+ import annotation .tailrec
3+
4+ /** @param caseLabels The case and element labels of the described ADT as encoded strings.
5+ */
6+ class ReflectedClass (caseLabels : Array [String ]) {
7+ import ReflectedClass ._
8+
9+ /** A mirror of case with ordinal number `ordinal` and elements as given by `Product` */
10+ def mirror (ordinal : Int , product : Product ): Mirror =
11+ new Mirror (this , ordinal, product)
12+
13+ /** A mirror with elements given as an array */
14+ def mirror (ordinal : Int , elems : Array [AnyRef ]): Mirror =
15+ mirror(ordinal, new ArrayProduct (elems))
16+
17+ /** A mirror with an initial empty array of `numElems` elements, to be filled in. */
18+ def mirror (ordinal : Int , numElems : Int ): Mirror =
19+ mirror(ordinal, new Array [AnyRef ](numElems))
20+
21+ /** A mirror of a case with no elements */
22+ def mirror (ordinal : Int ): Mirror =
23+ mirror(ordinal, EmptyProduct )
24+
25+ private [typelevel] def label (ordinal : Int , idx : Int ): String = {
26+ val labels = caseLabels(ordinal)
27+ @ tailrec def separatorPos (from : Int ): Int =
28+ if (from == labels.length || labels(from) == separator) from
29+ else separatorPos(from + 1 )
30+ @ tailrec def findLabel (count : Int , idx : Int ): String =
31+ if (idx == labels.length) " "
32+ else if (count == 0 ) labels.substring(idx, separatorPos(idx))
33+ else findLabel(if (labels(idx) == separator) count - 1 else count, idx + 1 )
34+ findLabel(idx, 0 )
35+ }
36+ }
37+
38+ object ReflectedClass {
39+
40+ private final val separator = '\000 '
41+
42+ /** Helper class to turn arrays into products */
43+ private class ArrayProduct (val elems : Array [AnyRef ]) extends Product {
44+ def canEqual (that : Any ): Boolean = true
45+ def productElement (n : Int ) = elems(n)
46+ def productArity = elems.length
47+ override def productIterator : Iterator [Any ] = elems.iterator
48+ def update (n : Int , x : Any ) = elems(n) = x.asInstanceOf [AnyRef ]
49+ }
50+
51+ /** Helper object */
52+ private object EmptyProduct extends Product {
53+ def canEqual (that : Any ): Boolean = true
54+ def productElement (n : Int ) = throw new IndexOutOfBoundsException
55+ def productArity = 0
56+ }
57+ }
0 commit comments