or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

advanced-classes.mdcore-operations.mdextensions.mdindex.mditerators.mdstreaming.md

extensions.mddocs/

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.