0
# Buffer Reading and Writing
1
2
Core protocol buffer reading and writing functionality with support for all protocol buffer data types, packed fields, and direct buffer manipulation.
3
4
## Reading Operations
5
6
### Field-Level Reading
7
8
Read protocol buffer messages using field-based callbacks:
9
10
```typescript { .api }
11
class Pbf {
12
/**
13
* Read all fields in a message using a callback function
14
*/
15
readFields<T>(readField: (tag: number, result: T, pbf: Pbf) => void, result: T, end?: number): T;
16
17
/**
18
* Read an embedded message
19
*/
20
readMessage<T>(readField: (tag: number, result: T, pbf: Pbf) => void, result: T): T;
21
}
22
```
23
24
### Scalar Data Type Reading
25
26
Read individual data types from the buffer:
27
28
```typescript { .api }
29
class Pbf {
30
// Integer types
31
readVarint(isSigned?: boolean): number;
32
readSVarint(): number;
33
readFixed32(): number;
34
readSFixed32(): number;
35
readFixed64(): number;
36
readSFixed64(): number;
37
38
// Floating point types
39
readFloat(): number;
40
readDouble(): number;
41
42
// Other types
43
readBoolean(): boolean;
44
readString(): string;
45
readBytes(): Uint8Array;
46
47
// Legacy compatibility
48
readVarint64(): number;
49
50
// Internal helper for packed field reading
51
readPackedEnd(): number;
52
}
53
```
54
55
### Packed Field Reading
56
57
Read packed repeated fields efficiently:
58
59
```typescript { .api }
60
class Pbf {
61
readPackedVarint(arr?: number[], isSigned?: boolean): number[];
62
readPackedSVarint(arr?: number[]): number[];
63
readPackedBoolean(arr?: boolean[]): boolean[];
64
readPackedFloat(arr?: number[]): number[];
65
readPackedDouble(arr?: number[]): number[];
66
readPackedFixed32(arr?: number[]): number[];
67
readPackedSFixed32(arr?: number[]): number[];
68
readPackedFixed64(arr?: number[]): number[];
69
readPackedSFixed64(arr?: number[]): number[];
70
}
71
```
72
73
### Buffer Navigation
74
75
Control reading position and skip unwanted fields:
76
77
```typescript { .api }
78
class Pbf {
79
buf: Uint8Array; // Underlying buffer
80
dataView: DataView; // Data view for binary operations
81
pos: number; // Current reading/writing position
82
type: number; // Current field wire type
83
length: number; // Total buffer length
84
85
/**
86
* Skip a field value based on its wire type
87
*/
88
skip(val: number): void;
89
90
/**
91
* Internal helper method for packed field reading
92
* Determines the end position for packed field data
93
*/
94
readPackedEnd(): number;
95
}
96
```
97
98
## Writing Operations
99
100
### Buffer Management
101
102
Manage buffer allocation and finalization:
103
104
```typescript { .api }
105
class Pbf {
106
/**
107
* Ensure buffer has space for at least min bytes
108
*/
109
realloc(min: number): void;
110
111
/**
112
* Finalize buffer and return the written data
113
*/
114
finish(): Uint8Array;
115
116
/**
117
* Write a field tag and wire type
118
*/
119
writeTag(tag: number, type: number): void;
120
}
121
```
122
123
### Scalar Data Type Writing
124
125
Write individual data types to the buffer:
126
127
```typescript { .api }
128
class Pbf {
129
// Integer types
130
writeVarint(val: number): void;
131
writeSVarint(val: number): void;
132
writeFixed32(val: number): void;
133
writeSFixed32(val: number): void;
134
writeFixed64(val: number): void;
135
writeSFixed64(val: number): void;
136
137
// Floating point types
138
writeFloat(val: number): void;
139
writeDouble(val: number): void;
140
141
// Other types
142
writeBoolean(val: boolean): void;
143
writeString(str: string): void;
144
writeBytes(buffer: Uint8Array): void;
145
}
146
```
147
148
### Field Writing
149
150
Write fields with tags and wire types:
151
152
```typescript { .api }
153
class Pbf {
154
// Field writing with tags
155
writeVarintField(tag: number, val: number): void;
156
writeSVarintField(tag: number, val: number): void;
157
writeFixed32Field(tag: number, val: number): void;
158
writeSFixed32Field(tag: number, val: number): void;
159
writeFixed64Field(tag: number, val: number): void;
160
writeSFixed64Field(tag: number, val: number): void;
161
writeFloatField(tag: number, val: number): void;
162
writeDoubleField(tag: number, val: number): void;
163
writeBooleanField(tag: number, val: boolean): void;
164
writeStringField(tag: number, str: string): void;
165
writeBytesField(tag: number, buffer: Uint8Array): void;
166
}
167
```
168
169
### Message Writing
170
171
Write embedded messages and raw message data:
172
173
```typescript { .api }
174
class Pbf {
175
/**
176
* Write an embedded message with tag
177
*/
178
writeMessage<T>(tag: number, fn: (obj: T, pbf: Pbf) => void, obj: T): void;
179
180
/**
181
* Write a raw message without tag
182
*/
183
writeRawMessage<T>(fn: (obj: T, pbf: Pbf) => void, obj: T): void;
184
}
185
```
186
187
### Packed Field Writing
188
189
Write packed repeated fields efficiently:
190
191
```typescript { .api }
192
class Pbf {
193
writePackedVarint(tag: number, arr: number[]): void;
194
writePackedSVarint(tag: number, arr: number[]): void;
195
writePackedBoolean(tag: number, arr: boolean[]): void;
196
writePackedFloat(tag: number, arr: number[]): void;
197
writePackedDouble(tag: number, arr: number[]): void;
198
writePackedFixed32(tag: number, arr: number[]): void;
199
writePackedSFixed32(tag: number, arr: number[]): void;
200
writePackedFixed64(tag: number, arr: number[]): void;
201
writePackedSFixed64(tag: number, arr: number[]): void;
202
}
203
```
204
205
## Usage Examples
206
207
### Custom Reading
208
209
```typescript
210
const pbf = new Pbf(buffer);
211
const data = pbf.readFields(readDataField, {});
212
213
function readDataField(tag, data, pbf) {
214
if (tag === 1) data.name = pbf.readString();
215
else if (tag === 2) data.version = pbf.readVarint();
216
else if (tag === 3) data.tags = pbf.readPackedVarint(data.tags || []);
217
else if (tag === 4) {
218
data.metadata = pbf.readMessage(readMetadata, {});
219
}
220
}
221
222
function readMetadata(tag, metadata, pbf) {
223
if (tag === 1) metadata.author = pbf.readString();
224
else if (tag === 2) metadata.timestamp = pbf.readFixed64();
225
}
226
```
227
228
### Custom Writing
229
230
```typescript
231
const pbf = new Pbf();
232
writeData(data, pbf);
233
const buffer = pbf.finish();
234
235
function writeData(data, pbf) {
236
if (data.name) pbf.writeStringField(1, data.name);
237
if (data.version) pbf.writeVarintField(2, data.version);
238
if (data.tags && data.tags.length) pbf.writePackedVarint(3, data.tags);
239
if (data.metadata) pbf.writeMessage(4, writeMetadata, data.metadata);
240
}
241
242
function writeMetadata(metadata, pbf) {
243
if (metadata.author) pbf.writeStringField(1, metadata.author);
244
if (metadata.timestamp) pbf.writeFixed64Field(2, metadata.timestamp);
245
}
246
```
247
248
### Lazy Decoding
249
250
```typescript
251
const pbf = new Pbf(buffer);
252
let metadataPos = -1;
253
254
// First pass - save position of expensive field
255
pbf.readFields((tag, result, pbf) => {
256
if (tag === 1) result.name = pbf.readString();
257
else if (tag === 4) metadataPos = pbf.pos; // Save position, don't read yet
258
}, {});
259
260
// Later - decode the expensive field when needed
261
if (metadataPos >= 0) {
262
pbf.pos = metadataPos;
263
const metadata = pbf.readMessage(readMetadata, {});
264
}
265
```
266
267
## Wire Format Constants
268
269
```typescript { .api }
270
declare const PBF_VARINT: 0; // int32, int64, uint32, uint64, sint32, sint64, bool, enum
271
declare const PBF_FIXED64: 1; // double, fixed64, sfixed64
272
declare const PBF_BYTES: 2; // string, bytes, embedded messages, packed repeated fields
273
declare const PBF_FIXED32: 5; // float, fixed32, sfixed32
274
```