@sap/odata-v4
Version:
OData V4.0 server library
108 lines (85 loc) • 3.22 kB
JavaScript
'use strict';
const HeaderReader = require('./HeaderReader');
const Reader = require('./Reader');
const STATES = {
RUN_HEADER_READER: 'RUN_HEADER_READER',
RUN_HEADER_READER_RETURN: 'RUN_HEADER_READER_RETURN',
RUN_READER: 'RUN_READER',
RUN_READER_RETURN: 'RUN_READER_RETURN',
FINISHED: 'finished'
};
/**
* Events
* @enum {{DATA: string, END: string}}
*/
const EVENTS = {
START: 'part.start',
HEADERS: 'part.headers',
END: 'part.end'
};
/**
* Reads a part of a multipart request from the Cache.
*
* @extends Reader
*/
class PartReader extends Reader {
/**
* @param {string} crlfBoundary - The boundary determining the end of the multipart reader
*/
constructor(crlfBoundary) {
super();
this._crlfBoundary = crlfBoundary;
this._headerReader = null;
this._bodyReader = null;
this._state = STATES.RUN_HEADER_READER;
this._partHeaderInfos = null;
}
/**
* Read data from cache until the boundary is reached or the cache is empty. If the cache is empty and more data
* is required, this is signaled and readCach is called again. The state is preserved.
*
* @param {ContentDeserializer} reader
* @returns {boolean}
* this: this reader needs more data and caller should call this method again with more data in cache
* false: this reader is finished caller should pop this reader from stack
* null: new sub reader is on stack, call this method again after the sub reader is finished
*/
readCache(reader) {
// let done = false;
let needMoreData = false;
while (needMoreData === false && this._state !== STATES.FINISHED) {
switch (this._state) {
case STATES.RUN_HEADER_READER:
this.emit(EVENTS.START);
this._headerReader = new HeaderReader().setEmitter(this._emitter);
reader.pushReader(this._headerReader);
this._state = STATES.RUN_HEADER_READER_RETURN;
needMoreData = null;
break;
case STATES.RUN_HEADER_READER_RETURN:
this._partHeaderInfos = this._headerReader.getHeaderInfos();
this.emit(EVENTS.HEADERS, this._partHeaderInfos);
this._state = STATES.RUN_READER;
break;
case STATES.RUN_READER:
this._bodyReader = reader.getNextReader(this._partHeaderInfos).setEmitter(this._emitter);
this._bodyReader.setStopPattern(this._crlfBoundary);
reader.pushReader(this._bodyReader);
this._state = STATES.RUN_READER_RETURN;
needMoreData = null;
break;
case STATES.RUN_READER_RETURN:
this._state = STATES.FINISHED;
break;
default:
break;
}
}
if (this._state === STATES.FINISHED) {
this.emit(EVENTS.END);
}
return needMoreData;
}
}
PartReader.EVENTS = EVENTS;
module.exports = PartReader;