Skip to content

Commit

Permalink
The functions that act on buffers are now sync.
Browse files Browse the repository at this point in the history
Breaking change; will be accompanied by a major number bump.
  • Loading branch information
ceejbot committed Mar 31, 2016
1 parent 9e33bb4 commit a0561f6
Show file tree
Hide file tree
Showing 4 changed files with 113 additions and 210 deletions.
53 changes: 22 additions & 31 deletions README.md
Expand Up @@ -15,37 +15,28 @@ Tested on node 0.10, 4.x, and 5.x.

## Usage

Avon exports `sumFile()`, `sumBuffer()`, and `sumStream()` functions to calculate a hash for whatever sort of data you have. All three functions take an optional callback. If no callback is provided, they return promises. Use the control flow method you prefer! The calculated hash is a node Buffer.
Avon exports `sumFile()`, `sumBuffer()`, and `sumStream()` functions to calculate a hash for whatever sort of data you have. `sumBuffer()` is synchronous. `sumFile()` and `sumStream()` take an optional callback. If no callback is provided, they return promises. Use the control flow method you prefer! The calculated hash is a node Buffer.

If you don't specify an algorithm, the 64-bit single-core `B` algorithm is used.

```javascript
```js
var Avon = require('avon');
var assert = require('assert');

var buf = new Buffer('this is some input');

Avon.sumBuffer(buf, Avon.ALGORITHMS.BP)
.then(function(hash)
{
assert(hash instanceof Buffer);
console.log(hash.toString('hex'));
}, function(err)
{
console.error('noooooo! ' + err.message);
}).done();
var hash = Avon.sumBuffer(buf, Avon.ALGORITHMS.BP);
assert(hash instanceof Buffer);
console.log(hash.toString('hex'));

Avon.sumBuffer(buf, function(err, buffer)
{
if (err) console.error('noooo!');
else console.log(buffer.toString('hex'))
});
var sum = Avon.sumBuffer(buf, Avon.ALGORITHMS.SP);
console.log(sum.toString('hex');
```
There are variations that take a filename as input:
Want to hash a file? Sure!
```javascript
Avon.sumFile('my_file.dat', , Avon.ALGORITHMS.SP, function(err, buffer)
Avon.sumFile('my_file.dat', Avon.ALGORITHMS.SP, function(err, buffer)
{
if (err) console.error('noooo!');
else console.log(buffer.toString('hex'))
Expand All @@ -72,21 +63,21 @@ input.pipe(hasher);
`Avon.ALGORITHMS` exports the enum-like list of algorithms: `B`, `BP`, `S`, and `SP`.
Blake2 provides a bewildering variety of variations. Avon exposes all of them. This chart might help you decide which to use.
Blake2 provides a bewildering variety of variations. Avon exposes all of them both in the general-purpose functions given above, and in some convenience wrappers. This chart might help you decide which to use.
| function | input | arch | multicore? | algo name
| function | input | arch | multicore? | async? | algo name
| --- | --- | --- | --- | ---
| sumStream | stream | * | * | pass algo name
| sumBuffer | buffer | * | * | pass algo name
| sumFile | file | * | * | pass algo name
| blake2 | buffer | 64 | n | B
| blake2SMP | buffer | 64 | y | BP
| blake2_32 | buffer | 32 | n | S
| blake2_32SMP | buffer | 32 | y | SP
| blake2File | file | 64 | n | B
| blake2SMPFile | file | 64 | y | BP
| blake2_32File | file | 32 | n | S
| blake2_32SMPFile | file | 32 | y | SP
| sumStream | stream | * | * | - | pass algo name
| sumBuffer | buffer | * | * | n | pass algo name
| sumFile | file | * | * | y | pass algo name
| blake2 | buffer | 64 | n | n | B
| blake2SMP | buffer | 64 | y | n | BP
| blake2_32 | buffer | 32 | n | n | S
| blake2_32SMP | buffer | 32 | y | n | SP
| blake2File | file | 64 | n | y | B
| blake2SMPFile | file | 64 | y | y | BP
| blake2_32File | file | 32 | n | y | S
| blake2_32SMPFile | file | 32 | y | y | SP
## Notes
Expand Down
37 changes: 12 additions & 25 deletions index.js
Expand Up @@ -6,22 +6,6 @@ var

var B = 0, BP = 1, S = 2, SP = 3;

function wrapper(algo, buffer)
{
if (!Buffer.isBuffer(buffer))
return P.reject(new Error('You must pass a buffer as input.'));

var deferred = P.defer();

blake2.b2_buffer(algo, buffer, function(err, result)
{
if (err) deferred.reject(err);
else deferred.resolve(result);
});

return deferred.promise;
}

function wrapperFile(algo, fname)
{
if (typeof fname !== 'string')
Expand All @@ -38,14 +22,17 @@ function wrapperFile(algo, fname)
return deferred.promise;
}

function sumBuffer(buffer, algorithm, callback)
function sumBuffer(buffer, algorithm)
{
if (typeof algorithm === 'function')
{
callback = algorithm;
if (!algorithm)
algorithm = B;

if (!Buffer.isBuffer(buffer))
{
throw new Error('You must pass a buffer as input.');
}
return wrapper(algorithm, buffer).nodeify(callback);

return blake2.b2_buffer(algorithm, buffer);
}

function sumFile(fname, algorithm, callback)
Expand All @@ -67,10 +54,10 @@ module.exports =
ALGORITHMS: require('./streaming').ALGORITHMS,

// exposing the implementations
blake2: function(buffer, callback) { return wrapper(B, buffer).nodeify(callback); },
blake2SMP: function(buffer, callback) { return wrapper(BP, buffer).nodeify(callback); },
blake2_32: function(buffer, callback) { return wrapper(S, buffer).nodeify(callback); },
blake2_32SMP: function(buffer, callback) { return wrapper(SP, buffer).nodeify(callback); },
blake2: function(buffer) { return sumBuffer(buffer, B); },
blake2SMP: function(buffer) { return sumBuffer(buffer, BP); },
blake2_32: function(buffer) { return sumBuffer(buffer, S); },
blake2_32SMP: function(buffer) { return sumBuffer(buffer, SP); },
blake2File: function(fname, callback) { return wrapperFile(B, fname).nodeify(callback); },
blake2SMPFile: function(fname, callback) { return wrapperFile(BP, fname).nodeify(callback); },
blake2_32File: function(fname, callback) { return wrapperFile(S, fname).nodeify(callback); },
Expand Down
117 changes: 40 additions & 77 deletions src/avon.cc
Expand Up @@ -102,88 +102,51 @@ NAN_METHOD(HashFile)
Nan::AsyncQueueWorker(new FileWorker(callback, algo, **name));
}

//------ operate on buffers

class BufferWorker : public Nan::AsyncWorker
{
public:
BufferWorker(int algo, char* buf, size_t bufferLen, Nan::Callback *callback)
: Nan::AsyncWorker(callback)
, algorithm(algo)
, buffer(buf)
, bufferLen(bufferLen)
{
}

~BufferWorker() { }

void Execute()
{
blake2bufferfn func;

switch (algorithm)
{
case B:
func = blake2b_buffer;
resultLen = BLAKE2B_OUTBYTES;
break;

case BP:
func = blake2bp_buffer;
resultLen = BLAKE2B_OUTBYTES;
break;

case S:
func = blake2s_buffer;
resultLen = BLAKE2S_OUTBYTES;
break;

case SP:
func = blake2sp_buffer;
resultLen = BLAKE2S_OUTBYTES;
break;

default:
SetErrorMessage("Unknown hash type.");
return;
}

if (func(buffer, bufferLen, hash) < 0)
{
SetErrorMessage("Failed to calculate hash.");
return;
}
}

void HandleOKCallback()
{
Local<Value> argv[] =
{
Nan::Null(),
Nan::CopyBuffer(hash, resultLen).ToLocalChecked()
};
callback->Call(2, argv);
};

private:
int algorithm;
char* buffer;
size_t bufferLen;
size_t resultLen;
// The 2S hashes emit 32 bytes instead of 64, so we get away with
// this size.
char hash[BLAKE2B_OUTBYTES];
};

NAN_METHOD(HashBuffer)
NAN_METHOD(HashBufferSync)
{
int algo = info[0]->Uint32Value();
Local<Object> buffer = info[1].As<Object>();
size_t length = node::Buffer::Length(buffer);
char* data = node::Buffer::Data(buffer);

Nan::Callback *callback = new Nan::Callback(info[2].As<Function>());
Nan::AsyncQueueWorker(new BufferWorker(algo, data, length, callback));
blake2bufferfn func;
size_t resultLen;
char hash[BLAKE2B_OUTBYTES];

switch (algo)
{
case B:
func = blake2b_buffer;
resultLen = BLAKE2B_OUTBYTES;
break;

case BP:
func = blake2bp_buffer;
resultLen = BLAKE2B_OUTBYTES;
break;

case S:
func = blake2s_buffer;
resultLen = BLAKE2S_OUTBYTES;
break;

case SP:
func = blake2sp_buffer;
resultLen = BLAKE2S_OUTBYTES;
break;

default:
Nan::ThrowTypeError("Unknown hash type.");
return;
}

if (func(data, length, hash) < 0)
{
Nan::ThrowTypeError("Failed to calculate hash.");
return;
}

info.GetReturnValue().Set(Nan::CopyBuffer(hash, resultLen).ToLocalChecked());
}

// ------------ ceremony
Expand All @@ -196,7 +159,7 @@ NAN_MODULE_INIT(InitAll)
);
Nan::Set(target,
Nan::New<String>("b2_buffer").ToLocalChecked(),
Nan::GetFunction(Nan::New<FunctionTemplate>(HashBuffer)).ToLocalChecked()
Nan::GetFunction(Nan::New<FunctionTemplate>(HashBufferSync)).ToLocalChecked()
);
AvonStream::Initialize(target);
}
Expand Down

0 comments on commit a0561f6

Please sign in to comment.