<commit_before>#include <node.h>

#include <stdint.h>
#include <cstring>
#include <string>
#include <tuple>

#include "../argon2/include/argon2.h"
#include "argon2_node.h"

namespace NodeArgon2 {

template<class T>
T fromJust(v8::Local<v8::Value> info) {
    return Nan::To<T>(info).FromJust();
}

using size_type = std::string::size_type;
const auto HASH_LEN = 32u;

enum OBJECTS {
    RESERVED = 0,
    THIS_OBJ,
    RESOLVE,
    REJECT,
};

constexpr auto log(uint64_t number, uint64_t base = 2u) -> decltype(number)
{
    return (number > 1) ? 1u + log(number / base, base) : 0u;
}

constexpr auto base64Length(size_type length) -> decltype(length)
{
    return ((length  + 2u) / 3u) * 4u;
}

auto encodedLength(size_type saltLength) -> decltype(saltLength)
{
    /* statically calculate maximum encoded hash length */
    constexpr size_type extraLength = sizeof "$argon2x$m=,t=,p=$$" +
        log(ARGON2_MAX_MEMORY + 1u, 10u) + log(ARGON2_MAX_TIME + 1u, 10u) +
        log(ARGON2_MAX_LANES + 1u, 10u) + base64Length(HASH_LEN);

    /* (number + 3) & ~3 rounds up to the nearest 4-byte boundary */
    return extraLength + base64Length(saltLength);
}

HashWorker::HashWorker(std::string&& plain, std::string&& salt,
        std::tuple<uint32_t, uint32_t, uint32_t, argon2_type>&& params):
    Nan::AsyncWorker{nullptr}, plain{plain}, salt{salt},
    time_cost{std::get<0>(params)}, memory_cost{std::get<1>(params)},
    parallelism{std::get<2>(params)}, type{std::get<3>(params)}
{ }

void HashWorker::Execute()
{
    const auto ENCODED_LEN = encodedLength(salt.size());
    output.reset(new char[ENCODED_LEN]);

    auto result = argon2_hash(time_cost, memory_cost, parallelism,
            plain.c_str(), plain.size(), salt.c_str(), salt.size(), nullptr,
            HASH_LEN, output.get(), ENCODED_LEN, type, ARGON2_VERSION_NUMBER);

    if (result != ARGON2_OK) {
        /* LCOV_EXCL_START */<commit_msg>Fix spacing issue and remove old comment<commit_after>#include <node.h>

#include <stdint.h>
#include <cstring>
#include <string>
#include <tuple>

#include "../argon2/include/argon2.h"
#include "argon2_node.h"

namespace NodeArgon2 {

template<class T>
T fromJust(v8::Local<v8::Value> info) {
    return Nan::To<T>(info).FromJust();
}

using size_type = std::string::size_type;
const auto HASH_LEN = 32u;

enum OBJECTS {
    RESERVED = 0,
    THIS_OBJ,
    RESOLVE,
    REJECT,
};

constexpr auto log(uint64_t number, uint64_t base = 2u) -> decltype(number)
{
    return (number > 1) ? 1u + log(number / base, base) : 0u;
}

constexpr auto base64Length(size_type length) -> decltype(length)
{
    return ((length + 2u) / 3u) * 4u;
}

auto encodedLength(size_type saltLength) -> decltype(saltLength)
{
    /* statically calculate maximum encoded hash length */
    constexpr size_type extraLength = sizeof "$argon2x$m=,t=,p=$$" +
        log(ARGON2_MAX_MEMORY + 1u, 10u) + log(ARGON2_MAX_TIME + 1u, 10u) +
        log(ARGON2_MAX_LANES + 1u, 10u) + base64Length(HASH_LEN);

    return extraLength + base64Length(saltLength);
}

HashWorker::HashWorker(std::string&& plain, std::string&& salt,
        std::tuple<uint32_t, uint32_t, uint32_t, argon2_type>&& params):
    Nan::AsyncWorker{nullptr}, plain{plain}, salt{salt},
    time_cost{std::get<0>(params)}, memory_cost{std::get<1>(params)},
    parallelism{std::get<2>(params)}, type{std::get<3>(params)}
{ }

void HashWorker::Execute()
{
    const auto ENCODED_LEN = encodedLength(salt.size());
    output.reset(new char[ENCODED_LEN]);

    auto result = argon2_hash(time_cost, memory_cost, parallelism,
            plain.c_str(), plain.size(), salt.c_str(), salt.size(), nullptr,
            HASH_LEN, output.get(), ENCODED_LEN, type, ARGON2_VERSION_NUMBER);

    if (result != ARGON2_OK) {
        /* LCOV_EXCL_START */
{'fraction_non_alphanumeric': 0.15368365460786904, 'fraction_numerical': 0.02878267758119884, 'mean_word_length': 4.297902097902098, 'pattern_counts': {'":': 0, '<': 29, '<?xml version=': 0, '>': 37, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6676338', 'n_tokens_mistral': 1468, 'n_tokens_neox': 1396, 'n_words': 284}