full site update
This commit is contained in:
21
node_modules/restructure/LICENSE
generated
vendored
Normal file
21
node_modules/restructure/LICENSE
generated
vendored
Normal file
@@ -0,0 +1,21 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2015-present Devon Govett
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
300
node_modules/restructure/README.md
generated
vendored
Normal file
300
node_modules/restructure/README.md
generated
vendored
Normal file
@@ -0,0 +1,300 @@
|
||||
# Restructure
|
||||
|
||||
[](https://travis-ci.org/devongovett/restructure)
|
||||
[](https://coveralls.io/r/devongovett/restructure?branch=master)
|
||||
|
||||
Restructure allows you to declaratively encode and decode binary data.
|
||||
It supports a wide variety of types to enable you to express a multitude
|
||||
of binary formats without writing any parsing code.
|
||||
|
||||
Some of the supported features are C-like structures, versioned structures,
|
||||
pointers, arrays of any type, strings of a large number of encodings, enums,
|
||||
bitfields, and more. See the documentation below for more details.
|
||||
|
||||
## Example
|
||||
|
||||
This is just a small example of what Restructure can do. Check out the API documentation
|
||||
below for more information.
|
||||
|
||||
```javascript
|
||||
import * as r from 'restructure';
|
||||
|
||||
let Person = new r.Struct({
|
||||
name: new r.String(r.uint8, 'utf8'),
|
||||
age: r.uint8
|
||||
});
|
||||
|
||||
// decode a person from a buffer
|
||||
let value = Person.fromBuffer(new Uint8Array([/* ... */])); // returns an object with the fields defined above
|
||||
|
||||
// encode a person from an object
|
||||
let buffer = Person.toBuffer({
|
||||
name: 'Devon',
|
||||
age: 21
|
||||
});
|
||||
```
|
||||
|
||||
## API
|
||||
|
||||
All of the following types support three standard methods:
|
||||
|
||||
* `fromBuffer(buffer)` - decodes an instance of the type from the given Uint8Array
|
||||
* `size(value)` - returns the amount of space the value would take if encoded
|
||||
* `toBuffer(value)` - encodes the given value into a Uint8Array
|
||||
|
||||
Restructure supports a wide variety of types, but if you need to write your own for
|
||||
some custom use that cannot be represented by them, you can do so by just implementing
|
||||
the above methods. Then you can use your type just as you would any other type, in structures
|
||||
and whatnot.
|
||||
|
||||
### Number Types
|
||||
|
||||
The following built-in number types are available:
|
||||
|
||||
```javascript
|
||||
uint8, uint16, uint24, uint32, int8, int16, int24, int32, float, double, fixed16, fixed32
|
||||
```
|
||||
|
||||
Numbers are big-endian (network order) by default, but little-endian is supported, too:
|
||||
|
||||
```javascript
|
||||
uint16le, uint24le, uint32le, int16le, int24le, int32le, floatle, doublele, fixed16le, fixed32le
|
||||
```
|
||||
|
||||
To avoid ambiguity, big-endian may be used explicitly:
|
||||
|
||||
```javascript
|
||||
uint16be, uint24be, uint32be, int16be, int24be, int32be, floatbe, doublebe, fixed16be, fixed32be
|
||||
```
|
||||
|
||||
### Boolean
|
||||
|
||||
Booleans are encoded as `0` or `1` using one of the above number types.
|
||||
|
||||
```javascript
|
||||
var bool = new r.Boolean(r.uint32);
|
||||
```
|
||||
|
||||
### Reserved
|
||||
|
||||
The `Reserved` type simply skips data in a structure, where there are reserved fields.
|
||||
Encoding produces zeros.
|
||||
|
||||
```javascript
|
||||
// 10 reserved uint8s (default is 1)
|
||||
var reserved = new r.Reserved(r.uint8, 10);
|
||||
```
|
||||
|
||||
### Optional
|
||||
|
||||
The `Optional` type only encodes or decodes when given condition is truthy.
|
||||
|
||||
```javascript
|
||||
// includes field
|
||||
var optional = new r.Optional(r.uint8, true);
|
||||
|
||||
// excludes field
|
||||
var optional = new r.Optional(r.uint8, false);
|
||||
|
||||
// determine whether field is to be included at runtime with a function
|
||||
var optional = new r.Optional(r.uint8, function() {
|
||||
return this.flags & 0x50;
|
||||
});
|
||||
```
|
||||
|
||||
### Enum
|
||||
|
||||
The `Enum` type maps a number to the value at that index in an array.
|
||||
|
||||
```javascript
|
||||
var color = new r.Enum(r.uint8, ['red', 'orange', 'yellow', 'green', 'blue', 'purple']);
|
||||
```
|
||||
|
||||
### Bitfield
|
||||
|
||||
The `Bitfield` type maps a number to an object with boolean keys mapping to each bit in that number,
|
||||
as defined in an array.
|
||||
|
||||
```javascript
|
||||
var bitfield = new r.Bitfield(r.uint8, ['Jack', 'Kack', 'Lack', 'Mack', 'Nack', 'Oack', 'Pack', 'Quack']);
|
||||
bitfield.decode(stream);
|
||||
|
||||
var result = {
|
||||
Jack: true,
|
||||
Kack: false,
|
||||
Lack: false,
|
||||
Mack: true,
|
||||
Nack: true,
|
||||
Oack: false,
|
||||
Pack: true,
|
||||
Quack: true
|
||||
};
|
||||
|
||||
bitfield.encode(stream, result);
|
||||
```
|
||||
|
||||
### Buffer
|
||||
|
||||
Extracts a slice of the buffer to a `Uint8Array`. The length can be a constant, or taken from
|
||||
a previous field in the parent structure.
|
||||
|
||||
```javascript
|
||||
// fixed length
|
||||
var buf = new r.Buffer(2);
|
||||
|
||||
// length from parent structure
|
||||
var struct = new r.Struct({
|
||||
bufLen: r.uint8,
|
||||
buf: new r.Buffer('bufLen')
|
||||
});
|
||||
```
|
||||
|
||||
### String
|
||||
|
||||
A `String` maps a JavaScript string to and from binary encodings. The length, in bytes, can be a constant,
|
||||
taken from a previous field in the parent structure, encoded using a number type immediately before the
|
||||
string.
|
||||
|
||||
Fully supported encodings include `'ascii'`, `'utf8'`, `'ucs2'`, `'utf16le'`, `'utf16be'`. Decoding is also possible
|
||||
with any encoding supported by [TextDecoder](https://developer.mozilla.org/en-US/docs/Web/API/Encoding_API/Encodings),
|
||||
however encoding these is not supported.
|
||||
|
||||
```javascript
|
||||
// fixed length, ascii encoding by default
|
||||
var str = new r.String(2);
|
||||
|
||||
// length encoded as number before the string, utf8 encoding
|
||||
var str = new r.String(r.uint8, 'utf8');
|
||||
|
||||
// length from parent structure
|
||||
var struct = new r.Struct({
|
||||
len: r.uint8,
|
||||
str: new r.String('len', 'utf16be')
|
||||
});
|
||||
|
||||
// null-terminated string (also known as C string)
|
||||
var str = new r.String(null, 'utf8');
|
||||
```
|
||||
|
||||
### Array
|
||||
|
||||
An `Array` maps to and from a JavaScript array containing instances of a sub-type. The length can be a constant,
|
||||
taken from a previous field in the parent structure, encoded using a number type immediately
|
||||
before the string, or computed by a function.
|
||||
|
||||
```javascript
|
||||
// fixed length, containing numbers
|
||||
var arr = new r.Array(r.uint16, 2);
|
||||
|
||||
// length encoded as number before the array containing strings
|
||||
var arr = new r.Array(new r.String(10), r.uint8);
|
||||
|
||||
// length computed by a function
|
||||
var arr = new r.Array(r.uint8, function() { return 5 });
|
||||
|
||||
// length from parent structure
|
||||
var struct = new r.Struct({
|
||||
len: r.uint8,
|
||||
arr: new r.Array(r.uint8, 'len')
|
||||
});
|
||||
|
||||
// treat as amount of bytes instead (may be used in all the above scenarios)
|
||||
var arr = new r.Array(r.uint16, 6, 'bytes');
|
||||
```
|
||||
|
||||
### LazyArray
|
||||
|
||||
The `LazyArray` type extends from the `Array` type, and is useful for large arrays that you do not need to access sequentially.
|
||||
It avoids decoding the entire array upfront, and instead only decodes and caches individual items as needed. It only works when
|
||||
the elements inside the array have a fixed size.
|
||||
|
||||
Instead of returning a JavaScript array, the `LazyArray` type returns a custom object that can be used to access the elements.
|
||||
|
||||
```javascript
|
||||
var arr = new r.LazyArray(r.uint16, 2048);
|
||||
var res = arr.decode(stream);
|
||||
|
||||
// get a single element
|
||||
var el = res.get(2);
|
||||
|
||||
// convert to a normal array (decode all elements)
|
||||
var array = res.toArray();
|
||||
```
|
||||
|
||||
### Struct
|
||||
|
||||
A `Struct` maps to and from JavaScript objects, containing keys of various previously discussed types. Sub structures,
|
||||
arrays of structures, and pointers to other types (discussed below) are supported.
|
||||
|
||||
```javascript
|
||||
var Person = new r.Struct({
|
||||
name: new r.String(r.uint8, 'utf8'),
|
||||
age: r.uint8
|
||||
});
|
||||
```
|
||||
|
||||
### VersionedStruct
|
||||
|
||||
A `VersionedStruct` is a `Struct` that has multiple versions. The version is typically encoded at
|
||||
the beginning of the structure, or as a field in a parent structure. There is an optional `header`
|
||||
common to all versions, and separate fields listed for each version number.
|
||||
|
||||
```javascript
|
||||
// the version is read as a uint8 in this example
|
||||
// you could also get the version from a key on the parent struct
|
||||
var Person = new r.VersionedStruct(r.uint8, {
|
||||
// optional header common to all versions
|
||||
header: {
|
||||
name: new r.String(r.uint8, 'utf8')
|
||||
},
|
||||
0: {
|
||||
age: r.uint8
|
||||
},
|
||||
1: {
|
||||
hairColor: r.Enum(r.uint8, ['black', 'brown', 'blonde'])
|
||||
}
|
||||
});
|
||||
```
|
||||
|
||||
### Pointer
|
||||
|
||||
Pointers map an address or offset encoded as a number, to a value encoded elsewhere in the buffer.
|
||||
There are a few options you can use: `type`, `relativeTo`, `allowNull`, and `nullValue`.
|
||||
The `type` option has these possible values:
|
||||
|
||||
* `local` (default) - the encoded offset is relative to the start of the containing structure
|
||||
* `immediate` - the encoded offset is relative to the position of the pointer itself
|
||||
* `parent` - the encoded offset is relative to the parent structure of the immediate container
|
||||
* `global` - the encoded offset is global to the start of the file
|
||||
|
||||
The `relativeTo` option accepts a function callback that should return the field on the containing structure which the encoded offset is relative to. The callback is called with the context as parameter.
|
||||
By default, pointers are relative to the start of the containing structure (`local`).
|
||||
|
||||
The `allowNull` option lets you specify whether zero offsets are allowed or should produce `null`. This is
|
||||
set to `true` by default. The `nullValue` option is related, and lets you override the encoded value that
|
||||
represents `null`. By default, the `nullValue` is zero.
|
||||
|
||||
The `lazy` option allows lazy decoding of the pointer's value by defining a getter on the parent object.
|
||||
This only works when the pointer is contained within a Struct, but can be used to speed up decoding
|
||||
quite a bit when not all of the data is needed right away.
|
||||
|
||||
```javascript
|
||||
var Address = new r.Struct({
|
||||
street: new r.String(r.uint8),
|
||||
zip: new r.String(5)
|
||||
});
|
||||
|
||||
var Person = new r.Struct({
|
||||
name: new r.String(r.uint8, 'utf8'),
|
||||
age: r.uint8,
|
||||
ptrStart: r.uint8,
|
||||
address: new r.Pointer(r.uint8, Address)
|
||||
});
|
||||
```
|
||||
|
||||
If the type of a pointer is set to 'void', it is not decoded and the computed address in the buffer
|
||||
is simply returned. To encode a void pointer, create a `new r.VoidPointer(type, value)`.
|
||||
|
||||
## License
|
||||
|
||||
MIT
|
1019
node_modules/restructure/dist/main.cjs
generated
vendored
Normal file
1019
node_modules/restructure/dist/main.cjs
generated
vendored
Normal file
File diff suppressed because it is too large
Load Diff
1
node_modules/restructure/dist/main.cjs.map
generated
vendored
Normal file
1
node_modules/restructure/dist/main.cjs.map
generated
vendored
Normal file
File diff suppressed because one or more lines are too long
17
node_modules/restructure/index.js
generated
vendored
Normal file
17
node_modules/restructure/index.js
generated
vendored
Normal file
@@ -0,0 +1,17 @@
|
||||
export {EncodeStream} from './src/EncodeStream.js';
|
||||
export {DecodeStream} from './src/DecodeStream.js';
|
||||
export {Array} from './src/Array.js';
|
||||
export {LazyArray} from './src/LazyArray.js';
|
||||
export {Bitfield} from './src/Bitfield.js';
|
||||
export {Boolean} from './src/Boolean.js';
|
||||
export {Buffer} from './src/Buffer.js';
|
||||
export {Enum} from './src/Enum.js';
|
||||
export {Optional} from './src/Optional.js';
|
||||
export {Reserved} from './src/Reserved.js';
|
||||
export {String} from './src/String.js';
|
||||
export {Struct} from './src/Struct.js';
|
||||
export {VersionedStruct} from './src/VersionedStruct.js';
|
||||
|
||||
export * from './src/utils.js';
|
||||
export * from './src/Number.js';
|
||||
export * from './src/Pointer.js';
|
41
node_modules/restructure/package.json
generated
vendored
Normal file
41
node_modules/restructure/package.json
generated
vendored
Normal file
@@ -0,0 +1,41 @@
|
||||
{
|
||||
"name": "restructure",
|
||||
"version": "3.0.2",
|
||||
"description": "Declaratively encode and decode binary data",
|
||||
"type": "module",
|
||||
"main": "./dist/main.cjs",
|
||||
"module": "./index.js",
|
||||
"source": "./index.js",
|
||||
"exports": {
|
||||
"import": "./index.js",
|
||||
"require": "./dist/main.cjs"
|
||||
},
|
||||
"targets": {
|
||||
"module": false
|
||||
},
|
||||
"devDependencies": {
|
||||
"mocha": "^10.0.0",
|
||||
"parcel": "^2.6.1"
|
||||
},
|
||||
"scripts": {
|
||||
"test": "mocha",
|
||||
"build": "parcel build",
|
||||
"prepublishOnly": "parcel build"
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git://github.com/devongovett/restructure.git"
|
||||
},
|
||||
"keywords": [
|
||||
"binary",
|
||||
"struct",
|
||||
"encode",
|
||||
"decode"
|
||||
],
|
||||
"author": "Devon Govett <devongovett@gmail.com>",
|
||||
"license": "MIT",
|
||||
"bugs": {
|
||||
"url": "https://github.com/devongovett/restructure/issues"
|
||||
},
|
||||
"homepage": "https://github.com/devongovett/restructure"
|
||||
}
|
106
node_modules/restructure/src/Array.js
generated
vendored
Normal file
106
node_modules/restructure/src/Array.js
generated
vendored
Normal file
@@ -0,0 +1,106 @@
|
||||
import {Base} from './Base.js';
|
||||
import {Number as NumberT} from './Number.js';
|
||||
import * as utils from './utils.js';
|
||||
|
||||
class ArrayT extends Base {
|
||||
constructor(type, length, lengthType = 'count') {
|
||||
super();
|
||||
this.type = type;
|
||||
this.length = length;
|
||||
this.lengthType = lengthType;
|
||||
}
|
||||
|
||||
decode(stream, parent) {
|
||||
let length;
|
||||
const { pos } = stream;
|
||||
|
||||
const res = [];
|
||||
let ctx = parent;
|
||||
|
||||
if (this.length != null) {
|
||||
length = utils.resolveLength(this.length, stream, parent);
|
||||
}
|
||||
|
||||
if (this.length instanceof NumberT) {
|
||||
// define hidden properties
|
||||
Object.defineProperties(res, {
|
||||
parent: { value: parent },
|
||||
_startOffset: { value: pos },
|
||||
_currentOffset: { value: 0, writable: true },
|
||||
_length: { value: length }
|
||||
});
|
||||
|
||||
ctx = res;
|
||||
}
|
||||
|
||||
if ((length == null) || (this.lengthType === 'bytes')) {
|
||||
const target = (length != null) ?
|
||||
stream.pos + length
|
||||
: (parent != null ? parent._length : undefined) ?
|
||||
parent._startOffset + parent._length
|
||||
:
|
||||
stream.length;
|
||||
|
||||
while (stream.pos < target) {
|
||||
res.push(this.type.decode(stream, ctx));
|
||||
}
|
||||
|
||||
} else {
|
||||
for (let i = 0, end = length; i < end; i++) {
|
||||
res.push(this.type.decode(stream, ctx));
|
||||
}
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
size(array, ctx, includePointers = true) {
|
||||
if (!array) {
|
||||
return this.type.size(null, ctx) * utils.resolveLength(this.length, null, ctx);
|
||||
}
|
||||
|
||||
let size = 0;
|
||||
if (this.length instanceof NumberT) {
|
||||
size += this.length.size();
|
||||
ctx = {parent: ctx, pointerSize: 0};
|
||||
}
|
||||
|
||||
for (let item of array) {
|
||||
size += this.type.size(item, ctx);
|
||||
}
|
||||
|
||||
if (ctx && includePointers && this.length instanceof NumberT) {
|
||||
size += ctx.pointerSize;
|
||||
}
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
encode(stream, array, parent) {
|
||||
let ctx = parent;
|
||||
if (this.length instanceof NumberT) {
|
||||
ctx = {
|
||||
pointers: [],
|
||||
startOffset: stream.pos,
|
||||
parent
|
||||
};
|
||||
|
||||
ctx.pointerOffset = stream.pos + this.size(array, ctx, false);
|
||||
this.length.encode(stream, array.length);
|
||||
}
|
||||
|
||||
for (let item of array) {
|
||||
this.type.encode(stream, item, ctx);
|
||||
}
|
||||
|
||||
if (this.length instanceof NumberT) {
|
||||
let i = 0;
|
||||
while (i < ctx.pointers.length) {
|
||||
const ptr = ctx.pointers[i++];
|
||||
ptr.type.encode(stream, ptr.val, ptr.parent);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export {ArrayT as Array};
|
17
node_modules/restructure/src/Base.js
generated
vendored
Normal file
17
node_modules/restructure/src/Base.js
generated
vendored
Normal file
@@ -0,0 +1,17 @@
|
||||
import {DecodeStream} from './DecodeStream.js';
|
||||
import {EncodeStream} from './EncodeStream.js';
|
||||
|
||||
export class Base {
|
||||
fromBuffer(buffer) {
|
||||
let stream = new DecodeStream(buffer);
|
||||
return this.decode(stream);
|
||||
}
|
||||
|
||||
toBuffer(value) {
|
||||
let size = this.size(value);
|
||||
let buffer = new Uint8Array(size);
|
||||
let stream = new EncodeStream(buffer);
|
||||
this.encode(stream, value);
|
||||
return buffer;
|
||||
}
|
||||
}
|
39
node_modules/restructure/src/Bitfield.js
generated
vendored
Normal file
39
node_modules/restructure/src/Bitfield.js
generated
vendored
Normal file
@@ -0,0 +1,39 @@
|
||||
import {Base} from './Base.js';
|
||||
|
||||
export class Bitfield extends Base {
|
||||
constructor(type, flags = []) {
|
||||
super();
|
||||
this.type = type;
|
||||
this.flags = flags;
|
||||
}
|
||||
|
||||
decode(stream) {
|
||||
const val = this.type.decode(stream);
|
||||
|
||||
const res = {};
|
||||
for (let i = 0; i < this.flags.length; i++) {
|
||||
const flag = this.flags[i];
|
||||
if (flag != null) {
|
||||
res[flag] = !!(val & (1 << i));
|
||||
}
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
size() {
|
||||
return this.type.size();
|
||||
}
|
||||
|
||||
encode(stream, keys) {
|
||||
let val = 0;
|
||||
for (let i = 0; i < this.flags.length; i++) {
|
||||
const flag = this.flags[i];
|
||||
if (flag != null) {
|
||||
if (keys[flag]) { val |= (1 << i); }
|
||||
}
|
||||
}
|
||||
|
||||
return this.type.encode(stream, val);
|
||||
}
|
||||
}
|
22
node_modules/restructure/src/Boolean.js
generated
vendored
Normal file
22
node_modules/restructure/src/Boolean.js
generated
vendored
Normal file
@@ -0,0 +1,22 @@
|
||||
import {Base} from './Base.js';
|
||||
|
||||
export class BooleanT extends Base {
|
||||
constructor(type) {
|
||||
super();
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
decode(stream, parent) {
|
||||
return !!this.type.decode(stream, parent);
|
||||
}
|
||||
|
||||
size(val, parent) {
|
||||
return this.type.size(val, parent);
|
||||
}
|
||||
|
||||
encode(stream, val, parent) {
|
||||
return this.type.encode(stream, +val, parent);
|
||||
}
|
||||
}
|
||||
|
||||
export {BooleanT as Boolean};
|
38
node_modules/restructure/src/Buffer.js
generated
vendored
Normal file
38
node_modules/restructure/src/Buffer.js
generated
vendored
Normal file
@@ -0,0 +1,38 @@
|
||||
import {Base} from './Base.js';
|
||||
import {Number as NumberT} from './Number.js';
|
||||
import * as utils from './utils.js';
|
||||
|
||||
export class BufferT extends Base {
|
||||
constructor(length) {
|
||||
super();
|
||||
this.length = length;
|
||||
}
|
||||
|
||||
decode(stream, parent) {
|
||||
const length = utils.resolveLength(this.length, stream, parent);
|
||||
return stream.readBuffer(length);
|
||||
}
|
||||
|
||||
size(val, parent) {
|
||||
if (!val) {
|
||||
return utils.resolveLength(this.length, null, parent);
|
||||
}
|
||||
|
||||
let len = val.length;
|
||||
if (this.length instanceof NumberT) {
|
||||
len += this.length.size();
|
||||
}
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
encode(stream, buf, parent) {
|
||||
if (this.length instanceof NumberT) {
|
||||
this.length.encode(stream, buf.length);
|
||||
}
|
||||
|
||||
return stream.writeBuffer(buf);
|
||||
}
|
||||
}
|
||||
|
||||
export {BufferT as Buffer};
|
85
node_modules/restructure/src/DecodeStream.js
generated
vendored
Normal file
85
node_modules/restructure/src/DecodeStream.js
generated
vendored
Normal file
@@ -0,0 +1,85 @@
|
||||
// Node back-compat.
|
||||
const ENCODING_MAPPING = {
|
||||
utf16le: 'utf-16le',
|
||||
ucs2: 'utf-16le',
|
||||
utf16be: 'utf-16be'
|
||||
}
|
||||
|
||||
export class DecodeStream {
|
||||
constructor(buffer) {
|
||||
this.buffer = buffer;
|
||||
this.view = new DataView(buffer.buffer, buffer.byteOffset, buffer.byteLength);
|
||||
this.pos = 0;
|
||||
this.length = this.buffer.length;
|
||||
}
|
||||
|
||||
readString(length, encoding = 'ascii') {
|
||||
encoding = ENCODING_MAPPING[encoding] || encoding;
|
||||
|
||||
let buf = this.readBuffer(length);
|
||||
try {
|
||||
let decoder = new TextDecoder(encoding);
|
||||
return decoder.decode(buf);
|
||||
} catch (err) {
|
||||
return buf;
|
||||
}
|
||||
}
|
||||
|
||||
readBuffer(length) {
|
||||
return this.buffer.slice(this.pos, (this.pos += length));
|
||||
}
|
||||
|
||||
readUInt24BE() {
|
||||
return (this.readUInt16BE() << 8) + this.readUInt8();
|
||||
}
|
||||
|
||||
readUInt24LE() {
|
||||
return this.readUInt16LE() + (this.readUInt8() << 16);
|
||||
}
|
||||
|
||||
readInt24BE() {
|
||||
return (this.readInt16BE() << 8) + this.readUInt8();
|
||||
}
|
||||
|
||||
readInt24LE() {
|
||||
return this.readUInt16LE() + (this.readInt8() << 16);
|
||||
}
|
||||
}
|
||||
|
||||
DecodeStream.TYPES = {
|
||||
UInt8: 1,
|
||||
UInt16: 2,
|
||||
UInt24: 3,
|
||||
UInt32: 4,
|
||||
Int8: 1,
|
||||
Int16: 2,
|
||||
Int24: 3,
|
||||
Int32: 4,
|
||||
Float: 4,
|
||||
Double: 8
|
||||
};
|
||||
|
||||
for (let key of Object.getOwnPropertyNames(DataView.prototype)) {
|
||||
if (key.slice(0, 3) === 'get') {
|
||||
let type = key.slice(3).replace('Ui', 'UI');
|
||||
if (type === 'Float32') {
|
||||
type = 'Float';
|
||||
} else if (type === 'Float64') {
|
||||
type = 'Double';
|
||||
}
|
||||
let bytes = DecodeStream.TYPES[type];
|
||||
DecodeStream.prototype['read' + type + (bytes === 1 ? '' : 'BE')] = function () {
|
||||
const ret = this.view[key](this.pos, false);
|
||||
this.pos += bytes;
|
||||
return ret;
|
||||
};
|
||||
|
||||
if (bytes !== 1) {
|
||||
DecodeStream.prototype['read' + type + 'LE'] = function () {
|
||||
const ret = this.view[key](this.pos, true);
|
||||
this.pos += bytes;
|
||||
return ret;
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
129
node_modules/restructure/src/EncodeStream.js
generated
vendored
Normal file
129
node_modules/restructure/src/EncodeStream.js
generated
vendored
Normal file
@@ -0,0 +1,129 @@
|
||||
import {DecodeStream} from './DecodeStream.js';
|
||||
|
||||
const textEncoder = new TextEncoder();
|
||||
const isBigEndian = new Uint8Array(new Uint16Array([0x1234]).buffer)[0] == 0x12;
|
||||
|
||||
export class EncodeStream {
|
||||
constructor(buffer) {
|
||||
this.buffer = buffer;
|
||||
this.view = new DataView(this.buffer.buffer, this.buffer.byteOffset, this.buffer.byteLength);
|
||||
this.pos = 0;
|
||||
}
|
||||
|
||||
writeBuffer(buffer) {
|
||||
this.buffer.set(buffer, this.pos);
|
||||
this.pos += buffer.length;
|
||||
}
|
||||
|
||||
writeString(string, encoding = 'ascii') {
|
||||
let buf;
|
||||
switch (encoding) {
|
||||
case 'utf16le':
|
||||
case 'utf16-le':
|
||||
case 'ucs2': // node treats this the same as utf16.
|
||||
buf = stringToUtf16(string, isBigEndian);
|
||||
break;
|
||||
|
||||
case 'utf16be':
|
||||
case 'utf16-be':
|
||||
buf = stringToUtf16(string, !isBigEndian);
|
||||
break;
|
||||
|
||||
case 'utf8':
|
||||
buf = textEncoder.encode(string);
|
||||
break;
|
||||
|
||||
case 'ascii':
|
||||
buf = stringToAscii(string);
|
||||
break;
|
||||
|
||||
default:
|
||||
throw new Error(`Unsupported encoding: ${encoding}`);
|
||||
}
|
||||
|
||||
this.writeBuffer(buf);
|
||||
}
|
||||
|
||||
writeUInt24BE(val) {
|
||||
this.buffer[this.pos++] = (val >>> 16) & 0xff;
|
||||
this.buffer[this.pos++] = (val >>> 8) & 0xff;
|
||||
this.buffer[this.pos++] = val & 0xff;
|
||||
}
|
||||
|
||||
writeUInt24LE(val) {
|
||||
this.buffer[this.pos++] = val & 0xff;
|
||||
this.buffer[this.pos++] = (val >>> 8) & 0xff;
|
||||
this.buffer[this.pos++] = (val >>> 16) & 0xff;
|
||||
}
|
||||
|
||||
writeInt24BE(val) {
|
||||
if (val >= 0) {
|
||||
this.writeUInt24BE(val);
|
||||
} else {
|
||||
this.writeUInt24BE(val + 0xffffff + 1);
|
||||
}
|
||||
}
|
||||
|
||||
writeInt24LE(val) {
|
||||
if (val >= 0) {
|
||||
this.writeUInt24LE(val);
|
||||
} else {
|
||||
this.writeUInt24LE(val + 0xffffff + 1);
|
||||
}
|
||||
}
|
||||
|
||||
fill(val, length) {
|
||||
if (length < this.buffer.length) {
|
||||
this.buffer.fill(val, this.pos, this.pos + length);
|
||||
this.pos += length;
|
||||
} else {
|
||||
const buf = new Uint8Array(length);
|
||||
buf.fill(val);
|
||||
this.writeBuffer(buf);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function stringToUtf16(string, swap) {
|
||||
let buf = new Uint16Array(string.length);
|
||||
for (let i = 0; i < string.length; i++) {
|
||||
let code = string.charCodeAt(i);
|
||||
if (swap) {
|
||||
code = (code >> 8) | ((code & 0xff) << 8);
|
||||
}
|
||||
buf[i] = code;
|
||||
}
|
||||
return new Uint8Array(buf.buffer);
|
||||
}
|
||||
|
||||
function stringToAscii(string) {
|
||||
let buf = new Uint8Array(string.length);
|
||||
for (let i = 0; i < string.length; i++) {
|
||||
// Match node.js behavior - encoding allows 8-bit rather than 7-bit.
|
||||
buf[i] = string.charCodeAt(i);
|
||||
}
|
||||
return buf;
|
||||
}
|
||||
|
||||
for (let key of Object.getOwnPropertyNames(DataView.prototype)) {
|
||||
if (key.slice(0, 3) === 'set') {
|
||||
let type = key.slice(3).replace('Ui', 'UI');
|
||||
if (type === 'Float32') {
|
||||
type = 'Float';
|
||||
} else if (type === 'Float64') {
|
||||
type = 'Double';
|
||||
}
|
||||
let bytes = DecodeStream.TYPES[type];
|
||||
EncodeStream.prototype['write' + type + (bytes === 1 ? '' : 'BE')] = function (value) {
|
||||
this.view[key](this.pos, value, false);
|
||||
this.pos += bytes;
|
||||
};
|
||||
|
||||
if (bytes !== 1) {
|
||||
EncodeStream.prototype['write' + type + 'LE'] = function (value) {
|
||||
this.view[key](this.pos, value, true);
|
||||
this.pos += bytes;
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
27
node_modules/restructure/src/Enum.js
generated
vendored
Normal file
27
node_modules/restructure/src/Enum.js
generated
vendored
Normal file
@@ -0,0 +1,27 @@
|
||||
import {Base} from './Base.js';
|
||||
|
||||
export class Enum extends Base {
|
||||
constructor(type, options = []) {
|
||||
super();
|
||||
this.type = type;
|
||||
this.options = options;
|
||||
}
|
||||
|
||||
decode(stream) {
|
||||
const index = this.type.decode(stream);
|
||||
return this.options[index] || index;
|
||||
}
|
||||
|
||||
size() {
|
||||
return this.type.size();
|
||||
}
|
||||
|
||||
encode(stream, val) {
|
||||
const index = this.options.indexOf(val);
|
||||
if (index === -1) {
|
||||
throw new Error(`Unknown option in enum: ${val}`);
|
||||
}
|
||||
|
||||
return this.type.encode(stream, index);
|
||||
}
|
||||
}
|
74
node_modules/restructure/src/LazyArray.js
generated
vendored
Normal file
74
node_modules/restructure/src/LazyArray.js
generated
vendored
Normal file
@@ -0,0 +1,74 @@
|
||||
import {Array as ArrayT} from './Array.js';
|
||||
import {Number as NumberT} from './Number.js';
|
||||
import * as utils from './utils.js';
|
||||
|
||||
export class LazyArray extends ArrayT {
|
||||
decode(stream, parent) {
|
||||
const { pos } = stream;
|
||||
const length = utils.resolveLength(this.length, stream, parent);
|
||||
|
||||
if (this.length instanceof NumberT) {
|
||||
parent = {
|
||||
parent,
|
||||
_startOffset: pos,
|
||||
_currentOffset: 0,
|
||||
_length: length
|
||||
};
|
||||
}
|
||||
|
||||
const res = new LazyArrayValue(this.type, length, stream, parent);
|
||||
|
||||
stream.pos += length * this.type.size(null, parent);
|
||||
return res;
|
||||
}
|
||||
|
||||
size(val, ctx) {
|
||||
if (val instanceof LazyArrayValue) {
|
||||
val = val.toArray();
|
||||
}
|
||||
|
||||
return super.size(val, ctx);
|
||||
}
|
||||
|
||||
encode(stream, val, ctx) {
|
||||
if (val instanceof LazyArrayValue) {
|
||||
val = val.toArray();
|
||||
}
|
||||
|
||||
return super.encode(stream, val, ctx);
|
||||
}
|
||||
}
|
||||
|
||||
class LazyArrayValue {
|
||||
constructor(type, length, stream, ctx) {
|
||||
this.type = type;
|
||||
this.length = length;
|
||||
this.stream = stream;
|
||||
this.ctx = ctx;
|
||||
this.base = this.stream.pos;
|
||||
this.items = [];
|
||||
}
|
||||
|
||||
get(index) {
|
||||
if ((index < 0) || (index >= this.length)) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
if (this.items[index] == null) {
|
||||
const { pos } = this.stream;
|
||||
this.stream.pos = this.base + (this.type.size(null, this.ctx) * index);
|
||||
this.items[index] = this.type.decode(this.stream, this.ctx);
|
||||
this.stream.pos = pos;
|
||||
}
|
||||
|
||||
return this.items[index];
|
||||
}
|
||||
|
||||
toArray() {
|
||||
const result = [];
|
||||
for (let i = 0, end = this.length; i < end; i++) {
|
||||
result.push(this.get(i));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
77
node_modules/restructure/src/Number.js
generated
vendored
Normal file
77
node_modules/restructure/src/Number.js
generated
vendored
Normal file
@@ -0,0 +1,77 @@
|
||||
import {DecodeStream} from './DecodeStream.js';
|
||||
import {Base} from './Base.js';
|
||||
|
||||
class NumberT extends Base {
|
||||
constructor(type, endian = 'BE') {
|
||||
super();
|
||||
this.type = type;
|
||||
this.endian = endian;
|
||||
this.fn = this.type;
|
||||
if (this.type[this.type.length - 1] !== '8') {
|
||||
this.fn += this.endian;
|
||||
}
|
||||
}
|
||||
|
||||
size() {
|
||||
return DecodeStream.TYPES[this.type];
|
||||
}
|
||||
|
||||
decode(stream) {
|
||||
return stream[`read${this.fn}`]();
|
||||
}
|
||||
|
||||
encode(stream, val) {
|
||||
return stream[`write${this.fn}`](val);
|
||||
}
|
||||
}
|
||||
|
||||
export {NumberT as Number};
|
||||
|
||||
export const uint8 = new NumberT('UInt8');
|
||||
export const uint16be = new NumberT('UInt16', 'BE');
|
||||
export const uint16 = uint16be;
|
||||
export const uint16le = new NumberT('UInt16', 'LE');
|
||||
export const uint24be = new NumberT('UInt24', 'BE');
|
||||
export const uint24 = uint24be;
|
||||
export const uint24le = new NumberT('UInt24', 'LE');
|
||||
export const uint32be = new NumberT('UInt32', 'BE');
|
||||
export const uint32 = uint32be;
|
||||
export const uint32le = new NumberT('UInt32', 'LE');
|
||||
export const int8 = new NumberT('Int8');
|
||||
export const int16be = new NumberT('Int16', 'BE');
|
||||
export const int16 = int16be;
|
||||
export const int16le = new NumberT('Int16', 'LE');
|
||||
export const int24be = new NumberT('Int24', 'BE');
|
||||
export const int24 = int24be;
|
||||
export const int24le = new NumberT('Int24', 'LE');
|
||||
export const int32be = new NumberT('Int32', 'BE');
|
||||
export const int32 = int32be;
|
||||
export const int32le = new NumberT('Int32', 'LE');
|
||||
export const floatbe = new NumberT('Float', 'BE');
|
||||
export const float = floatbe;
|
||||
export const floatle = new NumberT('Float', 'LE');
|
||||
export const doublebe = new NumberT('Double', 'BE');
|
||||
export const double = doublebe;
|
||||
export const doublele = new NumberT('Double', 'LE');
|
||||
|
||||
export class Fixed extends NumberT {
|
||||
constructor(size, endian, fracBits = size >> 1) {
|
||||
super(`Int${size}`, endian);
|
||||
this._point = 1 << fracBits;
|
||||
}
|
||||
|
||||
decode(stream) {
|
||||
return super.decode(stream) / this._point;
|
||||
}
|
||||
|
||||
encode(stream, val) {
|
||||
return super.encode(stream, (val * this._point) | 0);
|
||||
}
|
||||
}
|
||||
|
||||
export const fixed16be = new Fixed(16, 'BE');
|
||||
export const fixed16 = fixed16be;
|
||||
export const fixed16le = new Fixed(16, 'LE');
|
||||
export const fixed32be = new Fixed(32, 'BE');
|
||||
export const fixed32 = fixed32be;
|
||||
export const fixed32le = new Fixed(32, 'LE');
|
44
node_modules/restructure/src/Optional.js
generated
vendored
Normal file
44
node_modules/restructure/src/Optional.js
generated
vendored
Normal file
@@ -0,0 +1,44 @@
|
||||
import {Base} from './Base.js';
|
||||
|
||||
export class Optional extends Base {
|
||||
constructor(type, condition = true) {
|
||||
super();
|
||||
this.type = type;
|
||||
this.condition = condition;
|
||||
}
|
||||
|
||||
decode(stream, parent) {
|
||||
let { condition } = this;
|
||||
if (typeof condition === 'function') {
|
||||
condition = condition.call(parent, parent);
|
||||
}
|
||||
|
||||
if (condition) {
|
||||
return this.type.decode(stream, parent);
|
||||
}
|
||||
}
|
||||
|
||||
size(val, parent) {
|
||||
let { condition } = this;
|
||||
if (typeof condition === 'function') {
|
||||
condition = condition.call(parent, parent);
|
||||
}
|
||||
|
||||
if (condition) {
|
||||
return this.type.size(val, parent);
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
encode(stream, val, parent) {
|
||||
let { condition } = this;
|
||||
if (typeof condition === 'function') {
|
||||
condition = condition.call(parent, parent);
|
||||
}
|
||||
|
||||
if (condition) {
|
||||
return this.type.encode(stream, val, parent);
|
||||
}
|
||||
}
|
||||
}
|
167
node_modules/restructure/src/Pointer.js
generated
vendored
Normal file
167
node_modules/restructure/src/Pointer.js
generated
vendored
Normal file
@@ -0,0 +1,167 @@
|
||||
import * as utils from './utils.js';
|
||||
import {Base} from './Base.js';
|
||||
|
||||
export class Pointer extends Base {
|
||||
constructor(offsetType, type, options = {}) {
|
||||
super();
|
||||
this.offsetType = offsetType;
|
||||
this.type = type;
|
||||
this.options = options;
|
||||
if (this.type === 'void') { this.type = null; }
|
||||
if (this.options.type == null) { this.options.type = 'local'; }
|
||||
if (this.options.allowNull == null) { this.options.allowNull = true; }
|
||||
if (this.options.nullValue == null) { this.options.nullValue = 0; }
|
||||
if (this.options.lazy == null) { this.options.lazy = false; }
|
||||
if (this.options.relativeTo) {
|
||||
if (typeof this.options.relativeTo !== 'function') {
|
||||
throw new Error('relativeTo option must be a function');
|
||||
}
|
||||
this.relativeToGetter = options.relativeTo;
|
||||
}
|
||||
}
|
||||
|
||||
decode(stream, ctx) {
|
||||
const offset = this.offsetType.decode(stream, ctx);
|
||||
|
||||
// handle NULL pointers
|
||||
if ((offset === this.options.nullValue) && this.options.allowNull) {
|
||||
return null;
|
||||
}
|
||||
|
||||
let relative;
|
||||
switch (this.options.type) {
|
||||
case 'local': relative = ctx._startOffset; break;
|
||||
case 'immediate': relative = stream.pos - this.offsetType.size(); break;
|
||||
case 'parent': relative = ctx.parent._startOffset; break;
|
||||
default:
|
||||
var c = ctx;
|
||||
while (c.parent) {
|
||||
c = c.parent;
|
||||
}
|
||||
|
||||
relative = c._startOffset || 0;
|
||||
}
|
||||
|
||||
if (this.options.relativeTo) {
|
||||
relative += this.relativeToGetter(ctx);
|
||||
}
|
||||
|
||||
const ptr = offset + relative;
|
||||
|
||||
if (this.type != null) {
|
||||
let val = null;
|
||||
const decodeValue = () => {
|
||||
if (val != null) { return val; }
|
||||
|
||||
const { pos } = stream;
|
||||
stream.pos = ptr;
|
||||
val = this.type.decode(stream, ctx);
|
||||
stream.pos = pos;
|
||||
return val;
|
||||
};
|
||||
|
||||
// If this is a lazy pointer, define a getter to decode only when needed.
|
||||
// This obviously only works when the pointer is contained by a Struct.
|
||||
if (this.options.lazy) {
|
||||
return new utils.PropertyDescriptor({
|
||||
get: decodeValue});
|
||||
}
|
||||
|
||||
return decodeValue();
|
||||
} else {
|
||||
return ptr;
|
||||
}
|
||||
}
|
||||
|
||||
size(val, ctx) {
|
||||
const parent = ctx;
|
||||
switch (this.options.type) {
|
||||
case 'local': case 'immediate':
|
||||
break;
|
||||
case 'parent':
|
||||
ctx = ctx.parent;
|
||||
break;
|
||||
default: // global
|
||||
while (ctx.parent) {
|
||||
ctx = ctx.parent;
|
||||
}
|
||||
}
|
||||
|
||||
let { type } = this;
|
||||
if (type == null) {
|
||||
if (!(val instanceof VoidPointer)) {
|
||||
throw new Error("Must be a VoidPointer");
|
||||
}
|
||||
|
||||
({ type } = val);
|
||||
val = val.value;
|
||||
}
|
||||
|
||||
if (val && ctx) {
|
||||
// Must be written as two separate lines rather than += in case `type.size` mutates ctx.pointerSize.
|
||||
let size = type.size(val, parent);
|
||||
ctx.pointerSize += size;
|
||||
}
|
||||
|
||||
return this.offsetType.size();
|
||||
}
|
||||
|
||||
encode(stream, val, ctx) {
|
||||
let relative;
|
||||
const parent = ctx;
|
||||
if ((val == null)) {
|
||||
this.offsetType.encode(stream, this.options.nullValue);
|
||||
return;
|
||||
}
|
||||
|
||||
switch (this.options.type) {
|
||||
case 'local':
|
||||
relative = ctx.startOffset;
|
||||
break;
|
||||
case 'immediate':
|
||||
relative = stream.pos + this.offsetType.size(val, parent);
|
||||
break;
|
||||
case 'parent':
|
||||
ctx = ctx.parent;
|
||||
relative = ctx.startOffset;
|
||||
break;
|
||||
default: // global
|
||||
relative = 0;
|
||||
while (ctx.parent) {
|
||||
ctx = ctx.parent;
|
||||
}
|
||||
}
|
||||
|
||||
if (this.options.relativeTo) {
|
||||
relative += this.relativeToGetter(parent.val);
|
||||
}
|
||||
|
||||
this.offsetType.encode(stream, ctx.pointerOffset - relative);
|
||||
|
||||
let { type } = this;
|
||||
if (type == null) {
|
||||
if (!(val instanceof VoidPointer)) {
|
||||
throw new Error("Must be a VoidPointer");
|
||||
}
|
||||
|
||||
({ type } = val);
|
||||
val = val.value;
|
||||
}
|
||||
|
||||
ctx.pointers.push({
|
||||
type,
|
||||
val,
|
||||
parent
|
||||
});
|
||||
|
||||
return ctx.pointerOffset += type.size(val, parent);
|
||||
}
|
||||
}
|
||||
|
||||
// A pointer whose type is determined at decode time
|
||||
export class VoidPointer {
|
||||
constructor(type, value) {
|
||||
this.type = type;
|
||||
this.value = value;
|
||||
}
|
||||
}
|
23
node_modules/restructure/src/Reserved.js
generated
vendored
Normal file
23
node_modules/restructure/src/Reserved.js
generated
vendored
Normal file
@@ -0,0 +1,23 @@
|
||||
import {Base} from './Base.js';
|
||||
import * as utils from './utils.js';
|
||||
|
||||
export class Reserved extends Base {
|
||||
constructor(type, count = 1) {
|
||||
super();
|
||||
this.type = type;
|
||||
this.count = count;
|
||||
}
|
||||
decode(stream, parent) {
|
||||
stream.pos += this.size(null, parent);
|
||||
return undefined;
|
||||
}
|
||||
|
||||
size(data, parent) {
|
||||
const count = utils.resolveLength(this.count, null, parent);
|
||||
return this.type.size() * count;
|
||||
}
|
||||
|
||||
encode(stream, val, parent) {
|
||||
return stream.fill(0, this.size(val, parent));
|
||||
}
|
||||
}
|
155
node_modules/restructure/src/String.js
generated
vendored
Normal file
155
node_modules/restructure/src/String.js
generated
vendored
Normal file
@@ -0,0 +1,155 @@
|
||||
import {Base} from './Base.js';
|
||||
import {Number as NumberT} from './Number.js';
|
||||
import * as utils from './utils.js';
|
||||
|
||||
class StringT extends Base {
|
||||
constructor(length, encoding = 'ascii') {
|
||||
super();
|
||||
this.length = length;
|
||||
this.encoding = encoding;
|
||||
}
|
||||
|
||||
decode(stream, parent) {
|
||||
let length, pos;
|
||||
|
||||
let { encoding } = this;
|
||||
if (typeof encoding === 'function') {
|
||||
encoding = encoding.call(parent, parent) || 'ascii';
|
||||
}
|
||||
let width = encodingWidth(encoding);
|
||||
|
||||
if (this.length != null) {
|
||||
length = utils.resolveLength(this.length, stream, parent);
|
||||
} else {
|
||||
let buffer;
|
||||
({buffer, length, pos} = stream);
|
||||
|
||||
while ((pos < length - width + 1) &&
|
||||
(buffer[pos] !== 0x00 ||
|
||||
(width === 2 && buffer[pos+1] !== 0x00)
|
||||
)) {
|
||||
pos += width;
|
||||
}
|
||||
|
||||
length = pos - stream.pos;
|
||||
}
|
||||
|
||||
|
||||
const string = stream.readString(length, encoding);
|
||||
|
||||
if ((this.length == null) && (stream.pos < stream.length)) {
|
||||
stream.pos+=width;
|
||||
}
|
||||
|
||||
return string;
|
||||
}
|
||||
|
||||
size(val, parent) {
|
||||
// Use the defined value if no value was given
|
||||
if (val === undefined || val === null) {
|
||||
return utils.resolveLength(this.length, null, parent);
|
||||
}
|
||||
|
||||
let { encoding } = this;
|
||||
if (typeof encoding === 'function') {
|
||||
encoding = encoding.call(parent != null ? parent.val : undefined, parent != null ? parent.val : undefined) || 'ascii';
|
||||
}
|
||||
|
||||
if (encoding === 'utf16be') {
|
||||
encoding = 'utf16le';
|
||||
}
|
||||
|
||||
let size = byteLength(val, encoding);
|
||||
if (this.length instanceof NumberT) {
|
||||
size += this.length.size();
|
||||
}
|
||||
|
||||
if ((this.length == null)) {
|
||||
size += encodingWidth(encoding);
|
||||
}
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
encode(stream, val, parent) {
|
||||
let { encoding } = this;
|
||||
if (typeof encoding === 'function') {
|
||||
encoding = encoding.call(parent != null ? parent.val : undefined, parent != null ? parent.val : undefined) || 'ascii';
|
||||
}
|
||||
|
||||
if (this.length instanceof NumberT) {
|
||||
this.length.encode(stream, byteLength(val, encoding));
|
||||
}
|
||||
|
||||
stream.writeString(val, encoding);
|
||||
|
||||
if ((this.length == null)) {
|
||||
return encodingWidth(encoding) == 2 ?
|
||||
stream.writeUInt16LE(0x0000) :
|
||||
stream.writeUInt8(0x00);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function encodingWidth(encoding) {
|
||||
switch(encoding) {
|
||||
case 'ascii':
|
||||
case 'utf8': // utf8 is a byte-based encoding for zero-term string
|
||||
return 1;
|
||||
case 'utf16le':
|
||||
case 'utf16-le':
|
||||
case 'utf-16be':
|
||||
case 'utf-16le':
|
||||
case 'utf16be':
|
||||
case 'utf16-be':
|
||||
case 'ucs2':
|
||||
return 2;
|
||||
default:
|
||||
//TODO: assume all other encodings are 1-byters
|
||||
//throw new Error('Unknown encoding ' + encoding);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
function byteLength(string, encoding) {
|
||||
switch (encoding) {
|
||||
case 'ascii':
|
||||
return string.length;
|
||||
case 'utf8':
|
||||
let len = 0;
|
||||
for (let i = 0; i < string.length; i++) {
|
||||
let c = string.charCodeAt(i);
|
||||
|
||||
if (c >= 0xd800 && c <= 0xdbff && i < string.length - 1) {
|
||||
let c2 = string.charCodeAt(++i);
|
||||
if ((c2 & 0xfc00) === 0xdc00) {
|
||||
c = ((c & 0x3ff) << 10) + (c2 & 0x3ff) + 0x10000;
|
||||
} else {
|
||||
// unmatched surrogate.
|
||||
i--;
|
||||
}
|
||||
}
|
||||
|
||||
if ((c & 0xffffff80) === 0) {
|
||||
len++;
|
||||
} else if ((c & 0xfffff800) === 0) {
|
||||
len += 2;
|
||||
} else if ((c & 0xffff0000) === 0) {
|
||||
len += 3;
|
||||
} else if ((c & 0xffe00000) === 0) {
|
||||
len += 4;
|
||||
}
|
||||
}
|
||||
return len;
|
||||
case 'utf16le':
|
||||
case 'utf16-le':
|
||||
case 'utf16be':
|
||||
case 'utf16-be':
|
||||
case 'ucs2':
|
||||
return string.length * 2;
|
||||
default:
|
||||
throw new Error('Unknown encoding ' + encoding);
|
||||
}
|
||||
}
|
||||
|
||||
export {StringT as String};
|
113
node_modules/restructure/src/Struct.js
generated
vendored
Normal file
113
node_modules/restructure/src/Struct.js
generated
vendored
Normal file
@@ -0,0 +1,113 @@
|
||||
import {Base} from './Base.js';
|
||||
import * as utils from './utils.js';
|
||||
|
||||
export class Struct extends Base {
|
||||
constructor(fields = {}) {
|
||||
super();
|
||||
this.fields = fields;
|
||||
}
|
||||
|
||||
decode(stream, parent, length = 0) {
|
||||
const res = this._setup(stream, parent, length);
|
||||
this._parseFields(stream, res, this.fields);
|
||||
|
||||
if (this.process != null) {
|
||||
this.process.call(res, stream);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
_setup(stream, parent, length) {
|
||||
const res = {};
|
||||
|
||||
// define hidden properties
|
||||
Object.defineProperties(res, {
|
||||
parent: { value: parent },
|
||||
_startOffset: { value: stream.pos },
|
||||
_currentOffset: { value: 0, writable: true },
|
||||
_length: { value: length }
|
||||
});
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
_parseFields(stream, res, fields) {
|
||||
for (let key in fields) {
|
||||
var val;
|
||||
const type = fields[key];
|
||||
if (typeof type === 'function') {
|
||||
val = type.call(res, res);
|
||||
} else {
|
||||
val = type.decode(stream, res);
|
||||
}
|
||||
|
||||
if (val !== undefined) {
|
||||
if (val instanceof utils.PropertyDescriptor) {
|
||||
Object.defineProperty(res, key, val);
|
||||
} else {
|
||||
res[key] = val;
|
||||
}
|
||||
}
|
||||
|
||||
res._currentOffset = stream.pos - res._startOffset;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
size(val, parent, includePointers = true) {
|
||||
if (val == null) { val = {}; }
|
||||
const ctx = {
|
||||
parent,
|
||||
val,
|
||||
pointerSize: 0
|
||||
};
|
||||
|
||||
if (this.preEncode != null) {
|
||||
this.preEncode.call(val);
|
||||
}
|
||||
|
||||
let size = 0;
|
||||
for (let key in this.fields) {
|
||||
const type = this.fields[key];
|
||||
if (type.size != null) {
|
||||
size += type.size(val[key], ctx);
|
||||
}
|
||||
}
|
||||
|
||||
if (includePointers) {
|
||||
size += ctx.pointerSize;
|
||||
}
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
encode(stream, val, parent) {
|
||||
let type;
|
||||
if (this.preEncode != null) {
|
||||
this.preEncode.call(val, stream);
|
||||
}
|
||||
|
||||
const ctx = {
|
||||
pointers: [],
|
||||
startOffset: stream.pos,
|
||||
parent,
|
||||
val,
|
||||
pointerSize: 0
|
||||
};
|
||||
|
||||
ctx.pointerOffset = stream.pos + this.size(val, ctx, false);
|
||||
|
||||
for (let key in this.fields) {
|
||||
type = this.fields[key];
|
||||
if (type.encode != null) {
|
||||
type.encode(stream, val[key], ctx);
|
||||
}
|
||||
}
|
||||
|
||||
let i = 0;
|
||||
while (i < ctx.pointers.length) {
|
||||
const ptr = ctx.pointers[i++];
|
||||
ptr.type.encode(stream, ptr.val, ptr.parent);
|
||||
}
|
||||
}
|
||||
}
|
139
node_modules/restructure/src/VersionedStruct.js
generated
vendored
Normal file
139
node_modules/restructure/src/VersionedStruct.js
generated
vendored
Normal file
@@ -0,0 +1,139 @@
|
||||
import {Struct} from './Struct.js';
|
||||
|
||||
const getPath = (object, pathArray) => {
|
||||
return pathArray.reduce((prevObj, key) => prevObj && prevObj[key], object);
|
||||
};
|
||||
|
||||
export class VersionedStruct extends Struct {
|
||||
constructor(type, versions = {}) {
|
||||
super();
|
||||
this.type = type;
|
||||
this.versions = versions;
|
||||
if (typeof type === 'string') {
|
||||
this.versionPath = type.split('.');
|
||||
}
|
||||
}
|
||||
|
||||
decode(stream, parent, length = 0) {
|
||||
const res = this._setup(stream, parent, length);
|
||||
|
||||
if (typeof this.type === 'string') {
|
||||
res.version = getPath(parent, this.versionPath);
|
||||
} else {
|
||||
res.version = this.type.decode(stream);
|
||||
}
|
||||
|
||||
if (this.versions.header) {
|
||||
this._parseFields(stream, res, this.versions.header);
|
||||
}
|
||||
|
||||
const fields = this.versions[res.version];
|
||||
if ((fields == null)) {
|
||||
throw new Error(`Unknown version ${res.version}`);
|
||||
}
|
||||
|
||||
if (fields instanceof VersionedStruct) {
|
||||
return fields.decode(stream, parent);
|
||||
}
|
||||
|
||||
this._parseFields(stream, res, fields);
|
||||
|
||||
if (this.process != null) {
|
||||
this.process.call(res, stream);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
size(val, parent, includePointers = true) {
|
||||
let key, type;
|
||||
if (!val) {
|
||||
throw new Error('Not a fixed size');
|
||||
}
|
||||
|
||||
if (this.preEncode != null) {
|
||||
this.preEncode.call(val);
|
||||
}
|
||||
|
||||
const ctx = {
|
||||
parent,
|
||||
val,
|
||||
pointerSize: 0
|
||||
};
|
||||
|
||||
let size = 0;
|
||||
if (typeof this.type !== 'string') {
|
||||
size += this.type.size(val.version, ctx);
|
||||
}
|
||||
|
||||
if (this.versions.header) {
|
||||
for (key in this.versions.header) {
|
||||
type = this.versions.header[key];
|
||||
if (type.size != null) {
|
||||
size += type.size(val[key], ctx);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const fields = this.versions[val.version];
|
||||
if ((fields == null)) {
|
||||
throw new Error(`Unknown version ${val.version}`);
|
||||
}
|
||||
|
||||
for (key in fields) {
|
||||
type = fields[key];
|
||||
if (type.size != null) {
|
||||
size += type.size(val[key], ctx);
|
||||
}
|
||||
}
|
||||
|
||||
if (includePointers) {
|
||||
size += ctx.pointerSize;
|
||||
}
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
encode(stream, val, parent) {
|
||||
let key, type;
|
||||
if (this.preEncode != null) {
|
||||
this.preEncode.call(val, stream);
|
||||
}
|
||||
|
||||
const ctx = {
|
||||
pointers: [],
|
||||
startOffset: stream.pos,
|
||||
parent,
|
||||
val,
|
||||
pointerSize: 0
|
||||
};
|
||||
|
||||
ctx.pointerOffset = stream.pos + this.size(val, ctx, false);
|
||||
|
||||
if (typeof this.type !== 'string') {
|
||||
this.type.encode(stream, val.version);
|
||||
}
|
||||
|
||||
if (this.versions.header) {
|
||||
for (key in this.versions.header) {
|
||||
type = this.versions.header[key];
|
||||
if (type.encode != null) {
|
||||
type.encode(stream, val[key], ctx);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const fields = this.versions[val.version];
|
||||
for (key in fields) {
|
||||
type = fields[key];
|
||||
if (type.encode != null) {
|
||||
type.encode(stream, val[key], ctx);
|
||||
}
|
||||
}
|
||||
|
||||
let i = 0;
|
||||
while (i < ctx.pointers.length) {
|
||||
const ptr = ctx.pointers[i++];
|
||||
ptr.type.encode(stream, ptr.val, ptr.parent);
|
||||
}
|
||||
}
|
||||
}
|
35
node_modules/restructure/src/utils.js
generated
vendored
Normal file
35
node_modules/restructure/src/utils.js
generated
vendored
Normal file
@@ -0,0 +1,35 @@
|
||||
import {Number as NumberT} from './Number.js';
|
||||
|
||||
export function resolveLength(length, stream, parent) {
|
||||
let res;
|
||||
if (typeof length === 'number') {
|
||||
res = length;
|
||||
|
||||
} else if (typeof length === 'function') {
|
||||
res = length.call(parent, parent);
|
||||
|
||||
} else if (parent && (typeof length === 'string')) {
|
||||
res = parent[length];
|
||||
|
||||
} else if (stream && length instanceof NumberT) {
|
||||
res = length.decode(stream);
|
||||
}
|
||||
|
||||
if (isNaN(res)) {
|
||||
throw new Error('Not a fixed size');
|
||||
}
|
||||
|
||||
return res;
|
||||
};
|
||||
|
||||
export class PropertyDescriptor {
|
||||
constructor(opts = {}) {
|
||||
this.enumerable = true;
|
||||
this.configurable = true;
|
||||
|
||||
for (let key in opts) {
|
||||
const val = opts[key];
|
||||
this[key] = val;
|
||||
}
|
||||
}
|
||||
}
|
103
node_modules/restructure/test/Array.js
generated
vendored
Normal file
103
node_modules/restructure/test/Array.js
generated
vendored
Normal file
@@ -0,0 +1,103 @@
|
||||
import assert from 'assert';
|
||||
import {Array as ArrayT, Pointer, uint8, uint16, DecodeStream, EncodeStream} from 'restructure';
|
||||
|
||||
describe('Array', function() {
|
||||
describe('decode', function() {
|
||||
it('should decode fixed length', function() {
|
||||
const buffer = new Uint8Array([1, 2, 3, 4, 5]);
|
||||
const array = new ArrayT(uint8, 4);
|
||||
assert.deepEqual(array.fromBuffer(buffer), [1, 2, 3, 4]);
|
||||
});
|
||||
|
||||
it('should decode fixed amount of bytes', function() {
|
||||
const buffer = new Uint8Array([1, 2, 3, 4, 5]);
|
||||
const array = new ArrayT(uint16, 4, 'bytes');
|
||||
assert.deepEqual(array.fromBuffer(buffer), [258, 772]);
|
||||
});
|
||||
|
||||
it('should decode length from parent key', function() {
|
||||
const stream = new DecodeStream(new Uint8Array([1, 2, 3, 4, 5]));
|
||||
const array = new ArrayT(uint8, 'len');
|
||||
assert.deepEqual(array.decode(stream, {len: 4}), [1, 2, 3, 4]);
|
||||
});
|
||||
|
||||
it('should decode amount of bytes from parent key', function() {
|
||||
const stream = new DecodeStream(new Uint8Array([1, 2, 3, 4, 5]));
|
||||
const array = new ArrayT(uint16, 'len', 'bytes');
|
||||
assert.deepEqual(array.decode(stream, {len: 4}), [258, 772]);
|
||||
});
|
||||
|
||||
it('should decode length as number before array', function() {
|
||||
const buffer = new Uint8Array([4, 1, 2, 3, 4, 5]);
|
||||
const array = new ArrayT(uint8, uint8);
|
||||
assert.deepEqual(array.fromBuffer(buffer), [1, 2, 3, 4]);
|
||||
});
|
||||
|
||||
it('should decode amount of bytes as number before array', function() {
|
||||
const buffer = new Uint8Array([4, 1, 2, 3, 4, 5]);
|
||||
const array = new ArrayT(uint16, uint8, 'bytes');
|
||||
assert.deepEqual(array.fromBuffer(buffer), [258, 772]);
|
||||
});
|
||||
|
||||
it('should decode length from function', function() {
|
||||
const buffer = new Uint8Array([1, 2, 3, 4, 5]);
|
||||
const array = new ArrayT(uint8, function() { return 4; });
|
||||
assert.deepEqual(array.fromBuffer(buffer), [1, 2, 3, 4]);
|
||||
});
|
||||
|
||||
it('should decode amount of bytes from function', function() {
|
||||
const buffer = new Uint8Array([1, 2, 3, 4, 5]);
|
||||
const array = new ArrayT(uint16, (function() { return 4; }), 'bytes');
|
||||
assert.deepEqual(array.fromBuffer(buffer), [258, 772]);
|
||||
});
|
||||
|
||||
it('should decode to the end of the parent if no length is given', function() {
|
||||
const stream = new DecodeStream(new Uint8Array([1, 2, 3, 4, 5]));
|
||||
const array = new ArrayT(uint8);
|
||||
assert.deepEqual(array.decode(stream, {_length: 4, _startOffset: 0}), [1, 2, 3, 4]);
|
||||
});
|
||||
|
||||
it('should decode to the end of the stream if no parent and length is given', function() {
|
||||
const buffer = new Uint8Array([1, 2, 3, 4]);
|
||||
const array = new ArrayT(uint8);
|
||||
assert.deepEqual(array.fromBuffer(buffer), [1, 2, 3, 4]);
|
||||
});
|
||||
});
|
||||
|
||||
describe('size', function() {
|
||||
it('should use array length', function() {
|
||||
const array = new ArrayT(uint8, 10);
|
||||
assert.equal(array.size([1, 2, 3, 4]), 4);
|
||||
});
|
||||
|
||||
it('should add size of length field before string', function() {
|
||||
const array = new ArrayT(uint8, uint8);
|
||||
assert.equal(array.size([1, 2, 3, 4]), 5);
|
||||
});
|
||||
|
||||
it('should use defined length if no value given', function() {
|
||||
const array = new ArrayT(uint8, 10);
|
||||
assert.equal(array.size(), 10);
|
||||
});
|
||||
});
|
||||
|
||||
describe('encode', function() {
|
||||
it('should encode using array length', function() {
|
||||
const array = new ArrayT(uint8, 10);
|
||||
const buffer = array.toBuffer([1, 2, 3, 4]);
|
||||
assert.deepEqual(buffer, new Uint8Array([1, 2, 3, 4]));
|
||||
});
|
||||
|
||||
it('should encode length as number before array', function() {
|
||||
const array = new ArrayT(uint8, uint8);
|
||||
const buffer = array.toBuffer([1, 2, 3, 4]);
|
||||
assert.deepEqual(buffer, new Uint8Array([4, 1, 2, 3, 4]));
|
||||
});
|
||||
|
||||
it('should add pointers after array if length is encoded at start', function() {
|
||||
const array = new ArrayT(new Pointer(uint8, uint8), uint8);
|
||||
const buffer = array.toBuffer([1, 2, 3, 4]);
|
||||
assert.deepEqual(buffer, new Uint8Array([4, 5, 6, 7, 8, 1, 2, 3, 4]));
|
||||
});
|
||||
});
|
||||
});
|
29
node_modules/restructure/test/Bitfield.js
generated
vendored
Normal file
29
node_modules/restructure/test/Bitfield.js
generated
vendored
Normal file
@@ -0,0 +1,29 @@
|
||||
import assert from 'assert';
|
||||
import {Bitfield, uint8, DecodeStream, EncodeStream} from 'restructure';
|
||||
|
||||
describe('Bitfield', function() {
|
||||
const bitfield = new Bitfield(uint8, ['Jack', 'Kack', 'Lack', 'Mack', 'Nack', 'Oack', 'Pack', 'Quack']);
|
||||
const JACK = 1 << 0;
|
||||
const KACK = 1 << 1;
|
||||
const LACK = 1 << 2;
|
||||
const MACK = 1 << 3;
|
||||
const NACK = 1 << 4;
|
||||
const OACK = 1 << 5;
|
||||
const PACK = 1 << 6;
|
||||
const QUACK = 1 << 7;
|
||||
|
||||
it('should have the right size', () => assert.equal(bitfield.size(), 1));
|
||||
|
||||
it('should decode', function() {
|
||||
const buffer = new Uint8Array([JACK | MACK | PACK | NACK | QUACK]);
|
||||
assert.deepEqual(
|
||||
bitfield.fromBuffer(buffer),
|
||||
{Jack: true, Kack: false, Lack: false, Mack: true, Nack: true, Oack: false, Pack: true, Quack: true}
|
||||
);
|
||||
});
|
||||
|
||||
it('should encode', function() {
|
||||
let buffer = bitfield.toBuffer({Jack: true, Kack: false, Lack: false, Mack: true, Nack: true, Oack: false, Pack: true, Quack: true});
|
||||
assert.deepEqual(buffer, Buffer.from([JACK | MACK | PACK | NACK | QUACK]));
|
||||
});
|
||||
});
|
39
node_modules/restructure/test/Boolean.js
generated
vendored
Normal file
39
node_modules/restructure/test/Boolean.js
generated
vendored
Normal file
@@ -0,0 +1,39 @@
|
||||
import assert from 'assert';
|
||||
import {Boolean, uint8, DecodeStream, EncodeStream} from 'restructure';
|
||||
|
||||
describe('Boolean', function() {
|
||||
describe('decode', function() {
|
||||
it('should decode 0 as false', function() {
|
||||
const buffer = new Uint8Array([0]);
|
||||
const boolean = new Boolean(uint8);
|
||||
assert.deepEqual(boolean.fromBuffer(buffer), false);
|
||||
});
|
||||
|
||||
it('should decode 1 as true', function() {
|
||||
const buffer = new Uint8Array([1]);
|
||||
const boolean = new Boolean(uint8);
|
||||
assert.deepEqual(boolean.fromBuffer(buffer), true);
|
||||
});
|
||||
});
|
||||
|
||||
describe('size', () =>
|
||||
it('should return given type size', function() {
|
||||
const boolean = new Boolean(uint8);
|
||||
assert.deepEqual(boolean.size(), 1);
|
||||
})
|
||||
);
|
||||
|
||||
describe('encode', function() {
|
||||
it('should encode false as 0', function() {
|
||||
const boolean = new Boolean(uint8);
|
||||
const buffer = boolean.toBuffer(false);
|
||||
assert.deepEqual(buffer, Buffer.from([0]));
|
||||
});
|
||||
|
||||
it('should encode true as 1', function() {
|
||||
const boolean = new Boolean(uint8);
|
||||
const buffer = boolean.toBuffer(true);
|
||||
assert.deepEqual(buffer, Buffer.from([1]));
|
||||
});
|
||||
});
|
||||
});
|
45
node_modules/restructure/test/Buffer.js
generated
vendored
Normal file
45
node_modules/restructure/test/Buffer.js
generated
vendored
Normal file
@@ -0,0 +1,45 @@
|
||||
import assert from 'assert';
|
||||
import {Buffer as BufferT, uint8, DecodeStream, EncodeStream} from 'restructure';
|
||||
|
||||
describe('Buffer', function() {
|
||||
describe('decode', function() {
|
||||
it('should decode', function() {
|
||||
const buffer = new Uint8Array([0xab, 0xff]);
|
||||
const buf = new BufferT(2);
|
||||
assert.deepEqual(buf.fromBuffer(buffer), new Uint8Array([0xab, 0xff]));
|
||||
});
|
||||
|
||||
it('should decode with parent key length', function() {
|
||||
const stream = new DecodeStream(new Uint8Array([0xab, 0xff, 0x1f, 0xb6]));
|
||||
const buf = new BufferT('len');
|
||||
assert.deepEqual(buf.decode(stream, {len: 3}), new Uint8Array([0xab, 0xff, 0x1f]));
|
||||
assert.deepEqual(buf.decode(stream, {len: 1}), new Uint8Array([0xb6]));
|
||||
});
|
||||
});
|
||||
|
||||
describe('size', function() {
|
||||
it('should return size', function() {
|
||||
const buf = new BufferT(2);
|
||||
assert.equal(buf.size(new Uint8Array([0xab, 0xff])), 2);
|
||||
});
|
||||
|
||||
it('should use defined length if no value given', function() {
|
||||
const array = new BufferT(10);
|
||||
assert.equal(array.size(), 10);
|
||||
});
|
||||
});
|
||||
|
||||
describe('encode', function() {
|
||||
it('should encode', function() {
|
||||
const buf = new BufferT(2);
|
||||
const buffer = buf.toBuffer(new Uint8Array([0xab, 0xff]));
|
||||
assert.deepEqual(buffer, new Uint8Array([0xab, 0xff]));
|
||||
});
|
||||
|
||||
it('should encode length before buffer', function() {
|
||||
const buf = new BufferT(uint8);
|
||||
const buffer = buf.toBuffer(new Uint8Array([0xab, 0xff]));
|
||||
assert.deepEqual(buffer, new Uint8Array([2, 0xab, 0xff]));
|
||||
});
|
||||
});
|
||||
});
|
101
node_modules/restructure/test/DecodeStream.js
generated
vendored
Normal file
101
node_modules/restructure/test/DecodeStream.js
generated
vendored
Normal file
@@ -0,0 +1,101 @@
|
||||
import {DecodeStream} from 'restructure';
|
||||
import assert from 'assert';
|
||||
|
||||
describe('DecodeStream', function() {
|
||||
it('should read a buffer', function() {
|
||||
const buf = new Uint8Array([1,2,3]);
|
||||
const stream = new DecodeStream(buf);
|
||||
assert.deepEqual(stream.readBuffer(buf.length), new Uint8Array([1,2,3]));
|
||||
});
|
||||
|
||||
it('should readUInt16BE', function() {
|
||||
const buf = new Uint8Array([0xab, 0xcd]);
|
||||
const stream = new DecodeStream(buf);
|
||||
assert.deepEqual(stream.readUInt16BE(), 0xabcd);
|
||||
});
|
||||
|
||||
it('should readUInt16LE', function() {
|
||||
const buf = new Uint8Array([0xab, 0xcd]);
|
||||
const stream = new DecodeStream(buf);
|
||||
assert.deepEqual(stream.readUInt16LE(), 0xcdab);
|
||||
});
|
||||
|
||||
it('should readUInt24BE', function() {
|
||||
const buf = new Uint8Array([0xab, 0xcd, 0xef]);
|
||||
const stream = new DecodeStream(buf);
|
||||
assert.deepEqual(stream.readUInt24BE(), 0xabcdef);
|
||||
});
|
||||
|
||||
it('should readUInt24LE', function() {
|
||||
const buf = new Uint8Array([0xab, 0xcd, 0xef]);
|
||||
const stream = new DecodeStream(buf);
|
||||
assert.deepEqual(stream.readUInt24LE(), 0xefcdab);
|
||||
});
|
||||
|
||||
it('should readInt24BE', function() {
|
||||
const buf = new Uint8Array([0xff, 0xab, 0x24]);
|
||||
const stream = new DecodeStream(buf);
|
||||
assert.deepEqual(stream.readInt24BE(), -21724);
|
||||
});
|
||||
|
||||
it('should readInt24LE', function() {
|
||||
const buf = new Uint8Array([0x24, 0xab, 0xff]);
|
||||
const stream = new DecodeStream(buf);
|
||||
assert.deepEqual(stream.readInt24LE(), -21724);
|
||||
});
|
||||
|
||||
describe('readString', function() {
|
||||
it('should decode ascii by default', function() {
|
||||
const buf = Buffer.from('some text', 'ascii');
|
||||
const stream = new DecodeStream(buf);
|
||||
assert.equal(stream.readString(buf.length), 'some text');
|
||||
});
|
||||
|
||||
it('should decode ascii', function() {
|
||||
const buf = Buffer.from('some text', 'ascii');
|
||||
const stream = new DecodeStream(buf);
|
||||
assert.equal(stream.readString(buf.length, 'ascii'), 'some text');
|
||||
});
|
||||
|
||||
it('should decode utf8', function() {
|
||||
const buf = Buffer.from('unicode! 👍', 'utf8');
|
||||
const stream = new DecodeStream(buf);
|
||||
assert.equal(stream.readString(buf.length, 'utf8'), 'unicode! 👍');
|
||||
});
|
||||
|
||||
it('should decode utf16le', function() {
|
||||
const buf = Buffer.from('unicode! 👍', 'utf16le');
|
||||
const stream = new DecodeStream(buf);
|
||||
assert.equal(stream.readString(buf.length, 'utf16le'), 'unicode! 👍');
|
||||
});
|
||||
|
||||
it('should decode ucs2', function() {
|
||||
const buf = Buffer.from('unicode! 👍', 'ucs2');
|
||||
const stream = new DecodeStream(buf);
|
||||
assert.equal(stream.readString(buf.length, 'ucs2'), 'unicode! 👍');
|
||||
});
|
||||
|
||||
it('should decode utf16be', function() {
|
||||
const buf = Buffer.from('unicode! 👍', 'utf16le');
|
||||
for (let i = 0, end = buf.length - 1; i < end; i += 2) {
|
||||
const byte = buf[i];
|
||||
buf[i] = buf[i + 1];
|
||||
buf[i + 1] = byte;
|
||||
}
|
||||
|
||||
const stream = new DecodeStream(buf);
|
||||
assert.equal(stream.readString(buf.length, 'utf16be'), 'unicode! 👍');
|
||||
});
|
||||
|
||||
it('should decode macroman', function() {
|
||||
const buf = new Uint8Array([0x8a, 0x63, 0x63, 0x65, 0x6e, 0x74, 0x65, 0x64, 0x20, 0x63, 0x68, 0x87, 0x72, 0x61, 0x63, 0x74, 0x65, 0x72, 0x73]);
|
||||
const stream = new DecodeStream(buf);
|
||||
assert.equal(stream.readString(buf.length, 'mac'), 'äccented cháracters');
|
||||
});
|
||||
|
||||
it('should return a buffer for unsupported encodings', function() {
|
||||
const stream = new DecodeStream(new Uint8Array([1, 2, 3]));
|
||||
assert.deepEqual(stream.readString(3, 'unsupported'), new Uint8Array([1, 2, 3]));
|
||||
});
|
||||
});
|
||||
});
|
104
node_modules/restructure/test/EncodeStream.js
generated
vendored
Normal file
104
node_modules/restructure/test/EncodeStream.js
generated
vendored
Normal file
@@ -0,0 +1,104 @@
|
||||
import {EncodeStream} from 'restructure';
|
||||
import assert from 'assert';
|
||||
|
||||
describe('EncodeStream', function() {
|
||||
it('should write a buffer', function() {
|
||||
const stream = new EncodeStream(new Uint8Array(3));
|
||||
stream.writeBuffer(new Uint8Array([1,2,3]));
|
||||
assert.deepEqual(stream.buffer, new Uint8Array([1,2,3]));
|
||||
});
|
||||
|
||||
it('should writeUInt16BE', function() {
|
||||
const stream = new EncodeStream(new Uint8Array(2));
|
||||
stream.writeUInt16BE(0xabcd);
|
||||
assert.deepEqual(stream.buffer, new Uint8Array([0xab, 0xcd]));
|
||||
});
|
||||
|
||||
it('should writeUInt16LE', function() {
|
||||
const stream = new EncodeStream(new Uint8Array(2));
|
||||
stream.writeUInt16LE(0xcdab);
|
||||
assert.deepEqual(stream.buffer, new Uint8Array([0xab, 0xcd]));
|
||||
});
|
||||
|
||||
it('should writeUInt24BE', function() {
|
||||
const stream = new EncodeStream(new Uint8Array(3));
|
||||
stream.writeUInt24BE(0xabcdef);
|
||||
assert.deepEqual(stream.buffer, new Uint8Array([0xab, 0xcd, 0xef]));
|
||||
});
|
||||
|
||||
it('should writeUInt24LE', function() {
|
||||
const stream = new EncodeStream(new Uint8Array(3));
|
||||
stream.writeUInt24LE(0xabcdef);
|
||||
assert.deepEqual(stream.buffer, new Uint8Array([0xef, 0xcd, 0xab]));
|
||||
});
|
||||
|
||||
it('should writeInt24BE', function() {
|
||||
const stream = new EncodeStream(new Uint8Array(6));
|
||||
stream.writeInt24BE(-21724);
|
||||
stream.writeInt24BE(0xabcdef);
|
||||
assert.deepEqual(stream.buffer, new Uint8Array([0xff, 0xab, 0x24, 0xab, 0xcd, 0xef]));
|
||||
});
|
||||
|
||||
it('should writeInt24LE', function() {
|
||||
const stream = new EncodeStream(new Uint8Array(6));
|
||||
stream.writeInt24LE(-21724);
|
||||
stream.writeInt24LE(0xabcdef);
|
||||
assert.deepEqual(stream.buffer, new Uint8Array([0x24, 0xab, 0xff, 0xef, 0xcd, 0xab]));
|
||||
});
|
||||
|
||||
it('should fill', function() {
|
||||
const stream = new EncodeStream(new Uint8Array(5));
|
||||
stream.fill(10, 5);
|
||||
assert.deepEqual(stream.buffer, new Uint8Array([10, 10, 10, 10, 10]));
|
||||
});
|
||||
|
||||
describe('writeString', function() {
|
||||
it('should encode ascii by default', function() {
|
||||
const expected = Buffer.from('some text', 'ascii');
|
||||
const stream = new EncodeStream(new Uint8Array(expected.length));
|
||||
stream.writeString('some text');
|
||||
assert.deepEqual(stream.buffer, expected);
|
||||
});
|
||||
|
||||
it('should encode ascii', function() {
|
||||
const expected = Buffer.from('some text', 'ascii');
|
||||
const stream = new EncodeStream(new Uint8Array(expected.length));
|
||||
stream.writeString('some text', 'ascii');
|
||||
assert.deepEqual(stream.buffer, expected);
|
||||
});
|
||||
|
||||
it('should encode utf8', function() {
|
||||
const expected = Buffer.from('unicode! 👍', 'utf8');
|
||||
const stream = new EncodeStream(new Uint8Array(expected.length));
|
||||
stream.writeString('unicode! 👍', 'utf8');
|
||||
assert.deepEqual(stream.buffer, expected);
|
||||
});
|
||||
|
||||
it('should encode utf16le', function() {
|
||||
const expected = Buffer.from('unicode! 👍', 'utf16le');
|
||||
const stream = new EncodeStream(new Uint8Array(expected.length));
|
||||
stream.writeString('unicode! 👍', 'utf16le');
|
||||
assert.deepEqual(stream.buffer, expected);
|
||||
});
|
||||
|
||||
it('should encode ucs2', function() {
|
||||
const expected = Buffer.from('unicode! 👍', 'ucs2');
|
||||
const stream = new EncodeStream(new Uint8Array(expected.length));
|
||||
stream.writeString('unicode! 👍', 'ucs2');
|
||||
assert.deepEqual(stream.buffer, expected);
|
||||
});
|
||||
|
||||
it('should encode utf16be', function() {
|
||||
const expected = Buffer.from('unicode! 👍', 'utf16le');
|
||||
for (let i = 0, end = expected.length - 1; i < end; i += 2) {
|
||||
const byte = expected[i];
|
||||
expected[i] = expected[i + 1];
|
||||
expected[i + 1] = byte;
|
||||
}
|
||||
|
||||
const stream = new EncodeStream(new Uint8Array(expected.length));
|
||||
stream.writeString('unicode! 👍', 'utf16be');
|
||||
assert.deepEqual(stream.buffer, expected);
|
||||
});
|
||||
});
|
||||
});
|
24
node_modules/restructure/test/Enum.js
generated
vendored
Normal file
24
node_modules/restructure/test/Enum.js
generated
vendored
Normal file
@@ -0,0 +1,24 @@
|
||||
import assert from 'assert';
|
||||
import {Enum, uint8, DecodeStream, EncodeStream} from 'restructure';
|
||||
|
||||
describe('Enum', function() {
|
||||
const e = new Enum(uint8, ['foo', 'bar', 'baz']);
|
||||
it('should have the right size', () => assert.equal(e.size(), 1));
|
||||
|
||||
it('should decode', function() {
|
||||
const stream = new DecodeStream(new Uint8Array([1, 2, 0]));
|
||||
assert.equal(e.decode(stream), 'bar');
|
||||
assert.equal(e.decode(stream), 'baz');
|
||||
assert.equal(e.decode(stream), 'foo');
|
||||
});
|
||||
|
||||
it('should encode', function() {
|
||||
assert.deepEqual(e.toBuffer('bar'), new Uint8Array([1]));
|
||||
assert.deepEqual(e.toBuffer('baz'), new Uint8Array([2]));
|
||||
assert.deepEqual(e.toBuffer('foo'), new Uint8Array([0]));
|
||||
});
|
||||
|
||||
it('should throw on unknown option', function() {
|
||||
return assert.throws(() => e.toBuffer('unknown'));
|
||||
});
|
||||
});
|
59
node_modules/restructure/test/LazyArray.js
generated
vendored
Normal file
59
node_modules/restructure/test/LazyArray.js
generated
vendored
Normal file
@@ -0,0 +1,59 @@
|
||||
import assert from 'assert';
|
||||
import {LazyArray, Pointer, uint8, uint16, DecodeStream, EncodeStream} from 'restructure';
|
||||
|
||||
describe('LazyArray', function() {
|
||||
describe('decode', function() {
|
||||
it('should decode items lazily', function() {
|
||||
const stream = new DecodeStream(new Uint8Array([1, 2, 3, 4, 5]));
|
||||
const array = new LazyArray(uint8, 4);
|
||||
|
||||
const arr = array.decode(stream);
|
||||
assert(!(arr instanceof Array));
|
||||
assert.equal(arr.length, 4);
|
||||
assert.equal(stream.pos, 4);
|
||||
|
||||
assert.equal(arr.get(0), 1);
|
||||
assert.equal(arr.get(1), 2);
|
||||
assert.equal(arr.get(2), 3);
|
||||
assert.equal(arr.get(3), 4);
|
||||
|
||||
assert.equal(arr.get(-1), null);
|
||||
assert.equal(arr.get(5), null);
|
||||
});
|
||||
|
||||
it('should be able to convert to an array', function() {
|
||||
const stream = new DecodeStream(new Uint8Array([1, 2, 3, 4, 5]));
|
||||
const array = new LazyArray(uint8, 4);
|
||||
|
||||
const arr = array.decode(stream);
|
||||
assert.deepEqual(arr.toArray(), [1, 2, 3, 4]);
|
||||
});
|
||||
|
||||
it('should decode length as number before array', function() {
|
||||
const stream = new DecodeStream(new Uint8Array([4, 1, 2, 3, 4, 5]));
|
||||
const array = new LazyArray(uint8, uint8);
|
||||
const arr = array.decode(stream);
|
||||
|
||||
assert.deepEqual(arr.toArray(), [1, 2, 3, 4]);
|
||||
});
|
||||
});
|
||||
|
||||
describe('size', () =>
|
||||
it('should work with LazyArrays', function() {
|
||||
const stream = new DecodeStream(new Uint8Array([1, 2, 3, 4, 5]));
|
||||
const array = new LazyArray(uint8, 4);
|
||||
const arr = array.decode(stream);
|
||||
|
||||
assert.equal(array.size(arr), 4);
|
||||
})
|
||||
);
|
||||
|
||||
describe('encode', () =>
|
||||
it('should work with LazyArrays', function() {
|
||||
const array = new LazyArray(uint8, 4);
|
||||
const arr = array.fromBuffer(new Uint8Array([1, 2, 3, 4, 5]));
|
||||
const buffer = array.toBuffer(arr);
|
||||
assert.deepEqual(buffer, new Uint8Array([1, 2, 3, 4]));
|
||||
})
|
||||
);
|
||||
});
|
356
node_modules/restructure/test/Number.js
generated
vendored
Normal file
356
node_modules/restructure/test/Number.js
generated
vendored
Normal file
@@ -0,0 +1,356 @@
|
||||
import {
|
||||
uint8,
|
||||
uint16, uint16be, uint16le,
|
||||
uint24, uint24be, uint24le,
|
||||
uint32, uint32be, uint32le,
|
||||
int8,
|
||||
int16, int16be, int16le,
|
||||
int24, int24be, int24le,
|
||||
int32, int32be, int32le,
|
||||
float, floatbe, floatle,
|
||||
double, doublebe, doublele,
|
||||
fixed16, fixed16be, fixed16le,
|
||||
fixed32, fixed32be, fixed32le,
|
||||
DecodeStream, EncodeStream
|
||||
} from 'restructure';
|
||||
import assert from 'assert';
|
||||
|
||||
describe('Number', function() {
|
||||
describe('uint8', function() {
|
||||
it('should decode', function() {
|
||||
const stream = new DecodeStream(new Uint8Array([0xab, 0xff]));
|
||||
assert.equal(uint8.decode(stream), 0xab);
|
||||
assert.equal(uint8.decode(stream), 0xff);
|
||||
});
|
||||
|
||||
it('should have a size', () => assert.equal(uint8.size(), 1));
|
||||
|
||||
it('should encode', function() {
|
||||
assert.deepEqual(uint8.toBuffer(0xab), new Uint8Array([0xab]));
|
||||
assert.deepEqual(uint8.toBuffer(0xff), new Uint8Array([0xff]));
|
||||
});
|
||||
});
|
||||
|
||||
describe('uint16', () =>
|
||||
it('is an alias for uint16be', () => assert.deepEqual(uint16, uint16be))
|
||||
);
|
||||
|
||||
describe('uint16be', function() {
|
||||
it('should decode', function() {
|
||||
const stream = new DecodeStream(new Uint8Array([0xab, 0xff]));
|
||||
assert.equal(uint16be.decode(stream), 0xabff);
|
||||
});
|
||||
|
||||
it('should have a size', () => assert.equal(uint16be.size(), 2));
|
||||
|
||||
it('should encode', function() {
|
||||
assert.deepEqual(uint16be.toBuffer(0xabff), new Uint8Array([0xab, 0xff]));
|
||||
});
|
||||
});
|
||||
|
||||
describe('uint16le', function() {
|
||||
it('should decode', function() {
|
||||
const stream = new DecodeStream(new Uint8Array([0xff, 0xab]));
|
||||
assert.equal(uint16le.decode(stream), 0xabff);
|
||||
});
|
||||
|
||||
it('should have a size', () => assert.equal(uint16le.size(), 2));
|
||||
|
||||
it('should encode', function() {
|
||||
assert.deepEqual(uint16le.toBuffer(0xabff), new Uint8Array([0xff, 0xab]));
|
||||
});
|
||||
});
|
||||
|
||||
describe('uint24', () =>
|
||||
it('is an alias for uint24be', () => assert.deepEqual(uint24, uint24be))
|
||||
);
|
||||
|
||||
describe('uint24be', function() {
|
||||
it('should decode', function() {
|
||||
const stream = new DecodeStream(new Uint8Array([0xff, 0xab, 0x24]));
|
||||
assert.equal(uint24be.decode(stream), 0xffab24);
|
||||
});
|
||||
|
||||
it('should have a size', () => assert.equal(uint24be.size(), 3));
|
||||
|
||||
it('should encode', function() {
|
||||
assert.deepEqual(uint24be.toBuffer(0xffab24), new Uint8Array([0xff, 0xab, 0x24]));
|
||||
});
|
||||
});
|
||||
|
||||
describe('uint24le', function() {
|
||||
it('should decode', function() {
|
||||
const stream = new DecodeStream(new Uint8Array([0x24, 0xab, 0xff]));
|
||||
assert.equal(uint24le.decode(stream), 0xffab24);
|
||||
});
|
||||
|
||||
it('should have a size', () => assert.equal(uint24le.size(), 3));
|
||||
|
||||
it('should encode', function() {
|
||||
assert.deepEqual(uint24le.toBuffer(0xffab24), new Uint8Array([0x24, 0xab, 0xff]));
|
||||
});
|
||||
});
|
||||
|
||||
describe('uint32', () =>
|
||||
it('is an alias for uint32be', () => assert.deepEqual(uint32, uint32be))
|
||||
);
|
||||
|
||||
describe('uint32be', function() {
|
||||
it('should decode', function() {
|
||||
const stream = new DecodeStream(new Uint8Array([0xff, 0xab, 0x24, 0xbf]));
|
||||
assert.equal(uint32be.decode(stream), 0xffab24bf);
|
||||
});
|
||||
|
||||
it('should have a size', () => assert.equal(uint32be.size(), 4));
|
||||
|
||||
it('should encode', function() {
|
||||
assert.deepEqual(uint32be.toBuffer(0xffab24bf), new Uint8Array([0xff, 0xab, 0x24, 0xbf]));
|
||||
});
|
||||
});
|
||||
|
||||
describe('uint32le', function() {
|
||||
it('should decode', function() {
|
||||
const stream = new DecodeStream(new Uint8Array([0xbf, 0x24, 0xab, 0xff]));
|
||||
assert.equal(uint32le.decode(stream), 0xffab24bf);
|
||||
});
|
||||
|
||||
it('should have a size', () => assert.equal(uint32le.size(), 4));
|
||||
|
||||
it('should encode', function() {
|
||||
assert.deepEqual(uint32le.toBuffer(0xffab24bf), new Uint8Array([0xbf, 0x24, 0xab, 0xff]));
|
||||
});
|
||||
});
|
||||
|
||||
describe('int8', function() {
|
||||
it('should decode', function() {
|
||||
const stream = new DecodeStream(new Uint8Array([0x7f, 0xff]));
|
||||
assert.equal(int8.decode(stream), 127);
|
||||
assert.equal(int8.decode(stream), -1);
|
||||
});
|
||||
|
||||
it('should have a size', () => assert.equal(int8.size(), 1));
|
||||
|
||||
it('should encode', function() {
|
||||
assert.deepEqual(uint8.toBuffer(127), new Uint8Array([0x7f]));
|
||||
assert.deepEqual(uint8.toBuffer(-1), new Uint8Array([0xff]));
|
||||
});
|
||||
});
|
||||
|
||||
describe('int16', () =>
|
||||
it('is an alias for int16be', () => assert.deepEqual(int16, int16be))
|
||||
);
|
||||
|
||||
describe('int16be', function() {
|
||||
it('should decode', function() {
|
||||
const stream = new DecodeStream(new Uint8Array([0xff, 0xab]));
|
||||
assert.equal(int16be.decode(stream), -85);
|
||||
});
|
||||
|
||||
it('should have a size', () => assert.equal(int16be.size(), 2));
|
||||
|
||||
it('should encode', function() {
|
||||
assert.deepEqual(int16be.toBuffer(-85), new Uint8Array([0xff, 0xab]));
|
||||
});
|
||||
});
|
||||
|
||||
describe('int16le', function() {
|
||||
it('should decode', function() {
|
||||
const stream = new DecodeStream(new Uint8Array([0xab, 0xff]));
|
||||
assert.equal(int16le.decode(stream), -85);
|
||||
});
|
||||
|
||||
it('should have a size', () => assert.equal(int16le.size(), 2));
|
||||
|
||||
it('should encode', function() {
|
||||
assert.deepEqual(int16le.toBuffer(-85), new Uint8Array([0xab, 0xff]));
|
||||
});
|
||||
});
|
||||
|
||||
describe('int24', () =>
|
||||
it('is an alias for int24be', () => assert.deepEqual(int24, int24be))
|
||||
);
|
||||
|
||||
describe('int24be', function() {
|
||||
it('should decode', function() {
|
||||
const stream = new DecodeStream(new Uint8Array([0xff, 0xab, 0x24]));
|
||||
assert.equal(int24be.decode(stream), -21724);
|
||||
});
|
||||
|
||||
it('should have a size', () => assert.equal(int24be.size(), 3));
|
||||
|
||||
it('should encode', function() {
|
||||
assert.deepEqual(int24be.toBuffer(-21724), new Uint8Array([0xff, 0xab, 0x24]));
|
||||
});
|
||||
});
|
||||
|
||||
describe('int24le', function() {
|
||||
it('should decode', function() {
|
||||
const stream = new DecodeStream(new Uint8Array([0x24, 0xab, 0xff]));
|
||||
assert.equal(int24le.decode(stream), -21724);
|
||||
});
|
||||
|
||||
it('should have a size', () => assert.equal(int24le.size(), 3));
|
||||
|
||||
it('should encode', function() {
|
||||
assert.deepEqual(int24le.toBuffer(-21724), new Uint8Array([0x24, 0xab, 0xff]));
|
||||
});
|
||||
});
|
||||
|
||||
describe('int32', () =>
|
||||
it('is an alias for int32be', () => assert.deepEqual(int32, int32be))
|
||||
);
|
||||
|
||||
describe('int32be', function() {
|
||||
it('should decode', function() {
|
||||
const stream = new DecodeStream(new Uint8Array([0xff, 0xab, 0x24, 0xbf]));
|
||||
assert.equal(int32be.decode(stream), -5561153);
|
||||
});
|
||||
|
||||
it('should have a size', () => assert.equal(int32be.size(), 4));
|
||||
|
||||
it('should encode', function() {
|
||||
assert.deepEqual(int32be.toBuffer(-5561153), new Uint8Array([0xff, 0xab, 0x24, 0xbf]));
|
||||
});
|
||||
});
|
||||
|
||||
describe('int32le', function() {
|
||||
it('should decode', function() {
|
||||
const stream = new DecodeStream(new Uint8Array([0xbf, 0x24, 0xab, 0xff]));
|
||||
assert.equal(int32le.decode(stream), -5561153);
|
||||
});
|
||||
|
||||
it('should have a size', () => assert.equal(int32le.size(), 4));
|
||||
|
||||
it('should encode', function() {
|
||||
assert.deepEqual(int32le.toBuffer(-5561153), new Uint8Array([0xbf, 0x24, 0xab, 0xff]));
|
||||
});
|
||||
});
|
||||
|
||||
describe('float', () =>
|
||||
it('is an alias for floatbe', () => assert.deepEqual(float, floatbe))
|
||||
);
|
||||
|
||||
describe('floatbe', function() {
|
||||
it('should decode', function() {
|
||||
const value = floatbe.fromBuffer(new Uint8Array([0x43, 0x7a, 0x8c, 0xcd]));
|
||||
assert(value >= 250.55 - 0.005);
|
||||
assert(value <= 250.55 + 0.005);
|
||||
});
|
||||
|
||||
it('should have a size', () => assert.equal(floatbe.size(), 4));
|
||||
|
||||
it('should encode', function() {
|
||||
assert.deepEqual(floatbe.toBuffer(250.55), new Uint8Array([0x43, 0x7a, 0x8c, 0xcd]));
|
||||
});
|
||||
});
|
||||
|
||||
describe('floatle', function() {
|
||||
it('should decode', function() {
|
||||
const value = floatle.fromBuffer(new Uint8Array([0xcd, 0x8c, 0x7a, 0x43]));
|
||||
assert(value >= 250.55 - 0.005);
|
||||
assert(value <= 250.55 + 0.005);
|
||||
});
|
||||
|
||||
it('should have a size', () => assert.equal(floatle.size(), 4));
|
||||
|
||||
it('should encode', function() {
|
||||
assert.deepEqual(floatle.toBuffer(250.55), new Uint8Array([0xcd, 0x8c, 0x7a, 0x43]));
|
||||
});
|
||||
});
|
||||
|
||||
describe('double', () =>
|
||||
it('is an alias for doublebe', () => assert.deepEqual(double, doublebe))
|
||||
);
|
||||
|
||||
describe('doublebe', function() {
|
||||
it('should decode', function() {
|
||||
const value = doublebe.fromBuffer(new Uint8Array([0x40, 0x93, 0x4a, 0x3d, 0x70, 0xa3, 0xd7, 0x0a]));
|
||||
assert(value >= 1234.56 - 0.005);
|
||||
assert(value <= 1234.56 + 0.005);
|
||||
});
|
||||
|
||||
it('should have a size', () => assert.equal(doublebe.size(), 8));
|
||||
|
||||
it('should encode', function() {
|
||||
assert.deepEqual(doublebe.toBuffer(1234.56), new Uint8Array([0x40, 0x93, 0x4a, 0x3d, 0x70, 0xa3, 0xd7, 0x0a]));
|
||||
});
|
||||
});
|
||||
|
||||
describe('doublele', function() {
|
||||
it('should decode', function() {
|
||||
const value = doublele.fromBuffer(new Uint8Array([0x0a, 0xd7, 0xa3, 0x70, 0x3d, 0x4a, 0x93, 0x40]));
|
||||
assert(value >= 1234.56 - 0.005);
|
||||
assert(value <= 1234.56 + 0.005);
|
||||
});
|
||||
|
||||
it('should have a size', () => assert.equal(doublele.size(), 8));
|
||||
|
||||
it('should encode', function() {
|
||||
assert.deepEqual(doublele.toBuffer(1234.56), new Uint8Array([0x0a, 0xd7, 0xa3, 0x70, 0x3d, 0x4a, 0x93, 0x40]));
|
||||
});
|
||||
});
|
||||
|
||||
describe('fixed16', () =>
|
||||
it('is an alias for fixed16be', () => assert.deepEqual(fixed16, fixed16be))
|
||||
);
|
||||
|
||||
describe('fixed16be', function() {
|
||||
it('should decode', function() {
|
||||
const value = fixed16be.fromBuffer(new Uint8Array([0x19, 0x57]));
|
||||
assert(value >= 25.34 - 0.005);
|
||||
assert(value <= 25.34 + 0.005);
|
||||
});
|
||||
|
||||
it('should have a size', () => assert.equal(fixed16be.size(), 2));
|
||||
|
||||
it('should encode', function() {
|
||||
assert.deepEqual(fixed16be.toBuffer(25.34), new Uint8Array([0x19, 0x57]));
|
||||
});
|
||||
});
|
||||
|
||||
describe('fixed16le', function() {
|
||||
it('should decode', function() {
|
||||
const value = fixed16le.fromBuffer(new Uint8Array([0x57, 0x19]));
|
||||
assert(value >= 25.34 - 0.005);
|
||||
assert(value <= 25.34 + 0.005);
|
||||
});
|
||||
|
||||
it('should have a size', () => assert.equal(fixed16le.size(), 2));
|
||||
|
||||
it('should encode', function() {
|
||||
assert.deepEqual(fixed16le.toBuffer(25.34), new Uint8Array([0x57, 0x19]));
|
||||
});
|
||||
});
|
||||
|
||||
describe('fixed32', () =>
|
||||
it('is an alias for fixed32be', () => assert.deepEqual(fixed32, fixed32be))
|
||||
);
|
||||
|
||||
describe('fixed32be', function() {
|
||||
it('should decode', function() {
|
||||
const value = fixed32be.fromBuffer(new Uint8Array([0x00, 0xfa, 0x8c, 0xcc]));
|
||||
assert(value >= 250.55 - 0.005);
|
||||
assert(value <= 250.55 + 0.005);
|
||||
});
|
||||
|
||||
it('should have a size', () => assert.equal(fixed32be.size(), 4));
|
||||
|
||||
it('should encode', function() {
|
||||
assert.deepEqual(fixed32be.toBuffer(250.55), new Uint8Array([0x00, 0xfa, 0x8c, 0xcc]));
|
||||
});
|
||||
});
|
||||
|
||||
describe('fixed32le', function() {
|
||||
it('should decode', function() {
|
||||
const value = fixed32le.fromBuffer(new Uint8Array([0xcc, 0x8c, 0xfa, 0x00]));
|
||||
assert(value >= 250.55 - 0.005);
|
||||
assert(value <= 250.55 + 0.005);
|
||||
});
|
||||
|
||||
it('should have a size', () => assert.equal(fixed32le.size(), 4));
|
||||
|
||||
it('should encode', function() {
|
||||
assert.deepEqual(fixed32le.toBuffer(250.55), new Uint8Array([0xcc, 0x8c, 0xfa, 0x00]));
|
||||
});
|
||||
});
|
||||
});
|
100
node_modules/restructure/test/Optional.js
generated
vendored
Normal file
100
node_modules/restructure/test/Optional.js
generated
vendored
Normal file
@@ -0,0 +1,100 @@
|
||||
import assert from 'assert';
|
||||
import {Optional, uint8, DecodeStream, EncodeStream} from 'restructure';
|
||||
|
||||
describe('Optional', function() {
|
||||
describe('decode', function() {
|
||||
it('should not decode when condition is falsy', function() {
|
||||
const stream = new DecodeStream(new Uint8Array([0]));
|
||||
const optional = new Optional(uint8, false);
|
||||
assert.equal(optional.decode(stream), null);
|
||||
assert.equal(stream.pos, 0);
|
||||
});
|
||||
|
||||
it('should not decode when condition is a function and falsy', function() {
|
||||
const stream = new DecodeStream(new Uint8Array([0]));
|
||||
const optional = new Optional(uint8, function() { return false; });
|
||||
assert.equal(optional.decode(stream), null);
|
||||
assert.equal(stream.pos, 0);
|
||||
});
|
||||
|
||||
it('should decode when condition is omitted', function() {
|
||||
const stream = new DecodeStream(new Uint8Array([0]));
|
||||
const optional = new Optional(uint8);
|
||||
assert(optional.decode(stream) != null);
|
||||
assert.equal(stream.pos, 1);
|
||||
});
|
||||
|
||||
it('should decode when condition is truthy', function() {
|
||||
const stream = new DecodeStream(new Uint8Array([0]));
|
||||
const optional = new Optional(uint8, true);
|
||||
assert(optional.decode(stream) != null);
|
||||
assert.equal(stream.pos, 1);
|
||||
});
|
||||
|
||||
it('should decode when condition is a function and truthy', function() {
|
||||
const stream = new DecodeStream(new Uint8Array([0]));
|
||||
const optional = new Optional(uint8, function() { return true; });
|
||||
assert(optional.decode(stream) != null);
|
||||
assert.equal(stream.pos, 1);
|
||||
});
|
||||
});
|
||||
|
||||
describe('size', function() {
|
||||
it('should return 0 when condition is falsy', function() {
|
||||
const stream = new DecodeStream(new Uint8Array([0]));
|
||||
const optional = new Optional(uint8, false);
|
||||
assert.equal(optional.size(), 0);
|
||||
});
|
||||
|
||||
it('should return 0 when condition is a function and falsy', function() {
|
||||
const stream = new DecodeStream(new Uint8Array([0]));
|
||||
const optional = new Optional(uint8, function() { return false; });
|
||||
assert.equal(optional.size(), 0);
|
||||
});
|
||||
|
||||
it('should return given type size when condition is omitted', function() {
|
||||
const stream = new DecodeStream(new Uint8Array([0]));
|
||||
const optional = new Optional(uint8);
|
||||
assert.equal(optional.size(), 1);
|
||||
});
|
||||
|
||||
it('should return given type size when condition is truthy', function() {
|
||||
const stream = new DecodeStream(new Uint8Array([0]));
|
||||
const optional = new Optional(uint8, true);
|
||||
assert.equal(optional.size(), 1);
|
||||
});
|
||||
|
||||
it('should return given type size when condition is a function and truthy', function() {
|
||||
const stream = new DecodeStream(new Uint8Array([0]));
|
||||
const optional = new Optional(uint8, function() { return true; });
|
||||
assert.equal(optional.size(), 1);
|
||||
});
|
||||
});
|
||||
|
||||
describe('encode', function() {
|
||||
it('should not encode when condition is falsy', function() {
|
||||
const optional = new Optional(uint8, false);
|
||||
assert.deepEqual(optional.toBuffer(128), new Uint8Array(0));
|
||||
});
|
||||
|
||||
it('should not encode when condition is a function and falsy', function() {
|
||||
const optional = new Optional(uint8, function() { return false; });
|
||||
assert.deepEqual(optional.toBuffer(128), new Uint8Array(0));
|
||||
});
|
||||
|
||||
it('should encode when condition is omitted', function() {
|
||||
const optional = new Optional(uint8);
|
||||
assert.deepEqual(optional.toBuffer(128), new Uint8Array([128]));
|
||||
});
|
||||
|
||||
it('should encode when condition is truthy', function() {
|
||||
const optional = new Optional(uint8, true);
|
||||
assert.deepEqual(optional.toBuffer(128), new Uint8Array([128]));
|
||||
});
|
||||
|
||||
it('should encode when condition is a function and truthy', function() {
|
||||
const optional = new Optional(uint8, function() { return true; });
|
||||
assert.deepEqual(optional.toBuffer(128), new Uint8Array([128]));
|
||||
});
|
||||
});
|
||||
});
|
289
node_modules/restructure/test/Pointer.js
generated
vendored
Normal file
289
node_modules/restructure/test/Pointer.js
generated
vendored
Normal file
@@ -0,0 +1,289 @@
|
||||
import assert from 'assert';
|
||||
import {Pointer, VoidPointer, uint8, DecodeStream, EncodeStream, Struct} from 'restructure';
|
||||
|
||||
describe('Pointer', function() {
|
||||
describe('decode', function() {
|
||||
it('should handle null pointers', function() {
|
||||
const stream = new DecodeStream(new Uint8Array([0]));
|
||||
const pointer = new Pointer(uint8, uint8);
|
||||
return assert.equal(pointer.decode(stream, {_startOffset: 50}), null);
|
||||
});
|
||||
|
||||
it('should use local offsets from start of parent by default', function() {
|
||||
const stream = new DecodeStream(new Uint8Array([1, 53]));
|
||||
const pointer = new Pointer(uint8, uint8);
|
||||
assert.equal(pointer.decode(stream, {_startOffset: 0}), 53);
|
||||
});
|
||||
|
||||
it('should support immediate offsets', function() {
|
||||
const stream = new DecodeStream(new Uint8Array([1, 53]));
|
||||
const pointer = new Pointer(uint8, uint8, {type: 'immediate'});
|
||||
assert.equal(pointer.decode(stream), 53);
|
||||
});
|
||||
|
||||
it('should support offsets relative to the parent', function() {
|
||||
const stream = new DecodeStream(new Uint8Array([0, 0, 1, 53]));
|
||||
stream.pos = 2;
|
||||
const pointer = new Pointer(uint8, uint8, {type: 'parent'});
|
||||
assert.equal(pointer.decode(stream, {parent: {_startOffset: 2}}), 53);
|
||||
});
|
||||
|
||||
it('should support global offsets', function() {
|
||||
const stream = new DecodeStream(new Uint8Array([1, 2, 4, 0, 0, 0, 53]));
|
||||
const pointer = new Pointer(uint8, uint8, {type: 'global'});
|
||||
stream.pos = 2;
|
||||
assert.equal(pointer.decode(stream, {parent: {parent: {_startOffset: 2}}}), 53);
|
||||
});
|
||||
|
||||
it('should support offsets relative to a property on the parent', function() {
|
||||
const stream = new DecodeStream(new Uint8Array([1, 0, 0, 0, 0, 53]));
|
||||
const pointer = new Pointer(uint8, uint8, {relativeTo: ctx => ctx.parent.ptr});
|
||||
assert.equal(pointer.decode(stream, {_startOffset: 0, parent: {ptr: 4}}), 53);
|
||||
});
|
||||
|
||||
it('should throw when passing a non function relativeTo option', function() {
|
||||
return assert.throws(() => new Pointer(uint8, uint8, {relativeTo: 'parent.ptr'}));
|
||||
});
|
||||
|
||||
it('should support returning pointer if there is no decode type', function() {
|
||||
const stream = new DecodeStream(new Uint8Array([4]));
|
||||
const pointer = new Pointer(uint8, 'void');
|
||||
assert.equal(pointer.decode(stream, {_startOffset: 0}), 4);
|
||||
});
|
||||
|
||||
it('should support decoding pointers lazily', function() {
|
||||
const stream = new DecodeStream(new Uint8Array([1, 53]));
|
||||
const struct = new Struct({
|
||||
ptr: new Pointer(uint8, uint8, {lazy: true})});
|
||||
|
||||
const res = struct.decode(stream);
|
||||
assert.equal(typeof Object.getOwnPropertyDescriptor(res, 'ptr').get, 'function');
|
||||
assert.equal(Object.getOwnPropertyDescriptor(res, 'ptr').enumerable, true);
|
||||
assert.equal(res.ptr, 53);
|
||||
});
|
||||
});
|
||||
|
||||
describe('size', function() {
|
||||
it('should add to local pointerSize', function() {
|
||||
const pointer = new Pointer(uint8, uint8);
|
||||
const ctx = {pointerSize: 0};
|
||||
assert.equal(pointer.size(10, ctx), 1);
|
||||
assert.equal(ctx.pointerSize, 1);
|
||||
});
|
||||
|
||||
it('should add to immediate pointerSize', function() {
|
||||
const pointer = new Pointer(uint8, uint8, {type: 'immediate'});
|
||||
const ctx = {pointerSize: 0};
|
||||
assert.equal(pointer.size(10, ctx), 1);
|
||||
assert.equal(ctx.pointerSize, 1);
|
||||
});
|
||||
|
||||
it('should add to parent pointerSize', function() {
|
||||
const pointer = new Pointer(uint8, uint8, {type: 'parent'});
|
||||
const ctx = {parent: {pointerSize: 0}};
|
||||
assert.equal(pointer.size(10, ctx), 1);
|
||||
assert.equal(ctx.parent.pointerSize, 1);
|
||||
});
|
||||
|
||||
it('should add to global pointerSize', function() {
|
||||
const pointer = new Pointer(uint8, uint8, {type: 'global'});
|
||||
const ctx = {parent: {parent: {parent: {pointerSize: 0}}}};
|
||||
assert.equal(pointer.size(10, ctx), 1);
|
||||
assert.equal(ctx.parent.parent.parent.pointerSize, 1);
|
||||
});
|
||||
|
||||
it('should handle void pointers', function() {
|
||||
const pointer = new Pointer(uint8, 'void');
|
||||
const ctx = {pointerSize: 0};
|
||||
assert.equal(pointer.size(new VoidPointer(uint8, 50), ctx), 1);
|
||||
assert.equal(ctx.pointerSize, 1);
|
||||
});
|
||||
|
||||
it('should throw if no type and not a void pointer', function() {
|
||||
const pointer = new Pointer(uint8, 'void');
|
||||
const ctx = {pointerSize: 0};
|
||||
assert.throws(() => pointer.size(30, ctx));
|
||||
});
|
||||
|
||||
it('should return a fixed size without a value', function() {
|
||||
const pointer = new Pointer(uint8, uint8);
|
||||
assert.equal(pointer.size(), 1);
|
||||
});
|
||||
});
|
||||
|
||||
describe('encode', function() {
|
||||
it('should handle null pointers', function() {
|
||||
const ptr = new Pointer(uint8, uint8);
|
||||
const ctx = {
|
||||
pointerSize: 0,
|
||||
startOffset: 0,
|
||||
pointerOffset: 0,
|
||||
pointers: []
|
||||
};
|
||||
|
||||
const stream = new EncodeStream(new Uint8Array(ptr.size(null)));
|
||||
ptr.encode(stream, null, ctx);
|
||||
assert.equal(ctx.pointerSize, 0);
|
||||
|
||||
assert.deepEqual(stream.buffer, new Uint8Array([0]));
|
||||
});
|
||||
|
||||
it('should handle local offsets', function() {
|
||||
const ptr = new Pointer(uint8, uint8);
|
||||
const ctx = {
|
||||
pointerSize: 0,
|
||||
startOffset: 0,
|
||||
pointerOffset: 1,
|
||||
pointers: []
|
||||
};
|
||||
|
||||
const stream = new EncodeStream(new Uint8Array(ptr.size(10)));
|
||||
ptr.encode(stream, 10, ctx);
|
||||
assert.equal(ctx.pointerOffset, 2);
|
||||
assert.deepEqual(ctx.pointers, [
|
||||
{ type: uint8, val: 10, parent: ctx }
|
||||
]);
|
||||
|
||||
assert.deepEqual(stream.buffer, new Uint8Array([1]));
|
||||
});
|
||||
|
||||
it('should handle immediate offsets', function() {
|
||||
const ptr = new Pointer(uint8, uint8, {type: 'immediate'});
|
||||
const ctx = {
|
||||
pointerSize: 0,
|
||||
startOffset: 0,
|
||||
pointerOffset: 1,
|
||||
pointers: []
|
||||
};
|
||||
|
||||
const stream = new EncodeStream(new Uint8Array(ptr.size(10)));
|
||||
ptr.encode(stream, 10, ctx);
|
||||
assert.equal(ctx.pointerOffset, 2);
|
||||
assert.deepEqual(ctx.pointers, [
|
||||
{ type: uint8, val: 10, parent: ctx }
|
||||
]);
|
||||
|
||||
assert.deepEqual(stream.buffer, new Uint8Array([0]));
|
||||
});
|
||||
|
||||
it('should handle immediate offsets', function() {
|
||||
const ptr = new Pointer(uint8, uint8, {type: 'immediate'});
|
||||
const ctx = {
|
||||
pointerSize: 0,
|
||||
startOffset: 0,
|
||||
pointerOffset: 1,
|
||||
pointers: []
|
||||
};
|
||||
|
||||
const stream = new EncodeStream(new Uint8Array(ptr.size(10)));
|
||||
ptr.encode(stream, 10, ctx);
|
||||
assert.equal(ctx.pointerOffset, 2);
|
||||
assert.deepEqual(ctx.pointers, [
|
||||
{ type: uint8, val: 10, parent: ctx }
|
||||
]);
|
||||
|
||||
assert.deepEqual(stream.buffer, new Uint8Array([0]));
|
||||
});
|
||||
|
||||
it('should handle offsets relative to parent', function() {
|
||||
const ptr = new Pointer(uint8, uint8, {type: 'parent'});
|
||||
const ctx = {
|
||||
parent: {
|
||||
pointerSize: 0,
|
||||
startOffset: 3,
|
||||
pointerOffset: 5,
|
||||
pointers: []
|
||||
}
|
||||
};
|
||||
|
||||
const stream = new EncodeStream(new Uint8Array(ptr.size(10, {parent: {...ctx.parent}})));
|
||||
ptr.encode(stream, 10, ctx);
|
||||
assert.equal(ctx.parent.pointerOffset, 6);
|
||||
assert.deepEqual(ctx.parent.pointers, [
|
||||
{ type: uint8, val: 10, parent: ctx }
|
||||
]);
|
||||
|
||||
assert.deepEqual(stream.buffer, new Uint8Array([2]));
|
||||
});
|
||||
|
||||
it('should handle global offsets', function() {
|
||||
const ptr = new Pointer(uint8, uint8, {type: 'global'});
|
||||
const ctx = {
|
||||
parent: {
|
||||
parent: {
|
||||
parent: {
|
||||
pointerSize: 0,
|
||||
startOffset: 3,
|
||||
pointerOffset: 5,
|
||||
pointers: []
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
const stream = new EncodeStream(new Uint8Array(ptr.size(10, JSON.parse(JSON.stringify(ctx)))));
|
||||
ptr.encode(stream, 10, ctx);
|
||||
assert.equal(ctx.parent.parent.parent.pointerOffset, 6);
|
||||
assert.deepEqual(ctx.parent.parent.parent.pointers, [
|
||||
{ type: uint8, val: 10, parent: ctx }
|
||||
]);
|
||||
|
||||
assert.deepEqual(stream.buffer, new Uint8Array([5]));
|
||||
});
|
||||
|
||||
it('should support offsets relative to a property on the parent', function() {
|
||||
const ptr = new Pointer(uint8, uint8, {relativeTo: ctx => ctx.ptr});
|
||||
const ctx = {
|
||||
pointerSize: 0,
|
||||
startOffset: 0,
|
||||
pointerOffset: 10,
|
||||
pointers: [],
|
||||
val: {
|
||||
ptr: 4
|
||||
}
|
||||
};
|
||||
|
||||
const stream = new EncodeStream(new Uint8Array(ptr.size(10, {...ctx})));
|
||||
ptr.encode(stream, 10, ctx);
|
||||
assert.equal(ctx.pointerOffset, 11);
|
||||
assert.deepEqual(ctx.pointers, [
|
||||
{ type: uint8, val: 10, parent: ctx }
|
||||
]);
|
||||
|
||||
assert.deepEqual(stream.buffer, new Uint8Array([6]));
|
||||
});
|
||||
|
||||
it('should support void pointers', function() {
|
||||
const ptr = new Pointer(uint8, 'void');
|
||||
const ctx = {
|
||||
pointerSize: 0,
|
||||
startOffset: 0,
|
||||
pointerOffset: 1,
|
||||
pointers: []
|
||||
};
|
||||
|
||||
const val = new VoidPointer(uint8, 55);
|
||||
const stream = new EncodeStream(new Uint8Array(ptr.size(val, {...ctx})));
|
||||
ptr.encode(stream, val, ctx);
|
||||
assert.equal(ctx.pointerOffset, 2);
|
||||
assert.deepEqual(ctx.pointers, [
|
||||
{ type: uint8, val: 55, parent: ctx }
|
||||
]);
|
||||
|
||||
assert.deepEqual(stream.buffer, new Uint8Array([1]));
|
||||
});
|
||||
|
||||
it('should throw if not a void pointer instance', function() {
|
||||
const ptr = new Pointer(uint8, 'void');
|
||||
const ctx = {
|
||||
pointerSize: 0,
|
||||
startOffset: 0,
|
||||
pointerOffset: 1,
|
||||
pointers: []
|
||||
};
|
||||
|
||||
const stream = new EncodeStream(new Uint8Array(0));
|
||||
assert.throws(() => ptr.encode(stream, 44, ctx));
|
||||
});
|
||||
});
|
||||
});
|
26
node_modules/restructure/test/Reserved.js
generated
vendored
Normal file
26
node_modules/restructure/test/Reserved.js
generated
vendored
Normal file
@@ -0,0 +1,26 @@
|
||||
import assert from 'assert';
|
||||
import {Reserved, uint8, uint16, DecodeStream, EncodeStream} from 'restructure';
|
||||
|
||||
describe('Reserved', function() {
|
||||
it('should have a default count of 1', function() {
|
||||
const reserved = new Reserved(uint8);
|
||||
assert.equal(reserved.size(), 1);
|
||||
});
|
||||
|
||||
it('should allow custom counts and types', function() {
|
||||
const reserved = new Reserved(uint16, 10);
|
||||
assert.equal(reserved.size(), 20);
|
||||
});
|
||||
|
||||
it('should decode', function() {
|
||||
const stream = new DecodeStream(new Uint8Array([0, 0]));
|
||||
const reserved = new Reserved(uint16);
|
||||
assert.equal(reserved.decode(stream), null);
|
||||
assert.equal(stream.pos, 2);
|
||||
});
|
||||
|
||||
it('should encode', function() {
|
||||
const reserved = new Reserved(uint16);
|
||||
assert.deepEqual(reserved.toBuffer(), new Uint8Array([0, 0]));
|
||||
});
|
||||
});
|
151
node_modules/restructure/test/String.js
generated
vendored
Normal file
151
node_modules/restructure/test/String.js
generated
vendored
Normal file
@@ -0,0 +1,151 @@
|
||||
import assert from 'assert';
|
||||
import {String as StringT, uint16le, uint8, DecodeStream, Struct} from 'restructure';
|
||||
|
||||
describe('String', function() {
|
||||
describe('decode', function() {
|
||||
it('should decode fixed length', function() {
|
||||
const string = new StringT(7);
|
||||
assert.equal(string.fromBuffer(Buffer.from('testing')), 'testing');
|
||||
});
|
||||
|
||||
it('should decode length from parent key', function() {
|
||||
const stream = new DecodeStream(Buffer.from('testing'));
|
||||
const string = new StringT('len');
|
||||
assert.equal(string.decode(stream, {len: 7}), 'testing');
|
||||
});
|
||||
|
||||
it('should decode length as number before string', function() {
|
||||
const string = new StringT(uint8);
|
||||
assert.equal(string.fromBuffer(Buffer.from('\x07testing')), 'testing');
|
||||
});
|
||||
|
||||
it('should decode utf8', function() {
|
||||
const string = new StringT(4, 'utf8');
|
||||
assert.equal(string.fromBuffer(Buffer.from('🍻')), '🍻');
|
||||
});
|
||||
|
||||
it('should decode encoding computed from function', function() {
|
||||
const string = new StringT(4, function() { return 'utf8'; });
|
||||
assert.equal(string.fromBuffer(Buffer.from('🍻')), '🍻');
|
||||
});
|
||||
|
||||
it('should decode null-terminated string and read past terminator', function() {
|
||||
const stream = new DecodeStream(Buffer.from('🍻\x00'));
|
||||
const string = new StringT(null, 'utf8');
|
||||
assert.equal(string.decode(stream), '🍻');
|
||||
assert.equal(stream.pos, 5);
|
||||
});
|
||||
|
||||
it('should decode remainder of buffer when null-byte missing', function() {
|
||||
const string = new StringT(null, 'utf8');
|
||||
assert.equal(string.fromBuffer(Buffer.from('🍻')), '🍻');
|
||||
});
|
||||
|
||||
it('should decode two-byte null-terminated string for utf16le', function() {
|
||||
const stream = new DecodeStream(Buffer.from('🍻\x00', 'utf16le'));
|
||||
const string = new StringT(null, 'utf16le');
|
||||
assert.equal(string.decode(stream), '🍻');
|
||||
assert.equal(stream.pos, 6);
|
||||
});
|
||||
|
||||
it('should decode remainder of buffer when null-byte missing, utf16le', function() {
|
||||
const string = new StringT(null, 'utf16le');
|
||||
assert.equal(string.fromBuffer(Buffer.from('🍻', 'utf16le')), '🍻');
|
||||
});
|
||||
|
||||
it('should decode x-mac-roman', function() {
|
||||
const string = new StringT(null, 'x-mac-roman');
|
||||
const buf = new Uint8Array([0x8a, 0x63, 0x63, 0x65, 0x6e, 0x74, 0x65, 0x64, 0x20, 0x63, 0x68, 0x87, 0x72, 0x61, 0x63, 0x74, 0x65, 0x72, 0x73]);
|
||||
assert.equal(string.fromBuffer(buf), 'äccented cháracters');
|
||||
})
|
||||
});
|
||||
|
||||
describe('size', function() {
|
||||
it('should use string length', function() {
|
||||
const string = new StringT(7);
|
||||
assert.equal(string.size('testing'), 7);
|
||||
});
|
||||
|
||||
it('should use correct encoding', function() {
|
||||
const string = new StringT(10, 'utf8');
|
||||
assert.equal(string.size('🍻'), 4);
|
||||
});
|
||||
|
||||
it('should use encoding from function', function() {
|
||||
const string = new StringT(10, function() { return 'utf8'; });
|
||||
assert.equal(string.size('🍻'), 4);
|
||||
});
|
||||
|
||||
it('should add size of length field before string', function() {
|
||||
const string = new StringT(uint8, 'utf8');
|
||||
assert.equal(string.size('🍻'), 5);
|
||||
});
|
||||
|
||||
it('should work with utf16be encoding', function() {
|
||||
const string = new StringT(10, 'utf16be');
|
||||
assert.equal(string.size('🍻'), 4);
|
||||
});
|
||||
|
||||
it('should take null-byte into account', function() {
|
||||
const string = new StringT(null, 'utf8');
|
||||
assert.equal(string.size('🍻'), 5);
|
||||
});
|
||||
|
||||
it('should take null-byte into account, utf16le', function() {
|
||||
const string = new StringT(null, 'utf16le');
|
||||
assert.equal(string.size('🍻'), 6);
|
||||
});
|
||||
|
||||
it('should use defined length if no value given', function() {
|
||||
const array = new StringT(10);
|
||||
assert.equal(array.size(), 10);
|
||||
});
|
||||
});
|
||||
|
||||
describe('encode', function() {
|
||||
it('should encode using string length', function() {
|
||||
const string = new StringT(7);
|
||||
assert.deepEqual(string.toBuffer('testing'), Buffer.from('testing'));
|
||||
});
|
||||
|
||||
it('should encode length as number before string', function() {
|
||||
const string = new StringT(uint8);
|
||||
assert.deepEqual(string.toBuffer('testing'), Buffer.from('\x07testing'));
|
||||
});
|
||||
|
||||
it('should encode length as number before string utf8', function() {
|
||||
const string = new StringT(uint8, 'utf8');
|
||||
assert.deepEqual(string.toBuffer('testing 😜'), Buffer.from('\x0ctesting 😜', 'utf8'));
|
||||
});
|
||||
|
||||
it('should encode utf8', function() {
|
||||
const string = new StringT(4, 'utf8');
|
||||
assert.deepEqual(string.toBuffer('🍻'), Buffer.from('🍻'));
|
||||
});
|
||||
|
||||
it('should encode encoding computed from function', function() {
|
||||
const string = new StringT(4, function() { return 'utf8'; });
|
||||
assert.deepEqual(string.toBuffer('🍻'), Buffer.from('🍻'));
|
||||
});
|
||||
|
||||
it('should encode null-terminated string', function() {
|
||||
const string = new StringT(null, 'utf8');
|
||||
assert.deepEqual(string.toBuffer('🍻'), Buffer.from('🍻\x00'));
|
||||
});
|
||||
|
||||
it('should encode using string length, utf16le', function() {
|
||||
const string = new StringT(16, 'utf16le');
|
||||
assert.deepEqual(string.toBuffer('testing'), Buffer.from('testing', 'utf16le'));
|
||||
});
|
||||
|
||||
it('should encode length as number before string utf16le', function() {
|
||||
const string = new StringT(uint16le, 'utf16le');
|
||||
assert.deepEqual(string.toBuffer('testing 😜'), Buffer.from('\u0014testing 😜', 'utf16le'));
|
||||
});
|
||||
|
||||
it('should encode two-byte null-terminated string for UTF-16', function() {
|
||||
const string = new StringT(null, 'utf16le');
|
||||
assert.deepEqual(string.toBuffer('🍻'), Buffer.from('🍻\x00', 'utf16le'));
|
||||
});
|
||||
});
|
||||
});
|
146
node_modules/restructure/test/Struct.js
generated
vendored
Normal file
146
node_modules/restructure/test/Struct.js
generated
vendored
Normal file
@@ -0,0 +1,146 @@
|
||||
import assert from 'assert';
|
||||
import {Struct, String as StringT, Pointer, uint8, DecodeStream, EncodeStream} from 'restructure';
|
||||
|
||||
describe('Struct', function() {
|
||||
describe('decode', function() {
|
||||
it('should decode into an object', function() {
|
||||
const struct = new Struct({
|
||||
name: new StringT(uint8),
|
||||
age: uint8
|
||||
});
|
||||
|
||||
assert.deepEqual(struct.fromBuffer(Buffer.from('\x05devon\x15')), {
|
||||
name: 'devon',
|
||||
age: 21
|
||||
});
|
||||
});
|
||||
|
||||
it('should support process hook', function() {
|
||||
const struct = new Struct({
|
||||
name: new StringT(uint8),
|
||||
age: uint8
|
||||
});
|
||||
|
||||
struct.process = function() {
|
||||
return this.canDrink = this.age >= 21;
|
||||
};
|
||||
|
||||
assert.deepEqual(struct.fromBuffer(Buffer.from('\x05devon\x20')), {
|
||||
name: 'devon',
|
||||
age: 32,
|
||||
canDrink: true
|
||||
});
|
||||
});
|
||||
|
||||
it('should support function keys', function() {
|
||||
const struct = new Struct({
|
||||
name: new StringT(uint8),
|
||||
age: uint8,
|
||||
canDrink() { return this.age >= 21; }
|
||||
});
|
||||
|
||||
assert.deepEqual(struct.fromBuffer(Buffer.from('\x05devon\x20')), {
|
||||
name: 'devon',
|
||||
age: 32,
|
||||
canDrink: true
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('size', function() {
|
||||
it('should compute the correct size', function() {
|
||||
const struct = new Struct({
|
||||
name: new StringT(uint8),
|
||||
age: uint8
|
||||
});
|
||||
|
||||
assert.equal(struct.size({name: 'devon', age: 21}), 7);
|
||||
});
|
||||
|
||||
it('should compute the correct size with pointers', function() {
|
||||
const struct = new Struct({
|
||||
name: new StringT(uint8),
|
||||
age: uint8,
|
||||
ptr: new Pointer(uint8, new StringT(uint8))
|
||||
});
|
||||
|
||||
const size = struct.size({
|
||||
name: 'devon',
|
||||
age: 21,
|
||||
ptr: 'hello'
|
||||
});
|
||||
|
||||
assert.equal(size, 14);
|
||||
});
|
||||
|
||||
it('should get the correct size when no value is given', function() {
|
||||
const struct = new Struct({
|
||||
name: new StringT(4),
|
||||
age: uint8
|
||||
});
|
||||
|
||||
assert.equal(struct.size(), 5);
|
||||
});
|
||||
|
||||
it('should throw when getting non-fixed length size and no value is given', function() {
|
||||
const struct = new Struct({
|
||||
name: new StringT(uint8),
|
||||
age: uint8
|
||||
});
|
||||
|
||||
assert.throws(() => struct.size(), /not a fixed size/i);
|
||||
});
|
||||
});
|
||||
|
||||
describe('encode', function() {
|
||||
it('should encode objects to buffers', function() {
|
||||
const struct = new Struct({
|
||||
name: new StringT(uint8),
|
||||
age: uint8
|
||||
});
|
||||
|
||||
const buf = struct.toBuffer({
|
||||
name: 'devon',
|
||||
age: 21
|
||||
});
|
||||
|
||||
assert.deepEqual(buf, Buffer.from('\x05devon\x15'));
|
||||
});
|
||||
|
||||
it('should support preEncode hook', function() {
|
||||
const struct = new Struct({
|
||||
nameLength: uint8,
|
||||
name: new StringT('nameLength'),
|
||||
age: uint8
|
||||
});
|
||||
|
||||
struct.preEncode = function() {
|
||||
return this.nameLength = this.name.length;
|
||||
};
|
||||
|
||||
const buf = struct.toBuffer({
|
||||
name: 'devon',
|
||||
age: 21
|
||||
});
|
||||
|
||||
assert.deepEqual(buf, Buffer.from('\x05devon\x15'));
|
||||
});
|
||||
|
||||
it('should encode pointer data after structure', function() {
|
||||
const struct = new Struct({
|
||||
name: new StringT(uint8),
|
||||
age: uint8,
|
||||
ptr: new Pointer(uint8, new StringT(uint8))
|
||||
});
|
||||
|
||||
const buf = struct.toBuffer({
|
||||
name: 'devon',
|
||||
age: 21,
|
||||
ptr: 'hello'
|
||||
});
|
||||
|
||||
assert.deepEqual(buf, Buffer.from('\x05devon\x15\x08\x05hello'));
|
||||
});
|
||||
});
|
||||
});
|
||||
|
495
node_modules/restructure/test/VersionedStruct.js
generated
vendored
Normal file
495
node_modules/restructure/test/VersionedStruct.js
generated
vendored
Normal file
@@ -0,0 +1,495 @@
|
||||
import assert from 'assert';
|
||||
import {VersionedStruct, String as StringT, Pointer, uint8, DecodeStream, EncodeStream} from 'restructure';
|
||||
|
||||
describe('VersionedStruct', function() {
|
||||
describe('decode', function() {
|
||||
it('should get version from number type', function() {
|
||||
const struct = new VersionedStruct(uint8, {
|
||||
0: {
|
||||
name: new StringT(uint8, 'ascii'),
|
||||
age: uint8
|
||||
},
|
||||
1: {
|
||||
name: new StringT(uint8, 'utf8'),
|
||||
age: uint8,
|
||||
gender: uint8
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
let stream = new DecodeStream(Buffer.from('\x00\x05devon\x15'));
|
||||
assert.deepEqual(struct.decode(stream), {
|
||||
version: 0,
|
||||
name: 'devon',
|
||||
age: 21
|
||||
});
|
||||
|
||||
stream = new DecodeStream(Buffer.from('\x01\x0adevon 👍\x15\x00', 'utf8'));
|
||||
assert.deepEqual(struct.decode(stream), {
|
||||
version: 1,
|
||||
name: 'devon 👍',
|
||||
age: 21,
|
||||
gender: 0
|
||||
});
|
||||
});
|
||||
|
||||
it('should throw for unknown version', function() {
|
||||
const struct = new VersionedStruct(uint8, {
|
||||
0: {
|
||||
name: new StringT(uint8, 'ascii'),
|
||||
age: uint8
|
||||
},
|
||||
1: {
|
||||
name: new StringT(uint8, 'utf8'),
|
||||
age: uint8,
|
||||
gender: uint8
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
const stream = new DecodeStream(Buffer.from('\x05\x05devon\x15'));
|
||||
return assert.throws(() => struct.decode(stream));
|
||||
});
|
||||
|
||||
it('should support common header block', function() {
|
||||
const struct = new VersionedStruct(uint8, {
|
||||
header: {
|
||||
age: uint8,
|
||||
alive: uint8
|
||||
},
|
||||
0: {
|
||||
name: new StringT(uint8, 'ascii')
|
||||
},
|
||||
1: {
|
||||
name: new StringT(uint8, 'utf8'),
|
||||
gender: uint8
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
let stream = new DecodeStream(Buffer.from('\x00\x15\x01\x05devon'));
|
||||
assert.deepEqual(struct.decode(stream), {
|
||||
version: 0,
|
||||
age: 21,
|
||||
alive: 1,
|
||||
name: 'devon'
|
||||
});
|
||||
|
||||
stream = new DecodeStream(Buffer.from('\x01\x15\x01\x0adevon 👍\x00', 'utf8'));
|
||||
assert.deepEqual(struct.decode(stream), {
|
||||
version: 1,
|
||||
age: 21,
|
||||
alive: 1,
|
||||
name: 'devon 👍',
|
||||
gender: 0
|
||||
});
|
||||
});
|
||||
|
||||
it('should support parent version key', function() {
|
||||
const struct = new VersionedStruct('version', {
|
||||
0: {
|
||||
name: new StringT(uint8, 'ascii'),
|
||||
age: uint8
|
||||
},
|
||||
1: {
|
||||
name: new StringT(uint8, 'utf8'),
|
||||
age: uint8,
|
||||
gender: uint8
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
let stream = new DecodeStream(Buffer.from('\x05devon\x15'));
|
||||
assert.deepEqual(struct.decode(stream, {version: 0}), {
|
||||
version: 0,
|
||||
name: 'devon',
|
||||
age: 21
|
||||
});
|
||||
|
||||
stream = new DecodeStream(Buffer.from('\x0adevon 👍\x15\x00', 'utf8'));
|
||||
assert.deepEqual(struct.decode(stream, {version: 1}), {
|
||||
version: 1,
|
||||
name: 'devon 👍',
|
||||
age: 21,
|
||||
gender: 0
|
||||
});
|
||||
});
|
||||
|
||||
it('should support parent version nested key', function() {
|
||||
const struct = new VersionedStruct('obj.version', {
|
||||
0: {
|
||||
name: new StringT(uint8, 'ascii'),
|
||||
age: uint8
|
||||
},
|
||||
1: {
|
||||
name: new StringT(uint8, 'utf8'),
|
||||
age: uint8,
|
||||
gender: uint8
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
let stream = new DecodeStream(Buffer.from('\x05devon\x15'));
|
||||
assert.deepEqual(struct.decode(stream, {obj: {version: 0}}), {
|
||||
version: 0,
|
||||
name: 'devon',
|
||||
age: 21
|
||||
});
|
||||
|
||||
stream = new DecodeStream(Buffer.from('\x0adevon 👍\x15\x00', 'utf8'));
|
||||
assert.deepEqual(struct.decode(stream, {obj: {version: 1}}), {
|
||||
version: 1,
|
||||
name: 'devon 👍',
|
||||
age: 21,
|
||||
gender: 0
|
||||
});
|
||||
});
|
||||
|
||||
it('should support sub versioned structs', function() {
|
||||
const struct = new VersionedStruct(uint8, {
|
||||
0: {
|
||||
name: new StringT(uint8, 'ascii'),
|
||||
age: uint8
|
||||
},
|
||||
1: new VersionedStruct(uint8, {
|
||||
0: {
|
||||
name: new StringT(uint8)
|
||||
},
|
||||
1: {
|
||||
name: new StringT(uint8),
|
||||
isDesert: uint8
|
||||
}
|
||||
}
|
||||
)
|
||||
}
|
||||
);
|
||||
|
||||
let stream = new DecodeStream(Buffer.from('\x00\x05devon\x15'));
|
||||
assert.deepEqual(struct.decode(stream, {version: 0}), {
|
||||
version: 0,
|
||||
name: 'devon',
|
||||
age: 21
|
||||
});
|
||||
|
||||
stream = new DecodeStream(Buffer.from('\x01\x00\x05pasta'));
|
||||
assert.deepEqual(struct.decode(stream, {version: 0}), {
|
||||
version: 0,
|
||||
name: 'pasta'
|
||||
});
|
||||
|
||||
stream = new DecodeStream(Buffer.from('\x01\x01\x09ice cream\x01'));
|
||||
assert.deepEqual(struct.decode(stream, {version: 0}), {
|
||||
version: 1,
|
||||
name: 'ice cream',
|
||||
isDesert: 1
|
||||
});
|
||||
});
|
||||
|
||||
it('should support process hook', function() {
|
||||
const struct = new VersionedStruct(uint8, {
|
||||
0: {
|
||||
name: new StringT(uint8, 'ascii'),
|
||||
age: uint8
|
||||
},
|
||||
1: {
|
||||
name: new StringT(uint8, 'utf8'),
|
||||
age: uint8,
|
||||
gender: uint8
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
struct.process = function() {
|
||||
return this.processed = true;
|
||||
};
|
||||
|
||||
const stream = new DecodeStream(Buffer.from('\x00\x05devon\x15'));
|
||||
assert.deepEqual(struct.decode(stream), {
|
||||
version: 0,
|
||||
name: 'devon',
|
||||
age: 21,
|
||||
processed: true
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('size', function() {
|
||||
it('should compute the correct size', function() {
|
||||
const struct = new VersionedStruct(uint8, {
|
||||
0: {
|
||||
name: new StringT(uint8, 'ascii'),
|
||||
age: uint8
|
||||
},
|
||||
1: {
|
||||
name: new StringT(uint8, 'utf8'),
|
||||
age: uint8,
|
||||
gender: uint8
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
let size = struct.size({
|
||||
version: 0,
|
||||
name: 'devon',
|
||||
age: 21
|
||||
});
|
||||
|
||||
assert.equal(size, 8);
|
||||
|
||||
size = struct.size({
|
||||
version: 1,
|
||||
name: 'devon 👍',
|
||||
age: 21,
|
||||
gender: 0
|
||||
});
|
||||
|
||||
assert.equal(size, 14);
|
||||
});
|
||||
|
||||
it('should throw for unknown version', function() {
|
||||
const struct = new VersionedStruct(uint8, {
|
||||
0: {
|
||||
name: new StringT(uint8, 'ascii'),
|
||||
age: uint8
|
||||
},
|
||||
1: {
|
||||
name: new StringT(uint8, 'utf8'),
|
||||
age: uint8,
|
||||
gender: uint8
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
assert.throws(() =>
|
||||
struct.size({
|
||||
version: 5,
|
||||
name: 'devon',
|
||||
age: 21
|
||||
})
|
||||
);
|
||||
});
|
||||
|
||||
it('should support common header block', function() {
|
||||
const struct = new VersionedStruct(uint8, {
|
||||
header: {
|
||||
age: uint8,
|
||||
alive: uint8
|
||||
},
|
||||
0: {
|
||||
name: new StringT(uint8, 'ascii')
|
||||
},
|
||||
1: {
|
||||
name: new StringT(uint8, 'utf8'),
|
||||
gender: uint8
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
let size = struct.size({
|
||||
version: 0,
|
||||
age: 21,
|
||||
alive: 1,
|
||||
name: 'devon'
|
||||
});
|
||||
|
||||
assert.equal(size, 9);
|
||||
|
||||
size = struct.size({
|
||||
version: 1,
|
||||
age: 21,
|
||||
alive: 1,
|
||||
name: 'devon 👍',
|
||||
gender: 0
|
||||
});
|
||||
|
||||
assert.equal(size, 15);
|
||||
});
|
||||
|
||||
it('should compute the correct size with pointers', function() {
|
||||
const struct = new VersionedStruct(uint8, {
|
||||
0: {
|
||||
name: new StringT(uint8, 'ascii'),
|
||||
age: uint8
|
||||
},
|
||||
1: {
|
||||
name: new StringT(uint8, 'utf8'),
|
||||
age: uint8,
|
||||
ptr: new Pointer(uint8, new StringT(uint8))
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
const size = struct.size({
|
||||
version: 1,
|
||||
name: 'devon',
|
||||
age: 21,
|
||||
ptr: 'hello'
|
||||
});
|
||||
|
||||
assert.equal(size, 15);
|
||||
});
|
||||
|
||||
it('should throw if no value is given', function() {
|
||||
const struct = new VersionedStruct(uint8, {
|
||||
0: {
|
||||
name: new StringT(4, 'ascii'),
|
||||
age: uint8
|
||||
},
|
||||
1: {
|
||||
name: new StringT(4, 'utf8'),
|
||||
age: uint8,
|
||||
gender: uint8
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
assert.throws(() => struct.size(), /not a fixed size/i);
|
||||
});
|
||||
});
|
||||
|
||||
describe('encode', function() {
|
||||
it('should encode objects to buffers', function() {
|
||||
const struct = new VersionedStruct(uint8, {
|
||||
0: {
|
||||
name: new StringT(uint8, 'ascii'),
|
||||
age: uint8
|
||||
},
|
||||
1: {
|
||||
name: new StringT(uint8, 'utf8'),
|
||||
age: uint8,
|
||||
gender: uint8
|
||||
}
|
||||
});
|
||||
|
||||
const buf1 = struct.toBuffer({
|
||||
version: 0,
|
||||
name: 'devon',
|
||||
age: 21
|
||||
});
|
||||
|
||||
assert.deepEqual(buf1, Buffer.from('\x00\x05devon\x15', 'utf8'));
|
||||
|
||||
const buf2 = struct.toBuffer({
|
||||
version: 1,
|
||||
name: 'devon 👍',
|
||||
age: 21,
|
||||
gender: 0
|
||||
});
|
||||
|
||||
assert.deepEqual(buf2, Buffer.from('\x01\x0adevon 👍\x15\x00', 'utf8'));
|
||||
});
|
||||
|
||||
it('should throw for unknown version', function() {
|
||||
const struct = new VersionedStruct(uint8, {
|
||||
0: {
|
||||
name: new StringT(uint8, 'ascii'),
|
||||
age: uint8
|
||||
},
|
||||
1: {
|
||||
name: new StringT(uint8, 'utf8'),
|
||||
age: uint8,
|
||||
gender: uint8
|
||||
}
|
||||
});
|
||||
|
||||
assert.throws(() =>
|
||||
struct.toBuffer({
|
||||
version: 5,
|
||||
name: 'devon',
|
||||
age: 21
|
||||
})
|
||||
);
|
||||
});
|
||||
|
||||
it('should support common header block', function() {
|
||||
const struct = new VersionedStruct(uint8, {
|
||||
header: {
|
||||
age: uint8,
|
||||
alive: uint8
|
||||
},
|
||||
0: {
|
||||
name: new StringT(uint8, 'ascii')
|
||||
},
|
||||
1: {
|
||||
name: new StringT(uint8, 'utf8'),
|
||||
gender: uint8
|
||||
}
|
||||
});
|
||||
|
||||
const buf1 = struct.toBuffer({
|
||||
version: 0,
|
||||
age: 21,
|
||||
alive: 1,
|
||||
name: 'devon'
|
||||
});
|
||||
|
||||
assert.deepEqual(buf1, Buffer.from('\x00\x15\x01\x05devon', 'utf8'));
|
||||
|
||||
const buf2 = struct.toBuffer({
|
||||
version: 1,
|
||||
age: 21,
|
||||
alive: 1,
|
||||
name: 'devon 👍',
|
||||
gender: 0
|
||||
});
|
||||
|
||||
assert.deepEqual(buf2, Buffer.from('\x01\x15\x01\x0adevon 👍\x00', 'utf8'));
|
||||
});
|
||||
|
||||
it('should encode pointer data after structure', function() {
|
||||
const struct = new VersionedStruct(uint8, {
|
||||
0: {
|
||||
name: new StringT(uint8, 'ascii'),
|
||||
age: uint8
|
||||
},
|
||||
1: {
|
||||
name: new StringT(uint8, 'utf8'),
|
||||
age: uint8,
|
||||
ptr: new Pointer(uint8, new StringT(uint8))
|
||||
}
|
||||
});
|
||||
|
||||
const buf = struct.toBuffer({
|
||||
version: 1,
|
||||
name: 'devon',
|
||||
age: 21,
|
||||
ptr: 'hello'
|
||||
});
|
||||
|
||||
assert.deepEqual(buf, Buffer.from('\x01\x05devon\x15\x09\x05hello', 'utf8'));
|
||||
});
|
||||
|
||||
it('should support preEncode hook', function() {
|
||||
const struct = new VersionedStruct(uint8, {
|
||||
0: {
|
||||
name: new StringT(uint8, 'ascii'),
|
||||
age: uint8
|
||||
},
|
||||
1: {
|
||||
name: new StringT(uint8, 'utf8'),
|
||||
age: uint8,
|
||||
gender: uint8
|
||||
}
|
||||
});
|
||||
|
||||
struct.preEncode = function() {
|
||||
return this.version = (this.gender != null) ? 1 : 0;
|
||||
};
|
||||
|
||||
const buf1 = struct.toBuffer({
|
||||
name: 'devon',
|
||||
age: 21
|
||||
});
|
||||
|
||||
assert.deepEqual(buf1, Buffer.from('\x00\x05devon\x15', 'utf8'));
|
||||
|
||||
const buf2 = struct.toBuffer({
|
||||
name: 'devon 👍',
|
||||
age: 21,
|
||||
gender: 0
|
||||
});
|
||||
|
||||
assert.deepEqual(buf2, Buffer.from('\x01\x0adevon 👍\x15\x00', 'utf8'));
|
||||
});
|
||||
});
|
||||
});
|
Reference in New Issue
Block a user