1+ import assert from 'assert' ;
12import fromAsyncIterable from './fromAsyncIterable.js' ;
23import exhaust from './exhaust.js' ;
34
@@ -13,6 +14,38 @@ export default function split(tape, sep) {
1314 return fromAsyncIterable ( _split ( tape , sep ) ) ;
1415}
1516
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+
1649/**
1750 * Same as {@link split}, but returns an iterable rather than a tape.
1851 *
@@ -21,32 +54,45 @@ export default function split(tape, sep) {
2154 * @param {Iterable } sep - An iterable of separators.
2255 * @returns {AsyncIterable } An iterable of tapes.
2356 */
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+ }
3360
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+ }
3769
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 ) ) ;
4078
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+ }
4286
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+ }
4791
48- yield group ;
92+ return { done : true } ;
93+ }
4994
50- await exhaust ( group ) ; // eslint-disable-line no-await-in-loop
95+ [ Symbol . asyncIterator ] ( ) {
96+ return this ;
5197 }
5298}
0 commit comments