mirror of
https://github.com/nodemailer/wildduck.git
synced 2024-11-10 17:47:07 +08:00
76 lines
2.4 KiB
JavaScript
76 lines
2.4 KiB
JavaScript
'use strict';
|
|
|
|
const streams = require('stream');
|
|
const Transform = streams.Transform;
|
|
|
|
// make sure that a stream piped to this transform stream
|
|
// always emits a fixed amounts of bytes. Either by truncating
|
|
// input or emitting padding characters
|
|
class LengthLimiter extends Transform {
|
|
constructor(expectedLength, padding, startFrom, byteCounter) {
|
|
super();
|
|
this.expectedLength = expectedLength;
|
|
this.padding = padding || ' ';
|
|
this.byteCounter = byteCounter || 0;
|
|
this.startFrom = startFrom || 0;
|
|
this.finished = false;
|
|
Transform.call(this);
|
|
}
|
|
|
|
_transform(chunk, encoding, done) {
|
|
if (encoding !== 'buffer') {
|
|
chunk = Buffer.from(chunk, encoding);
|
|
}
|
|
|
|
if (!chunk || !chunk.length || this.finished) {
|
|
return done();
|
|
}
|
|
|
|
// not yet at allowed position
|
|
if (chunk.length + this.byteCounter <= this.startFrom) {
|
|
// ignore
|
|
this.byteCounter += chunk.length;
|
|
return done();
|
|
}
|
|
|
|
// start emitting at middle of chunk
|
|
if (this.byteCounter < this.startFrom) {
|
|
// split the chunk and ignore the first part
|
|
chunk = chunk.slice(this.startFrom - this.byteCounter);
|
|
this.byteCounter += this.startFrom - this.byteCounter;
|
|
}
|
|
|
|
// can emit full chunk
|
|
if (chunk.length + this.byteCounter <= this.expectedLength) {
|
|
this.byteCounter += chunk.length;
|
|
this.push(chunk);
|
|
if (this.byteCounter >= this.expectedLength) {
|
|
this.finished = true;
|
|
this.emit('done', false);
|
|
}
|
|
return setImmediate(done);
|
|
}
|
|
|
|
// stop emitting in the middle of chunk
|
|
let buf = chunk.slice(0, this.expectedLength - this.byteCounter);
|
|
let remaining = chunk.slice(this.expectedLength - this.byteCounter);
|
|
this.push(buf);
|
|
this.finished = true;
|
|
this.emit('done', remaining);
|
|
return setImmediate(done);
|
|
}
|
|
|
|
_flush(done) {
|
|
if (!this.finished) {
|
|
// add padding if incoming stream stopped too early
|
|
if (this.expectedLength > this.byteCounter) {
|
|
let buf = Buffer.from(this.padding.repeat(this.expectedLength - this.byteCounter));
|
|
this.push(buf);
|
|
}
|
|
this.finished = true;
|
|
}
|
|
done();
|
|
}
|
|
}
|
|
|
|
module.exports = LengthLimiter;
|