Created
October 12, 2015 08:27
-
-
Save XeCycle/59a0ac7089ff1e8a5bc7 to your computer and use it in GitHub Desktop.
something like stream.readline(), returning a promise.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import {Writable} from "stream"; | |
// scanner returns remaining string if succeeded, null/undefined otherwise | |
class ScanningState { | |
constructor(buf, scanner) { | |
this.buf = buf; | |
this.scanner = scanner; | |
} | |
scan() { | |
throw new Error("Another scan in progress"); | |
} | |
data(chunk, _continue) { | |
var buf = this.buf + chunk; | |
var remaining = this.scanner(buf); | |
if (typeof remaining === "string") { | |
return new PausedBlockState(remaining, _continue); | |
} | |
_continue(); | |
return new ScanningState(buf, this.scanner); | |
} | |
} | |
class PausedNoBlockState { | |
constructor(buf) { | |
this.buf = buf; | |
} | |
scan(scanner) { | |
var remaining = scanner(this.buf); | |
if (typeof remaining === "string") | |
return new PausedNoBlockState(remaining); | |
return new ScanningState(this.buf, scanner); | |
} | |
data(chunk, _continue) { | |
return new PausedBlockState(this.buf + chunk, _continue); | |
} | |
} | |
class PausedBlockState { | |
constructor(buf, _continue) { | |
this.buf = buf; | |
this.continue = _continue; | |
} | |
scan(scanner) { | |
var remaining = scanner(this.buf); | |
if (typeof remaining === "string") | |
return new PausedBlockState(remaining, this.continue); | |
this.continue(); | |
return new ScanningState(this.buf, scanner); | |
} | |
data() { | |
throw new Error("Are you really using node streams?"); | |
} | |
} | |
export default class ScannableStream extends Writable { | |
constructor() { | |
super({ | |
decodeStrings: false, | |
objectMode: false | |
}); | |
this._state = new PausedNoBlockState(""); | |
} | |
_write(chunk, encoding, _continue) { | |
this._state = this._state.data(chunk, _continue); | |
} | |
scan(sep) { | |
return new Promise(resolve => { | |
if (typeof sep === "string") | |
this._state = this._state.scan(scanByString(sep, resolve)); | |
else this._state = this._state.scan(scanByRegex(sep, resolve)); | |
}); | |
} | |
} | |
function scanByString(sep, resolve) { | |
return function stringScanner(buf) { | |
var iSep = buf.indexOf(sep); | |
if (iSep >= 0) { | |
resolve(buf.substring(0, iSep)); | |
return buf.substr(iSep + sep.length); | |
} | |
}; | |
} | |
function scanByRegex(sep, resolve) { | |
return function regexScanner(buf) { | |
var match = sep.exec(buf); | |
if (match) { | |
resolve(buf.substring(0, match.index)); | |
return buf.substr(match.index + match[0].length); | |
} | |
}; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment