GitHub Access Token became invalid

It seems like the GitHub access token used for retrieving details about this repository from GitHub became invalid. This might prevent certain types of inspections from being run (in particular, everything related to pull requests).
Please ask an admin of your repository to re-new the access token on this website.
Passed
Push — master ( 487322...eaa181 )
by Baptiste
02:18 queued 28s
created

Sequence::count()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 2
CRAP Score 1

Importance

Changes 0
Metric Value
cc 1
eloc 1
nc 1
nop 0
dl 0
loc 3
ccs 2
cts 2
cp 1
crap 1
rs 10
c 0
b 0
f 0
1
<?php
2
declare(strict_types = 1);
3
4
namespace Innmind\Immutable;
5
6
use Innmind\Immutable\Exception\{
7
    LogicException,
8
    CannotGroupEmptyStructure,
9
    ElementNotFound,
10
    OutOfBoundException,
11
};
12
13
/**
14
 * @template T
15
 */
16
final class Sequence implements \Countable
17
{
18
    private string $type;
19
    private ValidateArgument $validate;
20
    private Sequence\Implementation $implementation;
21 396
22
    private function __construct(string $type, Sequence\Implementation $implementation)
23 396
    {
24 396
        $this->type = $type;
25
        $this->validate = Type::of($type);
26 6
        $this->implementation = $implementation;
27
    }
28 6
29 6
    /**
30
     * @param T $values
31 6
     *
32
     * @return self<T>
33
     */
34
    public static function of(string $type, ...$values): self
35
    {
36
        $self = new self($type, new Sequence\Primitive($type, ...$values));
37 272
        $self->implementation->reduce(
38
            1,
39 272
            static function(int $position, $element) use ($self): int {
40
                ($self->validate)($element, $position);
41
42
                return ++$position;
43
            }
44
        );
45 2
46
        return $self;
47 2
    }
48
49
    /**
50
     * It will load the values inside the generator only upon the first use
51
     * of the sequence
52
     *
53 88
     * Use this mode when the amount of data may not fit in memory
54
     *
55 88
     * @param \Generator<T> $generator
56
     *
57
     * @return self<T>
58
     */
59
    public static function defer(string $type, \Generator $generator): self
60
    {
61 68
        return new self($type, new Sequence\Defer($type, $generator));
62
    }
63 68
64
    /**
65
     * It will call the given function every time a new operation is done on the
66
     * sequence. This means the returned structure may not be truly immutable
67
     * as between the calls the underlying source may change.
68
     *
69 88
     * Use this mode when calling to an external source (meaning IO bound) such
70
     * as parsing a file or calling an API
71 88
     *
72 88
     * @param callable(): \Generator<T> $generator
73
     *
74
     * @return self<T>
75
     */
76
    public static function lazy(string $type, callable $generator): self
77 88
    {
78
        return new self($type, new Sequence\Lazy($type, $generator));
79 88
    }
80 88
81
    /**
82
     * @param mixed $values
83
     *
84
     * @return self<mixed>
85 88
     */
86
    public static function mixed(...$values): self
87 88
    {
88
        return new self('mixed', new Sequence\Primitive('mixed', ...$values));
89
    }
90
91
    /**
92
     * @return self<int>
93 2
     */
94
    public static function ints(int ...$values): self
95 2
    {
96
        /** @var self<int> */
97
        $self = new self('int', new Sequence\Primitive('int', ...$values));
98
99
        return $self;
100
    }
101 2
102
    /**
103 2
     * @return self<float>
104
     */
105
    public static function floats(float ...$values): self
106
    {
107
        /** @var self<float> */
108
        $self = new self('float', new Sequence\Primitive('float', ...$values));
109 2
110
        return $self;
111 2
    }
112
113
    /**
114
     * @return self<string>
115
     */
116
    public static function strings(string ...$values): self
117 2
    {
118
        /** @var self<string> */
119 2
        $self = new self('string', new Sequence\Primitive('string', ...$values));
120
121
        return $self;
122
    }
123
124
    /**
125 194
     * @return self<object>
126
     */
127 194
    public static function objects(object ...$values): self
128
    {
129
        /** @var self<object> */
130
        $self = new self('object', new Sequence\Primitive('object', ...$values));
131
132
        return $self;
133 62
    }
134
135 62
    public function isOfType(string $type): bool
136 6
    {
137
        return $this->type === $type;
138
    }
139 56
140
    /**
141
     * Type of the elements
142
     */
143
    public function type(): string
144
    {
145 74
        return $this->type;
146
    }
147 74
148
    public function size(): int
149
    {
150
        return $this->implementation->size();
151
    }
152
153 8
    /**
154
     * {@inheritdoc}
155
     */
156 8
    public function count(): int
157 8
    {
158
        return $this->implementation->size();
159
    }
160
161
    /**
162
     * Return the element at the given index
163 70
     *
164
     * @throws OutOfBoundException
165 70
     *
166 70
     * @return T
167
     */
168 54
    public function get(int $index)
169 8
    {
170
        /** @var T */
171
        return $this->implementation->get($index);
172 54
    }
173 70
174
    /**
175
     * Return the diff between this sequence and another
176
     *
177
     * @param self<T> $sequence
178
     *
179
     * @return self<T>
180 10
     */
181
    public function diff(self $sequence): self
182 10
    {
183 10
        assertSequence($this->type, $sequence, 1);
184
185 10
        $self = clone $this;
186
        $self->implementation = $this->implementation->diff(
187
            $sequence->implementation,
188
        );
189
190
        return $self;
191 4
    }
192
193 4
    /**
194 4
     * Remove all duplicates from the sequence
195
     *
196 4
     * @return self<T>
197
     */
198
    public function distinct(): self
199
    {
200
        $self = clone $this;
201
        $self->implementation = $this->implementation->distinct();
202 16
203
        return $self;
204 16
    }
205
206
    /**
207
     * Remove the n first elements
208
     *
209
     * @return self<T>
210 40
     */
211
    public function drop(int $size): self
212 40
    {
213 40
        $self = clone $this;
214 40
        $self->implementation = $this->implementation->drop($size);
215
216
        return $self;
217
    }
218
219
    /**
220
     * Remove the n last elements
221 108
     *
222
     * @return self<T>
223 108
     */
224 86
    public function dropEnd(int $size): self
225
    {
226
        $self = clone $this;
227 106
        $self->implementation = $this->implementation->dropEnd($size);
228
229
        return $self;
230
    }
231
232
    /**
233 4
     * Check if the two sequences are equal
234
     *
235 4
     * @param self<T> $sequence
236 2
     */
237
    public function equals(self $sequence): bool
238
    {
239 2
        assertSequence($this->type, $sequence, 1);
240
241 2
        return $this->implementation->equals(
242 2
            $sequence->implementation,
243
        );
244 2
    }
245 2
246 2
    /**
247 2
     * Return all elements that satisfy the given predicate
248
     *
249
     * @param callable(T): bool $predicate
250
     *
251 2
     * @return self<T>
252 2
     */
253 2
    public function filter(callable $predicate): self
254 2
    {
255
        $self = clone $this;
256
        $self->implementation = $this->implementation->filter($predicate);
257 2
258
        return $self;
259
    }
260
261 2
    /**
262
     * Apply the given function to all elements of the sequence
263
     *
264
     * @param callable(T): void $function
265
     */
266
    public function foreach(callable $function): void
267 8
    {
268
        $this->implementation->foreach($function);
269 8
    }
270 2
271
    /**
272
     * Return a new map of pairs grouped by keys determined with the given
273 6
     * discriminator function
274
     *
275
     * @template D
276
     * @param callable(T): D $discriminator
277
     *
278
     * @throws CannotGroupEmptyStructure
279 8
     *
280
     * @return Map<D, self<T>>
281 8
     */
282 2
    public function groupBy(callable $discriminator): Map
283
    {
284
        return $this->implementation->groupBy($discriminator);
285 6
    }
286
287
    /**
288
     * Return the first element
289
     *
290
     * @return T
291 160
     */
292
    public function first()
293 160
    {
294
        /** @var T */
295
        return $this->implementation->first();
296
    }
297
298
    /**
299 42
     * Return the last element
300
     *
301 42
     * @return T
302
     */
303 42
    public function last()
304 2
    {
305
        /** @var T */
306
        return $this->implementation->last();
307 40
    }
308
309
    /**
310
     * Check if the sequence contains the given element
311
     *
312
     * @param T $element
313 8
     */
314
    public function contains($element): bool
315 8
    {
316 4
        ($this->validate)($element, 1);
317
318
        return $this->implementation->contains($element);
319 4
    }
320
321
    /**
322
     * Return the index for the given element
323
     *
324
     * @param T $element
325 8
     *
326
     * @throws ElementNotFound
327 8
     */
328 8
    public function indexOf($element): int
329
    {
330 8
        ($this->validate)($element, 1);
331
332
        return $this->implementation->indexOf($element);
333
    }
334
335
    /**
336 4
     * Return the list of indices
337
     *
338 4
     * @return self<int>
339 4
     */
340
    public function indices(): self
341 4
    {
342
        /** @var self<int> */
343
        $self = new self('int', $this->implementation->indices());
344
345
        return $self;
346
    }
347 2
348
    /**
349 2
     * Return a new sequence by applying the given function to all elements
350 2
     *
351
     * @param callable(T): T $function
352 2
     *
353 2
     * @return self<T>
354 2
     */
355
    public function map(callable $function): self
356 2
    {
357
        $self = clone $this;
358
        $self->implementation = $this->implementation->map($function);
359
360 2
        return $self;
361 2
    }
362 2
363 2
    /**
364
     * Create a new Sequence with the exact same number of elements but with a
365 2
     * new type transformed via the given function
366 2
     *
367 2
     * @template S
368
     *
369
     * @param callable(T): S $map
370
     *
371
     * @return self<S>
372
     */
373 26
    public function mapTo(string $type, callable $map): self
374
    {
375 26
        /** @psalm-suppress MixedArgument */
376 26
        return $this->toSequenceOf(
377 26
            $type,
378 26
            static fn($value): \Generator => yield $map($value),
0 ignored issues
show
Bug introduced by
A parse error occurred: Syntax error, unexpected T_FN, expecting T_PAAMAYIM_NEKUDOTAYIM on line 378 at column 19
Loading history...
379 26
        );
380
    }
381
382 26
    /**
383
     * Pad the sequence to a defined size with the given element
384
     *
385
     * @param T $element
386
     *
387
     * @return self<T>
388 4
     */
389
    public function pad(int $size, $element): self
390 4
    {
391 4
        ($this->validate)($element, 2);
392 4
393
        $self = clone $this;
394
        $self->implementation = $this->implementation->pad($size, $element);
395
396
        return $self;
397
    }
398 10
399
    /**
400 10
     * Return a sequence of 2 sequences partitioned according to the given predicate
401
     *
402
     * @param callable(T): bool $predicate
403
     *
404
     * @return Map<bool, self<T>>
405
     */
406 4
    public function partition(callable $predicate): Map
407
    {
408 4
        return $this->implementation->partition($predicate);
409
    }
410
411
    /**
412
     * Slice the sequence
413
     *
414 14
     * @return self<T>
415
     */
416 14
    public function slice(int $from, int $until): self
417 14
    {
418
        $self = clone $this;
419 14
        $self->implementation = $this->implementation->slice($from, $until);
420
421
        return $self;
422
    }
423
424
    /**
425 26
     * Split the sequence in a sequence of 2 sequences splitted at the given position
426
     *
427
     * @throws OutOfBoundException
428 26
     *
429 26
     * @return self<self<T>>
430
     */
431
    public function splitAt(int $position): self
432
    {
433
        return $this->implementation->splitAt($position);
434
    }
435 22
436
    /**
437 22
     * Return a sequence with the n first elements
438
     *
439
     * @return self<T>
440
     */
441
    public function take(int $size): self
442
    {
443 246
        $self = clone $this;
444
        $self->implementation = $this->implementation->take($size);
445 246
446 246
        return $self;
447 246
    }
448
449 246
    /**
450
     * Return a sequence with the n last elements
451
     *
452
     * @return self<T>
453
     */
454
    public function takeEnd(int $size): self
455 6
    {
456
        $self = clone $this;
457 6
        $self->implementation = $this->implementation->takeEnd($size);
458 6
459
        return $self;
460 6
    }
461
462
    /**
463
     * Append the given sequence to the current one
464
     *
465
     * @param self<T> $sequence
466 84
     *
467
     * @return self<T>
468 84
     */
469
    public function append(self $sequence): self
470
    {
471
        assertSequence($this->type, $sequence, 1);
472
473
        $self = clone $this;
474 6
        $self->implementation = $this->implementation->append(
475
            $sequence->implementation,
476 6
        );
477 6
478
        return $self;
479 6
    }
480
481
    /**
482 8
     * Return a sequence with all elements from the current one that exist
483
     * in the given one
484 8
     *
485
     * @param self<T> $sequence
486
     *
487
     * @return self<T>
488
     */
489
    public function intersect(self $sequence): self
490
    {
491
        assertSequence($this->type, $sequence, 1);
492
493
        $self = clone $this;
494
        $self->implementation = $this->implementation->intersect(
495
            $sequence->implementation,
496
        );
497
498
        return $self;
499
    }
500
501
    /**
502
     * Add the given element at the end of the sequence
503
     *
504
     * @param T $element
505
     *
506
     * @return self<T>
507
     */
508
    public function add($element): self
509
    {
510
        return ($this)($element);
511
    }
512
513
    /**
514
     * Add the given element at the end of the sequence
515
     *
516
     * Example:
517
     * <code>
518
     * Sequence::of('int')(1)(3)
519
     * </code>
520
     *
521
     * @param T $element
522
     *
523
     * @return self<T>
524
     */
525
    public function __invoke($element): self
526
    {
527
        ($this->validate)($element, 1);
528
529
        $self = clone $this;
530
        $self->implementation = ($this->implementation)($element);
531
532
        return $self;
533
        return $this->add($element);
534
    }
535
536
    /**
537
     * Sort the sequence in a different order
538
     *
539
     * @param callable(T, T): int $function
540
     *
541
     * @return self<T>
542
     */
543
    public function sort(callable $function): self
544
    {
545
        $self = clone $this;
546
        $self->implementation = $this->implementation->sort($function);
547
548
        return $self;
549
    }
550
551
    /**
552
     * Reduce the sequence to a single value
553
     *
554
     * @template R
555
     * @param R $carry
556
     * @param callable(R, T): R $reducer
557
     *
558
     * @return R
559
     */
560
    public function reduce($carry, callable $reducer)
561
    {
562
        return $this->implementation->reduce($carry, $reducer);
563
    }
564
565
    /**
566
     * Return a set of the same type but without any value
567
     *
568
     * @return self<T>
569
     */
570
    public function clear(): self
571
    {
572
        $self = clone $this;
573
        $self->implementation = new Sequence\Primitive($this->type);
574
575
        return $self;
576
    }
577
578
    /**
579
     * Return the same sequence but in reverse order
580
     *
581
     * @return self<T>
582
     */
583
    public function reverse(): self
584
    {
585
        $self = clone $this;
586
        $self->implementation = $this->implementation->reverse();
587
588
        return $self;
589
    }
590
591
    public function empty(): bool
592
    {
593
        return $this->implementation->empty();
594
    }
595
596
    /**
597
     * @template ST
598
     *
599
     * @param null|callable(T): \Generator<ST> $mapper
600
     *
601
     * @return self<ST>
602
     */
603
    public function toSequenceOf(string $type, callable $mapper = null): self
604
    {
605
        return $this->implementation->toSequenceOf($type, $mapper);
606
    }
607
608
    /**
609
     * @template ST
610
     *
611
     * @param null|callable(T): \Generator<ST> $mapper
612
     *
613
     * @return Set<ST>
614
     */
615
    public function toSetOf(string $type, callable $mapper = null): Set
616
    {
617
        return $this->implementation->toSetOf($type, $mapper);
618
    }
619
620
    /**
621
     * @template MT
622
     * @template MS
623
     *
624
     * @param callable(T): \Generator<MT, MS> $mapper
625
     *
626
     * @return Map<MT, MS>
627
     */
628
    public function toMapOf(string $key, string $value, callable $mapper): Map
629
    {
630
        return $this->implementation->toMapOf($key, $value, $mapper);
631
    }
632
}
633