forked from olcxjas-softworks/LarpixClient
big updat:
- update dependencies - add webp support and webp conversion for profile images
This commit is contained in:
parent
19c3dbb42d
commit
95aaaa69ea
244 changed files with 121382 additions and 86 deletions
3
node_modules/js-binary-schema-parser/.babelrc
generated
vendored
Normal file
3
node_modules/js-binary-schema-parser/.babelrc
generated
vendored
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
{
|
||||
"presets": ["@babel/preset-env"]
|
||||
}
|
||||
7
node_modules/js-binary-schema-parser/.prettierrc
generated
vendored
Normal file
7
node_modules/js-binary-schema-parser/.prettierrc
generated
vendored
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
{
|
||||
"singleQuote": true,
|
||||
"write": true,
|
||||
"semi": false,
|
||||
"tabWidth": 2,
|
||||
"printWidth": 80
|
||||
}
|
||||
22
node_modules/js-binary-schema-parser/LICENSE
generated
vendored
Normal file
22
node_modules/js-binary-schema-parser/LICENSE
generated
vendored
Normal file
|
|
@ -0,0 +1,22 @@
|
|||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2015 Matt Way
|
||||
|
||||
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.
|
||||
|
||||
83
node_modules/js-binary-schema-parser/README.md
generated
vendored
Normal file
83
node_modules/js-binary-schema-parser/README.md
generated
vendored
Normal file
|
|
@ -0,0 +1,83 @@
|
|||
# js Binary Schema Parser
|
||||
|
||||
Parse binary files in javascript using a schema to convert to plain objects.
|
||||
|
||||
Years ago I needed to parse GIF images for our **[Ruffle][1]** messaging app. While this readme describes how to parse binary files in general, our _[GIF Parser][2]_ library exhibits a full use of this library (including a _[demo][2]_). I suggest looking at the other library for a quick understanding.
|
||||
|
||||
Basically, you provide a schema object and some data, and it will step through the binary data, and convert it into the object defined by your schema. Included in this library is a parser for the `Uint8TypedArray`, but it is easy to add them for your own types if necessary. It can parse bytes, arrays, chunks, conditionals, loops, etc.
|
||||
|
||||
### How to Use
|
||||
|
||||
_Installation:_
|
||||
|
||||
npm install js-binary-schema-parser
|
||||
|
||||
_Create a schema and parse a file:_
|
||||
|
||||
import { parse, conditional } from 'js-binary-schema-parser'
|
||||
import { buildStream, readByte } from 'js-binary-schema-parser/lib/parsers/uint8'
|
||||
|
||||
const schema = [
|
||||
// part definitions...
|
||||
{ someKey: readByte() }
|
||||
];
|
||||
|
||||
// get the input file data
|
||||
const data = new Uint8Array(fileArrayBuffer);
|
||||
// create a stream object and parse it
|
||||
const parsedObject = parse(buildStream(data), schema)
|
||||
|
||||
### Schemas
|
||||
|
||||
So far in this library there is only one built in schema, which is for the GIF format. You can import included schemas like:
|
||||
|
||||
import GIF from 'js-binary-schema-parser/lib/schemas/gif'
|
||||
|
||||
Schemas are an array of _parts_, which are objects containing a single key label, and the parser to use at that point in time. This format was chosen to ensure parse ordering was consistent. _Parts_ can also contain other parts internally, and include syntax for loops, and conditionals. You can also include your own custom functions for parsing, providing direct access to the given data stream. Below is an example of a schema using the `Uint8TypedArray` parser provided to parse the GIF format header. You can also see a full example [here][2] of parsing entire GIF files.
|
||||
|
||||
### Example
|
||||
|
||||
var gifSchema = [
|
||||
{
|
||||
label: 'header', // gif header
|
||||
parts: [
|
||||
{ label: 'signature', parser: Parsers.readString(3) },
|
||||
{ label: 'version', parser: Parsers.readString(3) }
|
||||
]
|
||||
},{
|
||||
label: 'lsd', // local screen descriptor
|
||||
parts: [
|
||||
{ label: 'width', parser: Parsers.readUnsigned(true) },
|
||||
{ label: 'height', parser: Parsers.readUnsigned(true) },
|
||||
{ label: 'gct', bits: {
|
||||
exists: { index: 0 },
|
||||
resolution: { index: 1, length: 3 },
|
||||
sort: { index: 4 },
|
||||
size: { index: 5, length: 3 }
|
||||
}},
|
||||
{ label: 'backgroundColorIndex', parser: Parsers.readByte() },
|
||||
{ label: 'pixelAspectRatio', parser: Parsers.readByte() }
|
||||
]
|
||||
}
|
||||
];
|
||||
|
||||
### Why this parser?
|
||||
|
||||
There are other good parsers around, like [jBinary][4], but we weren't a fan of relying on object key ordering, and defining parser types as strings. This one is also extremely small, and easily exstensible in any way you want.
|
||||
|
||||
### Demo
|
||||
|
||||
You can see a full demo **[here][2]** which uses this lib to parse GIF files for manipulation.
|
||||
|
||||
### Who are we?
|
||||
|
||||
[Matt Way][3] & [Nick Drewe][5]
|
||||
|
||||
[Wethrift.com][6]
|
||||
|
||||
[1]: https://www.producthunt.com/posts/ruffle
|
||||
[2]: https://github.com/matt-way/gifuct-js
|
||||
[3]: https://twitter.com/_MattWay
|
||||
[4]: https://github.com/jDataView/jBinary
|
||||
[5]: https://twitter.com/nickdrewe
|
||||
[6]: https://wethrift.com
|
||||
BIN
node_modules/js-binary-schema-parser/example/box.gif
generated
vendored
Normal file
BIN
node_modules/js-binary-schema-parser/example/box.gif
generated
vendored
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 69 B |
BIN
node_modules/js-binary-schema-parser/example/dog.gif
generated
vendored
Normal file
BIN
node_modules/js-binary-schema-parser/example/dog.gif
generated
vendored
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 76 KiB |
BIN
node_modules/js-binary-schema-parser/example/horses.gif
generated
vendored
Normal file
BIN
node_modules/js-binary-schema-parser/example/horses.gif
generated
vendored
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 2.9 MiB |
10
node_modules/js-binary-schema-parser/example/index.js
generated
vendored
Normal file
10
node_modules/js-binary-schema-parser/example/index.js
generated
vendored
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
import fs from 'fs'
|
||||
import { parse } from '../src'
|
||||
import { buildStream } from '../src/parsers/uint8'
|
||||
import { GIF } from '../src/schemas'
|
||||
|
||||
debugger
|
||||
|
||||
const data = fs.readFileSync('./example/dog.gif')
|
||||
const result = parse(buildStream(new Uint8Array(data)), GIF)
|
||||
console.log(result)
|
||||
66
node_modules/js-binary-schema-parser/lib/index.js
generated
vendored
Normal file
66
node_modules/js-binary-schema-parser/lib/index.js
generated
vendored
Normal file
|
|
@ -0,0 +1,66 @@
|
|||
"use strict";
|
||||
|
||||
Object.defineProperty(exports, "__esModule", {
|
||||
value: true
|
||||
});
|
||||
exports.loop = exports.conditional = exports.parse = void 0;
|
||||
|
||||
var parse = function parse(stream, schema) {
|
||||
var result = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {};
|
||||
var parent = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : result;
|
||||
|
||||
if (Array.isArray(schema)) {
|
||||
schema.forEach(function (partSchema) {
|
||||
return parse(stream, partSchema, result, parent);
|
||||
});
|
||||
} else if (typeof schema === 'function') {
|
||||
schema(stream, result, parent, parse);
|
||||
} else {
|
||||
var key = Object.keys(schema)[0];
|
||||
|
||||
if (Array.isArray(schema[key])) {
|
||||
parent[key] = {};
|
||||
parse(stream, schema[key], result, parent[key]);
|
||||
} else {
|
||||
parent[key] = schema[key](stream, result, parent, parse);
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
};
|
||||
|
||||
exports.parse = parse;
|
||||
|
||||
var conditional = function conditional(schema, conditionFunc) {
|
||||
return function (stream, result, parent, parse) {
|
||||
if (conditionFunc(stream, result, parent)) {
|
||||
parse(stream, schema, result, parent);
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
exports.conditional = conditional;
|
||||
|
||||
var loop = function loop(schema, continueFunc) {
|
||||
return function (stream, result, parent, parse) {
|
||||
var arr = [];
|
||||
var lastStreamPos = stream.pos;
|
||||
|
||||
while (continueFunc(stream, result, parent)) {
|
||||
var newParent = {};
|
||||
parse(stream, schema, result, newParent); // cases when whole file is parsed but no termination is there and stream position is not getting updated as well
|
||||
// it falls into infinite recursion, null check to avoid the same
|
||||
|
||||
if (stream.pos === lastStreamPos) {
|
||||
break;
|
||||
}
|
||||
|
||||
lastStreamPos = stream.pos;
|
||||
arr.push(newParent);
|
||||
}
|
||||
|
||||
return arr;
|
||||
};
|
||||
};
|
||||
|
||||
exports.loop = loop;
|
||||
122
node_modules/js-binary-schema-parser/lib/parsers/uint8.js
generated
vendored
Normal file
122
node_modules/js-binary-schema-parser/lib/parsers/uint8.js
generated
vendored
Normal file
|
|
@ -0,0 +1,122 @@
|
|||
"use strict";
|
||||
|
||||
Object.defineProperty(exports, "__esModule", {
|
||||
value: true
|
||||
});
|
||||
exports.readBits = exports.readArray = exports.readUnsigned = exports.readString = exports.peekBytes = exports.readBytes = exports.peekByte = exports.readByte = exports.buildStream = void 0;
|
||||
|
||||
// Default stream and parsers for Uint8TypedArray data type
|
||||
var buildStream = function buildStream(uint8Data) {
|
||||
return {
|
||||
data: uint8Data,
|
||||
pos: 0
|
||||
};
|
||||
};
|
||||
|
||||
exports.buildStream = buildStream;
|
||||
|
||||
var readByte = function readByte() {
|
||||
return function (stream) {
|
||||
return stream.data[stream.pos++];
|
||||
};
|
||||
};
|
||||
|
||||
exports.readByte = readByte;
|
||||
|
||||
var peekByte = function peekByte() {
|
||||
var offset = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 0;
|
||||
return function (stream) {
|
||||
return stream.data[stream.pos + offset];
|
||||
};
|
||||
};
|
||||
|
||||
exports.peekByte = peekByte;
|
||||
|
||||
var readBytes = function readBytes(length) {
|
||||
return function (stream) {
|
||||
return stream.data.subarray(stream.pos, stream.pos += length);
|
||||
};
|
||||
};
|
||||
|
||||
exports.readBytes = readBytes;
|
||||
|
||||
var peekBytes = function peekBytes(length) {
|
||||
return function (stream) {
|
||||
return stream.data.subarray(stream.pos, stream.pos + length);
|
||||
};
|
||||
};
|
||||
|
||||
exports.peekBytes = peekBytes;
|
||||
|
||||
var readString = function readString(length) {
|
||||
return function (stream) {
|
||||
return Array.from(readBytes(length)(stream)).map(function (value) {
|
||||
return String.fromCharCode(value);
|
||||
}).join('');
|
||||
};
|
||||
};
|
||||
|
||||
exports.readString = readString;
|
||||
|
||||
var readUnsigned = function readUnsigned(littleEndian) {
|
||||
return function (stream) {
|
||||
var bytes = readBytes(2)(stream);
|
||||
return littleEndian ? (bytes[1] << 8) + bytes[0] : (bytes[0] << 8) + bytes[1];
|
||||
};
|
||||
};
|
||||
|
||||
exports.readUnsigned = readUnsigned;
|
||||
|
||||
var readArray = function readArray(byteSize, totalOrFunc) {
|
||||
return function (stream, result, parent) {
|
||||
var total = typeof totalOrFunc === 'function' ? totalOrFunc(stream, result, parent) : totalOrFunc;
|
||||
var parser = readBytes(byteSize);
|
||||
var arr = new Array(total);
|
||||
|
||||
for (var i = 0; i < total; i++) {
|
||||
arr[i] = parser(stream);
|
||||
}
|
||||
|
||||
return arr;
|
||||
};
|
||||
};
|
||||
|
||||
exports.readArray = readArray;
|
||||
|
||||
var subBitsTotal = function subBitsTotal(bits, startIndex, length) {
|
||||
var result = 0;
|
||||
|
||||
for (var i = 0; i < length; i++) {
|
||||
result += bits[startIndex + i] && Math.pow(2, length - i - 1);
|
||||
}
|
||||
|
||||
return result;
|
||||
};
|
||||
|
||||
var readBits = function readBits(schema) {
|
||||
return function (stream) {
|
||||
var _byte = readByte()(stream); // convert the byte to bit array
|
||||
|
||||
|
||||
var bits = new Array(8);
|
||||
|
||||
for (var i = 0; i < 8; i++) {
|
||||
bits[7 - i] = !!(_byte & 1 << i);
|
||||
} // convert the bit array to values based on the schema
|
||||
|
||||
|
||||
return Object.keys(schema).reduce(function (res, key) {
|
||||
var def = schema[key];
|
||||
|
||||
if (def.length) {
|
||||
res[key] = subBitsTotal(bits, def.index, def.length);
|
||||
} else {
|
||||
res[key] = bits[def.index];
|
||||
}
|
||||
|
||||
return res;
|
||||
}, {});
|
||||
};
|
||||
};
|
||||
|
||||
exports.readBits = readBits;
|
||||
219
node_modules/js-binary-schema-parser/lib/schemas/gif.js
generated
vendored
Normal file
219
node_modules/js-binary-schema-parser/lib/schemas/gif.js
generated
vendored
Normal file
|
|
@ -0,0 +1,219 @@
|
|||
"use strict";
|
||||
|
||||
Object.defineProperty(exports, "__esModule", {
|
||||
value: true
|
||||
});
|
||||
exports["default"] = void 0;
|
||||
|
||||
var _ = require("../");
|
||||
|
||||
var _uint = require("../parsers/uint8");
|
||||
|
||||
// a set of 0x00 terminated subblocks
|
||||
var subBlocksSchema = {
|
||||
blocks: function blocks(stream) {
|
||||
var terminator = 0x00;
|
||||
var chunks = [];
|
||||
var streamSize = stream.data.length;
|
||||
var total = 0;
|
||||
|
||||
for (var size = (0, _uint.readByte)()(stream); size !== terminator; size = (0, _uint.readByte)()(stream)) {
|
||||
// size becomes undefined for some case when file is corrupted and terminator is not proper
|
||||
// null check to avoid recursion
|
||||
if (!size) break; // catch corrupted files with no terminator
|
||||
|
||||
if (stream.pos + size >= streamSize) {
|
||||
var availableSize = streamSize - stream.pos;
|
||||
chunks.push((0, _uint.readBytes)(availableSize)(stream));
|
||||
total += availableSize;
|
||||
break;
|
||||
}
|
||||
|
||||
chunks.push((0, _uint.readBytes)(size)(stream));
|
||||
total += size;
|
||||
}
|
||||
|
||||
var result = new Uint8Array(total);
|
||||
var offset = 0;
|
||||
|
||||
for (var i = 0; i < chunks.length; i++) {
|
||||
result.set(chunks[i], offset);
|
||||
offset += chunks[i].length;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
}; // global control extension
|
||||
|
||||
var gceSchema = (0, _.conditional)({
|
||||
gce: [{
|
||||
codes: (0, _uint.readBytes)(2)
|
||||
}, {
|
||||
byteSize: (0, _uint.readByte)()
|
||||
}, {
|
||||
extras: (0, _uint.readBits)({
|
||||
future: {
|
||||
index: 0,
|
||||
length: 3
|
||||
},
|
||||
disposal: {
|
||||
index: 3,
|
||||
length: 3
|
||||
},
|
||||
userInput: {
|
||||
index: 6
|
||||
},
|
||||
transparentColorGiven: {
|
||||
index: 7
|
||||
}
|
||||
})
|
||||
}, {
|
||||
delay: (0, _uint.readUnsigned)(true)
|
||||
}, {
|
||||
transparentColorIndex: (0, _uint.readByte)()
|
||||
}, {
|
||||
terminator: (0, _uint.readByte)()
|
||||
}]
|
||||
}, function (stream) {
|
||||
var codes = (0, _uint.peekBytes)(2)(stream);
|
||||
return codes[0] === 0x21 && codes[1] === 0xf9;
|
||||
}); // image pipeline block
|
||||
|
||||
var imageSchema = (0, _.conditional)({
|
||||
image: [{
|
||||
code: (0, _uint.readByte)()
|
||||
}, {
|
||||
descriptor: [{
|
||||
left: (0, _uint.readUnsigned)(true)
|
||||
}, {
|
||||
top: (0, _uint.readUnsigned)(true)
|
||||
}, {
|
||||
width: (0, _uint.readUnsigned)(true)
|
||||
}, {
|
||||
height: (0, _uint.readUnsigned)(true)
|
||||
}, {
|
||||
lct: (0, _uint.readBits)({
|
||||
exists: {
|
||||
index: 0
|
||||
},
|
||||
interlaced: {
|
||||
index: 1
|
||||
},
|
||||
sort: {
|
||||
index: 2
|
||||
},
|
||||
future: {
|
||||
index: 3,
|
||||
length: 2
|
||||
},
|
||||
size: {
|
||||
index: 5,
|
||||
length: 3
|
||||
}
|
||||
})
|
||||
}]
|
||||
}, (0, _.conditional)({
|
||||
lct: (0, _uint.readArray)(3, function (stream, result, parent) {
|
||||
return Math.pow(2, parent.descriptor.lct.size + 1);
|
||||
})
|
||||
}, function (stream, result, parent) {
|
||||
return parent.descriptor.lct.exists;
|
||||
}), {
|
||||
data: [{
|
||||
minCodeSize: (0, _uint.readByte)()
|
||||
}, subBlocksSchema]
|
||||
}]
|
||||
}, function (stream) {
|
||||
return (0, _uint.peekByte)()(stream) === 0x2c;
|
||||
}); // plain text block
|
||||
|
||||
var textSchema = (0, _.conditional)({
|
||||
text: [{
|
||||
codes: (0, _uint.readBytes)(2)
|
||||
}, {
|
||||
blockSize: (0, _uint.readByte)()
|
||||
}, {
|
||||
preData: function preData(stream, result, parent) {
|
||||
return (0, _uint.readBytes)(parent.text.blockSize)(stream);
|
||||
}
|
||||
}, subBlocksSchema]
|
||||
}, function (stream) {
|
||||
var codes = (0, _uint.peekBytes)(2)(stream);
|
||||
return codes[0] === 0x21 && codes[1] === 0x01;
|
||||
}); // application block
|
||||
|
||||
var applicationSchema = (0, _.conditional)({
|
||||
application: [{
|
||||
codes: (0, _uint.readBytes)(2)
|
||||
}, {
|
||||
blockSize: (0, _uint.readByte)()
|
||||
}, {
|
||||
id: function id(stream, result, parent) {
|
||||
return (0, _uint.readString)(parent.blockSize)(stream);
|
||||
}
|
||||
}, subBlocksSchema]
|
||||
}, function (stream) {
|
||||
var codes = (0, _uint.peekBytes)(2)(stream);
|
||||
return codes[0] === 0x21 && codes[1] === 0xff;
|
||||
}); // comment block
|
||||
|
||||
var commentSchema = (0, _.conditional)({
|
||||
comment: [{
|
||||
codes: (0, _uint.readBytes)(2)
|
||||
}, subBlocksSchema]
|
||||
}, function (stream) {
|
||||
var codes = (0, _uint.peekBytes)(2)(stream);
|
||||
return codes[0] === 0x21 && codes[1] === 0xfe;
|
||||
});
|
||||
var schema = [{
|
||||
header: [{
|
||||
signature: (0, _uint.readString)(3)
|
||||
}, {
|
||||
version: (0, _uint.readString)(3)
|
||||
}]
|
||||
}, {
|
||||
lsd: [{
|
||||
width: (0, _uint.readUnsigned)(true)
|
||||
}, {
|
||||
height: (0, _uint.readUnsigned)(true)
|
||||
}, {
|
||||
gct: (0, _uint.readBits)({
|
||||
exists: {
|
||||
index: 0
|
||||
},
|
||||
resolution: {
|
||||
index: 1,
|
||||
length: 3
|
||||
},
|
||||
sort: {
|
||||
index: 4
|
||||
},
|
||||
size: {
|
||||
index: 5,
|
||||
length: 3
|
||||
}
|
||||
})
|
||||
}, {
|
||||
backgroundColorIndex: (0, _uint.readByte)()
|
||||
}, {
|
||||
pixelAspectRatio: (0, _uint.readByte)()
|
||||
}]
|
||||
}, (0, _.conditional)({
|
||||
gct: (0, _uint.readArray)(3, function (stream, result) {
|
||||
return Math.pow(2, result.lsd.gct.size + 1);
|
||||
})
|
||||
}, function (stream, result) {
|
||||
return result.lsd.gct.exists;
|
||||
}), // content frames
|
||||
{
|
||||
frames: (0, _.loop)([gceSchema, applicationSchema, commentSchema, imageSchema, textSchema], function (stream) {
|
||||
var nextCode = (0, _uint.peekByte)()(stream); // rather than check for a terminator, we should check for the existence
|
||||
// of an ext or image block to avoid infinite loops
|
||||
//var terminator = 0x3B;
|
||||
//return nextCode !== terminator;
|
||||
|
||||
return nextCode === 0x21 || nextCode === 0x2c;
|
||||
})
|
||||
}];
|
||||
var _default = schema;
|
||||
exports["default"] = _default;
|
||||
35
node_modules/js-binary-schema-parser/package.json
generated
vendored
Normal file
35
node_modules/js-binary-schema-parser/package.json
generated
vendored
Normal file
|
|
@ -0,0 +1,35 @@
|
|||
{
|
||||
"name": "js-binary-schema-parser",
|
||||
"version": "2.0.3",
|
||||
"description": "Parse binary files with a schema into nicely readable objects",
|
||||
"dependencies": {},
|
||||
"devDependencies": {
|
||||
"@babel/cli": "^7.8.4",
|
||||
"@babel/core": "^7.8.4",
|
||||
"@babel/node": "^7.8.4",
|
||||
"@babel/preset-env": "^7.8.4"
|
||||
},
|
||||
"main": "lib/index.js",
|
||||
"scripts": {
|
||||
"example": "babel-node ./example/index.js",
|
||||
"example-debug": "babel-node --inspect-brk ./example/index.js",
|
||||
"build": "babel src --out-dir lib"
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/matt-way/jsBinarySchemaParser.git"
|
||||
},
|
||||
"keywords": [
|
||||
"javascript",
|
||||
"binary",
|
||||
"file",
|
||||
"parser",
|
||||
"schema"
|
||||
],
|
||||
"author": "Matt Way",
|
||||
"license": "MIT",
|
||||
"bugs": {
|
||||
"url": "https://github.com/matt-way/jsBinarySchemaParser/issues"
|
||||
},
|
||||
"homepage": "https://github.com/matt-way/jsBinarySchemaParser"
|
||||
}
|
||||
49
node_modules/js-binary-schema-parser/src/index.js
generated
vendored
Normal file
49
node_modules/js-binary-schema-parser/src/index.js
generated
vendored
Normal file
|
|
@ -0,0 +1,49 @@
|
|||
export const parse = (stream, schema, result = {}, parent = result) => {
|
||||
if (Array.isArray(schema)) {
|
||||
schema.forEach(partSchema => parse(stream, partSchema, result, parent))
|
||||
} else if (typeof schema === 'function') {
|
||||
schema(stream, result, parent, parse)
|
||||
} else {
|
||||
const key = Object.keys(schema)[0]
|
||||
if (Array.isArray(schema[key])) {
|
||||
parent[key] = {}
|
||||
parse(stream, schema[key], result, parent[key])
|
||||
} else {
|
||||
parent[key] = schema[key](stream, result, parent, parse)
|
||||
}
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
export const conditional = (schema, conditionFunc) => (
|
||||
stream,
|
||||
result,
|
||||
parent,
|
||||
parse
|
||||
) => {
|
||||
if (conditionFunc(stream, result, parent)) {
|
||||
parse(stream, schema, result, parent)
|
||||
}
|
||||
}
|
||||
|
||||
export const loop = (schema, continueFunc) => (
|
||||
stream,
|
||||
result,
|
||||
parent,
|
||||
parse
|
||||
) => {
|
||||
const arr = []
|
||||
let lastStreamPos = stream.pos;
|
||||
while (continueFunc(stream, result, parent)) {
|
||||
const newParent = {}
|
||||
parse(stream, schema, result, newParent)
|
||||
// cases when whole file is parsed but no termination is there and stream position is not getting updated as well
|
||||
// it falls into infinite recursion, null check to avoid the same
|
||||
if(stream.pos === lastStreamPos) {
|
||||
break
|
||||
}
|
||||
lastStreamPos = stream.pos
|
||||
arr.push(newParent)
|
||||
}
|
||||
return arr
|
||||
}
|
||||
78
node_modules/js-binary-schema-parser/src/parsers/uint8.js
generated
vendored
Normal file
78
node_modules/js-binary-schema-parser/src/parsers/uint8.js
generated
vendored
Normal file
|
|
@ -0,0 +1,78 @@
|
|||
// Default stream and parsers for Uint8TypedArray data type
|
||||
|
||||
export const buildStream = uint8Data => ({
|
||||
data: uint8Data,
|
||||
pos: 0
|
||||
})
|
||||
|
||||
export const readByte = () => stream => {
|
||||
return stream.data[stream.pos++]
|
||||
}
|
||||
|
||||
export const peekByte = (offset = 0) => stream => {
|
||||
return stream.data[stream.pos + offset]
|
||||
}
|
||||
|
||||
export const readBytes = length => stream => {
|
||||
return stream.data.subarray(stream.pos, (stream.pos += length))
|
||||
}
|
||||
|
||||
export const peekBytes = length => stream => {
|
||||
return stream.data.subarray(stream.pos, stream.pos + length)
|
||||
}
|
||||
|
||||
export const readString = length => stream => {
|
||||
return Array.from(readBytes(length)(stream))
|
||||
.map(value => String.fromCharCode(value))
|
||||
.join('')
|
||||
}
|
||||
|
||||
export const readUnsigned = littleEndian => stream => {
|
||||
const bytes = readBytes(2)(stream)
|
||||
return littleEndian ? (bytes[1] << 8) + bytes[0] : (bytes[0] << 8) + bytes[1]
|
||||
}
|
||||
|
||||
export const readArray = (byteSize, totalOrFunc) => (
|
||||
stream,
|
||||
result,
|
||||
parent
|
||||
) => {
|
||||
const total =
|
||||
typeof totalOrFunc === 'function'
|
||||
? totalOrFunc(stream, result, parent)
|
||||
: totalOrFunc
|
||||
|
||||
const parser = readBytes(byteSize)
|
||||
const arr = new Array(total)
|
||||
for (var i = 0; i < total; i++) {
|
||||
arr[i] = parser(stream)
|
||||
}
|
||||
return arr
|
||||
}
|
||||
|
||||
const subBitsTotal = (bits, startIndex, length) => {
|
||||
var result = 0
|
||||
for (var i = 0; i < length; i++) {
|
||||
result += bits[startIndex + i] && 2 ** (length - i - 1)
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
export const readBits = schema => stream => {
|
||||
const byte = readByte()(stream)
|
||||
// convert the byte to bit array
|
||||
const bits = new Array(8)
|
||||
for (var i = 0; i < 8; i++) {
|
||||
bits[7 - i] = !!(byte & (1 << i))
|
||||
}
|
||||
// convert the bit array to values based on the schema
|
||||
return Object.keys(schema).reduce((res, key) => {
|
||||
const def = schema[key]
|
||||
if (def.length) {
|
||||
res[key] = subBitsTotal(bits, def.index, def.length)
|
||||
} else {
|
||||
res[key] = bits[def.index]
|
||||
}
|
||||
return res
|
||||
}, {})
|
||||
}
|
||||
201
node_modules/js-binary-schema-parser/src/schemas/gif.js
generated
vendored
Normal file
201
node_modules/js-binary-schema-parser/src/schemas/gif.js
generated
vendored
Normal file
|
|
@ -0,0 +1,201 @@
|
|||
import { conditional, loop } from '../'
|
||||
import {
|
||||
readByte,
|
||||
peekByte,
|
||||
readBytes,
|
||||
peekBytes,
|
||||
readString,
|
||||
readUnsigned,
|
||||
readArray,
|
||||
readBits,
|
||||
} from '../parsers/uint8'
|
||||
|
||||
// a set of 0x00 terminated subblocks
|
||||
var subBlocksSchema = {
|
||||
blocks: (stream) => {
|
||||
const terminator = 0x00
|
||||
const chunks = []
|
||||
const streamSize = stream.data.length
|
||||
var total = 0
|
||||
for (
|
||||
var size = readByte()(stream);
|
||||
size !== terminator;
|
||||
size = readByte()(stream)
|
||||
) {
|
||||
// size becomes undefined for some case when file is corrupted and terminator is not proper
|
||||
// null check to avoid recursion
|
||||
if(!size) break;
|
||||
// catch corrupted files with no terminator
|
||||
if (stream.pos + size >= streamSize) {
|
||||
const availableSize = streamSize - stream.pos
|
||||
chunks.push(readBytes(availableSize)(stream))
|
||||
total += availableSize
|
||||
break
|
||||
}
|
||||
chunks.push(readBytes(size)(stream))
|
||||
total += size
|
||||
}
|
||||
const result = new Uint8Array(total)
|
||||
var offset = 0
|
||||
for (var i = 0; i < chunks.length; i++) {
|
||||
result.set(chunks[i], offset)
|
||||
offset += chunks[i].length
|
||||
}
|
||||
return result
|
||||
},
|
||||
}
|
||||
|
||||
// global control extension
|
||||
const gceSchema = conditional(
|
||||
{
|
||||
gce: [
|
||||
{ codes: readBytes(2) },
|
||||
{ byteSize: readByte() },
|
||||
{
|
||||
extras: readBits({
|
||||
future: { index: 0, length: 3 },
|
||||
disposal: { index: 3, length: 3 },
|
||||
userInput: { index: 6 },
|
||||
transparentColorGiven: { index: 7 },
|
||||
}),
|
||||
},
|
||||
{ delay: readUnsigned(true) },
|
||||
{ transparentColorIndex: readByte() },
|
||||
{ terminator: readByte() },
|
||||
],
|
||||
},
|
||||
(stream) => {
|
||||
var codes = peekBytes(2)(stream)
|
||||
return codes[0] === 0x21 && codes[1] === 0xf9
|
||||
}
|
||||
)
|
||||
|
||||
// image pipeline block
|
||||
const imageSchema = conditional(
|
||||
{
|
||||
image: [
|
||||
{ code: readByte() },
|
||||
{
|
||||
descriptor: [
|
||||
{ left: readUnsigned(true) },
|
||||
{ top: readUnsigned(true) },
|
||||
{ width: readUnsigned(true) },
|
||||
{ height: readUnsigned(true) },
|
||||
{
|
||||
lct: readBits({
|
||||
exists: { index: 0 },
|
||||
interlaced: { index: 1 },
|
||||
sort: { index: 2 },
|
||||
future: { index: 3, length: 2 },
|
||||
size: { index: 5, length: 3 },
|
||||
}),
|
||||
},
|
||||
],
|
||||
},
|
||||
conditional(
|
||||
{
|
||||
lct: readArray(3, (stream, result, parent) => {
|
||||
return Math.pow(2, parent.descriptor.lct.size + 1)
|
||||
}),
|
||||
},
|
||||
(stream, result, parent) => {
|
||||
return parent.descriptor.lct.exists
|
||||
}
|
||||
),
|
||||
{ data: [{ minCodeSize: readByte() }, subBlocksSchema] },
|
||||
],
|
||||
},
|
||||
(stream) => {
|
||||
return peekByte()(stream) === 0x2c
|
||||
}
|
||||
)
|
||||
|
||||
// plain text block
|
||||
const textSchema = conditional(
|
||||
{
|
||||
text: [
|
||||
{ codes: readBytes(2) },
|
||||
{ blockSize: readByte() },
|
||||
{
|
||||
preData: (stream, result, parent) =>
|
||||
readBytes(parent.text.blockSize)(stream),
|
||||
},
|
||||
subBlocksSchema,
|
||||
],
|
||||
},
|
||||
(stream) => {
|
||||
var codes = peekBytes(2)(stream)
|
||||
return codes[0] === 0x21 && codes[1] === 0x01
|
||||
}
|
||||
)
|
||||
|
||||
// application block
|
||||
const applicationSchema = conditional(
|
||||
{
|
||||
application: [
|
||||
{ codes: readBytes(2) },
|
||||
{ blockSize: readByte() },
|
||||
{ id: (stream, result, parent) => readString(parent.blockSize)(stream) },
|
||||
subBlocksSchema,
|
||||
],
|
||||
},
|
||||
(stream) => {
|
||||
var codes = peekBytes(2)(stream)
|
||||
return codes[0] === 0x21 && codes[1] === 0xff
|
||||
}
|
||||
)
|
||||
|
||||
// comment block
|
||||
const commentSchema = conditional(
|
||||
{
|
||||
comment: [{ codes: readBytes(2) }, subBlocksSchema],
|
||||
},
|
||||
(stream) => {
|
||||
var codes = peekBytes(2)(stream)
|
||||
return codes[0] === 0x21 && codes[1] === 0xfe
|
||||
}
|
||||
)
|
||||
|
||||
const schema = [
|
||||
{ header: [{ signature: readString(3) }, { version: readString(3) }] },
|
||||
{
|
||||
lsd: [
|
||||
{ width: readUnsigned(true) },
|
||||
{ height: readUnsigned(true) },
|
||||
{
|
||||
gct: readBits({
|
||||
exists: { index: 0 },
|
||||
resolution: { index: 1, length: 3 },
|
||||
sort: { index: 4 },
|
||||
size: { index: 5, length: 3 },
|
||||
}),
|
||||
},
|
||||
{ backgroundColorIndex: readByte() },
|
||||
{ pixelAspectRatio: readByte() },
|
||||
],
|
||||
},
|
||||
conditional(
|
||||
{
|
||||
gct: readArray(3, (stream, result) =>
|
||||
Math.pow(2, result.lsd.gct.size + 1)
|
||||
),
|
||||
},
|
||||
(stream, result) => result.lsd.gct.exists
|
||||
),
|
||||
// content frames
|
||||
{
|
||||
frames: loop(
|
||||
[gceSchema, applicationSchema, commentSchema, imageSchema, textSchema],
|
||||
(stream) => {
|
||||
var nextCode = peekByte()(stream)
|
||||
// rather than check for a terminator, we should check for the existence
|
||||
// of an ext or image block to avoid infinite loops
|
||||
//var terminator = 0x3B;
|
||||
//return nextCode !== terminator;
|
||||
return nextCode === 0x21 || nextCode === 0x2c
|
||||
}
|
||||
),
|
||||
},
|
||||
]
|
||||
|
||||
export default schema
|
||||
Loading…
Add table
Add a link
Reference in a new issue