-
Notifications
You must be signed in to change notification settings - Fork 348
/
WritePlatform.scala
104 lines (82 loc) · 3.62 KB
/
WritePlatform.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
// Copyright (c) 2013-2020 Rob Norris and Contributors
// This software is licensed under the MIT License (MIT).
// For more information see LICENSE or https://opensource.org/licenses/MIT
package doobie.util
import shapeless.{ HList, HNil, ::, Generic, Lazy, <:!< }
import shapeless.labelled.{ FieldType }
trait WritePlatform extends LowerPriorityWrite {
implicit def recordWrite[K <: Symbol, H, T <: HList](
implicit H: Lazy[Write[H]],
T: Lazy[Write[T]]
): Write[FieldType[K, H] :: T] = {
new Write(
H.value.puts ++ T.value.puts,
{ case h :: t => H.value.toList(h) ++ T.value.toList(t) },
{ case (ps, n, h :: t) => H.value.unsafeSet(ps, n, h); T.value.unsafeSet(ps, n + H.value.length, t) },
{ case (rs, n, h :: t) => H.value.unsafeUpdate(rs, n, h); T.value.unsafeUpdate(rs, n + H.value.length, t) }
)
}
}
trait LowerPriorityWrite extends EvenLowerPriorityWrite {
implicit def product[H, T <: HList](
implicit H: Lazy[Write[H]],
T: Lazy[Write[T]]
): Write[H :: T] =
new Write(
H.value.puts ++ T.value.puts,
{ case h :: t => H.value.toList(h) ++ T.value.toList(t) },
{ case (ps, n, h :: t) => H.value.unsafeSet(ps, n, h); T.value.unsafeSet(ps, n + H.value.length, t) },
{ case (rs, n, h :: t) => H.value.unsafeUpdate(rs, n, h); T.value.unsafeUpdate(rs, n + H.value.length, t) }
)
implicit def emptyProduct: Write[HNil] =
new Write[HNil](Nil, _ => Nil, (_, _, _) => (), (_, _, _) => ())
implicit def generic[B, A](implicit gen: Generic.Aux[B, A], A: Lazy[Write[A]]): Write[B] =
new Write[B](
A.value.puts,
b => A.value.toList(gen.to(b)),
(ps, n, b) => A.value.unsafeSet(ps, n, gen.to(b)),
(rs, n, b) => A.value.unsafeUpdate(rs, n, gen.to(b))
)
}
trait EvenLowerPriorityWrite {
implicit val ohnil: Write[Option[HNil]] =
new Write[Option[HNil]](Nil, _ => Nil, (_, _, _) => (), (_, _, _) => ())
implicit def ohcons1[H, T <: HList](
implicit H: Lazy[Write[Option[H]]],
T: Lazy[Write[Option[T]]],
N: H <:!< Option[α] forSome { type α }
): Write[Option[H :: T]] = {
void(N)
def split[A](i: Option[H :: T])(f: (Option[H], Option[T]) => A): A =
i.fold(f(None, None)) { case h :: t => f(Some(h), Some(t)) }
new Write(
H.value.puts ++ T.value.puts,
split(_) { (h, t) => H.value.toList(h) ++ T.value.toList(t) },
(ps, n, i) => split(i) { (h, t) => H.value.unsafeSet(ps, n, h); T.value.unsafeSet(ps, n + H.value.length, t) },
(rs, n, i) => split(i) { (h, t) => H.value.unsafeUpdate(rs, n, h); T.value.unsafeUpdate(rs, n + H.value.length, t) }
)
}
implicit def ohcons2[H, T <: HList](
implicit H: Lazy[Write[Option[H]]],
T: Lazy[Write[Option[T]]]
): Write[Option[Option[H] :: T]] = {
def split[A](i: Option[Option[H] :: T])(f: (Option[H], Option[T]) => A): A =
i.fold(f(None, None)) { case oh :: t => f(oh, Some(t)) }
new Write(
H.value.puts ++ T.value.puts,
split(_) { (h, t) => H.value.toList(h) ++ T.value.toList(t) },
(ps, n, i) => split(i) { (h, t) => H.value.unsafeSet(ps, n, h); T.value.unsafeSet(ps, n + H.value.length, t) },
(rs, n, i) => split(i) { (h, t) => H.value.unsafeUpdate(rs, n, h); T.value.unsafeUpdate(rs, n + H.value.length, t) }
)
}
implicit def ogeneric[B, A <: HList](
implicit G: Generic.Aux[B, A],
A: Lazy[Write[Option[A]]]
): Write[Option[B]] =
new Write(
A.value.puts,
b => A.value.toList(b.map(G.to)),
(rs, n, a) => A.value.unsafeSet(rs, n, a.map(G.to)),
(rs, n, a) => A.value.unsafeUpdate(rs, n, a.map(G.to))
)
}