68 lines
		
	
	
		
			2.0 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
			
		
		
	
	
			68 lines
		
	
	
		
			2.0 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
'use strict';
 | 
						|
 | 
						|
var fs = require('fs');
 | 
						|
var utilUtf8 = require('@smithy/util-utf8');
 | 
						|
var stream = require('stream');
 | 
						|
 | 
						|
class HashCalculator extends stream.Writable {
 | 
						|
    hash;
 | 
						|
    constructor(hash, options) {
 | 
						|
        super(options);
 | 
						|
        this.hash = hash;
 | 
						|
    }
 | 
						|
    _write(chunk, encoding, callback) {
 | 
						|
        try {
 | 
						|
            this.hash.update(utilUtf8.toUint8Array(chunk));
 | 
						|
        }
 | 
						|
        catch (err) {
 | 
						|
            return callback(err);
 | 
						|
        }
 | 
						|
        callback();
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
const fileStreamHasher = (hashCtor, fileStream) => new Promise((resolve, reject) => {
 | 
						|
    if (!isReadStream(fileStream)) {
 | 
						|
        reject(new Error("Unable to calculate hash for non-file streams."));
 | 
						|
        return;
 | 
						|
    }
 | 
						|
    const fileStreamTee = fs.createReadStream(fileStream.path, {
 | 
						|
        start: fileStream.start,
 | 
						|
        end: fileStream.end,
 | 
						|
    });
 | 
						|
    const hash = new hashCtor();
 | 
						|
    const hashCalculator = new HashCalculator(hash);
 | 
						|
    fileStreamTee.pipe(hashCalculator);
 | 
						|
    fileStreamTee.on("error", (err) => {
 | 
						|
        hashCalculator.end();
 | 
						|
        reject(err);
 | 
						|
    });
 | 
						|
    hashCalculator.on("error", reject);
 | 
						|
    hashCalculator.on("finish", function () {
 | 
						|
        hash.digest().then(resolve).catch(reject);
 | 
						|
    });
 | 
						|
});
 | 
						|
const isReadStream = (stream) => typeof stream.path === "string";
 | 
						|
 | 
						|
const readableStreamHasher = (hashCtor, readableStream) => {
 | 
						|
    if (readableStream.readableFlowing !== null) {
 | 
						|
        throw new Error("Unable to calculate hash for flowing readable stream");
 | 
						|
    }
 | 
						|
    const hash = new hashCtor();
 | 
						|
    const hashCalculator = new HashCalculator(hash);
 | 
						|
    readableStream.pipe(hashCalculator);
 | 
						|
    return new Promise((resolve, reject) => {
 | 
						|
        readableStream.on("error", (err) => {
 | 
						|
            hashCalculator.end();
 | 
						|
            reject(err);
 | 
						|
        });
 | 
						|
        hashCalculator.on("error", reject);
 | 
						|
        hashCalculator.on("finish", () => {
 | 
						|
            hash.digest().then(resolve).catch(reject);
 | 
						|
        });
 | 
						|
    });
 | 
						|
};
 | 
						|
 | 
						|
exports.fileStreamHasher = fileStreamHasher;
 | 
						|
exports.readableStreamHasher = readableStreamHasher;
 |