Skip to content

Merge in upstream binary-parser #18

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 92 commits into from
Nov 23, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
92 commits
Select commit Hold shift + click to select a range
0b4df23
JPG example should use assert, not validate
Simran-B Apr 23, 2018
85343d3
Convert to TS sources (#97)
Jun 2, 2019
a5accfc
Refactor Circle CI config
keichi Jun 2, 2019
4f3030e
Enable CircleCI workflow
keichi Jun 2, 2019
92dbe63
Collect test results
keichi Jun 2, 2019
667a30c
Merge pull request #99 from keichi/update-ci
keichi Jun 2, 2019
2374852
Publish from CircleCI
keichi Jun 2, 2019
51145ed
Fix YAML syntax error
keichi Jun 2, 2019
ecbfb29
Merge pull request #100 from keichi/ci-publish-npm
keichi Jun 2, 2019
cdea039
Bump to 1.3.3
keichi Jun 2, 2019
17f660d
Fix typo in CircleCI config
keichi Jun 2, 2019
0a83485
Trying to publish from CircleCI...
keichi Jun 2, 2019
e74c67f
statically declare all parser methods
Jun 2, 2019
b1ff796
formatting
Jun 2, 2019
63df130
Merge branch 'patch-1' of https://github.com/Simran-B/binary-parser i…
keichi Jun 2, 2019
2f14211
Merge pull request #80 from Simran-B/Simran-B-patch-1
keichi Jun 2, 2019
388ddf7
Update module path to dist/ after TS migration
keichi Jun 2, 2019
099276e
Fix #60
keichi Jun 2, 2019
3b4a2bd
Merge pull request #103 from keichi/fix-60
keichi Jun 2, 2019
a1a9442
Merge pull request #102 from keichi/fix-examples
keichi Jun 2, 2019
043f442
Merge pull request #101 from Toxicable/staticmethods
keichi Jun 3, 2019
75892ec
Use const and let instead of var
keichi Jun 3, 2019
6dfbbf2
Use arrow functions rather than JS anon functions
keichi Jun 3, 2019
ed9427a
Use TS string templates
keichi Jun 3, 2019
951f051
Run prettier
keichi Jun 3, 2019
9c597af
Update version field of package-lock.json
keichi Jun 3, 2019
1ea715b
Mark generateXXX() private
keichi Jun 3, 2019
c0c6aa6
Merge pull request #104 from keichi/ts-refactoring
keichi Jun 3, 2019
eb3a89d
Mark generate[U]IntXXX() private
keichi Jun 3, 2019
32ae69a
Statically call code generator methods
keichi Jun 3, 2019
59590e3
Rename PRIMITIVE_TYPES to PRIMITIVES_SIZES
keichi Jun 3, 2019
12f2cd4
Use string templates where possible
keichi Jun 3, 2019
32cb23f
Prettier
keichi Jun 3, 2019
f22dd53
Update dev deps
keichi Jun 3, 2019
da9ff34
Address review comment
keichi Jun 3, 2019
b3a05aa
Fix --noImplicitAny warnings
keichi Jun 3, 2019
95ef62d
Prettier
keichi Jun 3, 2019
d39e56c
Merge pull request #105 from keichi/remove-dynamic-calls
keichi Jun 3, 2019
8ee270d
add big int 64 support
Jun 3, 2019
6a5eaca
foramatting
Jun 3, 2019
443ac46
docs and remove big prefix
Jun 3, 2019
153fea4
Merge pull request #106 from Toxicable/int64
keichi Jun 3, 2019
1adba54
Implement pointer parser
keichi Jan 11, 2018
7c2a924
Add unit tests for pointer parser
keichi Jan 11, 2018
10e04a4
Add ELF32 parser
keichi Jan 11, 2018
45be2d4
Add anchor links
keichi Jan 11, 2018
ff322af
Improved README
keichi Jan 11, 2018
db10fb9
Add documentation for .pointer()
keichi Jan 11, 2018
56e941a
Format
keichi Jun 3, 2019
089fce1
Fix typos in doc
keichi Jun 3, 2019
221820b
Remove JS file
keichi Jun 3, 2019
ce437c6
Fix anchor links in doc
keichi Jun 3, 2019
53fb0cb
Fix doc
keichi Jun 3, 2019
e1d066a
Remove dependency to mocha-junit-reporter from published package
keichi Jun 3, 2019
c797760
Merge pull request #108 from keichi/fix-107
keichi Jun 3, 2019
810c290
Merge pull request #64 from keichi/pointer
keichi Jun 3, 2019
1b75344
add saveoffset method
Jun 4, 2019
099b08b
Add .editorconfig
keichi Jun 5, 2019
84a6694
Update README
keichi Jun 5, 2019
24c5565
Update LICENSE
keichi Jun 5, 2019
6e61b85
Merge pull request #110 from keichi/add-editorconfig
keichi Jun 5, 2019
c55dc04
Trigger tsc when running npm install/publish
keichi Jun 5, 2019
5101915
Merge pull request #113 from keichi/npm-prepare
keichi Jun 5, 2019
7dbf542
Merge pull request #111 from keichi/update-docs
keichi Jun 5, 2019
9d95f3d
Implement readUntil option for buffer
keichi Jun 6, 2019
e1b91ea
Format
keichi Jun 6, 2019
f6c2dd6
Merge pull request #115 from keichi/buffer-readuntil
keichi Jun 6, 2019
29e0de5
Exclude TypeScript files from package until typings are complete
keichi Jun 7, 2019
e190f80
Merge pull request #117 from keichi/exclude-ts
keichi Jun 7, 2019
c4e29ee
Bump to 1.4.0
keichi Jun 7, 2019
e94a593
Typescript support fixes.
Jun 7, 2019
844fee4
formatting
Jun 8, 2019
334ce37
Merge pull request #109 from Toxicable/offset-save
keichi Jun 8, 2019
27c24ef
change saveoffset -> saveOffset
Jun 9, 2019
d36029c
Merge pull request #120 from Toxicable/offsettname
keichi Jun 10, 2019
5367f44
Run tests in the browser
keichi Jun 11, 2019
ac8ec20
Merge pull request #121 from keichi/browser-tests
keichi Jun 11, 2019
0b33b62
Comments fixes
Jun 11, 2019
a2079a4
Merge remote-tracking branch 'xyi/master'
Jun 11, 2019
2726d2c
Rename skip() to seek()
keichi Jun 13, 2019
c7e4532
Merge pull request #122 from keichi/rename-skip
keichi Jun 13, 2019
66b13e2
Merge remote-tracking branch 'xyi/master'
Jun 13, 2019
21cb23f
Merge pull request #119 from melphis/master
keichi Jun 13, 2019
2cf194a
Don't need to use npx in npm-scripts
keichi Jun 16, 2019
fdd05c1
Merge pull request #124 from keichi/remove-npx
keichi Jun 16, 2019
3107338
Merge remote-tracking branch 'upstream/master' into encoder
NotBobTheBuilder Jul 13, 2019
ee14f95
Tests run against dist
NotBobTheBuilder Jul 13, 2019
d4637c5
fix encoder ordering bug
NotBobTheBuilder Jul 13, 2019
2097f98
types are lowercase
NotBobTheBuilder Jul 13, 2019
fa74c9b
fix bad indent
NotBobTheBuilder Jul 13, 2019
204705b
array readuntil bugfix
NotBobTheBuilder Jul 13, 2019
1f8bdfa
Resolve missing typeof
NotBobTheBuilder Jul 13, 2019
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
61 changes: 56 additions & 5 deletions .circleci/config.yml
Original file line number Diff line number Diff line change
@@ -1,19 +1,70 @@
version: 2

defaults: &defaults
working_directory: ~/repo
docker:
- image: circleci/node

jobs:
build:
docker:
- image: circleci/node
<<: *defaults
steps:
- checkout
- restore_cache:
key: deps-{{ checksum "package-lock.json" }}
- run:
command: npm install
- run:
command: npm test
- run:
command: npm run check-fmt
command: npm install --no-save mocha-junit-reporter
- save_cache:
key: deps-{{ checksum "package-lock.json" }}
paths:
- node_modules/
- persist_to_workspace:
root: ~/repo
paths: .
test:
<<: *defaults
steps:
- attach_workspace:
at: ~/repo
- run:
command: npx mocha --reporter mocha-junit-reporter
environment:
MOCHA_FILE: test-results/mocha/results.xml
- store_test_results:
path: test-results
- run:
command: npm run check-fmt
publish:
<<: *defaults
steps:
- attach_workspace:
at: ~/repo
- run:
command: echo "//registry.npmjs.org/:_authToken=$NPM_TOKEN" > ~/.npmrc
- run:
command: npm publish

workflows:
version: 2
build-test-publish:
jobs:
- build:
filters:
tags:
only: /^v.*/
- test:
requires:
- build
filters:
tags:
only: /^v.*/
- publish:
requires:
- test
filters:
tags:
only: /^v.*/
branches:
ignore: /.*/
11 changes: 11 additions & 0 deletions .editorconfig
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
root = true

[*]
end_of_line = lf
charset = utf-8
trim_trailing_whitespace = true
insert_final_newline = true

[*.{ts,js,json}]
indent_style = space
indent_size = 2
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -17,3 +17,6 @@ node_modules

coverage/
.nyc_output/
dist/

.cache/
3 changes: 0 additions & 3 deletions .npmignore

This file was deleted.

7 changes: 7 additions & 0 deletions .prettierrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"parser": "typescript",
"trailingComma": "es5",
"tabWidth": 2,
"semi": true,
"singleQuote": true
}
2 changes: 1 addition & 1 deletion LICENSE.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
Copyright (c) 2013-2017 Keichi Takahashi <keichi.t@me.com>
Copyright (c) 2013-2019 Keichi Takahashi <keichi.t@me.com>

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
Expand Down
149 changes: 96 additions & 53 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,31 +17,29 @@ data. Binary-parser dynamically generates and compiles the parser and encoder co
on-the-fly, which runs as fast as a hand-written parser/encoder (which takes much more
time and effort to write). Supported data types are:

- Integers (supports 8, 16, 32 bit signed- and unsigned integers)
- Floating point numbers (supports 32 and 64 bit floating point values)
- Bit fields (supports bit fields with length from 1 to 32 bits)
- Strings (supports various encodings, fixed-length and variable-length, zero
terminated string)
- Arrays (supports user-defined element type, fixed-length and variable-length)
- Choices
- User defined types

This library's features are inspired by [BinData](https://github.com/dmendel/bindata)
, its syntax by [binary](https://github.com/substack/node-binary).

## Installation
Binary-parser can be installed with [npm](https://npmjs.org/):

```shell
$ npm install binary-parser
```
- [Integers](#uint8-16-32-64le-bename-options) (8, 16, 32 and 64 bit signed
and unsigned integers)
- [Floating point numbers](#float-doublele-bename-options) (32 and 64 bit
floating point values)
- [Bit fields](#bit1-32name-options) (bit fields with length from 1 to 32
bits)
- [Strings](#stringname-options) (fixed-length, variable-length and zero
terminated strings with various encodings)
- [Arrays](#arrayname-options) (fixed-length and variable-length arrays of
builtin or user-defined element types)
- [Choices](#choicename-options) (supports integer keys)
- [Pointers](#pointername-options)
- User defined types (arbitrary combination of builtin types)

Binary-parser was inspired by [BinData](https://github.com/dmendel/bindata)
and [binary](https://github.com/substack/node-binary).

## Quick Start
1. Create an empty Parser object with `new Parser()`.
2. Chain builder methods to build the desired parser and/or encoder. (See
[API](https://github.com/Keichi/binary-parser#api) for detailed document of
each methods)
3. Call `Parser.prototype.parse` with an `Buffer` object passed as argument.
1. Create an empty Parser object with `new Parser()` or `Parser.start()`.
2. Chain methods to build your desired parser and/or encoder. (See
[API](https://github.com/keichi/binary-parser#api) for detailed document of
each method)
3. Call `Parser.prototype.parse` with an `Buffer` object passed as an argument.
4. Parsed result will be returned as an object.
5. Or call `Parser.prototype.encode` with an object passed as argument.
6. Encoded result will be returned as a `Buffer` object.
Expand Down Expand Up @@ -106,8 +104,8 @@ parser.

### parse(buffer)
Parse a `Buffer` object `buffer` with this parser and return the resulting
object. When `parse(buffer)` is called for the first time, parser code is
compiled on-the-fly and internally cached.
object. When `parse(buffer)` is called for the first time, the associated
parser code is compiled on-the-fly and internally cached.

### encode(obj)
Encode an `Object` object `obj` with this parser and return the resulting
Expand All @@ -118,12 +116,17 @@ compiled on-the-fly and internally cached.
Set the constructor function that should be called to create the object
returned from the `parse` method.

### [u]int{8, 16, 32}{le, be}(name[, options])
### [u]int{8, 16, 32, 64}{le, be}(name[, options])
Parse bytes as an integer and store it in a variable named `name`. `name`
should consist only of alphanumeric characters and start with an alphabet.
Number of bits can be chosen from 8, 16 and 32. Byte-ordering can be either
Number of bits can be chosen from 8, 16, 32 and 64. Byte-ordering can be either
`l` for little endian or `b` for big endian. With no prefix, it parses as a
signed number, with `u` prefixed as an unsigned number.
signed number, with `u` prefixed as an unsigned number. The runtime type
returned by the 8, 16, 32 bit methods is `number` while the type
returned by the 64 bit is `bigint`.

**Note:** [u]int64{be,le} methods only work if your runtime is node v12.0.0 or
greater. Lower version will throw a runtime error.

```javascript
var parser = new Parser()
Expand All @@ -133,6 +136,8 @@ var parser = new Parser()
.uint8("b")
// Signed 16-bit integer (big endian)
.int16be("c");
// signed 64-bit integer (big endian)
.int64be("d")
```

### bit\[1-32\](name[, options])
Expand All @@ -141,9 +146,8 @@ methods from `bit1` to `bit32` each corresponding to 1-bit-length to
32-bits-length bit field.

### {float, double}{le, be}(name[, options])
Parse bytes as an floating-point value and store it in a variable named
`name`. `name` should consist only of alphanumeric characters and start with
an alphabet.
Parse bytes as a floating-point value and stores it to a variable named
`name`.

```javascript
var parser = new Parser()
Expand All @@ -159,7 +163,7 @@ characters and start with an alphabet. `options` is an object which can have
the following keys:

- `encoding` - (Optional, defaults to `utf8`) Specify which encoding to use.
`"utf8"`, `"ascii"`, `"hex"` and else are valid. See
Supported encodings include `"utf8"`, `"ascii"` and `"hex"`. See
[`Buffer.toString`](http://nodejs.org/api/buffer.html#buffer_buf_tostring_encoding_start_end)
for more info.
- `length ` - (Optional) (Bytes)Length of the string. Can be a number, string or a
Expand Down Expand Up @@ -190,15 +194,17 @@ the following keys:
- `clone` - (Optional, defaults to `false`) By default,
`buffer(name [,options])` returns a new buffer which references the same
memory as the parser input, but offset and cropped by a certain range. If
this option is true, input buffer will be cloned and a new buffer referncing
another memory is returned.
this option is true, input buffer will be cloned and a new buffer
referencing a new memory region is returned.
- `length ` - (either `length` or `readUntil` is required) Length of the
buffer. Can be a number, string or a function. Use number for statically
sized buffers, string to reference another variable and function to do some
calculation.
- `readUntil` - (either `length` or `readUntil` is required) If `"eof"`, then
this parser will read till it reaches end of the `Buffer` object. (Note: has no
effect on encoding.)
If it is a function, this parser will read the buffer is read until the
function returns true.

### array(name, options)
Parse bytes as an array. `options` is an object which can have the following
Expand Down Expand Up @@ -242,7 +248,7 @@ var parser = new Parser()
type: "int32",
length: function() {
return this.dataLength - 1;
} // other fields are available through this
} // other fields are available through `this`
})

// Statically sized array
Expand All @@ -263,7 +269,7 @@ var parser = new Parser()
type: "int32",
lengthInBytes: function() {
return this.dataLengthInBytes - 4;
} // other fields are available through this
} // other fields are available through `this`
})

// Dynamically sized array (with stop-check on parsed item)
Expand Down Expand Up @@ -291,7 +297,7 @@ an object which can have the following keys:
`choices` Can be a string pointing to another field or a function.
- `choices` - (Required) An object which key is an integer and value is the
parser which is executed when `tag` equals the key value.
- `defaultChoice` - (Optional) In case of the tag value doesn't match any of
- `defaultChoice` - (Optional) In case if the tag value doesn't match any of
`choices`, this parser is used.

```javascript
Expand All @@ -302,15 +308,15 @@ var parser3 = ...;
var parser = new Parser().uint8("tagValue").choice("data", {
tag: "tagValue",
choices: {
1: parser1, // When tagValue == 1, execute parser1
4: parser2, // When tagValue == 4, execute parser2
5: parser3 // When tagValue == 5, execute parser3
1: parser1, // if tagValue == 1, execute parser1
4: parser2, // if tagValue == 4, execute parser2
5: parser3 // if tagValue == 5, execute parser3
}
});
```

Combining `choice` with `array` is an idiom to parse
[TLV](http://en.wikipedia.org/wiki/Type-length-value)-based formats.
[TLV](http://en.wikipedia.org/wiki/Type-length-value)-based binary formats.

### nest([name,] options)
Execute an inner parser and store its result to key `name`. If `name` is null
Expand All @@ -319,9 +325,46 @@ current object. `options` is an object which can have the following keys:

- `type` - (Required) A `Parser` object.

### skip(length)
Skip parsing for `length` bytes. (Note: when encoding, the skipped bytes will be filled
with zeros)
### pointer(name [,options])
Jump to `offset`, execute parser for `type` and rewind to previous offset.
Useful for parsing binary formats such as ELF where the offset of a field is
pointed by another field.

- `type` - (Required) Can be a string `[u]int{8, 16, 32, 64}{le, be}`
or an user defined Parser object.
- `offset` - (Required) Indicates absolute offset from the beginning of the
input buffer. Can be a number, string or a function.

### saveOffset(name [,options])
Save the current buffer offset as key `name`. This function is only useful
when called after another function which would advance the internal buffer
offset.

```javascript
var parser = new Parser()
// this call advances the buffer offset by
// a variable (i.e. unknown to us) number of bytes
.string('name', {
zeroTerminated: true
})
// this variable points to an absolute position
// in the buffer
.uint32('seekOffset')
// now, save the "current" offset in the stream
// as the variable "currentOffset"
.saveOffset('currentOffset')
// finally, use the saved offset to figure out
// how many bytes we need to skip
.seek(function() {
return this.seekOffset - this.currentOffset;
})
... // the parser would continue here
```

### seek(relOffset)
Move the buffer offset for `relOffset` bytes from the current position. Use a
negative `relOffset` value to rewind the offset. Previously named `skip(length)`.
(Note: when encoding, the skipped bytes will be filled with zeros)

### endianess(endianess)
Define what endianess to use in this parser. `endianess` can be either
Expand Down Expand Up @@ -399,9 +442,10 @@ will contain two similar parts of the code included, while with the named
approach, it will include a function with a name, and will just call this
function for every case of usage.

NB: This style could lead to circular references and infinite recursion, to
avoid this, ensure that every possible path has its end. Also, this recursion
is not tail-optimized, so could lead to memory leaks when it goes too deep.
**Note**: This style could lead to circular references and infinite recursion,
to avoid this, ensure that every possible path has its end. Also, this
recursion is not tail-optimized, so could lead to memory leaks when it goes
too deep.

An example of referencing other patches:

Expand Down Expand Up @@ -438,10 +482,10 @@ executed for the first time.

### getCode() and getCodeEncode()
Dynamically generates the code for this parser/encoder and returns it as a string.
Usually used for debugging.
Useful for debugging the generated code.

### Common options
These are common options that can be specified in all parsers.
These options can be used in all parsers.

- `formatter` - Function that transforms the parsed value into a more desired
form. *formatter*(value, obj, buffer, offset) &rarr; *new value* \
Expand Down Expand Up @@ -498,11 +542,10 @@ These are common options that can be specified in all parsers.
```

## Examples
See `example` for more complex examples.
See `example/` for real-world examples.

## Support
Please report issues to the
[issue tracker](https://github.com/Keichi/binary-parser/issues) if you have
[issue tracker](https://github.com/keichi/binary-parser/issues) if you have
any difficulties using this module, found a bug, or request a new feature.

Pull requests with fixes and improvements are welcomed!
Pull requests are welcomed.
Loading