Passed
Branch master (05df6c)
by Pol
03:59
created

AsyncMapN   A

Complexity

Total Complexity 2

Size/Duplication

Total Lines 50
Duplicated Lines 0 %

Test Coverage

Coverage 100%

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 13
dl 0
loc 50
ccs 10
cts 10
cp 1
rs 10
c 1
b 0
f 0
wmc 2

1 Method

Rating   Name   Duplication   Size   Complexity  
A __invoke() 0 43 2
1
<?php
2
3
/**
4
 * For the full copyright and license information, please view
5
 * the LICENSE file that was distributed with this source code.
6
 */
7
8
declare(strict_types=1);
9
10
namespace loophp\collection\Operation;
11
12
use Amp\Sync\LocalSemaphore;
13
use Closure;
14
use Exception;
15
use Generator;
16
use Iterator;
17
18
use function Amp\Iterator\fromIterable;
19
use function Amp\ParallelFunctions\parallel;
20
use function Amp\Promise\wait;
21
use function Amp\Sync\ConcurrentIterator\map;
0 ignored issues
show
Bug introduced by
This use statement conflicts with another class in this namespace, loophp\collection\Operation\map. Consider defining an alias.

Let?s assume that you have a directory layout like this:

.
|-- OtherDir
|   |-- Bar.php
|   `-- Foo.php
`-- SomeDir
    `-- Foo.php

and let?s assume the following content of Bar.php:

// Bar.php
namespace OtherDir;

use SomeDir\Foo; // This now conflicts the class OtherDir\Foo

If both files OtherDir/Foo.php and SomeDir/Foo.php are loaded in the same runtime, you will see a PHP error such as the following:

PHP Fatal error:  Cannot use SomeDir\Foo as Foo because the name is already in use in OtherDir/Foo.php

However, as OtherDir/Foo.php does not necessarily have to be loaded and the error is only triggered if it is loaded before OtherDir/Bar.php, this problem might go unnoticed for a while. In order to prevent this error from surfacing, you must import the namespace with a different alias:

// Bar.php
namespace OtherDir;

use SomeDir\Foo as SomeDirFoo; // There is no conflict anymore.
Loading history...
22
use function function_exists;
23
24
// phpcs:disable
25 1
if (false === function_exists('Amp\ParallelFunctions\parallel')) {
26
    throw new Exception('You need amphp/parallel-functions to get this operation working.');
27
}
28
// phpcs:enable
29
/**
30
 * @immutable
31
 *
32
 * @template TKey
33
 * @template T
34
 *
35
 * phpcs:disable Generic.Files.LineLength.TooLong
36
 */
37
final class AsyncMapN extends AbstractOperation
38
{
39
    /**
40
     * @pure
41
     *
42
     * @return Closure(callable(mixed, mixed): mixed ...): Closure(Iterator<TKey, T>): Generator<mixed, mixed>
43
     */
44 1
    public function __invoke(): Closure
45
    {
46
        return
47
            /**
48
             * @param callable(mixed, mixed): mixed ...$callbacks
49
             */
50 1
            static fn (callable ...$callbacks): Closure =>
51
                /**
52
                 * @param Iterator<TKey, T> $iterator
53
                 *
54
                 * @return Generator<mixed, mixed>
55
                 */
56 1
                static function (Iterator $iterator) use ($callbacks): Generator {
57
                    $callbackFactory =
58
                        /**
59
                         * @param mixed $key
60
                         *
61
                         * @return Closure(mixed, callable(mixed, mixed): mixed): mixed
62
                         */
63 1
                        static fn ($key): Closure =>
64
                            /**
65
                             * @param mixed $carry
66
                             * @param callable(mixed, mixed): mixed $callback
67
                             *
68
                             * @return mixed
69
                             */
70 1
                            static fn ($carry, callable $callback) => $callback($carry, $key);
71
72
                    $callback =
73
                        /**
74
                         * @param array{0: mixed, 1: mixed} $value
75
                         *
76
                         * @return array{0: mixed, 1: mixed}
77
                         */
78 1
                        static fn (array $value): array => [$value[0], array_reduce($callbacks, $callbackFactory($value[0]), $value[1])];
79
80 1
                    $iter = map(fromIterable(Pack::of()($iterator)), new LocalSemaphore(32), parallel($callback));
81
82 1
                    while (wait($iter->advance())) {
83
                        /** @var array{0: mixed, 1: mixed} $item */
84 1
                        $item = $iter->getCurrent();
85
86 1
                        yield $item[0] => $item[1];
87
                    }
88 1
                };
89
    }
90
}
91