"use strict"; const assert = require("assert"); const unreachable = require("@joepie91/unreachable")("zapdb-kv"); const integerCoder = require("./integer"); function decimalToInteger(value, precision = 0) { let multiplier = 10n ** BigInt(precision); let match = /^(-?)([0-9]+)(?:\.([0-9]+))?$/.exec(value); if (match != null) { let isNegative = (match[1] !== ""); let whole = BigInt(match[2]) * multiplier; let fraction = (match[3] != null) ? BigInt(match[3].slice(0, precision)) : BigInt(0); let signMultiplier = (isNegative) ? -1n : 1n; return (whole + fraction) * signMultiplier; } else { throw unreachable("Decimal regex did not match"); } } function integerToDecimal(integer, precision = 0) { let multiplier = 10n ** BigInt(precision); let wholes = integer / multiplier; // this is integer division! let fraction = integer - (wholes * multiplier); // modulo // TODO: Support float mode? Or maybe custom transforms on a database level, eg. to feed this through a user-specified decimal library? return `${wholes}.${fraction}`; } module.exports = { encode: function (value, asIndexKey, { precision }) { let integer = decimalToInteger(value, precision); return integerCoder.encode(integer, asIndexKey); }, decode: function (buffer, offset, { precision }) { let result = integerCoder.decode(buffer, offset); assert(result.blobID === undefined); let decimal = integerToDecimal(result.value, precision); return { bytesRead: result.bytesRead, value: decimal, auxiliaryBlob: undefined }; } };