functions/type_to_raw.js

const { DataType } = require('../types');
const { dateToTime } = require('./date');

/**
 * Convert a string to a Buffer.
 *
 * @param {string} value - data to convert.
 * @returns {Buffer} converted Buffer.
 * @private
 */
function stringToRaw(value) {
    let raw = (value) ? Buffer.from(value) : Buffer.alloc(0);

    const end = raw.indexOf('\0');
    if (end != -1)
        raw = raw.subarray(0, end);

    return raw;
}

/**
 * Convert a Date to a Buffer.
 *
 * @param {Date} value - data to convert.
 * @returns {Buffer} converted Buffer.
 * @private
 */
function dateToRaw(value) {
    const raw = Buffer.alloc(6);
    const { days, ms } = dateToTime(value);
    raw.writeUInt16LE(days, 4);
    raw.writeUInt32LE(ms, 0);
    return raw;
}

/**
 * Convert a value to a Buffer based on type.
 *
 * @param {number | bigint | string | Date} value - data to convert.
 * @param {DataType | string} type - how to interpret the data.
 * @param {number} [scaleFactor] - optional multiplier for numeric types.
 * @returns {Buffer} converted Buffer.
 */
function typeToRaw(value, type, scaleFactor=1.0) {
    if (value === undefined || value === null)
        value = 0;

    if (typeof type === 'string')
        type = DataType[type];

    let raw;
    switch (type) {
        case DataType.BOOLEAN:
            raw = Buffer.from(value ? [1] : [0]);
            break;
        case DataType.INTEGER8:
            raw = Buffer.alloc(1);
            raw.writeInt8(value / scaleFactor);
            break;
        case DataType.UNSIGNED8:
            raw = Buffer.alloc(1);
            raw.writeUInt8(value / scaleFactor);
            break;
        case DataType.INTEGER16:
            raw = Buffer.alloc(2);
            raw.writeInt16LE(value / scaleFactor);
            break;
        case DataType.UNSIGNED16:
            raw = Buffer.alloc(2);
            raw.writeUInt16LE(value / scaleFactor);
            break;
        case DataType.INTEGER24:
            raw = Buffer.alloc(3);
            raw.writeIntLE(value / scaleFactor, 0, 3);
            break;
        case DataType.UNSIGNED24:
            raw = Buffer.alloc(3);
            raw.writeUIntLE(value / scaleFactor, 0, 3);
            break;
        case DataType.INTEGER32:
            raw = Buffer.alloc(4);
            raw.writeInt32LE(value / scaleFactor);
            break;
        case DataType.UNSIGNED32:
            raw = Buffer.alloc(4);
            raw.writeUInt32LE(value / scaleFactor);
            break;
        case DataType.INTEGER40:
            raw = Buffer.alloc(5);
            raw.writeIntLE(value / scaleFactor, 0, 5);
            break;
        case DataType.UNSIGNED40:
            raw = Buffer.alloc(5);
            raw.writeUIntLE(value / scaleFactor, 0, 5);
            break;
        case DataType.INTEGER48:
            raw = Buffer.alloc(6);
            raw.writeIntLE(value / scaleFactor, 0, 6);
            break;
        case DataType.UNSIGNED48:
            raw = Buffer.alloc(6);
            raw.writeUIntLE(value / scaleFactor, 0, 6);
            break;
        case DataType.INTEGER56:
        case DataType.INTEGER64:
            if (typeof value != 'bigint')
                value = BigInt(value);

            raw = Buffer.alloc(8);
            raw.writeBigInt64LE(value / BigInt(scaleFactor));
            break;
        case DataType.UNSIGNED56:
        case DataType.UNSIGNED64:
            if (typeof value != 'bigint')
                value = BigInt(value);

            raw = Buffer.alloc(8);
            raw.writeBigUInt64LE(value / BigInt(scaleFactor));
            break;
        case DataType.REAL32:
            raw = Buffer.alloc(4);
            raw.writeFloatLE(value / scaleFactor);
            break;
        case DataType.REAL64:
            raw = Buffer.alloc(8);
            raw.writeDoubleLE(value / scaleFactor);
            break;
        case DataType.VISIBLE_STRING:
            raw = stringToRaw(value);
            break;
        case DataType.OCTET_STRING:
        case DataType.UNICODE_STRING:
            raw = (value) ? Buffer.from(value) : Buffer.alloc(0);
            break;
        case DataType.TIME_OF_DAY:
        case DataType.TIME_DIFFERENCE:
            raw = dateToRaw(value);
            break;
    }

    return raw;
}

module.exports = exports = typeToRaw;