0
# Binary I/O Operations
1
2
Low-level binary reading and writing operations for custom serialization needs, performance optimization, and direct protobuf wire format manipulation.
3
4
## Capabilities
5
6
### Writer Class
7
8
Binary writer for encoding protobuf wire format data with buffering and type-specific encoding methods.
9
10
```javascript { .api }
11
class Writer {
12
/**
13
* Current length of written data
14
*/
15
len: number;
16
17
/**
18
* Operation head (internal)
19
*/
20
head: Operation;
21
22
/**
23
* Operation tail (internal)
24
*/
25
tail: Operation;
26
27
/**
28
* State stack for nested operations
29
*/
30
states: State[];
31
32
/**
33
* Creates a new writer instance
34
* @returns Writer instance
35
*/
36
static create(): Writer;
37
38
/**
39
* Writes unsigned 32-bit integer
40
* @param value - Value to write (0 to 4294967295)
41
* @returns This writer
42
*/
43
uint32(value: number): Writer;
44
45
/**
46
* Writes signed 32-bit integer
47
* @param value - Value to write (-2147483648 to 2147483647)
48
* @returns This writer
49
*/
50
int32(value: number): Writer;
51
52
/**
53
* Writes signed zigzag-encoded 32-bit integer
54
* @param value - Value to write
55
* @returns This writer
56
*/
57
sint32(value: number): Writer;
58
59
/**
60
* Writes unsigned 64-bit integer
61
* @param value - Value as number or Long
62
* @returns This writer
63
*/
64
uint64(value: number | Long | string): Writer;
65
66
/**
67
* Writes signed 64-bit integer
68
* @param value - Value as number or Long
69
* @returns This writer
70
*/
71
int64(value: number | Long | string): Writer;
72
73
/**
74
* Writes signed zigzag-encoded 64-bit integer
75
* @param value - Value as number or Long
76
* @returns This writer
77
*/
78
sint64(value: number | Long | string): Writer;
79
80
/**
81
* Writes fixed 32-bit unsigned integer (little endian)
82
* @param value - Value to write
83
* @returns This writer
84
*/
85
fixed32(value: number): Writer;
86
87
/**
88
* Writes fixed 32-bit signed integer (little endian)
89
* @param value - Value to write
90
* @returns This writer
91
*/
92
sfixed32(value: number): Writer;
93
94
/**
95
* Writes fixed 64-bit unsigned integer (little endian)
96
* @param value - Value as number or Long
97
* @returns This writer
98
*/
99
fixed64(value: number | Long | string): Writer;
100
101
/**
102
* Writes fixed 64-bit signed integer (little endian)
103
* @param value - Value as number or Long
104
* @returns This writer
105
*/
106
sfixed64(value: number | Long | string): Writer;
107
108
/**
109
* Writes 32-bit float (IEEE 754)
110
* @param value - Float value
111
* @returns This writer
112
*/
113
float(value: number): Writer;
114
115
/**
116
* Writes 64-bit double (IEEE 754)
117
* @param value - Double value
118
* @returns This writer
119
*/
120
double(value: number): Writer;
121
122
/**
123
* Writes boolean value
124
* @param value - Boolean value
125
* @returns This writer
126
*/
127
bool(value: boolean): Writer;
128
129
/**
130
* Writes string value (UTF-8 encoded)
131
* @param value - String value
132
* @returns This writer
133
*/
134
string(value: string): Writer;
135
136
/**
137
* Writes byte array
138
* @param value - Byte array
139
* @returns This writer
140
*/
141
bytes(value: Uint8Array | string): Writer;
142
143
/**
144
* Writes protobuf tag (field number and wire type)
145
* @param id - Field id
146
* @param wireType - Wire type
147
* @returns This writer
148
*/
149
tag(id: number, wireType: number): Writer;
150
151
/**
152
* Forks this writer (creates nested length-delimited context)
153
* @returns Forked writer
154
*/
155
fork(): Writer;
156
157
/**
158
* Resets writer to initial state
159
* @returns This writer
160
*/
161
reset(): Writer;
162
163
/**
164
* Finishes length-delimited context
165
* @returns This writer
166
*/
167
ldelim(): Writer;
168
169
/**
170
* Finishes writing and returns buffer
171
* @returns Encoded binary data
172
*/
173
finish(): Uint8Array;
174
}
175
```
176
177
**Usage Examples:**
178
179
```javascript
180
const protobuf = require("protobufjs");
181
182
// Basic writer usage
183
const writer = protobuf.Writer.create();
184
writer.tag(1, 2) // Field 1, length-delimited
185
.string("hello") // String value
186
.tag(2, 0) // Field 2, varint
187
.uint32(42); // Integer value
188
189
const buffer = writer.finish();
190
console.log("Encoded bytes:", Array.from(buffer));
191
192
// Length-delimited message writing
193
const writer2 = protobuf.Writer.create();
194
writer2.tag(1, 2); // Field 1, length-delimited
195
196
const fork = writer2.fork(); // Start nested message
197
fork.tag(1, 2).string("nested");
198
fork.tag(2, 0).uint32(123);
199
writer2.ldelim(); // Finish nested message
200
201
const nestedBuffer = writer2.finish();
202
```
203
204
### BufferWriter Class
205
206
Node.js-specific writer that outputs Node.js Buffer instead of Uint8Array.
207
208
```javascript { .api }
209
class BufferWriter extends Writer {
210
/**
211
* Finishes writing and returns Node.js Buffer
212
* @returns Encoded binary data as Buffer
213
*/
214
finish(): Buffer;
215
}
216
```
217
218
**Usage Examples:**
219
220
```javascript
221
// Node.js specific buffer writing
222
const writer = new protobuf.BufferWriter();
223
writer.tag(1, 2).string("test");
224
const buffer = writer.finish();
225
console.log("Buffer type:", buffer instanceof Buffer); // true
226
```
227
228
### Reader Class
229
230
Binary reader for decoding protobuf wire format data with position tracking and type-specific decoding methods.
231
232
```javascript { .api }
233
class Reader {
234
/**
235
* Source buffer
236
*/
237
buf: Uint8Array;
238
239
/**
240
* Current reading position
241
*/
242
pos: number;
243
244
/**
245
* Buffer length
246
*/
247
len: number;
248
249
/**
250
* Creates reader from buffer
251
* @param buffer - Buffer to read from
252
* @returns Reader instance
253
*/
254
static create(buffer: Uint8Array): Reader;
255
256
/**
257
* Reads unsigned 32-bit integer
258
* @returns Decoded value
259
*/
260
uint32(): number;
261
262
/**
263
* Reads signed 32-bit integer
264
* @returns Decoded value
265
*/
266
int32(): number;
267
268
/**
269
* Reads signed zigzag-decoded 32-bit integer
270
* @returns Decoded value
271
*/
272
sint32(): number;
273
274
/**
275
* Reads unsigned 64-bit integer
276
* @returns Decoded value as Long
277
*/
278
uint64(): Long;
279
280
/**
281
* Reads signed 64-bit integer
282
* @returns Decoded value as Long
283
*/
284
int64(): Long;
285
286
/**
287
* Reads signed zigzag-decoded 64-bit integer
288
* @returns Decoded value as Long
289
*/
290
sint64(): Long;
291
292
/**
293
* Reads fixed 32-bit unsigned integer (little endian)
294
* @returns Decoded value
295
*/
296
fixed32(): number;
297
298
/**
299
* Reads fixed 32-bit signed integer (little endian)
300
* @returns Decoded value
301
*/
302
sfixed32(): number;
303
304
/**
305
* Reads fixed 64-bit unsigned integer (little endian)
306
* @returns Decoded value as Long
307
*/
308
fixed64(): Long;
309
310
/**
311
* Reads fixed 64-bit signed integer (little endian)
312
* @returns Decoded value as Long
313
*/
314
sfixed64(): Long;
315
316
/**
317
* Reads 32-bit float (IEEE 754)
318
* @returns Decoded float value
319
*/
320
float(): number;
321
322
/**
323
* Reads 64-bit double (IEEE 754)
324
* @returns Decoded double value
325
*/
326
double(): number;
327
328
/**
329
* Reads boolean value
330
* @returns Decoded boolean
331
*/
332
bool(): boolean;
333
334
/**
335
* Reads string value (UTF-8 decoded)
336
* @returns Decoded string
337
*/
338
string(): string;
339
340
/**
341
* Reads byte array
342
* @returns Decoded bytes
343
*/
344
bytes(): Uint8Array;
345
346
/**
347
* Reads protobuf tag
348
* @returns Object with id and wireType properties
349
*/
350
tag(): { id: number; wireType: number };
351
352
/**
353
* Skips specified number of bytes
354
* @param length - Number of bytes to skip
355
* @returns This reader
356
*/
357
skip(length: number): Reader;
358
359
/**
360
* Skips value of specified wire type
361
* @param wireType - Wire type to skip
362
* @returns This reader
363
*/
364
skipType(wireType: number): Reader;
365
}
366
```
367
368
**Usage Examples:**
369
370
```javascript
371
// Basic reader usage
372
const reader = protobuf.Reader.create(buffer);
373
374
while (reader.pos < reader.len) {
375
const tag = reader.tag();
376
console.log(`Field ${tag.id}, wireType ${tag.wireType}`);
377
378
switch (tag.wireType) {
379
case 0: // varint
380
const value = reader.uint32();
381
console.log("Varint value:", value);
382
break;
383
case 2: // length-delimited
384
const bytes = reader.bytes();
385
console.log("Bytes length:", bytes.length);
386
break;
387
default:
388
reader.skipType(tag.wireType);
389
}
390
}
391
392
// Manual message decoding
393
function decodeMessage(buffer) {
394
const reader = protobuf.Reader.create(buffer);
395
const message = {};
396
397
while (reader.pos < reader.len) {
398
const tag = reader.tag();
399
400
switch (tag.id) {
401
case 1:
402
message.name = reader.string();
403
break;
404
case 2:
405
message.id = reader.uint32();
406
break;
407
default:
408
reader.skipType(tag.wireType);
409
}
410
}
411
412
return message;
413
}
414
```
415
416
### BufferReader Class
417
418
Node.js-specific reader for reading from Node.js Buffer objects.
419
420
```javascript { .api }
421
class BufferReader extends Reader {
422
/**
423
* Source buffer as Node.js Buffer
424
*/
425
buf: Buffer;
426
427
/**
428
* Creates reader from Node.js Buffer
429
* @param buffer - Buffer to read from
430
* @returns BufferReader instance
431
*/
432
static create(buffer: Buffer): BufferReader;
433
}
434
```
435
436
### Wire Type Constants
437
438
Protobuf wire type constants for low-level operations.
439
440
```javascript { .api }
441
namespace WireType {
442
const Varint: 0; // int32, int64, uint32, uint64, sint32, sint64, bool, enum
443
const Fixed64: 1; // fixed64, sfixed64, double
444
const LengthDelimited: 2; // string, bytes, embedded messages, packed repeated fields
445
const StartGroup: 3; // deprecated
446
const EndGroup: 4; // deprecated
447
const Fixed32: 5; // fixed32, sfixed32, float
448
}
449
```
450
451
**Usage Examples:**
452
453
```javascript
454
// Using wire type constants
455
const writer = protobuf.Writer.create();
456
457
// Write string field (field 1)
458
writer.tag(1, protobuf.util.WireType.LengthDelimited);
459
writer.string("hello world");
460
461
// Write integer field (field 2)
462
writer.tag(2, protobuf.util.WireType.Varint);
463
writer.uint32(42);
464
465
// Write float field (field 3)
466
writer.tag(3, protobuf.util.WireType.Fixed32);
467
writer.float(3.14);
468
```
469
470
### Advanced Operations
471
472
Advanced binary I/O operations for complex use cases.
473
474
```javascript { .api }
475
class Writer {
476
/**
477
* Writes raw buffer data
478
* @param buffer - Raw buffer to write
479
* @returns This writer
480
*/
481
raw(buffer: Uint8Array): Writer;
482
483
/**
484
* Gets current operation state
485
* @returns Current state object
486
*/
487
state(): State;
488
489
/**
490
* Pushes new state onto stack
491
* @param state - State to push
492
* @returns This writer
493
*/
494
push(state: State): Writer;
495
496
/**
497
* Pops state from stack
498
* @returns Popped state
499
*/
500
pop(): State;
501
}
502
503
class Reader {
504
/**
505
* Creates sub-reader for specified length
506
* @param length - Length of sub-buffer
507
* @returns New reader for sub-buffer
508
*/
509
slice(length: number): Reader;
510
511
/**
512
* Reads remaining bytes
513
* @returns All remaining bytes
514
*/
515
remaining(): Uint8Array;
516
}
517
```
518
519
**Usage Examples:**
520
521
```javascript
522
// Advanced writer operations
523
const writer = protobuf.Writer.create();
524
525
// Write custom data format
526
const customData = new Uint8Array([0x01, 0x02, 0x03]);
527
writer.tag(1, 2); // Length-delimited
528
writer.uint32(customData.length); // Length prefix
529
writer.raw(customData); // Raw data
530
531
// Complex nested structures
532
const fork1 = writer.fork();
533
fork1.tag(1, 2).string("level1");
534
535
const fork2 = fork1.fork();
536
fork2.tag(1, 2).string("level2");
537
fork1.ldelim(); // Close level2
538
539
writer.ldelim(); // Close level1
540
541
// Advanced reader operations
542
const reader = protobuf.Reader.create(buffer);
543
const tag = reader.tag();
544
545
if (tag.wireType === 2) { // Length-delimited
546
const length = reader.uint32();
547
const subReader = reader.slice(length);
548
549
// Process sub-message with dedicated reader
550
while (subReader.pos < subReader.len) {
551
const subTag = subReader.tag();
552
// Process sub-fields...
553
}
554
}
555
```
556
557
## Types
558
559
```javascript { .api }
560
interface Operation {
561
fn: Function;
562
len: number;
563
next: Operation | null;
564
}
565
566
interface State {
567
head: Operation;
568
tail: Operation;
569
len: number;
570
}
571
572
interface Long {
573
low: number;
574
high: number;
575
unsigned: boolean;
576
toNumber(): number;
577
toString(): string;
578
}
579
580
namespace util {
581
namespace WireType {
582
const Varint: 0;
583
const Fixed64: 1;
584
const LengthDelimited: 2;
585
const StartGroup: 3;
586
const EndGroup: 4;
587
const Fixed32: 5;
588
}
589
}
590
```