Completed
Push — master ( 6ae8fd...612217 )
by Ryosuke
03:27
created

GeneratorContainer::getReturnOrThrown()   B

Complexity

Conditions 6
Paths 4

Size

Total Lines 11
Code Lines 7

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 8
CRAP Score 6

Importance

Changes 3
Bugs 0 Features 0
Metric Value
c 3
b 0
f 0
dl 0
loc 11
ccs 8
cts 8
cp 1
rs 8.8571
cc 6
eloc 7
nc 4
nop 0
crap 6
1
<?php
2
3
namespace mpyw\Co\Internal;
4
use mpyw\Co\CoInterface;
5
use mpyw\Co\Internal\CoOption;
6
7
class GeneratorContainer
8
{
9
    /**
10
     * Generator.
11
     * @var \Generator
12
     */
13
    private $g;
14
15
    /**
16
     * Generator object hash.
17
     * @var string
18
     */
19
    private $h;
20
21
    /**
22
     * Thrown exception.
23
     * @var \Throwable|\Exception
24
     */
25
    private $e;
26
27
    /**
28
     * Default options.
29
     * @var CoOption
30
     */
31
    private $options;
32
33
    /**
34
     * Constructor.
35
     * @param Generator $g
36
     * @param CoOption  $options
37
     * @param mixed     $yield_key
38
     */
39 22
    public function __construct(\Generator $g, CoOption $options = null, $yield_key = null)
40 22
    {
41 22
        $this->g = $g;
42 22
        $this->h = spl_object_hash($g);
43 22
        if ($options === null) {
44 9
            $options = new CoOption;
45
        }
46 22
        if ($yield_key === CoInterface::SAFE) {
47 3
            $options = $options->reconfigure(['throw' => false]);
48
        }
49 22
        if ($yield_key === CoInterface::UNSAFE) {
50 2
            $options = $options->reconfigure(['throw' => true]);
51
        }
52 22
        $this->options = $options;
53 22
        $this->valid();
54 22
    }
55
56
    /**
57
     * Return options.
58
     * @return CoOption
59
     */
60 11
    public function getOptions()
61 11
    {
62 11
        return $this->options;
63
    }
64
65
    /**
66
     * Return generator hash.
67
     * @return string
68
     */
69 8
    public function __toString()
70 8
    {
71 8
        return $this->h;
72
    }
73
74
    /**
75
     * Return whether generator is actually working.
76
     * @return bool
77
     */
78 22
    public function valid()
79 22
    {
80
        try {
81 22
            $this->g->current();
82 22
            return $this->e === null && $this->g->valid() && $this->g->key() !== CoInterface::RETURN_WITH;
83 2
        } catch (\RuntimeException $e) {
84 2
            $this->e = $e;
85 2
            return false;
86
        }
87
    }
88
89
    /**
90
     * Return current key.
91
     * @return mixed
92
     */
93 10
    public function key()
94 10
    {
95 10
        $this->validateValidity();
96 10
        return $this->g->key();
97
    }
98
99
    /**
100
     * Return current value.
101
     * @return mixed
102
     */
103 13
    public function current()
104 13
    {
105 13
        $this->validateValidity();
106 13
        return $this->g->current();
107
    }
108
109
    /**
110
     * Send value into generator.
111
     * @param mixed $value
112
     * @NOTE: This method returns nothing,
113
     *        while original generator returns something.
114
     */
115 13
    public function send($value)
116 13
    {
117 13
        $this->validateValidity();
118
        try {
119 13
            $this->g->send($value);
120 1
        } catch (\RuntimeException $e) {
121 1
            $this->e = $e;
122
        }
123 13
    }
124
125
    /**
126
     * Throw exception into generator.
127
     * @param RuntimeException $e
128
     * @NOTE: This method returns nothing,
129
     *        while original generator returns something.
130
     */
131 5
    public function throw_(\RuntimeException $e)
132 5
    {
133 5
        $this->validateValidity();
134
        try {
135 5
            $this->g->throw($e);
136 4
        } catch (\RuntimeException $e) {
137 4
            $this->e = $e;
138
        }
139 5
    }
140
141 9
    public function throwAcceptable()
142 9
    {
143 9
        $this->validateValidity();
144 9
        return $this->g->key() === CoInterface::UNSAFE ||
145 9
               $this->g->key() !== CoInterface::SAFE && $this->options['throw'];
146
    }
147
148
    /**
149
     * Return whether exception is thrown.
150
     * @return bool
151
     */
152 12
    public function thrown()
153 12
    {
154 12
        return $this->e !== null && $this->options['throw'];
155
    }
156
157
    /**
158
     * Return value that generator has returned or thrown.
159
     * @return mixed
160
     */
161 14
    public function getReturnOrThrown()
162 14
    {
163 14
        $this->validateInvalidity();
164 13
        if ($this->e === null && $this->g->valid() && !$this->valid()) {
165 8
            return $this->g->current();
166
        }
167 10
        if ($this->e) {
168 5
            return $this->e;
169
        }
170 7
        return method_exists($this->g, 'getReturn') ? $this->g->getReturn() : null;
171
    }
172
173
    /**
174
     * Validate that generator has finished running.
175
     * @throws LogicException
176
     */
177 14
    private function validateValidity()
178 14
    {
179 14
        if (!$this->valid()) {
180 2
            throw new \LogicException('Unreachable here.');
181
        }
182 14
    }
183
184
    /**
185
     * Validate that generator is still running.
186
     * @throws LogicException
187
     */
188 14
    private function validateInvalidity()
189 14
    {
190 14
        if ($this->valid()) {
191 1
            throw new \LogicException('Unreachable here.');
192
        }
193 13
    }
194
}
195