You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
96 lines
3.1 KiB
96 lines
3.1 KiB
const DEFAULT_FILE_BEGIN = '\u001b[5i';
|
|
const DEFAULT_FILE_END = '\u001b[4i';
|
|
|
|
export class FileDownloader {
|
|
constructor(
|
|
onCompleteFileCallback: (file: string) => any,
|
|
fileBegin: string = DEFAULT_FILE_BEGIN,
|
|
fileEnd: string = DEFAULT_FILE_END
|
|
) {
|
|
this.fileBuffer = [];
|
|
this.onCompleteFileCallback = onCompleteFileCallback;
|
|
this.fileBegin = fileBegin;
|
|
this.fileEnd = fileEnd;
|
|
this.partialFileBegin = '';
|
|
}
|
|
|
|
bufferCharacter(character: string): string {
|
|
// If we are not currently buffering a file.
|
|
if (this.fileBuffer.length === 0) {
|
|
// If we are not currently expecting the rest of the fileBegin sequences.
|
|
if (this.partialFileBegin.length === 0) {
|
|
// If the character is the first character of fileBegin we know to start
|
|
// expecting the rest of the fileBegin sequence.
|
|
if (character === this.fileBegin[0]) {
|
|
this.partialFileBegin = character;
|
|
return '';
|
|
}
|
|
// Otherwise, we just return the character for printing to the terminal.
|
|
|
|
return character;
|
|
}
|
|
// We're currently in the state of buffering a beginner marker...
|
|
|
|
const nextExpectedCharacter = this.fileBegin[
|
|
this.partialFileBegin.length
|
|
];
|
|
// If the next character *is* the next character in the fileBegin sequence.
|
|
if (character === nextExpectedCharacter) {
|
|
this.partialFileBegin += character;
|
|
// Do we now have the complete fileBegin sequence.
|
|
if (this.partialFileBegin === this.fileBegin) {
|
|
this.partialFileBegin = '';
|
|
this.fileBuffer = this.fileBuffer.concat(this.fileBegin.split(''));
|
|
return '';
|
|
}
|
|
// Otherwise, we just wait until the next character.
|
|
|
|
return '';
|
|
}
|
|
// If the next expected character wasn't found for the fileBegin sequence,
|
|
// we need to return all the data that was bufferd in the partialFileBegin
|
|
// back to the terminal.
|
|
|
|
const dataToReturn = this.partialFileBegin + character;
|
|
this.partialFileBegin = '';
|
|
return dataToReturn;
|
|
}
|
|
// If we are currently in the state of buffering a file.
|
|
|
|
this.fileBuffer.push(character);
|
|
// If we now have an entire fileEnd marker, we have a complete file!
|
|
if (
|
|
this.fileBuffer.length >= this.fileBegin.length + this.fileEnd.length &&
|
|
this.fileBuffer.slice(-this.fileEnd.length).join('') === this.fileEnd
|
|
) {
|
|
this.onCompleteFile(
|
|
this.fileBuffer
|
|
.slice(
|
|
this.fileBegin.length,
|
|
this.fileBuffer.length - this.fileEnd.length
|
|
)
|
|
.join('')
|
|
);
|
|
this.fileBuffer = [];
|
|
}
|
|
|
|
return '';
|
|
}
|
|
|
|
buffer(data: string): string {
|
|
// This is a optimization to quickly return if we know for
|
|
// sure we don't need to loop over each character.
|
|
if (
|
|
this.fileBuffer.length === 0 &&
|
|
this.partialFileBegin.length === 0 &&
|
|
data.indexOf(this.fileBegin[0]) === -1
|
|
) {
|
|
return data;
|
|
}
|
|
return data.split('').map(this.bufferCharacter.bind(this)).join('')
|
|
}
|
|
|
|
onCompleteFile(bufferCharacters: string) {
|
|
this.onCompleteFileCallback(bufferCharacters);
|
|
}
|
|
}
|
|
|