0
# Extensions
1
2
Custom MessagePack extensions and utility functions for specialized use cases, enabling support for custom data types and advanced functionality.
3
4
## Capabilities
5
6
### addExtension Function
7
8
Registers custom MessagePack extensions to handle specialized data types or implement custom serialization logic.
9
10
```javascript { .api }
11
/**
12
* Registers a custom MessagePack extension
13
* @param extension - Extension definition object
14
*/
15
function addExtension(extension: Extension): void;
16
17
interface Extension {
18
Class?: Function; // Constructor function to match
19
type?: number; // MessagePack extension type number (0-127)
20
pack?(value: any): Buffer | Uint8Array; // Custom packing function
21
unpack?(messagePack: Buffer | Uint8Array): any; // Custom unpacking function
22
read?(datum: any): any; // Read transformation
23
write?(instance: any): any; // Write transformation
24
}
25
```
26
27
**Usage Examples:**
28
29
```javascript
30
import { addExtension, pack, unpack } from "msgpackr";
31
32
// Custom Date extension with millisecond precision
33
addExtension({
34
type: 1,
35
Class: Date,
36
write: (date) => date.getTime(),
37
read: (timestamp) => new Date(timestamp)
38
});
39
40
// Usage
41
const now = new Date();
42
const packed = pack({ timestamp: now, message: "Hello" });
43
const unpacked = unpack(packed);
44
console.log(unpacked.timestamp instanceof Date); // true
45
46
// Custom class extension
47
class Point {
48
constructor(x, y) {
49
this.x = x;
50
this.y = y;
51
}
52
53
distance(other) {
54
return Math.sqrt((this.x - other.x) ** 2 + (this.y - other.y) ** 2);
55
}
56
}
57
58
addExtension({
59
type: 2,
60
Class: Point,
61
write: (point) => [point.x, point.y],
62
read: (coords) => new Point(coords[0], coords[1])
63
});
64
65
// Usage
66
const point = new Point(10, 20);
67
const packed = pack({ location: point });
68
const unpacked = unpack(packed);
69
console.log(unpacked.location instanceof Point); // true
70
console.log(unpacked.location.distance(new Point(0, 0))); // 22.36...
71
```
72
73
### Binary Data Extensions
74
75
Handling specialized binary data formats.
76
77
```javascript
78
import { addExtension } from "msgpackr";
79
80
// Custom binary format extension
81
addExtension({
82
type: 10,
83
pack: (value) => {
84
if (value && value.type === 'customBinary') {
85
return Buffer.from(value.data, 'base64');
86
}
87
},
88
unpack: (buffer) => ({
89
type: 'customBinary',
90
data: buffer.toString('base64'),
91
size: buffer.length
92
})
93
});
94
95
// UUID extension
96
addExtension({
97
type: 11,
98
pack: (value) => {
99
if (typeof value === 'string' && /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f-]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i.test(value)) {
100
return Buffer.from(value.replace(/-/g, ''), 'hex');
101
}
102
},
103
unpack: (buffer) => {
104
const hex = buffer.toString('hex');
105
return `${hex.slice(0,8)}-${hex.slice(8,12)}-${hex.slice(12,16)}-${hex.slice(16,20)}-${hex.slice(20,32)}`;
106
}
107
});
108
```
109
110
### Compression Extensions
111
112
Implementing compression for large data structures.
113
114
```javascript
115
import { addExtension } from "msgpackr";
116
import { gzipSync, gunzipSync } from "zlib";
117
118
// Compression extension for large objects
119
addExtension({
120
type: 20,
121
pack: (value) => {
122
if (value && value.compress === true) {
123
const json = JSON.stringify(value.data);
124
if (json.length > 1000) { // Only compress large objects
125
return gzipSync(Buffer.from(json));
126
}
127
}
128
},
129
unpack: (buffer) => {
130
const decompressed = gunzipSync(buffer);
131
return {
132
compress: true,
133
data: JSON.parse(decompressed.toString())
134
};
135
}
136
});
137
138
// Usage
139
const largeData = {
140
compress: true,
141
data: { /* large object */ }
142
};
143
144
const packed = pack(largeData); // Automatically compressed
145
const unpacked = unpack(packed); // Automatically decompressed
146
```
147
148
### clearSource Function
149
150
Clears internal source buffer references to free memory and prevent memory leaks.
151
152
```javascript { .api }
153
/**
154
* Clears internal source buffer references
155
* Useful for memory management in long-running applications
156
*/
157
function clearSource(): void;
158
```
159
160
**Usage Examples:**
161
162
```javascript
163
import { unpack, clearSource } from "msgpackr";
164
165
// Process large amounts of data
166
for (let i = 0; i < 10000; i++) {
167
const data = unpack(someBuffer);
168
processData(data);
169
170
// Periodically clear source references to prevent memory buildup
171
if (i % 1000 === 0) {
172
clearSource();
173
}
174
}
175
176
// Clear after batch processing
177
function processBatch(buffers) {
178
const results = buffers.map(buffer => unpack(buffer));
179
clearSource(); // Free memory after batch
180
return results;
181
}
182
```
183
184
### roundFloat32 Function
185
186
Rounds a number to float32 precision, useful for ensuring consistent floating-point behavior.
187
188
```javascript { .api }
189
/**
190
* Rounds a number to float32 precision
191
* @param float32Number - Number to round to float32 precision
192
* @returns Number rounded to float32 precision
193
*/
194
function roundFloat32(float32Number: number): number;
195
```
196
197
**Usage Examples:**
198
199
```javascript
200
import { roundFloat32, pack, unpack, FLOAT32_OPTIONS, Packr } from "msgpackr";
201
202
// Manual float32 rounding
203
const preciseNumber = 1.23456789012345;
204
const rounded = roundFloat32(preciseNumber);
205
console.log(rounded); // 1.2345678806304932 (float32 precision)
206
207
// Use with float32 packing
208
const packr = new Packr({ useFloat32: FLOAT32_OPTIONS.ALWAYS });
209
210
const data = {
211
value1: roundFloat32(3.14159265359),
212
value2: roundFloat32(2.71828182846)
213
};
214
215
const packed = packr.pack(data);
216
const unpacked = packr.unpack(packed);
217
218
// Verify consistency
219
console.log(data.value1 === unpacked.value1); // true
220
221
// Precision comparison
222
function compareFloatPrecision(original) {
223
const float32Rounded = roundFloat32(original);
224
const packed = pack(original);
225
const unpacked = unpack(packed);
226
227
console.log('Original:', original);
228
console.log('Float32 rounded:', float32Rounded);
229
console.log('Pack/unpack result:', unpacked);
230
}
231
232
compareFloatPrecision(Math.PI);
233
```
234
235
## Advanced Extension Patterns
236
237
### Conditional Extensions
238
239
Extensions that apply based on runtime conditions.
240
241
```javascript
242
import { addExtension } from "msgpackr";
243
244
// Environment-specific extension
245
addExtension({
246
type: 30,
247
pack: (value) => {
248
if (value && value.type === 'encrypted' && process.env.NODE_ENV === 'production') {
249
return encryptData(value.data);
250
}
251
},
252
unpack: (buffer) => {
253
if (process.env.NODE_ENV === 'production') {
254
return {
255
type: 'encrypted',
256
data: decryptData(buffer)
257
};
258
}
259
}
260
});
261
262
// Size-based extension
263
addExtension({
264
type: 31,
265
pack: (value) => {
266
if (Array.isArray(value) && value.length > 1000) {
267
// Use special encoding for large arrays
268
return Buffer.concat([
269
Buffer.from([0x01]), // Format marker
270
Buffer.from(JSON.stringify(value.length)),
271
...value.map(item => Buffer.from(JSON.stringify(item)))
272
]);
273
}
274
},
275
unpack: (buffer) => {
276
if (buffer[0] === 0x01) {
277
// Decode special large array format
278
// Implementation would parse the custom format
279
}
280
}
281
});
282
```
283
284
### Versioned Extensions
285
286
Extensions that handle different data format versions.
287
288
```javascript
289
import { addExtension } from "msgpackr";
290
291
// Versioned data extension
292
addExtension({
293
type: 40,
294
pack: (value) => {
295
if (value && value._version) {
296
const version = Buffer.from([value._version]);
297
const data = Buffer.from(JSON.stringify(value.data));
298
return Buffer.concat([version, data]);
299
}
300
},
301
unpack: (buffer) => {
302
const version = buffer[0];
303
const data = JSON.parse(buffer.slice(1).toString());
304
305
// Handle different versions
306
switch (version) {
307
case 1:
308
return { _version: 1, data: upgradeV1ToV2(data) };
309
case 2:
310
return { _version: 2, data };
311
default:
312
throw new Error(`Unsupported version: ${version}`);
313
}
314
}
315
});
316
```
317
318
### Performance-Optimized Extensions
319
320
Extensions designed for maximum performance.
321
322
```javascript
323
import { addExtension } from "msgpackr";
324
325
// High-performance binary data extension
326
const binaryPool = new Map(); // Reuse buffers
327
328
addExtension({
329
type: 50,
330
pack: (value) => {
331
if (value instanceof Uint8Array) {
332
// Direct binary pass-through for optimal performance
333
return value;
334
}
335
},
336
unpack: (buffer) => {
337
// Reuse typed array views for better performance
338
const key = buffer.length;
339
if (!binaryPool.has(key)) {
340
binaryPool.set(key, new Uint8Array(key));
341
}
342
343
const result = binaryPool.get(key);
344
result.set(buffer);
345
return result;
346
}
347
});
348
349
// Fast string interning extension
350
const stringInternMap = new Map();
351
let stringId = 0;
352
353
addExtension({
354
type: 51,
355
pack: (value) => {
356
if (typeof value === 'string' && value.length > 20) {
357
if (!stringInternMap.has(value)) {
358
stringInternMap.set(value, stringId++);
359
}
360
const id = stringInternMap.get(value);
361
return Buffer.from([id & 0xFF, (id >> 8) & 0xFF]);
362
}
363
},
364
unpack: (buffer) => {
365
const id = buffer[0] | (buffer[1] << 8);
366
// Reverse lookup would need additional data structure
367
// This is a simplified example
368
return `interned_string_${id}`;
369
}
370
});
371
```
372
373
## Constants and Utilities
374
375
### Acceleration Status
376
377
Check if native acceleration is available and enabled.
378
379
```javascript { .api }
380
/**
381
* Indicates whether native acceleration (msgpackr-extract) is enabled
382
*/
383
let isNativeAccelerationEnabled: boolean;
384
```
385
386
**Usage Examples:**
387
388
```javascript
389
import { isNativeAccelerationEnabled } from "msgpackr";
390
391
console.log('Native acceleration:', isNativeAccelerationEnabled);
392
393
if (isNativeAccelerationEnabled) {
394
console.log('Using optimized native implementation');
395
} else {
396
console.log('Using pure JavaScript implementation');
397
}
398
399
// Conditional configuration based on acceleration
400
const options = {
401
useRecords: true,
402
// Use more aggressive optimizations if native acceleration is available
403
sequential: isNativeAccelerationEnabled,
404
bundleStrings: isNativeAccelerationEnabled
405
};
406
```
407
408
### Special Constants
409
410
Special constant objects used internally by msgpackr.
411
412
```javascript { .api }
413
/**
414
* Internal constant object used by msgpackr
415
*/
416
const C1: {};
417
```
418
419
This constant is primarily for internal use and typically not needed in application code.