- From: Morgan Barrett <notifications@github.com>
- Date: Thu, 17 Dec 2020 16:04:13 -0800
- To: whatwg/streams <streams@noreply.github.com>
- Cc: Subscribed <subscribed@noreply.github.com>
- Message-ID: <whatwg/streams/issues/1097@github.com>
I was hoping to start a discussion about the class `BufferTransformer` that I've just mocked up. Is this an antipattern? Could this be a useful helper class in the spec?
### BufferTransformer
```typescript
class Lock {
promise: Promise<void>;
open : () => void;
close : () => void;
constructor(){
(this.close = () =>
this.promise = new Promise(r =>
this.open = r
)
)();
}
}
class BufferTransformer<I, O> implements Transformer<I[], O[]> {
private buffer: I[] = [];
private lock: Lock = new Lock();
private terminator: I;
constructor(terminator: I){
this.terminator = terminator;
}
transform(chunk: I[]){
this.buffer = this.buffer.concat(chunk);
this.lock.open();
}
flush(){
this.lock.open();
}
private async has(i: number): Promise<boolean> {
if(this.buffer.length > i) return true;
this.lock.close();
await this.lock.promise;
return this.buffer.length > i;
}
async read(): Promise<I> {
return await this.has(0) ? this.buffer.shift() : this.terminator;
}
async peek(i): Promise<I> {
return await this.has(i) ? this.buffer[i] : this.terminator;
}
reconsume(i: I){
this.buffer.unshift(i);
}
}
```
An example of its usage is shown below, it takes a stream of characters, reads an unknown amount of them and enqueues only 1 Token. This seems to be the opposite of how I've seen a transformer used, where a fixed buffer of data is given to the transformer and an unknown amount of things are then queued.
### TokenizerTransformer
```typescript
class TokenizerTransformer extends BufferTransformer<string, Token> {
async start(controller){
let token: Token;
while(token = await this.consumeToken()){
controller.enqueue(token);
}
}
async consumeToken(): Promise<Token>{
await this.consumeComments();
let c = await this.read();
if(c === "") return;
if(isWhitespace(c)){
while(isWhitespace(await this.peek(0))){
await this.read();
}
return {type: TokenType.whitespace};
}
if(isDigit(c)){
this.reconsume(c);
return this.consumeNumeric();
}
...
}
...
}
```
And another thing I was curious about is if I wanted to run this process on a string, is there no utility function or easier way than below to start the process?
```typescript
const stringToStream = str => new ReadableStream<string>({
start(controller){
str.split("").forEach(c =>
controller.enqueue(c)
);
controller.close();
}
});
stringToStream("foo").pipeThrough(new TokenizerTransformer)
````
--
You are receiving this because you are subscribed to this thread.
Reply to this email directly or view it on GitHub:
https://github.com/whatwg/streams/issues/1097
Received on Friday, 18 December 2020 00:04:25 UTC