object-transform
Version:
Composable object stream Transform
123 lines (99 loc) • 3.88 kB
JavaScript
// Copyright (c) 2013, Benjamin J. Kelly ("Author")
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// 1. Redistributions of source code must retain the above copyright notice, this
// list of conditions and the following disclaimer.
// 2. Redistributions in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
// ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
;
module.exports = ObjectTransform;
var Transform = require('stream').Transform;
if (!Transform) {
Transform = require('readable-stream/transform');
}
var util = require('util');
util.inherits(ObjectTransform, Transform);
function ObjectTransform(opts) {
var self = (this instanceof ObjectTransform)
? this
: Object.create(ObjectTransform.prototype);
opts = opts || {};
if (opts.objectMode === false) {
throw new Error('ObjectTransform requires stream objectMode; do not set ' +
'option {objectMode: false}');
}
opts.objectMode = true;
Transform.call(self, opts);
self._metaProp = opts.meta;
if (self._metaProp && typeof self._metaProp !== 'string') {
throw new Error('ObjectTransform optional "meta" property must be a ' +
'string specifying the msg property where metadata will ' +
'be stored.');
}
self[self._metaProp] = opts[self._metaProp];
return self;
}
ObjectTransform.prototype._transform = function(origMsg, encoding, callback) {
var self = this;
// TODO: consider changing the ObjectTransform API to not pass output func
var output = self.push.bind(self);
var msg = origMsg;
if (Buffer.isBuffer(msg)) {
msg = { data: msg, offset: 0 };
}
msg.offset = ~~msg.offset;
var metaData = null;
if (this._metaProp) {
metaData = msg[self._metaProp] || self[self._metaProp];
}
try {
var msgOut = null;
if (metaData) {
msg.data = self._grow(msg.data, msg.offset, ~~metaData.length);
msgOut = self._expand(metaData, msg, output, callback);
} else {
msgOut = self._reduce(msg, output, callback);
}
// convenience for sync, one-to-one _expand/_reduce functions
if (msgOut) {
output(msgOut);
callback();
}
} catch (error) {
self.emit('ignored', error, origMsg);
callback();
}
};
ObjectTransform.prototype._grow = function(buf, offset, length) {
var reqLength = offset + length;
if (reqLength <= buf.length) {
return buf;
}
if (!buf) {
return new Buffer(reqLength);
}
var newBuf = new Buffer(reqLength);
buf.copy(newBuf, 0, 0, offset);
return newBuf;
};
ObjectTransform.prototype._expand = function(metaData, msg, output, callback) {
throw new Error('ObjectTransform._expand() not implemented');
};
ObjectTransform.prototype._reduce = function(msg, output, callback) {
throw new Error('ObjectTransform._reduce() not implemented');
};