/
every.ts
106 lines (102 loc) · 3.31 KB
/
every.ts
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
105
106
import {$A, $S, IterationState, Operation} from '../types';
import {isPromiseLike} from '../typeguards';
import {createOperation} from '../utils';
/**
* Standard {@link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/every Array.every} logic for the iterable,
* extended with iteration state + async.
*
* It emits a `boolean`, indicating whether all elements pass the predicate test.
*
* ```ts
* import {pipe, every} from 'iter-ops';
*
* const i = pipe(
* [1, 2, 3],
* every(a => a % 2 === 0) // checks if every number is even
* );
*
* console.log(...i); //=> false
*
* console.log(i.first); //=> false
* ```
*
* Note that the predicate can only return a `Promise` inside an asynchronous pipeline,
* or else the `Promise` will be treated as a truthy value.
*
* @see
* - {@link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/every Array.every}
* - {@link some}
* @category Sync+Async
*/
export function every<T>(
cb: (
value: T,
index: number,
state: IterationState
) => boolean | Promise<boolean>
): Operation<T, boolean>;
export function every(...args: unknown[]) {
return createOperation(everySync, everyAsync, args);
}
function everySync<T>(
iterable: Iterable<T>,
cb: (value: T, index: number, state: IterationState) => boolean
): Iterable<boolean> {
return {
[$S](): Iterator<boolean> {
const i = iterable[$S]();
const state: IterationState = {};
let index = 0,
finished: boolean;
return {
next(): IteratorResult<boolean> {
if (!finished) {
let a;
while (
!(a = i.next()).done &&
cb(a.value, index++, state)
);
finished = true;
return {value: !!a.done, done: false};
}
return {value: undefined, done: true};
}
};
}
};
}
function everyAsync<T>(
iterable: AsyncIterable<T>,
cb: (
value: T,
index: number,
state: IterationState
) => boolean | Promise<boolean>
): AsyncIterable<boolean> {
return {
[$A](): AsyncIterator<boolean> {
const i = iterable[$A]();
const state: IterationState = {};
let index = 0,
finished: boolean;
return {
next(): Promise<IteratorResult<boolean>> {
if (finished) {
return Promise.resolve({value: undefined, done: true});
}
return i.next().then((a) => {
const r = (a.done ||
cb(a.value, index++, state)) as Promise<boolean>;
const out = (flag: any) => {
finished = a.done || !flag;
return finished
? {value: !!a.done, done: false}
: this.next();
};
return isPromiseLike(r) ? r.then(out) : out(r);
});
}
};
}
};
}