• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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