/
OptionMapper.scala
108 lines (93 loc) · 5.96 KB
/
OptionMapper.scala
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
package slick.lifted
import annotation.implicitNotFound
import slick.ast.{OptionType, FieldSymbol, OptionApply, FunctionSymbol, BaseTypedType, Node, TypedType}
trait OptionMapper[BR, R] extends (Rep[BR] => Rep[R]) {
def lift: Boolean
def column(fs: FunctionSymbol, ch: Node*)(implicit bt: TypedType[BR]): Rep[R] = {
implicit val tt = liftedType
Rep.forNode[R](fs.typed(tt, ch: _*))
}
def liftedType(implicit bt: TypedType[BR]): TypedType[R] =
(if(lift) bt.optionType else bt).asInstanceOf[TypedType[R]]
}
@implicitNotFound("Cannot perform option-mapped operation\n with type: (${P1}, ${P2}) => ${R}\n for base type: (${B1}, ${B2}) => ${BR}")
sealed trait OptionMapper2[B1, B2, BR, P1, P2, R] extends OptionMapper[BR, R]
object OptionMapper2 {
val plain = new OptionMapper2[Any,Any,Any,Any,Any,Any] {
def apply(n: Rep[Any]): Rep[Any] = n
def lift = false
override def toString = "OptionMapper2.plain"
}
val option = new OptionMapper2[Any,Any,Any,Any,Any,Option[Any]] {
def apply(n: Rep[Any]): Rep[Option[Any]] = Rep.forNode(OptionApply(n.toNode))(n.asInstanceOf[Rep.TypedRep[Any]].tpe.optionType)
def lift = true
override def toString = "OptionMapper2.option"
}
@inline implicit def getOptionMapper2TT[B1, B2 : BaseTypedType, BR] = OptionMapper2.plain .asInstanceOf[OptionMapper2[B1, B2, BR, B1, B2, BR]]
@inline implicit def getOptionMapper2TO[B1, B2 : BaseTypedType, BR] = OptionMapper2.option.asInstanceOf[OptionMapper2[B1, B2, BR, B1, Option[B2], Option[BR]]]
@inline implicit def getOptionMapper2OT[B1, B2 : BaseTypedType, BR] = OptionMapper2.option.asInstanceOf[OptionMapper2[B1, B2, BR, Option[B1], B2, Option[BR]]]
@inline implicit def getOptionMapper2OO[B1, B2 : BaseTypedType, BR] = OptionMapper2.option.asInstanceOf[OptionMapper2[B1, B2, BR, Option[B1], Option[B2], Option[BR]]]
}
@implicitNotFound("Cannot perform option-mapped operation\n with type: (${P1}, ${P2}, ${P3}) => ${R}\n for base type: (${B1}, ${B2}, ${B3}) => ${BR}")
sealed trait OptionMapper3[B1, B2, B3, BR, P1, P2, P3, R] extends OptionMapper[BR, R]
object OptionMapper3 {
val plain = new OptionMapper3[Any,Any,Any,Any,Any,Any,Any,Any] {
def apply(n: Rep[Any]): Rep[Any] = n
def lift = false
override def toString = "OptionMapper3.plain"
}
val option = new OptionMapper3[Any,Any,Any,Any,Any,Any,Any,Option[Any]] {
def apply(n: Rep[Any]): Rep[Option[Any]] = Rep.forNode(OptionApply(n.toNode))(n.asInstanceOf[Rep.TypedRep[Any]].tpe.optionType)
def lift = true
override def toString = "OptionMapper3.option"
}
@inline implicit def getOptionMapper3TTT[B1, B2 : BaseTypedType, B3 : BaseTypedType, BR] = OptionMapper3.plain .asInstanceOf[OptionMapper3[B1, B2, B3, BR, B1, B2, B3, BR]]
@inline implicit def getOptionMapper3TTO[B1, B2 : BaseTypedType, B3 : BaseTypedType, BR] = OptionMapper3.option.asInstanceOf[OptionMapper3[B1, B2, B3, BR, B1, B2, Option[B3], Option[BR]]]
@inline implicit def getOptionMapper3TOT[B1, B2 : BaseTypedType, B3 : BaseTypedType, BR] = OptionMapper3.option.asInstanceOf[OptionMapper3[B1, B2, B3, BR, B1, Option[B2], B3, Option[BR]]]
@inline implicit def getOptionMapper3TOO[B1, B2 : BaseTypedType, B3 : BaseTypedType, BR] = OptionMapper3.option.asInstanceOf[OptionMapper3[B1, B2, B3, BR, B1, Option[B2], Option[B3], Option[BR]]]
@inline implicit def getOptionMapper3OTT[B1, B2 : BaseTypedType, B3 : BaseTypedType, BR] = OptionMapper3.option.asInstanceOf[OptionMapper3[B1, B2, B3, BR, Option[B1], B2, B3, Option[BR]]]
@inline implicit def getOptionMapper3OTO[B1, B2 : BaseTypedType, B3 : BaseTypedType, BR] = OptionMapper3.option.asInstanceOf[OptionMapper3[B1, B2, B3, BR, Option[B1], B2, Option[B3], Option[BR]]]
@inline implicit def getOptionMapper3OOT[B1, B2 : BaseTypedType, B3 : BaseTypedType, BR] = OptionMapper3.option.asInstanceOf[OptionMapper3[B1, B2, B3, BR, Option[B1], Option[B2], B3, Option[BR]]]
@inline implicit def getOptionMapper3OOO[B1, B2 : BaseTypedType, B3 : BaseTypedType, BR] = OptionMapper3.option.asInstanceOf[OptionMapper3[B1, B2, B3, BR, Option[B1], Option[B2], Option[B3], Option[BR]]]
}
object OptionMapperDSL {
type arg[B1, P1] = {
type to[BR, PR] = OptionMapper2[Boolean, B1, BR, Boolean, P1, PR]
type arg[B2, P2] = {
type to[BR, PR] = OptionMapper2[B1, B2, BR, P1, P2, PR]
type arg[B3, P3] = {
type to[BR, PR] = OptionMapper3[B1, B2, B3, BR, P1, P2, P3, PR]
}
}
}
}
/** A typeclass that lifts a mixed type to the packed Option type. */
sealed trait OptionLift[M, O] {
def lift(v: M): O
}
object OptionLift extends OptionLiftLowPriority {
final implicit def repOptionLift[M <: Rep[_], P](implicit shape: Shape[_ <: FlatShapeLevel, M, _, Rep[P]]): OptionLift[M, Rep[Option[P]]] = new OptionLift[M, Rep[Option[P]]] {
def lift(v: M): Rep[Option[P]] = {
val n = OptionApply(v.toNode)
val packed = shape.pack(v)
packed match {
case r: Rep.TypedRep[_] if !r.tpe.isInstanceOf[OptionType] /* An primitive column */ =>
Rep.forNode[Option[P]](n)(r.tpe.asInstanceOf[TypedType[P]].optionType)
case _ =>
RepOption[P](ShapedValue(packed, shape.packedShape), n)
}
}
}
}
sealed trait OptionLiftLowPriority {
final implicit def anyOptionLift[M, P](implicit shape: Shape[_ <: FlatShapeLevel, M, _, P]): OptionLift[M, Rep[Option[P]]] = new OptionLift[M, Rep[Option[P]]] {
def lift(v: M): Rep[Option[P]] =
RepOption[P](ShapedValue(shape.pack(v), shape.packedShape), OptionApply(shape.toNode(v)))
}
/** Get a suitably typed base value for a `Rep[Option[_]]` */
def baseValue[M, O](v: O, path: Node): M = v match {
case RepOption(base, _) => base.asInstanceOf[ShapedValue[M, _]].encodeRef(path).value
case r: Rep.TypedRep[_] /* An Option column */ =>
Rep.columnPlaceholder[Any](r.tpe.asInstanceOf[OptionType].elementType.asInstanceOf[TypedType[Any]]).encodeRef(path).asInstanceOf[M]
}
}