node-firebird 2.3.2 → 2.3.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (49) hide show
  1. package/README.md +163 -31
  2. package/lib/index.d.ts +12 -0
  3. package/lib/pool.js +10 -1
  4. package/lib/srp.js +12 -1
  5. package/lib/wire/connection.js +39 -7
  6. package/lib/wire/socket.js +13 -1
  7. package/lib/wire/xsqlvar.js +69 -6
  8. package/package.json +1 -1
  9. package/poc/node_modules/.package-lock.json +14 -0
  10. package/poc/node_modules/node-firebird/.eslintrc.json +12 -0
  11. package/poc/node_modules/node-firebird/.github/workflows/codeql.yml +76 -0
  12. package/poc/node_modules/node-firebird/.github/workflows/node.js.yml +95 -0
  13. package/poc/node_modules/node-firebird/BIGINT_MIGRATION.md +374 -0
  14. package/poc/node_modules/node-firebird/CI_DEBUGGING_GUIDE.md +148 -0
  15. package/poc/node_modules/node-firebird/ENCRYPTION_CALLBACK.md +152 -0
  16. package/poc/node_modules/node-firebird/FIREBIRD_LOG_FEATURE.md +145 -0
  17. package/poc/node_modules/node-firebird/LICENSE +373 -0
  18. package/poc/node_modules/node-firebird/MINIMAL_CHANGES_SUMMARY.md +136 -0
  19. package/poc/node_modules/node-firebird/PR_SUMMARY.md +96 -0
  20. package/poc/node_modules/node-firebird/README.md +794 -0
  21. package/poc/node_modules/node-firebird/ROADMAP.md +223 -0
  22. package/poc/node_modules/node-firebird/SRP_PROTOCOL.md +482 -0
  23. package/poc/node_modules/node-firebird/lib/callback.js +38 -0
  24. package/poc/node_modules/node-firebird/lib/firebird.msg +0 -0
  25. package/poc/node_modules/node-firebird/lib/firebird.msg.json +1371 -0
  26. package/poc/node_modules/node-firebird/lib/gdscodes.d.ts +1524 -0
  27. package/poc/node_modules/node-firebird/lib/gdscodes.js +1531 -0
  28. package/poc/node_modules/node-firebird/lib/ieee754-decimal.js +500 -0
  29. package/poc/node_modules/node-firebird/lib/index.d.ts +316 -0
  30. package/poc/node_modules/node-firebird/lib/index.js +128 -0
  31. package/poc/node_modules/node-firebird/lib/messages.js +162 -0
  32. package/poc/node_modules/node-firebird/lib/pool.js +108 -0
  33. package/poc/node_modules/node-firebird/lib/srp.js +299 -0
  34. package/poc/node_modules/node-firebird/lib/unix-crypt.js +343 -0
  35. package/poc/node_modules/node-firebird/lib/utils.js +164 -0
  36. package/poc/node_modules/node-firebird/lib/wire/connection.js +2510 -0
  37. package/poc/node_modules/node-firebird/lib/wire/const.js +807 -0
  38. package/poc/node_modules/node-firebird/lib/wire/database.js +378 -0
  39. package/poc/node_modules/node-firebird/lib/wire/eventConnection.js +118 -0
  40. package/poc/node_modules/node-firebird/lib/wire/fbEventManager.js +326 -0
  41. package/poc/node_modules/node-firebird/lib/wire/serialize.js +588 -0
  42. package/poc/node_modules/node-firebird/lib/wire/service.js +1058 -0
  43. package/poc/node_modules/node-firebird/lib/wire/socket.js +175 -0
  44. package/poc/node_modules/node-firebird/lib/wire/statement.js +48 -0
  45. package/poc/node_modules/node-firebird/lib/wire/transaction.js +206 -0
  46. package/poc/node_modules/node-firebird/lib/wire/xsqlvar.js +703 -0
  47. package/poc/node_modules/node-firebird/package.json +38 -0
  48. package/poc/node_modules/node-firebird/vitest.config.js +24 -0
  49. package/vitest.config.js +3 -1
@@ -0,0 +1,500 @@
1
+ /**
2
+ * IEEE 754-2008 Decimal Floating Point Support
3
+ *
4
+ * This module implements encoding and decoding of IEEE 754 Decimal64 and Decimal128
5
+ * formats using the BID (Binary Integer Decimal) encoding.
6
+ *
7
+ * Based on the decimal-java library from FirebirdSQL:
8
+ * https://github.com/FirebirdSQL/decimal-java
9
+ *
10
+ * References:
11
+ * - IEEE 754-2008 Standard
12
+ * - https://en.wikipedia.org/wiki/Decimal64_floating-point_format
13
+ * - https://en.wikipedia.org/wiki/Decimal128_floating-point_format
14
+ */
15
+
16
+ // IEEE 754 Decimal64 constants (16 decimal digits of precision)
17
+ const DECIMAL64_BIAS = 398;
18
+ const DECIMAL64_MAX_EXPONENT = 369;
19
+ const DECIMAL64_MIN_EXPONENT = -398;
20
+ const DECIMAL64_MAX_COEFFICIENT = 9999999999999999n; // 16 digits
21
+
22
+ // IEEE 754 Decimal128 constants (34 decimal digits of precision)
23
+ const DECIMAL128_BIAS = 6176;
24
+ const DECIMAL128_MAX_EXPONENT = 6111;
25
+ const DECIMAL128_MIN_EXPONENT = -6176;
26
+ const DECIMAL128_MAX_COEFFICIENT = 9999999999999999999999999999999999n; // 34 digits
27
+
28
+ // Special value patterns
29
+ const DECIMAL64_INFINITY = 0x7800000000000000n;
30
+ const DECIMAL64_NEG_INFINITY = 0xF800000000000000n;
31
+ const DECIMAL64_NAN = 0x7C00000000000000n;
32
+ const DECIMAL64_SNAN = 0x7E00000000000000n;
33
+
34
+ const DECIMAL128_INFINITY_HIGH = 0x7800000000000000n;
35
+ const DECIMAL128_NEG_INFINITY_HIGH = 0xF800000000000000n;
36
+ const DECIMAL128_NAN_HIGH = 0x7C00000000000000n;
37
+ const DECIMAL128_SNAN_HIGH = 0x7E00000000000000n;
38
+
39
+ /**
40
+ * Encode a number to IEEE 754 Decimal64 format (8 bytes)
41
+ * @param {number|string|BigInt} value - The value to encode
42
+ * @returns {Buffer} - 8-byte buffer containing the Decimal64 encoding
43
+ */
44
+ function encodeDecimal64(value) {
45
+ // Handle special cases
46
+ if (value === null || value === undefined) {
47
+ return Buffer.alloc(8);
48
+ }
49
+
50
+ if (typeof value === 'number') {
51
+ if (isNaN(value)) {
52
+ return bigIntToBuffer(DECIMAL64_NAN, 8);
53
+ }
54
+ if (!isFinite(value)) {
55
+ return bigIntToBuffer(value > 0 ? DECIMAL64_INFINITY : DECIMAL64_NEG_INFINITY, 8);
56
+ }
57
+ value = value.toString();
58
+ }
59
+
60
+ if (Buffer.isBuffer(value)) {
61
+ return value.slice(0, 8);
62
+ }
63
+
64
+ // Parse the decimal string
65
+ const str = value.toString();
66
+ const sign = str.startsWith('-') ? 1n : 0n;
67
+ const absStr = str.replace(/^-/, '');
68
+
69
+ // Handle zero
70
+ if (parseFloat(absStr) === 0) {
71
+ return bigIntToBuffer(sign << 63n, 8);
72
+ }
73
+
74
+ // Parse coefficient and exponent
75
+ let coefficient, exponent;
76
+ const eIndex = absStr.toLowerCase().indexOf('e');
77
+
78
+ if (eIndex !== -1) {
79
+ const mantissa = absStr.substring(0, eIndex).replace('.', '');
80
+ coefficient = mantissa === '' || mantissa === '-' ? 0n : BigInt(mantissa);
81
+ const expPart = absStr.substring(eIndex + 1);
82
+ const dotIndex = absStr.indexOf('.');
83
+ if (dotIndex !== -1 && dotIndex < eIndex) {
84
+ exponent = parseInt(expPart) - (eIndex - dotIndex - 1);
85
+ } else {
86
+ exponent = parseInt(expPart);
87
+ }
88
+ } else {
89
+ const dotIndex = absStr.indexOf('.');
90
+ if (dotIndex !== -1) {
91
+ const withoutDot = absStr.replace('.', '');
92
+ coefficient = withoutDot === '' || withoutDot === '-' ? 0n : BigInt(withoutDot);
93
+ exponent = -(absStr.length - dotIndex - 1);
94
+ } else {
95
+ coefficient = absStr === '' || absStr === '-' ? 0n : BigInt(absStr);
96
+ exponent = 0;
97
+ }
98
+ }
99
+
100
+ // Normalize: remove trailing zeros
101
+ while (coefficient % 10n === 0n && coefficient !== 0n && exponent < DECIMAL64_MAX_EXPONENT) {
102
+ coefficient /= 10n;
103
+ exponent++;
104
+ }
105
+
106
+ // Check coefficient range
107
+ if (coefficient > DECIMAL64_MAX_COEFFICIENT) {
108
+ throw new Error(`Coefficient ${coefficient} exceeds Decimal64 maximum`);
109
+ }
110
+
111
+ // Adjust exponent with bias
112
+ const biasedExponent = exponent + DECIMAL64_BIAS;
113
+ if (biasedExponent < 0 || biasedExponent > 767) {
114
+ throw new Error(`Exponent ${exponent} out of Decimal64 range`);
115
+ }
116
+
117
+ // Encode using BID (Binary Integer Decimal) format
118
+ // Bit layout: S(1) | Combination(5) | Exponent continuation(8) | Coefficient continuation(50)
119
+
120
+ let encoded = 0n;
121
+
122
+ // Sign bit (bit 63)
123
+ encoded |= sign << 63n;
124
+
125
+ // Split coefficient into MSD and continuation
126
+ const msd = Number(coefficient / 1000000000000000n); // Most significant digit
127
+ const coeffCont = coefficient % 1000000000000000n; // Lower 15 digits (50 bits max)
128
+
129
+ const expBigInt = BigInt(biasedExponent);
130
+ const expTop = (expBigInt >> 8n) & 0x3n; // Top 2 bits of exponent (bits 9-8)
131
+ const expLow = expBigInt & 0xFFn; // Lower 8 bits of exponent (bits 7-0)
132
+
133
+ if (msd <= 7) {
134
+ // Combination: G0 G1 G2 G3 G4 where G0 G1 = expTop, G2 G3 G4 = MSD
135
+ const combo = (expTop << 3n) | BigInt(msd);
136
+ encoded |= combo << 58n;
137
+ // Exponent continuation (8 bits at position 57-50)
138
+ encoded |= expLow << 50n;
139
+ // Coefficient continuation (50 bits at position 49-0)
140
+ encoded |= coeffCont & 0x3FFFFFFFFFFFFn;
141
+ } else {
142
+ // Combination: 11 G2 G3 G4 where G2 = (MSD-8), G3 G4 = expTop
143
+ const combo = 0x18n | ((BigInt(msd - 8) & 0x1n) << 2n) | expTop;
144
+ encoded |= combo << 58n;
145
+ // Exponent continuation (8 bits at position 57-50)
146
+ encoded |= expLow << 50n;
147
+ // Coefficient continuation (50 bits at position 49-0)
148
+ encoded |= coeffCont & 0x3FFFFFFFFFFFFn;
149
+ }
150
+
151
+ return bigIntToBuffer(encoded, 8);
152
+ }
153
+
154
+ /**
155
+ * Decode IEEE 754 Decimal64 format (8 bytes) to a string
156
+ * @param {Buffer} buffer - 8-byte buffer containing the Decimal64 encoding
157
+ * @returns {string|number} - Decoded value as string or special value
158
+ */
159
+ function decodeDecimal64(buffer) {
160
+ if (buffer.length !== 8) {
161
+ throw new Error('Decimal64 buffer must be 8 bytes');
162
+ }
163
+
164
+ const encoded = bufferToBigInt(buffer);
165
+
166
+ // Extract sign
167
+ const sign = (encoded >> 63n) & 0x1n;
168
+
169
+ // Extract combination field (bits 62-58, 5 bits)
170
+ const combo = (encoded >> 58n) & 0x1Fn;
171
+
172
+ if ((combo & 0x1En) === 0x1En) {
173
+ // Special value (NaN or Infinity)
174
+ if ((combo & 0x1n) === 0n) {
175
+ return sign ? -Infinity : Infinity;
176
+ } else {
177
+ return NaN;
178
+ }
179
+ }
180
+
181
+ // Decode exponent and coefficient
182
+ let exponent, coefficient, msd;
183
+
184
+ if ((combo & 0x18n) !== 0x18n) {
185
+ // Combination: G0 G1 G2 G3 G4 where G0 G1 != 11
186
+ // MSD is G2 G3 G4 (bits 2-0 of combo)
187
+ msd = Number(combo & 0x7n);
188
+ // Exponent top 2 bits are G0 G1 (bits 4-3 of combo)
189
+ const expTop = (combo >> 3n) & 0x3n;
190
+ // Exponent continuation is bits 57-50 (8 bits)
191
+ const expLow = (encoded >> 50n) & 0xFFn;
192
+ exponent = (expTop << 8n) | expLow;
193
+ // Coefficient continuation is bits 49-0 (50 bits)
194
+ const coeffCont = encoded & 0x3FFFFFFFFFFFFn;
195
+ coefficient = BigInt(msd) * 1000000000000000n + coeffCont;
196
+ } else {
197
+ // Combination: 11 G2 G3 G4 (MSD 8-9)
198
+ // MSD is 8 + G2 (bit 2 of combo)
199
+ msd = 8 + Number((combo >> 2n) & 0x1n);
200
+ // Exponent top 2 bits are G3 G4 (bits 1-0 of combo)
201
+ const expTop = combo & 0x3n;
202
+ // Exponent continuation is bits 57-50 (8 bits)
203
+ const expLow = (encoded >> 50n) & 0xFFn;
204
+ exponent = (expTop << 8n) | expLow;
205
+ // Coefficient continuation is bits 49-0 (50 bits)
206
+ const coeffCont = encoded & 0x3FFFFFFFFFFFFn;
207
+ coefficient = BigInt(msd) * 1000000000000000n + coeffCont;
208
+ }
209
+
210
+ // Remove bias from exponent
211
+ const unbias = Number(exponent) - DECIMAL64_BIAS;
212
+
213
+ // Build result string
214
+ const coeffStr = coefficient.toString();
215
+ const signStr = sign ? '-' : '';
216
+
217
+ // Special case: if coefficient is 0, just return "0" regardless of exponent
218
+ if (coefficient === 0n) {
219
+ return signStr + '0';
220
+ }
221
+
222
+ if (unbias === 0) {
223
+ return signStr + coeffStr;
224
+ } else if (unbias > 0) {
225
+ return signStr + coeffStr + '0'.repeat(unbias);
226
+ } else {
227
+ const absExp = -unbias;
228
+ if (absExp >= coeffStr.length) {
229
+ return signStr + '0.' + '0'.repeat(absExp - coeffStr.length) + coeffStr;
230
+ } else {
231
+ const intPart = coeffStr.substring(0, coeffStr.length - absExp);
232
+ const fracPart = coeffStr.substring(coeffStr.length - absExp);
233
+ return signStr + intPart + '.' + fracPart;
234
+ }
235
+ }
236
+ }
237
+
238
+ /**
239
+ * Encode a number to IEEE 754 Decimal128 format (16 bytes)
240
+ * @param {number|string|BigInt} value - The value to encode
241
+ * @returns {Buffer} - 16-byte buffer containing the Decimal128 encoding
242
+ */
243
+ function encodeDecimal128(value) {
244
+ // Handle special cases
245
+ if (value === null || value === undefined) {
246
+ return Buffer.alloc(16);
247
+ }
248
+
249
+ if (typeof value === 'number') {
250
+ if (isNaN(value)) {
251
+ const buf = Buffer.alloc(16);
252
+ bufferWriteBigInt(buf, DECIMAL128_NAN_HIGH, 0, 8);
253
+ return buf;
254
+ }
255
+ if (!isFinite(value)) {
256
+ const buf = Buffer.alloc(16);
257
+ bufferWriteBigInt(buf, value > 0 ? DECIMAL128_INFINITY_HIGH : DECIMAL128_NEG_INFINITY_HIGH, 0, 8);
258
+ return buf;
259
+ }
260
+ value = value.toString();
261
+ }
262
+
263
+ if (Buffer.isBuffer(value)) {
264
+ return value.slice(0, 16);
265
+ }
266
+
267
+ // Parse the decimal string
268
+ const str = value.toString();
269
+ const sign = str.startsWith('-') ? 1n : 0n;
270
+ const absStr = str.replace(/^-/, '');
271
+
272
+ // Handle zero
273
+ if (parseFloat(absStr) === 0) {
274
+ const buf = Buffer.alloc(16);
275
+ bufferWriteBigInt(buf, sign << 63n, 0, 8);
276
+ return buf;
277
+ }
278
+
279
+ // Parse coefficient and exponent
280
+ let coefficient, exponent;
281
+ const eIndex = absStr.toLowerCase().indexOf('e');
282
+
283
+ if (eIndex !== -1) {
284
+ const mantissa = absStr.substring(0, eIndex).replace('.', '');
285
+ coefficient = mantissa === '' || mantissa === '-' ? 0n : BigInt(mantissa);
286
+ const expPart = absStr.substring(eIndex + 1);
287
+ const dotIndex = absStr.indexOf('.');
288
+ if (dotIndex !== -1 && dotIndex < eIndex) {
289
+ exponent = parseInt(expPart) - (eIndex - dotIndex - 1);
290
+ } else {
291
+ exponent = parseInt(expPart);
292
+ }
293
+ } else {
294
+ const dotIndex = absStr.indexOf('.');
295
+ if (dotIndex !== -1) {
296
+ const withoutDot = absStr.replace('.', '');
297
+ coefficient = withoutDot === '' || withoutDot === '-' ? 0n : BigInt(withoutDot);
298
+ exponent = -(absStr.length - dotIndex - 1);
299
+ } else {
300
+ coefficient = absStr === '' || absStr === '-' ? 0n : BigInt(absStr);
301
+ exponent = 0;
302
+ }
303
+ }
304
+
305
+ // Normalize: remove trailing zeros
306
+ while (coefficient % 10n === 0n && coefficient !== 0n && exponent < DECIMAL128_MAX_EXPONENT) {
307
+ coefficient /= 10n;
308
+ exponent++;
309
+ }
310
+
311
+ // Check coefficient range
312
+ if (coefficient > DECIMAL128_MAX_COEFFICIENT) {
313
+ throw new Error(`Coefficient ${coefficient} exceeds Decimal128 maximum`);
314
+ }
315
+
316
+ // Adjust exponent with bias
317
+ const biasedExponent = exponent + DECIMAL128_BIAS;
318
+ if (biasedExponent < 0 || biasedExponent > 12287) {
319
+ throw new Error(`Exponent ${exponent} out of Decimal128 range`);
320
+ }
321
+
322
+ // Encode using BID format
323
+ // Bit layout: S(1) | Combination(5) | Exponent continuation(12) | Coefficient continuation(110)
324
+
325
+ const expBigInt = BigInt(biasedExponent);
326
+
327
+ // Split coefficient into MSD and continuation
328
+ const msd = Number(coefficient / 1000000000000000000000000000000000n); // Most significant digit (10^33)
329
+ const coeffCont = coefficient % 1000000000000000000000000000000000n; // Lower 33 digits (110 bits max)
330
+
331
+ let high = 0n;
332
+ let low = coeffCont & ((1n << 64n) - 1n); // Lower 64 bits of coefficient
333
+
334
+ // Sign bit (bit 127)
335
+ high |= sign << 63n;
336
+
337
+ const expTop = (expBigInt >> 12n) & 0x3n; // Top 2 bits of exponent (bits 13-12)
338
+ const expLow = expBigInt & 0xFFFn; // Lower 12 bits of exponent (bits 11-0)
339
+
340
+ if (msd <= 7) {
341
+ // Combination: G0 G1 G2 G3 G4 where G0 G1 = expTop, G2 G3 G4 = MSD
342
+ const combo = (expTop << 3n) | BigInt(msd);
343
+ high |= combo << 58n;
344
+ // Exponent continuation (12 bits at position 121-110, which is bits 57-46 in high)
345
+ high |= expLow << 46n;
346
+ // Coefficient continuation high 46 bits (bits 109-64, which is bits 45-0 in high)
347
+ high |= (coeffCont >> 64n) & 0x3FFFFFFFFFFFn;
348
+ } else {
349
+ // Combination: 11 G2 G3 G4 where G2 = (MSD-8), G3 G4 = expTop
350
+ const combo = 0x18n | ((BigInt(msd - 8) & 0x1n) << 2n) | expTop;
351
+ high |= combo << 58n;
352
+ // Exponent continuation (12 bits at position 121-110)
353
+ high |= expLow << 46n;
354
+ // Coefficient continuation high 46 bits
355
+ high |= (coeffCont >> 64n) & 0x3FFFFFFFFFFFn;
356
+ }
357
+
358
+ const buf = Buffer.alloc(16);
359
+ bufferWriteBigInt(buf, high, 0, 8);
360
+ bufferWriteBigInt(buf, low, 8, 8);
361
+ return buf;
362
+ }
363
+
364
+ /**
365
+ * Decode IEEE 754 Decimal128 format (16 bytes) to a string
366
+ * @param {Buffer} buffer - 16-byte buffer containing the Decimal128 encoding
367
+ * @returns {string|number} - Decoded value as string or special value
368
+ */
369
+ function decodeDecimal128(buffer) {
370
+ if (buffer.length !== 16) {
371
+ throw new Error('Decimal128 buffer must be 16 bytes');
372
+ }
373
+
374
+ const high = bufferToBigInt(buffer.slice(0, 8));
375
+ const low = bufferToBigInt(buffer.slice(8, 16));
376
+
377
+ // Extract sign
378
+ const sign = (high >> 63n) & 0x1n;
379
+
380
+ // Check for special values
381
+ const combo = (high >> 58n) & 0x1Fn;
382
+
383
+ if ((combo & 0x1En) === 0x1En) {
384
+ // Special value (NaN or Infinity)
385
+ if ((combo & 0x1n) === 0n) {
386
+ return sign ? -Infinity : Infinity;
387
+ } else {
388
+ return NaN;
389
+ }
390
+ }
391
+
392
+ // Decode exponent and coefficient
393
+ let exponent, coefficient, msd;
394
+
395
+ if ((combo & 0x18n) !== 0x18n) {
396
+ // Combination: G0 G1 G2 G3 G4 where G0 G1 != 11
397
+ // MSD is G2 G3 G4 (bits 2-0 of combo)
398
+ msd = Number(combo & 0x7n);
399
+ // Exponent top 2 bits are G0 G1 (bits 4-3 of combo)
400
+ const expTop = (combo >> 3n) & 0x3n;
401
+ // Exponent continuation is bits 121-110 (bits 57-46 in high, 12 bits)
402
+ const expLow = (high >> 46n) & 0xFFFn;
403
+ exponent = (expTop << 12n) | expLow;
404
+ // Coefficient continuation is bits 109-0 (bits 45-0 in high + all 64 bits in low = 110 bits)
405
+ const coeffHigh = high & 0x3FFFFFFFFFFFn; // 46 bits
406
+ coefficient = (coeffHigh << 64n) | low; // Combine with low 64 bits
407
+ coefficient = BigInt(msd) * 1000000000000000000000000000000000n + coefficient;
408
+ } else {
409
+ // Combination: 11 G2 G3 G4 (MSD 8-9)
410
+ // MSD is 8 + G2 (bit 2 of combo)
411
+ msd = 8 + Number((combo >> 2n) & 0x1n);
412
+ // Exponent top 2 bits are G3 G4 (bits 1-0 of combo)
413
+ const expTop = combo & 0x3n;
414
+ // Exponent continuation is bits 121-110 (12 bits)
415
+ const expLow = (high >> 46n) & 0xFFFn;
416
+ exponent = (expTop << 12n) | expLow;
417
+ // Coefficient continuation is bits 109-0 (110 bits)
418
+ const coeffHigh = high & 0x3FFFFFFFFFFFn; // 46 bits
419
+ coefficient = (coeffHigh << 64n) | low;
420
+ coefficient = BigInt(msd) * 1000000000000000000000000000000000n + coefficient;
421
+ }
422
+
423
+ // Remove bias
424
+ const unbias = Number(exponent) - DECIMAL128_BIAS;
425
+
426
+ // Build result string
427
+ const coeffStr = coefficient.toString();
428
+ const signStr = sign ? '-' : '';
429
+
430
+ // Special case: if coefficient is 0, just return "0"
431
+ if (coefficient === 0n) {
432
+ return signStr + '0';
433
+ }
434
+
435
+ if (unbias === 0) {
436
+ return signStr + coeffStr;
437
+ } else if (unbias > 0) {
438
+ return signStr + coeffStr + '0'.repeat(unbias);
439
+ } else {
440
+ const absExp = -unbias;
441
+ if (absExp >= coeffStr.length) {
442
+ return signStr + '0.' + '0'.repeat(absExp - coeffStr.length) + coeffStr;
443
+ } else {
444
+ const intPart = coeffStr.substring(0, coeffStr.length - absExp);
445
+ const fracPart = coeffStr.substring(coeffStr.length - absExp);
446
+ return signStr + intPart + '.' + fracPart;
447
+ }
448
+ }
449
+ }
450
+
451
+ /**
452
+ * Convert a BigInt to a Buffer (big-endian)
453
+ * @param {BigInt} value - The BigInt value
454
+ * @param {number} size - Buffer size in bytes
455
+ * @returns {Buffer}
456
+ */
457
+ function bigIntToBuffer(value, size) {
458
+ const buf = Buffer.alloc(size);
459
+ let val = BigInt(value.toString());
460
+ for (let i = size - 1; i >= 0; i--) {
461
+ buf[i] = Number(val & 0xFFn);
462
+ val >>= 8n;
463
+ }
464
+ return buf;
465
+ }
466
+
467
+ /**
468
+ * Convert a Buffer to BigInt (big-endian)
469
+ * @param {Buffer} buffer
470
+ * @returns {BigInt}
471
+ */
472
+ function bufferToBigInt(buffer) {
473
+ let result = 0n;
474
+ for (let i = 0; i < buffer.length; i++) {
475
+ result = (result << 8n) | BigInt(buffer[i]);
476
+ }
477
+ return result;
478
+ }
479
+
480
+ /**
481
+ * Write BigInt to buffer at offset (big-endian)
482
+ * @param {Buffer} buffer
483
+ * @param {BigInt} value
484
+ * @param {number} offset
485
+ * @param {number} size
486
+ */
487
+ function bufferWriteBigInt(buffer, value, offset, size) {
488
+ let val = BigInt(value.toString());
489
+ for (let i = offset + size - 1; i >= offset; i--) {
490
+ buffer[i] = Number(val & 0xFFn);
491
+ val >>= 8n;
492
+ }
493
+ }
494
+
495
+ module.exports = {
496
+ encodeDecimal64,
497
+ decodeDecimal64,
498
+ encodeDecimal128,
499
+ decodeDecimal128
500
+ };