1
+ import assert from 'assert' ;
1
2
import fromAsyncIterable from './fromAsyncIterable.js' ;
2
3
import exhaust from './exhaust.js' ;
3
4
@@ -13,6 +14,38 @@ export default function split(tape, sep) {
13
14
return fromAsyncIterable ( _split ( tape , sep ) ) ;
14
15
}
15
16
17
+ export class Group {
18
+ constructor ( first , sep , tape ) {
19
+ this . first = first ;
20
+ this . sep = sep ;
21
+ this . tape = tape ;
22
+ this . state = 0 ;
23
+ }
24
+
25
+ async next ( ) {
26
+ if ( this . state === 0 ) {
27
+ this . state = 1 ;
28
+ return { done : false , value : this . first } ;
29
+ }
30
+
31
+ if ( this . state === 1 ) {
32
+ const value = await this . tape . read ( ) ;
33
+ if ( value !== this . tape . eof && ! this . sep . has ( value ) )
34
+ return { done : false , value} ;
35
+ this . sep = null ;
36
+ this . tape = null ;
37
+ this . state = 2 ;
38
+ return { done : true } ;
39
+ }
40
+
41
+ return { done : true } ;
42
+ }
43
+
44
+ [ Symbol . asyncIterator ] ( ) {
45
+ return this ;
46
+ }
47
+ }
48
+
16
49
/**
17
50
* Same as {@link split}, but returns an iterable rather than a tape.
18
51
*
@@ -21,32 +54,45 @@ export default function split(tape, sep) {
21
54
* @param {Iterable } sep - An iterable of separators.
22
55
* @returns {AsyncIterable } An iterable of tapes.
23
56
*/
24
- export async function * _split ( tape , sep ) {
25
- const _sep = new Set ( sep ) ;
26
-
27
- while ( true ) {
28
- const token = await tape . read ( ) ; // eslint-disable-line no-await-in-loop
29
-
30
- if ( token === tape . eof ) break ;
31
-
32
- if ( _sep . has ( token ) ) continue ;
57
+ export function _split ( tape , sep ) {
58
+ return new Split ( tape , sep ) ;
59
+ }
33
60
34
- const group = fromAsyncIterable (
35
- ( async function * ( ) {
36
- yield token ;
61
+ class Split {
62
+ constructor ( tape , sep ) {
63
+ this . tape = tape ;
64
+ this . sep = new Set ( sep ) ;
65
+ this . group = null ;
66
+ this . state = 0 ;
67
+ assert ( ! this . sep . has ( this . tape . eof ) ) ;
68
+ }
37
69
38
- while ( true ) {
39
- const token = await tape . read ( ) ; // eslint-disable-line no-await-in-loop
70
+ async next ( ) {
71
+ if ( this . state === 0 ) {
72
+ if ( this . group !== null ) await exhaust ( this . group ) ;
73
+ let token ;
74
+ do {
75
+ // eslint-disable-next-line no-await-in-loop
76
+ token = await this . tape . read ( ) ;
77
+ } while ( this . sep . has ( token ) ) ;
40
78
41
- if ( _sep . has ( token ) ) break ;
79
+ if ( token === this . tape . eof ) {
80
+ this . tape = null ;
81
+ this . sep = null ;
82
+ this . group = null ;
83
+ this . state = 1 ;
84
+ return { done : true } ;
85
+ }
42
86
43
- yield token ;
44
- }
45
- } ) ( ) ,
46
- ) ;
87
+ assert ( ! this . sep . has ( token ) ) ;
88
+ this . group = fromAsyncIterable ( new Group ( token , this . sep , this . tape ) ) ;
89
+ return { done : false , value : this . group } ;
90
+ }
47
91
48
- yield group ;
92
+ return { done : true } ;
93
+ }
49
94
50
- await exhaust ( group ) ; // eslint-disable-line no-await-in-loop
95
+ [ Symbol . asyncIterator ] ( ) {
96
+ return this ;
51
97
}
52
98
}
0 commit comments