|
4 | 4 |
|
5 | 5 | package doobie.util
|
6 | 6 |
|
7 |
| -import shapeless.{HList, HNil, ::, Generic, Lazy, <:!<, OrElse} |
8 |
| -import shapeless.labelled.{field, FieldType} |
| 7 | +import shapeless.{HList, HNil, ::, Generic, Lazy, OrElse} |
| 8 | +import shapeless.labelled.FieldType |
9 | 9 |
|
10 |
| -trait MkReadPlatform extends LowerPriorityRead { |
| 10 | +trait MkReadPlatform extends LowerPriorityMkRead { |
11 | 11 |
|
12 | 12 | // Derivation base case for product types (1-element)
|
13 | 13 | implicit def productBase[H](
|
14 |
| - implicit H: Read[H] OrElse MkRead[H] |
15 |
| - ): MkRead[H :: HNil] = { |
16 |
| - val head = H.unify |
17 |
| - |
18 |
| - new MkRead[H :: HNil]( |
19 |
| - head.gets, |
20 |
| - (rs, n) => head.unsafeGet(rs, n) :: HNil |
| 14 | + implicit H: Read[H] OrElse Derived[MkRead[H]] |
| 15 | + ): Derived[MkRead[H :: HNil]] = { |
| 16 | + val headInstance = H.fold(identity, _.instance) |
| 17 | + |
| 18 | + new Derived( |
| 19 | + new MkRead( |
| 20 | + new Read.Composite( |
| 21 | + List(headInstance), |
| 22 | + _.head.asInstanceOf[H] :: HNil |
| 23 | + ) |
| 24 | + ) |
21 | 25 | )
|
22 | 26 | }
|
23 | 27 |
|
24 | 28 | // Derivation base case for shapeless record (1-element)
|
25 | 29 | implicit def recordBase[K <: Symbol, H](
|
26 |
| - implicit H: Read[H] OrElse MkRead[H] |
27 |
| - ): MkRead[FieldType[K, H] :: HNil] = { |
28 |
| - val head = H.unify |
29 |
| - |
30 |
| - new MkRead[FieldType[K, H] :: HNil]( |
31 |
| - head.gets, |
32 |
| - (rs, n) => field[K](head.unsafeGet(rs, n)) :: HNil |
| 30 | + implicit H: Read[H] OrElse Derived[MkRead[H]] |
| 31 | + ): Derived[MkRead[FieldType[K, H] :: HNil]] = { |
| 32 | + val headInstance = H.fold(identity, _.instance) |
| 33 | + |
| 34 | + new Derived( |
| 35 | + new MkRead( |
| 36 | + new Read.Composite( |
| 37 | + List(headInstance), |
| 38 | + _.head.asInstanceOf[FieldType[K, H]] :: HNil |
| 39 | + ) |
| 40 | + ) |
33 | 41 | )
|
34 | 42 | }
|
35 | 43 | }
|
36 | 44 |
|
37 |
| -trait LowerPriorityRead extends EvenLowerPriorityRead { |
| 45 | +trait LowerPriorityMkRead { |
38 | 46 |
|
39 | 47 | // Derivation inductive case for product types
|
40 | 48 | implicit def product[H, T <: HList](
|
41 | 49 | implicit
|
42 |
| - H: Read[H] OrElse MkRead[H], |
43 |
| - T: MkRead[T] |
44 |
| - ): MkRead[H :: T] = { |
45 |
| - val head = H.unify |
46 |
| - |
47 |
| - new MkRead[H :: T]( |
48 |
| - head.gets ++ T.gets, |
49 |
| - (rs, n) => head.unsafeGet(rs, n) :: T.unsafeGet(rs, n + head.length) |
| 50 | + H: Read[H] OrElse Derived[MkRead[H]], |
| 51 | + T: Read[T] OrElse Derived[MkRead[T]] |
| 52 | + ): Derived[MkRead[H :: T]] = { |
| 53 | + val headInstance = H.fold(identity, _.instance) |
| 54 | + val tailInstance = T.fold(identity, _.instance) |
| 55 | + |
| 56 | + new Derived( |
| 57 | + new MkRead( |
| 58 | + new Read.Composite( |
| 59 | + List(headInstance, tailInstance), |
| 60 | + list => list(0).asInstanceOf[H] :: list(1).asInstanceOf[T] |
| 61 | + ) |
| 62 | + ) |
50 | 63 | )
|
51 | 64 | }
|
52 | 65 |
|
53 | 66 | // Derivation inductive case for shapeless records
|
54 | 67 | implicit def record[K <: Symbol, H, T <: HList](
|
55 | 68 | implicit
|
56 |
| - H: Read[H] OrElse MkRead[H], |
57 |
| - T: MkRead[T] |
58 |
| - ): MkRead[FieldType[K, H] :: T] = { |
59 |
| - val head = H.unify |
60 |
| - |
61 |
| - new MkRead[FieldType[K, H] :: T]( |
62 |
| - head.gets ++ T.gets, |
63 |
| - (rs, n) => field[K](head.unsafeGet(rs, n)) :: T.unsafeGet(rs, n + head.length) |
| 69 | + H: Read[H] OrElse Derived[MkRead[H]], |
| 70 | + T: Read[T] OrElse Derived[MkRead[T]] |
| 71 | + ): Derived[MkRead[FieldType[K, H] :: T]] = { |
| 72 | + val headInstance = H.fold(identity, _.instance) |
| 73 | + val tailInstance = T.fold(identity, _.instance) |
| 74 | + |
| 75 | + new Derived( |
| 76 | + new MkRead( |
| 77 | + new Read.Composite( |
| 78 | + List(headInstance, tailInstance), |
| 79 | + list => list(0).asInstanceOf[FieldType[K, H]] :: list(1).asInstanceOf[T] |
| 80 | + ) |
| 81 | + ) |
64 | 82 | )
|
65 | 83 | }
|
66 | 84 |
|
67 | 85 | // Derivation for product types (i.e. case class)
|
68 |
| - implicit def generic[T, Repr](implicit gen: Generic.Aux[T, Repr], G: Lazy[MkRead[Repr]]): MkRead[T] = |
69 |
| - new MkRead[T](G.value.gets, (rs, n) => gen.from(G.value.unsafeGet(rs, n))) |
70 |
| - |
71 |
| - // Derivation base case for Option of product types (1-element) |
72 |
| - implicit def optProductBase[H]( |
73 |
| - implicit |
74 |
| - H: Read[Option[H]] OrElse MkRead[Option[H]], |
75 |
| - N: H <:!< Option[α] forSome { type α } |
76 |
| - ): MkRead[Option[H :: HNil]] = { |
77 |
| - void(N) |
78 |
| - val head = H.unify |
79 |
| - |
80 |
| - new MkRead[Option[H :: HNil]]( |
81 |
| - head.gets, |
82 |
| - (rs, n) => |
83 |
| - head.unsafeGet(rs, n).map(_ :: HNil) |
84 |
| - ) |
85 |
| - } |
86 |
| - |
87 |
| - // Derivation base case for Option of product types (where the head element is Option) |
88 |
| - implicit def optProductOptBase[H]( |
89 |
| - implicit H: Read[Option[H]] OrElse MkRead[Option[H]] |
90 |
| - ): MkRead[Option[Option[H] :: HNil]] = { |
91 |
| - val head = H.unify |
92 |
| - |
93 |
| - new MkRead[Option[Option[H] :: HNil]]( |
94 |
| - head.gets, |
95 |
| - (rs, n) => head.unsafeGet(rs, n).map(h => Some(h) :: HNil) |
96 |
| - ) |
97 |
| - } |
98 |
| - |
99 |
| -} |
100 |
| - |
101 |
| -trait EvenLowerPriorityRead { |
102 |
| - |
103 |
| - // Read[Option[H]], Read[Option[T]] implies Read[Option[H *: T]] |
104 |
| - implicit def optProduct[H, T <: HList]( |
| 86 | + implicit def genericRead[T, Repr]( |
105 | 87 | implicit
|
106 |
| - H: Read[Option[H]] OrElse MkRead[Option[H]], |
107 |
| - T: MkRead[Option[T]], |
108 |
| - N: H <:!< Option[α] forSome { type α } |
109 |
| - ): MkRead[Option[H :: T]] = { |
110 |
| - void(N) |
111 |
| - val head = H.unify |
112 |
| - |
113 |
| - new MkRead[Option[H :: T]]( |
114 |
| - head.gets ++ T.gets, |
115 |
| - (rs, n) => |
116 |
| - for { |
117 |
| - h <- head.unsafeGet(rs, n) |
118 |
| - t <- T.unsafeGet(rs, n + head.length) |
119 |
| - } yield h :: t |
120 |
| - ) |
| 88 | + gen: Generic.Aux[T, Repr], |
| 89 | + hlistRead: Lazy[Read[Repr] OrElse Derived[MkRead[Repr]]] |
| 90 | + ): Derived[MkRead[T]] = { |
| 91 | + val hlistInstance: Read[Repr] = hlistRead.value.fold(identity, _.instance) |
| 92 | + new Derived(new MkRead(hlistInstance.map(gen.from))) |
121 | 93 | }
|
122 | 94 |
|
123 |
| - // Read[Option[H]], Read[Option[T]] implies Read[Option[Option[H] *: T]] |
124 |
| - implicit def optProductOpt[H, T <: HList]( |
125 |
| - implicit |
126 |
| - H: Read[Option[H]] OrElse MkRead[Option[H]], |
127 |
| - T: MkRead[Option[T]] |
128 |
| - ): MkRead[Option[Option[H] :: T]] = { |
129 |
| - val head = H.unify |
130 |
| - |
131 |
| - new MkRead[Option[Option[H] :: T]]( |
132 |
| - head.gets ++ T.gets, |
133 |
| - (rs, n) => T.unsafeGet(rs, n + head.length).map(head.unsafeGet(rs, n) :: _) |
134 |
| - ) |
135 |
| - } |
136 |
| - |
137 |
| - // Derivation for optional of product types (i.e. case class) |
138 |
| - implicit def ogeneric[A, Repr <: HList]( |
139 |
| - implicit |
140 |
| - G: Generic.Aux[A, Repr], |
141 |
| - B: Lazy[MkRead[Option[Repr]]] |
142 |
| - ): MkRead[Option[A]] = |
143 |
| - new MkRead[Option[A]](B.value.gets, B.value.unsafeGet(_, _).map(G.from)) |
144 |
| - |
145 | 95 | }
|
0 commit comments