1"use strict"; 2 3var Buffer = require("safer-buffer").Buffer; 4 5// NOTE: Due to 'stream' module being pretty large (~100Kb, significant in browser environments), 6// we opt to dependency-inject it instead of creating a hard dependency. 7module.exports = function(stream_module) { 8 var Transform = stream_module.Transform; 9 10 // == Encoder stream ======================================================= 11 12 function IconvLiteEncoderStream(conv, options) { 13 this.conv = conv; 14 options = options || {}; 15 options.decodeStrings = false; // We accept only strings, so we don't need to decode them. 16 Transform.call(this, options); 17 } 18 19 IconvLiteEncoderStream.prototype = Object.create(Transform.prototype, { 20 constructor: { value: IconvLiteEncoderStream } 21 }); 22 23 IconvLiteEncoderStream.prototype._transform = function(chunk, encoding, done) { 24 if (typeof chunk != 'string') 25 return done(new Error("Iconv encoding stream needs strings as its input.")); 26 try { 27 var res = this.conv.write(chunk); 28 if (res && res.length) this.push(res); 29 done(); 30 } 31 catch (e) { 32 done(e); 33 } 34 } 35 36 IconvLiteEncoderStream.prototype._flush = function(done) { 37 try { 38 var res = this.conv.end(); 39 if (res && res.length) this.push(res); 40 done(); 41 } 42 catch (e) { 43 done(e); 44 } 45 } 46 47 IconvLiteEncoderStream.prototype.collect = function(cb) { 48 var chunks = []; 49 this.on('error', cb); 50 this.on('data', function(chunk) { chunks.push(chunk); }); 51 this.on('end', function() { 52 cb(null, Buffer.concat(chunks)); 53 }); 54 return this; 55 } 56 57 58 // == Decoder stream ======================================================= 59 60 function IconvLiteDecoderStream(conv, options) { 61 this.conv = conv; 62 options = options || {}; 63 options.encoding = this.encoding = 'utf8'; // We output strings. 64 Transform.call(this, options); 65 } 66 67 IconvLiteDecoderStream.prototype = Object.create(Transform.prototype, { 68 constructor: { value: IconvLiteDecoderStream } 69 }); 70 71 IconvLiteDecoderStream.prototype._transform = function(chunk, encoding, done) { 72 if (!Buffer.isBuffer(chunk) && !(chunk instanceof Uint8Array)) 73 return done(new Error("Iconv decoding stream needs buffers as its input.")); 74 try { 75 var res = this.conv.write(chunk); 76 if (res && res.length) this.push(res, this.encoding); 77 done(); 78 } 79 catch (e) { 80 done(e); 81 } 82 } 83 84 IconvLiteDecoderStream.prototype._flush = function(done) { 85 try { 86 var res = this.conv.end(); 87 if (res && res.length) this.push(res, this.encoding); 88 done(); 89 } 90 catch (e) { 91 done(e); 92 } 93 } 94 95 IconvLiteDecoderStream.prototype.collect = function(cb) { 96 var res = ''; 97 this.on('error', cb); 98 this.on('data', function(chunk) { res += chunk; }); 99 this.on('end', function() { 100 cb(null, res); 101 }); 102 return this; 103 } 104 105 return { 106 IconvLiteEncoderStream: IconvLiteEncoderStream, 107 IconvLiteDecoderStream: IconvLiteDecoderStream, 108 }; 109}; 110