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

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);
}
}