-
Notifications
You must be signed in to change notification settings - Fork 63
/
PipelineBuilder.scala
97 lines (78 loc) · 2.85 KB
/
PipelineBuilder.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
/*
* Copyright 2014-2020 http4s.org
*
* SPDX-License-Identifier: Apache-2.0
*/
package org.http4s.blaze.pipeline
/** By requiring a LeafBuilder, you are ensuring that the pipeline is capped
* with a TailStage as the only way to get a LeafBuilder if by capping with a
* TailStage or getting a new LeafBuilder from a TailStage
* @param leaf the capped pipeline
* @tparam I type the pipeline will read and write
*/
final class LeafBuilder[I] private[pipeline] (leaf: Tail[I]) {
def prepend[N](stage: MidStage[N, I]): LeafBuilder[N] = {
if (stage._nextStage != null) sys.error(s"Stage $stage must be fresh")
if (stage.isInstanceOf[HeadStage[_]])
sys.error("LeafBuilder cannot accept HeadStages!")
leaf._prevStage = stage
stage._nextStage = leaf
new LeafBuilder[N](stage)
}
def prepend[N](tb: TrunkBuilder[N, I]): LeafBuilder[N] = tb.cap(this)
def +:[N](tb: TrunkBuilder[N, I]): LeafBuilder[N] = prepend(tb)
def base(root: HeadStage[I]): root.type = {
if (root._nextStage != null) sys.error(s"Stage $root must be fresh")
leaf._prevStage = root
root._nextStage = leaf
root
}
}
object LeafBuilder {
def apply[T](leaf: TailStage[T]): LeafBuilder[T] = new LeafBuilder[T](leaf)
}
/** Facilitates starting a pipeline from a MidStage. Can be appended and prepended
* to build up the pipeline
*/
final class TrunkBuilder[I1, O] private[pipeline] (
protected val head: MidStage[I1, _],
protected val tail: MidStage[_, O]) {
def append[N](stage: MidStage[O, N]): TrunkBuilder[I1, N] = {
if (stage._prevStage != null) sys.error(s"Stage $stage must be fresh")
if (stage.isInstanceOf[HeadStage[_]])
sys.error(s"Cannot append HeadStages: $stage")
tail._nextStage = stage
stage._prevStage = tail
new TrunkBuilder(head, stage)
}
def :+[N](stage: MidStage[O, N]): TrunkBuilder[I1, N] = append(stage)
def append[A](tb: TrunkBuilder[O, A]): TrunkBuilder[I1, A] = {
append(tb.head)
new TrunkBuilder(this.head, tb.tail)
}
def cap(stage: TailStage[O]): LeafBuilder[I1] = {
if (stage._prevStage != null)
sys.error(s"Stage $stage must be fresh")
tail._nextStage = stage
stage._prevStage = tail
new LeafBuilder(head)
}
def cap(lb: LeafBuilder[O]): LeafBuilder[I1] = {
lb.prepend(tail)
new LeafBuilder(head)
}
def prepend[A](stage: MidStage[A, I1]): TrunkBuilder[A, O] = {
if (stage._nextStage != null) sys.error(s"Stage $stage must be fresh")
if (stage.isInstanceOf[HeadStage[_]])
sys.error("Cannot prepend HeadStage. Use method base")
head._prevStage = stage
stage._nextStage = head
new TrunkBuilder(stage, tail)
}
def prepend[A1, A2](tb: TrunkBuilder[A1, I1]): TrunkBuilder[A1, O] =
tb.append(this)
}
object TrunkBuilder {
def apply[T1, T2](mid: MidStage[T1, T2]): TrunkBuilder[T1, T2] =
new TrunkBuilder(mid, mid)
}