0
# Binary Data Parsing
1
2
Specialized parsers for binary data formats, buffers, and bit-level operations. These parsers work with Node.js Buffer objects and provide precise control over binary data interpretation.
3
4
## Capabilities
5
6
### Basic Binary Parsers
7
8
Fundamental parsers for binary data structures.
9
10
```javascript { .api }
11
/**
12
* Parse a specific byte value
13
* @param {number} b - Byte value to match (0-255)
14
* @returns {Parser} Parser that matches the specific byte
15
*/
16
Parsimmon.Binary.byte(b);
17
18
/**
19
* Parse a buffer of specified length
20
* @param {number} length - Number of bytes to read
21
* @returns {Parser} Parser that returns Buffer of specified length
22
*/
23
Parsimmon.Binary.buffer(length);
24
25
/**
26
* Parse an encoded string of specified length
27
* @param {string} encoding - Character encoding (utf8, ascii, etc.)
28
* @param {number} length - Number of bytes to read
29
* @returns {Parser} Parser that returns decoded string
30
*/
31
Parsimmon.Binary.encodedString(encoding, length);
32
```
33
34
**Usage Examples:**
35
36
```javascript
37
// Parse specific bytes
38
const magicNumber = Parsimmon.Binary.byte(0x89)
39
.then(Parsimmon.Binary.byte(0x50))
40
.then(Parsimmon.Binary.byte(0x4E))
41
.then(Parsimmon.Binary.byte(0x47));
42
43
// Parse PNG signature
44
const pngSig = Parsimmon.seq(
45
Parsimmon.Binary.byte(0x89),
46
Parsimmon.Binary.byte(0x50),
47
Parsimmon.Binary.byte(0x4E),
48
Parsimmon.Binary.byte(0x47),
49
Parsimmon.Binary.byte(0x0D),
50
Parsimmon.Binary.byte(0x0A),
51
Parsimmon.Binary.byte(0x1A),
52
Parsimmon.Binary.byte(0x0A)
53
);
54
55
// Parse raw buffer data
56
const header = Parsimmon.Binary.buffer(16);
57
const data = header.parse(someBuffer);
58
59
// Parse encoded strings
60
const utf8String = Parsimmon.Binary.encodedString("utf8", 10);
61
const asciiString = Parsimmon.Binary.encodedString("ascii", 20);
62
```
63
64
### Integer Parsers
65
66
Parsers for various integer formats with different endianness.
67
68
```javascript { .api }
69
/**
70
* Parse unsigned big-endian integer
71
* @param {number} length - Byte length (1-6)
72
* @returns {Parser} Parser that returns unsigned integer
73
*/
74
Parsimmon.Binary.uintBE(length);
75
76
/**
77
* Parse unsigned little-endian integer
78
* @param {number} length - Byte length (1-6)
79
* @returns {Parser} Parser that returns unsigned integer
80
*/
81
Parsimmon.Binary.uintLE(length);
82
83
/**
84
* Parse signed big-endian integer
85
* @param {number} length - Byte length (1-6)
86
* @returns {Parser} Parser that returns signed integer
87
*/
88
Parsimmon.Binary.intBE(length);
89
90
/**
91
* Parse signed little-endian integer
92
* @param {number} length - Byte length (1-6)
93
* @returns {Parser} Parser that returns signed integer
94
*/
95
Parsimmon.Binary.intLE(length);
96
```
97
98
**Pre-defined Integer Parsers:**
99
100
```javascript { .api }
101
// Unsigned big-endian
102
Parsimmon.Binary.uint8BE; // 1-byte unsigned
103
Parsimmon.Binary.uint16BE; // 2-byte unsigned
104
Parsimmon.Binary.uint32BE; // 4-byte unsigned
105
106
// Unsigned little-endian
107
Parsimmon.Binary.uint8LE; // 1-byte unsigned
108
Parsimmon.Binary.uint16LE; // 2-byte unsigned
109
Parsimmon.Binary.uint32LE; // 4-byte unsigned
110
111
// Signed big-endian
112
Parsimmon.Binary.int8BE; // 1-byte signed
113
Parsimmon.Binary.int16BE; // 2-byte signed
114
Parsimmon.Binary.int32BE; // 4-byte signed
115
116
// Signed little-endian
117
Parsimmon.Binary.int8LE; // 1-byte signed
118
Parsimmon.Binary.int16LE; // 2-byte signed
119
Parsimmon.Binary.int32LE; // 4-byte signed
120
```
121
122
**Usage Examples:**
123
124
```javascript
125
// Parse various integer sizes
126
const header = Parsimmon.seqObj(
127
["magic", Parsimmon.Binary.uint32BE],
128
["version", Parsimmon.Binary.uint16BE],
129
["flags", Parsimmon.Binary.uint8BE],
130
["count", Parsimmon.Binary.uint32LE]
131
);
132
133
// Parse file header with mixed endianness
134
const fileHeader = Parsimmon.seqMap(
135
Parsimmon.Binary.uint32BE, // File size (big-endian)
136
Parsimmon.Binary.uint16LE, // Format version (little-endian)
137
Parsimmon.Binary.uint16BE, // Flags (big-endian)
138
(size, version, flags) => ({ size, version, flags })
139
);
140
141
// Parse signed values
142
const coordinate = Parsimmon.seqMap(
143
Parsimmon.Binary.int16BE,
144
Parsimmon.Binary.int16BE,
145
(x, y) => ({ x, y })
146
);
147
```
148
149
### Floating Point Parsers
150
151
Parsers for IEEE 754 floating point numbers.
152
153
```javascript { .api }
154
/**
155
* Parse 32-bit big-endian float
156
* @returns {Parser} Parser that returns 32-bit float
157
*/
158
Parsimmon.Binary.floatBE();
159
160
/**
161
* Parse 32-bit little-endian float
162
* @returns {Parser} Parser that returns 32-bit float
163
*/
164
Parsimmon.Binary.floatLE();
165
166
/**
167
* Parse 64-bit big-endian double
168
* @returns {Parser} Parser that returns 64-bit double
169
*/
170
Parsimmon.Binary.doubleBE();
171
172
/**
173
* Parse 64-bit little-endian double
174
* @returns {Parser} Parser that returns 64-bit double
175
*/
176
Parsimmon.Binary.doubleLE();
177
```
178
179
**Usage Examples:**
180
181
```javascript
182
// Parse 3D coordinates as floats
183
const vertex = Parsimmon.seqMap(
184
Parsimmon.Binary.floatLE(),
185
Parsimmon.Binary.floatLE(),
186
Parsimmon.Binary.floatLE(),
187
(x, y, z) => ({ x, y, z })
188
);
189
190
// Parse scientific data with doubles
191
const measurement = Parsimmon.seqObj(
192
["timestamp", Parsimmon.Binary.doubleBE()],
193
["value", Parsimmon.Binary.doubleBE()],
194
["error", Parsimmon.Binary.floatBE()]
195
);
196
197
// Parse mixed numeric data
198
const record = Parsimmon.seqMap(
199
Parsimmon.Binary.uint32BE, // ID
200
Parsimmon.Binary.floatLE(), // Temperature
201
Parsimmon.Binary.floatLE(), // Humidity
202
Parsimmon.Binary.doubleBE(), // Timestamp
203
(id, temp, humidity, time) => ({
204
id, temperature: temp, humidity, timestamp: time
205
})
206
);
207
```
208
209
### Bit-level Parsing
210
211
Advanced parsers for bit-level data manipulation.
212
213
```javascript { .api }
214
/**
215
* Parse sequence of bit fields
216
* @param {number[]} alignments - Array of bit counts for each field
217
* @returns {Parser} Parser that returns array of bit field values
218
*/
219
Parsimmon.Binary.bitSeq(alignments);
220
221
/**
222
* Parse bit fields into named object
223
* @param {Array} namedAlignments - Array of [name, bits] pairs or bit counts
224
* @returns {Parser} Parser that returns object with named bit fields
225
*/
226
Parsimmon.Binary.bitSeqObj(namedAlignments);
227
```
228
229
**Usage Examples:**
230
231
```javascript
232
// Parse IP header flags (3 bits total)
233
const ipFlags = Parsimmon.Binary.bitSeq([1, 1, 1]); // Reserved, DF, MF
234
ipFlags.parse(Buffer.from([0x40])); // [0, 1, 0] - Don't Fragment set
235
236
// Parse bit fields with names
237
const tcpFlags = Parsimmon.Binary.bitSeqObj([
238
["fin", 1],
239
["syn", 1],
240
["rst", 1],
241
["psh", 1],
242
["ack", 1],
243
["urg", 1],
244
["ece", 1],
245
["cwr", 1]
246
]);
247
248
// Parse complex bit structures
249
const bitmapHeader = Parsimmon.Binary.bitSeqObj([
250
["signature", 16],
251
["fileSize", 32],
252
4, // reserved
253
4, // reserved
254
["dataOffset", 32]
255
]);
256
257
// Parse packed data structures
258
const packedCoord = Parsimmon.Binary.bitSeqObj([
259
["x", 10], // X coordinate (10 bits)
260
["y", 10], // Y coordinate (10 bits)
261
["z", 10], // Z coordinate (10 bits)
262
["flags", 2] // Status flags (2 bits)
263
]);
264
```
265
266
### Binary Data Validation
267
268
Examples of validating binary data during parsing.
269
270
**Usage Examples:**
271
272
```javascript
273
// Validate magic numbers
274
const validateMagic = (expected) => (value) => {
275
if (value === expected) return Parsimmon.succeed(value);
276
return Parsimmon.fail(`expected magic ${expected.toString(16)}, got ${value.toString(16)}`);
277
};
278
279
const jpegHeader = Parsimmon.Binary.uint16BE
280
.chain(validateMagic(0xFFD8))
281
.desc("JPEG magic number");
282
283
// Validate ranges
284
const validateRange = (min, max) => (value) => {
285
if (value >= min && value <= max) return Parsimmon.succeed(value);
286
return Parsimmon.fail(`value ${value} out of range [${min}, ${max}]`);
287
};
288
289
const rgbColor = Parsimmon.seqMap(
290
Parsimmon.Binary.uint8BE.chain(validateRange(0, 255)),
291
Parsimmon.Binary.uint8BE.chain(validateRange(0, 255)),
292
Parsimmon.Binary.uint8BE.chain(validateRange(0, 255)),
293
(r, g, b) => ({ r, g, b })
294
);
295
296
// Parse with length validation
297
const lengthPrefixedString = Parsimmon.Binary.uint16BE.chain(length => {
298
if (length > 1024) return Parsimmon.fail("string too long");
299
return Parsimmon.Binary.encodedString("utf8", length);
300
});
301
302
// Parse arrays with count
303
const parseArray = (elementParser) => {
304
return Parsimmon.Binary.uint32BE.chain(count => {
305
if (count > 10000) return Parsimmon.fail("array too large");
306
return elementParser.times(count);
307
});
308
};
309
310
const intArray = parseArray(Parsimmon.Binary.int32BE);
311
```
312
313
### Complex Binary Structures
314
315
Examples of parsing complex binary file formats.
316
317
**Usage Examples:**
318
319
```javascript
320
// Parse TGA image header
321
const tgaHeader = Parsimmon.seqObj(
322
["idLength", Parsimmon.Binary.uint8BE],
323
["colorMapType", Parsimmon.Binary.uint8BE],
324
["imageType", Parsimmon.Binary.uint8BE],
325
["colorMapSpec", Parsimmon.seqObj(
326
["firstEntryIndex", Parsimmon.Binary.uint16LE],
327
["colorMapLength", Parsimmon.Binary.uint16LE],
328
["colorMapEntrySize", Parsimmon.Binary.uint8BE]
329
)],
330
["imageSpec", Parsimmon.seqObj(
331
["xOrigin", Parsimmon.Binary.uint16LE],
332
["yOrigin", Parsimmon.Binary.uint16LE],
333
["width", Parsimmon.Binary.uint16LE],
334
["height", Parsimmon.Binary.uint16LE],
335
["pixelDepth", Parsimmon.Binary.uint8BE],
336
["imageDescriptor", Parsimmon.Binary.uint8BE]
337
)]
338
);
339
340
// Parse WAV file header
341
const wavHeader = Parsimmon.seqObj(
342
["riff", Parsimmon.Binary.buffer(4)], // "RIFF"
343
["fileSize", Parsimmon.Binary.uint32LE],
344
["wave", Parsimmon.Binary.buffer(4)], // "WAVE"
345
["fmt", Parsimmon.Binary.buffer(4)], // "fmt "
346
["fmtSize", Parsimmon.Binary.uint32LE],
347
["audioFormat", Parsimmon.Binary.uint16LE],
348
["numChannels", Parsimmon.Binary.uint16LE],
349
["sampleRate", Parsimmon.Binary.uint32LE],
350
["byteRate", Parsimmon.Binary.uint32LE],
351
["blockAlign", Parsimmon.Binary.uint16LE],
352
["bitsPerSample", Parsimmon.Binary.uint16LE]
353
);
354
355
// Parse network packet
356
const ethernetFrame = Parsimmon.seqObj(
357
["destination", Parsimmon.Binary.buffer(6)],
358
["source", Parsimmon.Binary.buffer(6)],
359
["etherType", Parsimmon.Binary.uint16BE],
360
["payload", Parsimmon.Binary.buffer(46)] // Minimum payload
361
);
362
```