a minimal netron for onnx
commit
d00a6f792f
@ -0,0 +1,34 @@
|
||||
|
||||
import argparse
|
||||
import sys
|
||||
import os
|
||||
|
||||
from .server import start
|
||||
from .server import stop
|
||||
from .server import status
|
||||
from .server import wait
|
||||
from .server import serve
|
||||
from .__version__ import __version__
|
||||
|
||||
def main():
|
||||
parser = argparse.ArgumentParser(description='Viewer for neural network, deep learning and machine learning models.')
|
||||
parser.add_argument('file', metavar='MODEL_FILE', help='model file to serve', nargs='?', default=None)
|
||||
parser.add_argument('-v', '--version', help="print version", action='store_true')
|
||||
parser.add_argument('-b', '--browse', help='launch web browser', action='store_true')
|
||||
parser.add_argument('-p', '--port', help='port to serve', type=int)
|
||||
parser.add_argument('--host', help="host to serve")
|
||||
parser.add_argument('--log', help='log details to console', action='store_true')
|
||||
args = parser.parse_args()
|
||||
if args.file and not os.path.exists(args.file):
|
||||
print("Model file '" + args.file + "' does not exist.")
|
||||
sys.exit(2)
|
||||
if args.version:
|
||||
print(__version__)
|
||||
sys.exit(0)
|
||||
address = (args.host, args.port) if args.host else args.port if args.port else None
|
||||
start(args.file, address=address, browse=args.browse, log=args.log)
|
||||
wait()
|
||||
sys.exit(0)
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
@ -0,0 +1 @@
|
||||
__version__ = '0.0.0'
|
||||
@ -0,0 +1,678 @@
|
||||
|
||||
var base = base || {};
|
||||
|
||||
base.Int64 = class Int64 {
|
||||
|
||||
constructor(low, high) {
|
||||
this.low = low | 0;
|
||||
this.high = high | 0;
|
||||
}
|
||||
|
||||
static create(value) {
|
||||
if (isNaN(value)) {
|
||||
return base.Int64.zero;
|
||||
}
|
||||
if (value <= -9223372036854776000) {
|
||||
return base.Int64.min;
|
||||
}
|
||||
if (value + 1 >= 9223372036854776000) {
|
||||
return base.Int64.max;
|
||||
}
|
||||
if (value < 0) {
|
||||
return base.Int64.create(-value).negate();
|
||||
}
|
||||
return new base.Int64((value % 4294967296) | 0, (value / 4294967296));
|
||||
}
|
||||
|
||||
get isZero() {
|
||||
return this.low === 0 && this.high === 0;
|
||||
}
|
||||
|
||||
get isNegative() {
|
||||
return this.high < 0;
|
||||
}
|
||||
|
||||
negate() {
|
||||
if (this.equals(base.Int64.min)) {
|
||||
return base.Int64.min;
|
||||
}
|
||||
return this.not().add(base.Int64.one);
|
||||
}
|
||||
|
||||
not() {
|
||||
return new Int64(~this.low, ~this.high);
|
||||
}
|
||||
|
||||
equals(other) {
|
||||
if (!(other instanceof base.Int64) && (this.high >>> 31) === 1 && (other.high >>> 31) === 1) {
|
||||
return false;
|
||||
}
|
||||
return this.high === other.high && this.low === other.low;
|
||||
}
|
||||
|
||||
compare(other) {
|
||||
if (this.equals(other)) {
|
||||
return 0;
|
||||
}
|
||||
const thisNeg = this.isNegative;
|
||||
const otherNeg = other.isNegative;
|
||||
if (thisNeg && !otherNeg) {
|
||||
return -1;
|
||||
}
|
||||
if (!thisNeg && otherNeg) {
|
||||
return 1;
|
||||
}
|
||||
return this.subtract(other).isNegative ? -1 : 1;
|
||||
}
|
||||
|
||||
add(other) {
|
||||
return base.Utility.add(this, other, false);
|
||||
}
|
||||
|
||||
subtract(other) {
|
||||
return base.Utility.subtract(this, other, false);
|
||||
}
|
||||
|
||||
multiply(other) {
|
||||
return base.Utility.multiply(this, other, false);
|
||||
}
|
||||
|
||||
divide(other) {
|
||||
return base.Utility.divide(this, other, false);
|
||||
}
|
||||
|
||||
toInteger() {
|
||||
return this.low;
|
||||
}
|
||||
|
||||
toNumber() {
|
||||
if (this.high === 0) {
|
||||
return this.low >>> 0;
|
||||
}
|
||||
if (this.high === -1) {
|
||||
return this.low;
|
||||
}
|
||||
return (this.high * 4294967296) + (this.low >>> 0);
|
||||
}
|
||||
|
||||
toString(radix) {
|
||||
const r = radix || 10;
|
||||
if (r < 2 || r > 16) {
|
||||
throw RangeError('radix');
|
||||
}
|
||||
if (this.isZero) {
|
||||
return '0';
|
||||
}
|
||||
if (this.high < 0) {
|
||||
if (this.equals(base.Int64.min)) {
|
||||
const r = new Int64(radix, 0);
|
||||
const div = this.divide(r);
|
||||
const remainder = div.multiply(r).subtract(this);
|
||||
return div.toString(r) + (remainder.low >>> 0).toString(r);
|
||||
}
|
||||
return '-' + this.negate().toString(r);
|
||||
}
|
||||
if (this.high === 0) {
|
||||
return this.low.toString(radix);
|
||||
}
|
||||
return base.Utility.text(this, false, r);
|
||||
}
|
||||
};
|
||||
|
||||
base.Int64.min = new base.Int64(0, -2147483648);
|
||||
base.Int64.zero = new base.Int64(0, 0);
|
||||
base.Int64.one = new base.Int64(1, 0);
|
||||
base.Int64.power24 = new base.Int64(1 << 24, 0);
|
||||
base.Int64.max = new base.Int64(0, 2147483647);
|
||||
|
||||
base.Uint64 = class Uint64 {
|
||||
|
||||
constructor(low, high) {
|
||||
this.low = low | 0;
|
||||
this.high = high | 0;
|
||||
}
|
||||
|
||||
static create(value) {
|
||||
if (isNaN(value)) {
|
||||
return base.Uint64.zero;
|
||||
}
|
||||
if (value < 0) {
|
||||
return base.Uint64.zero;
|
||||
}
|
||||
if (value >= 18446744073709552000) {
|
||||
return base.Uint64.max;
|
||||
}
|
||||
if (value < 0) {
|
||||
return base.Uint64.create(-value).negate();
|
||||
}
|
||||
return new base.Uint64((value % 4294967296) | 0, (value / 4294967296));
|
||||
}
|
||||
|
||||
get isZero() {
|
||||
return this.low === 0 && this.high === 0;
|
||||
}
|
||||
|
||||
get isNegative() {
|
||||
return false;
|
||||
}
|
||||
|
||||
negate() {
|
||||
return this.not().add(base.Int64.one);
|
||||
}
|
||||
|
||||
not() {
|
||||
return new base.Uint64(~this.low, ~this.high);
|
||||
}
|
||||
|
||||
equals(other) {
|
||||
if (!(other instanceof base.Uint64) && (this.high >>> 31) === 1 && (other.high >>> 31) === 1) {
|
||||
return false;
|
||||
}
|
||||
return this.high === other.high && this.low === other.low;
|
||||
}
|
||||
|
||||
compare(other) {
|
||||
if (this.equals(other)) {
|
||||
return 0;
|
||||
}
|
||||
const thisNeg = this.isNegative;
|
||||
const otherNeg = other.isNegative;
|
||||
if (thisNeg && !otherNeg) {
|
||||
return -1;
|
||||
}
|
||||
if (!thisNeg && otherNeg) {
|
||||
return 1;
|
||||
}
|
||||
return (other.high >>> 0) > (this.high >>> 0) || (other.high === this.high && (other.low >>> 0) > (this.low >>> 0)) ? -1 : 1;
|
||||
}
|
||||
|
||||
add(other) {
|
||||
return base.Utility.add(this, other, true);
|
||||
}
|
||||
|
||||
subtract(other) {
|
||||
return base.Utility.subtract(this, other, true);
|
||||
}
|
||||
|
||||
multiply(other) {
|
||||
return base.Utility.multiply(this, other, true);
|
||||
}
|
||||
|
||||
divide(other) {
|
||||
return base.Utility.divide(this, other, true);
|
||||
}
|
||||
|
||||
toInteger() {
|
||||
return this.low >>> 0;
|
||||
}
|
||||
|
||||
toNumber() {
|
||||
if (this.high === 0) {
|
||||
return this.low >>> 0;
|
||||
}
|
||||
return ((this.high >>> 0) * 4294967296) + (this.low >>> 0);
|
||||
}
|
||||
|
||||
toString(radix) {
|
||||
const r = radix || 10;
|
||||
if (r < 2 || 36 < r) {
|
||||
throw RangeError('radix');
|
||||
}
|
||||
if (this.isZero) {
|
||||
return '0';
|
||||
}
|
||||
if (this.high === 0) {
|
||||
return this.low.toString(radix);
|
||||
}
|
||||
return base.Utility.text(this, true, r);
|
||||
}
|
||||
};
|
||||
|
||||
base.Utility = class {
|
||||
|
||||
static add(a, b, unsigned) {
|
||||
const a48 = a.high >>> 16;
|
||||
const a32 = a.high & 0xFFFF;
|
||||
const a16 = a.low >>> 16;
|
||||
const a00 = a.low & 0xFFFF;
|
||||
const b48 = b.high >>> 16;
|
||||
const b32 = b.high & 0xFFFF;
|
||||
const b16 = b.low >>> 16;
|
||||
const b00 = b.low & 0xFFFF;
|
||||
let c48 = 0;
|
||||
let c32 = 0;
|
||||
let c16 = 0;
|
||||
let c00 = 0;
|
||||
c00 += a00 + b00;
|
||||
c16 += c00 >>> 16;
|
||||
c00 &= 0xFFFF;
|
||||
c16 += a16 + b16;
|
||||
c32 += c16 >>> 16;
|
||||
c16 &= 0xFFFF;
|
||||
c32 += a32 + b32;
|
||||
c48 += c32 >>> 16;
|
||||
c32 &= 0xFFFF;
|
||||
c48 += a48 + b48;
|
||||
c48 &= 0xFFFF;
|
||||
return base.Utility._create((c16 << 16) | c00, (c48 << 16) | c32, unsigned);
|
||||
}
|
||||
|
||||
static subtract(a, b, unsigned) {
|
||||
return base.Utility.add(a, b.negate(), unsigned);
|
||||
}
|
||||
|
||||
static multiply(a, b, unsigned) {
|
||||
if (a.isZero) {
|
||||
return base.Int64.zero;
|
||||
}
|
||||
if (b.isZero) {
|
||||
return base.Int64.zero;
|
||||
}
|
||||
if (a.equals(base.Int64.min)) {
|
||||
return b.isOdd() ? base.Int64.min : base.Int64.zero;
|
||||
}
|
||||
if (b.equals(base.Int64.min)) {
|
||||
return b.isOdd() ? base.Int64.min : base.Int64.zero;
|
||||
}
|
||||
if (a.isNegative) {
|
||||
if (b.isNegative) {
|
||||
return this.negate().multiply(b.negate());
|
||||
}
|
||||
else {
|
||||
return this.negate().multiply(b).negate();
|
||||
}
|
||||
}
|
||||
else if (b.isNegative) {
|
||||
return this.multiply(b.negate()).negate();
|
||||
}
|
||||
if (a.compare(base.Int64.power24) < 0 && b.compare(base.Int64.power24) < 0) {
|
||||
return unsigned ? base.Uint64.create(a.toNumber() * b.toNumber()) : base.Int64.create(a.toNumber() * b.toNumber());
|
||||
}
|
||||
const a48 = a.high >>> 16;
|
||||
const a32 = a.high & 0xFFFF;
|
||||
const a16 = a.low >>> 16;
|
||||
const a00 = a.low & 0xFFFF;
|
||||
const b48 = b.high >>> 16;
|
||||
const b32 = b.high & 0xFFFF;
|
||||
const b16 = b.low >>> 16;
|
||||
const b00 = b.low & 0xFFFF;
|
||||
let c48 = 0;
|
||||
let c32 = 0;
|
||||
let c16 = 0;
|
||||
let c00 = 0;
|
||||
c00 += a00 * b00;
|
||||
c16 += c00 >>> 16;
|
||||
c00 &= 0xFFFF;
|
||||
c16 += a16 * b00;
|
||||
c32 += c16 >>> 16;
|
||||
c16 &= 0xFFFF;
|
||||
c16 += a00 * b16;
|
||||
c32 += c16 >>> 16;
|
||||
c16 &= 0xFFFF;
|
||||
c32 += a32 * b00;
|
||||
c48 += c32 >>> 16;
|
||||
c32 &= 0xFFFF;
|
||||
c32 += a16 * b16;
|
||||
c48 += c32 >>> 16;
|
||||
c32 &= 0xFFFF;
|
||||
c32 += a00 * b32;
|
||||
c48 += c32 >>> 16;
|
||||
c32 &= 0xFFFF;
|
||||
c48 += a48 * b00 + a32 * b16 + a16 * b32 + a00 * b48;
|
||||
c48 &= 0xFFFF;
|
||||
return base.Utility._create((c16 << 16) | c00, (c48 << 16) | c32, unsigned);
|
||||
}
|
||||
|
||||
static divide(a, b, unsigned) {
|
||||
if (b.isZero) {
|
||||
throw Error('Division by zero.');
|
||||
}
|
||||
if (a.isZero) {
|
||||
return unsigned ? base.Uint64.zero : base.Int64.zero;
|
||||
}
|
||||
let approx;
|
||||
let remainder;
|
||||
let result;
|
||||
if (!unsigned) {
|
||||
if (a.equals(base.Int64.min)) {
|
||||
if (b.equals(base.Int64.one) || b.equals(base.Int64.negativeOne)) {
|
||||
return base.Int64.min;
|
||||
}
|
||||
else if (b.equals(base.Int64.min)) {
|
||||
return base.Int64.one;
|
||||
}
|
||||
else {
|
||||
const half = base.Utility._shiftRight(a, unsigned, 1);
|
||||
const halfDivide = half.divide(b);
|
||||
approx = base.Utility._shiftLeft(halfDivide, halfDivide instanceof base.Uint64, 1);
|
||||
if (approx.eq(base.Int64.zero)) {
|
||||
return b.isNegative ? base.Int64.one : base.Int64.negativeOne;
|
||||
}
|
||||
else {
|
||||
remainder = a.subtract(b.multiply(approx));
|
||||
result = approx.add(remainder.divide(b));
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (b.equals(base.Int64.min)) {
|
||||
return unsigned ? base.Uint64.zero : base.Int64.zero;
|
||||
}
|
||||
if (a.isNegative) {
|
||||
if (b.isNegative) {
|
||||
return this.negate().divide(b.negate());
|
||||
}
|
||||
return a.negate().divide(b).negate();
|
||||
}
|
||||
else if (b.isNegative) {
|
||||
return a.divide(b.negate()).negate();
|
||||
}
|
||||
result = base.Int64.zero;
|
||||
}
|
||||
else {
|
||||
if (!(b instanceof base.Uint64)) {
|
||||
b = new base.Uint64(b.low, b.high);
|
||||
}
|
||||
if (b.compare(a) > 0) {
|
||||
return base.Int64.zero;
|
||||
}
|
||||
if (b.compare(base.Utility._shiftRight(a, unsigned, 1)) > 0) {
|
||||
return base.Uint64.one;
|
||||
}
|
||||
result = base.Uint64.zero;
|
||||
}
|
||||
remainder = a;
|
||||
while (remainder.compare(b) >= 0) {
|
||||
let approx = Math.max(1, Math.floor(remainder.toNumber() / b.toNumber()));
|
||||
const log2 = Math.ceil(Math.log(approx) / Math.LN2);
|
||||
const delta = (log2 <= 48) ? 1 : Math.pow(2, log2 - 48);
|
||||
let approxResult = base.Int64.create(approx);
|
||||
let approxRemainder = approxResult.multiply(b);
|
||||
while (approxRemainder.isNegative || approxRemainder.compare(remainder) > 0) {
|
||||
approx -= delta;
|
||||
approxResult = unsigned ? base.Uint64.create(approx) : base.Int64.create(approx);
|
||||
approxRemainder = approxResult.multiply(b);
|
||||
}
|
||||
if (approxResult.isZero) {
|
||||
approxResult = base.Int64.one;
|
||||
}
|
||||
result = result.add(approxResult);
|
||||
remainder = remainder.subtract(approxRemainder);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
static text(value, unsigned, radix) {
|
||||
const power = unsigned ? base.Uint64.create(Math.pow(radix, 6)) : base.Int64.create(Math.pow(radix, 6));
|
||||
let remainder = value;
|
||||
let result = '';
|
||||
for (;;) {
|
||||
const remainderDiv = remainder.divide(power);
|
||||
const intval = remainder.subtract(remainderDiv.multiply(power)).toInteger() >>> 0;
|
||||
let digits = intval.toString(radix);
|
||||
remainder = remainderDiv;
|
||||
if (remainder.low === 0 && remainder.high === 0) {
|
||||
return digits + result;
|
||||
}
|
||||
while (digits.length < 6) {
|
||||
digits = '0' + digits;
|
||||
}
|
||||
result = '' + digits + result;
|
||||
}
|
||||
}
|
||||
|
||||
static _shiftLeft(value, unsigned, shift) {
|
||||
return base.Utility._create(value.low << shift, (value.high << shift) | (value.low >>> (32 - shift)), unsigned);
|
||||
}
|
||||
|
||||
static _shiftRight(value, unsigned, shift) {
|
||||
return base.Utility._create((value.low >>> shift) | (value.high << (32 - shift)), value.high >> shift, unsigned);
|
||||
}
|
||||
|
||||
static _create(low, high, unsigned) {
|
||||
return unsigned ? new base.Uint64(low, high) : new base.Int64(low, high);
|
||||
}
|
||||
};
|
||||
|
||||
base.Uint64.zero = new base.Uint64(0, 0);
|
||||
base.Uint64.one = new base.Uint64(1, 0);
|
||||
base.Uint64.max = new base.Uint64(-1, -1);
|
||||
|
||||
if (!DataView.prototype.getFloat16) {
|
||||
DataView.prototype.getFloat16 = function(byteOffset, littleEndian) {
|
||||
const value = this.getUint16(byteOffset, littleEndian);
|
||||
const e = (value & 0x7C00) >> 10;
|
||||
let f = value & 0x03FF;
|
||||
if (e == 0) {
|
||||
f = 0.00006103515625 * (f / 1024);
|
||||
}
|
||||
else if (e == 0x1F) {
|
||||
f = f ? NaN : Infinity;
|
||||
}
|
||||
else {
|
||||
f = DataView.__float16_pow[e] * (1 + (f / 1024));
|
||||
}
|
||||
return value & 0x8000 ? -f : f;
|
||||
};
|
||||
DataView.__float16_pow = {
|
||||
1: 1/16384, 2: 1/8192, 3: 1/4096, 4: 1/2048, 5: 1/1024, 6: 1/512, 7: 1/256, 8: 1/128,
|
||||
9: 1/64, 10: 1/32, 11: 1/16, 12: 1/8, 13: 1/4, 14: 1/2, 15: 1, 16: 2,
|
||||
17: 4, 18: 8, 19: 16, 20: 32, 21: 64, 22: 128, 23: 256, 24: 512,
|
||||
25: 1024, 26: 2048, 27: 4096, 28: 8192, 29: 16384, 30: 32768, 31: 65536
|
||||
};
|
||||
}
|
||||
|
||||
if (!DataView.prototype.setFloat16) {
|
||||
DataView.prototype.setFloat16 = function(byteOffset, value, littleEndian) {
|
||||
DataView.__float16_float[0] = value;
|
||||
value = DataView.__float16_int[0];
|
||||
const s = (value >>> 16) & 0x8000;
|
||||
const e = (value >>> 23) & 0xff;
|
||||
const f = value & 0x7fffff;
|
||||
const v = s | DataView.__float16_base[e] | (f >> DataView.__float16_shift[e]);
|
||||
this.setUint16(byteOffset, v, littleEndian);
|
||||
};
|
||||
DataView.__float16_float = new Float32Array(1);
|
||||
DataView.__float16_int = new Uint32Array(DataView.__float16_float.buffer, 0, DataView.__float16_float.length);
|
||||
DataView.__float16_base = new Uint32Array(256);
|
||||
DataView.__float16_shift = new Uint32Array(256);
|
||||
for (let i = 0; i < 256; ++i) {
|
||||
const e = i - 127;
|
||||
if (e < -27) {
|
||||
DataView.__float16_base[i] = 0x0000;
|
||||
DataView.__float16_shift[i] = 24;
|
||||
}
|
||||
else if (e < -14) {
|
||||
DataView.__float16_base[i] = 0x0400 >> -e - 14;
|
||||
DataView.__float16_shift[i] = -e - 1;
|
||||
}
|
||||
else if (e <= 15) {
|
||||
DataView.__float16_base[i] = e + 15 << 10;
|
||||
DataView.__float16_shift[i] = 13;
|
||||
}
|
||||
else if (e < 128) {
|
||||
DataView.__float16_base[i] = 0x7c00;
|
||||
DataView.__float16_shift[i] = 24;
|
||||
}
|
||||
else {
|
||||
DataView.__float16_base[i] = 0x7c00;
|
||||
DataView.__float16_shift[i] = 13;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
DataView.prototype.getInt64 = DataView.prototype.getInt64 || function(byteOffset, littleEndian) {
|
||||
return littleEndian ?
|
||||
new base.Int64(this.getUint32(byteOffset, true), this.getUint32(byteOffset + 4, true)) :
|
||||
new base.Int64(this.getUint32(byteOffset + 4, true), this.getUint32(byteOffset, true));
|
||||
};
|
||||
|
||||
DataView.prototype.setInt64 = DataView.prototype.setInt64 || function(byteOffset, value, littleEndian) {
|
||||
if (littleEndian) {
|
||||
this.setUint32(byteOffset, value.low, true);
|
||||
this.setUint32(byteOffset + 4, value.high, true);
|
||||
}
|
||||
else {
|
||||
this.setUint32(byteOffset + 4, value.low, false);
|
||||
this.setUint32(byteOffset, value.high, false);
|
||||
}
|
||||
};
|
||||
|
||||
DataView.prototype.getUint64 = DataView.prototype.getUint64 || function(byteOffset, littleEndian) {
|
||||
return littleEndian ?
|
||||
new base.Uint64(this.getUint32(byteOffset, true), this.getUint32(byteOffset + 4, true)) :
|
||||
new base.Uint64(this.getUint32(byteOffset + 4, true), this.getUint32(byteOffset, true));
|
||||
};
|
||||
|
||||
DataView.prototype.setUint64 = DataView.prototype.setUint64 || function(byteOffset, value, littleEndian) {
|
||||
if (littleEndian) {
|
||||
this.setUInt32(byteOffset, value.low, true);
|
||||
this.setUInt32(byteOffset + 4, value.high, true);
|
||||
}
|
||||
else {
|
||||
this.setUInt32(byteOffset + 4, value.low, false);
|
||||
this.setUInt32(byteOffset, value.high, false);
|
||||
}
|
||||
};
|
||||
|
||||
DataView.prototype.getBits = DataView.prototype.getBits || function(offset, bits /*, signed */) {
|
||||
offset = offset * bits;
|
||||
const available = (this.byteLength << 3) - offset;
|
||||
if (bits > available) {
|
||||
throw new RangeError();
|
||||
}
|
||||
let value = 0;
|
||||
let index = 0;
|
||||
while (index < bits) {
|
||||
const remainder = offset & 7;
|
||||
const size = Math.min(bits - index, 8 - remainder);
|
||||
value <<= size;
|
||||
value |= (this.getUint8(offset >> 3) >> (8 - size - remainder)) & ~(0xff << size);
|
||||
offset += size;
|
||||
index += size;
|
||||
}
|
||||
return value;
|
||||
};
|
||||
|
||||
base.BinaryReader = class {
|
||||
|
||||
constructor(data) {
|
||||
this._buffer = data instanceof Uint8Array ? data : data.peek();
|
||||
this._position = 0;
|
||||
this._length = this._buffer.length;
|
||||
this._view = new DataView(this._buffer.buffer, this._buffer.byteOffset, this._buffer.byteLength);
|
||||
this._utf8 = new TextDecoder('utf-8');
|
||||
}
|
||||
|
||||
get length() {
|
||||
return this._length;
|
||||
}
|
||||
|
||||
get position() {
|
||||
return this._position;
|
||||
}
|
||||
|
||||
seek(position) {
|
||||
this._position = position >= 0 ? position : this._length + position;
|
||||
if (this._position > this._length || this._position < 0) {
|
||||
throw new Error('Expected ' + (this._position - this._length) + ' more bytes. The file might be corrupted. Unexpected end of file.');
|
||||
}
|
||||
}
|
||||
|
||||
skip(offset) {
|
||||
this._position += offset;
|
||||
if (this._position > this._length) {
|
||||
throw new Error('Expected ' + (this._position - this._length) + ' more bytes. The file might be corrupted. Unexpected end of file.');
|
||||
}
|
||||
}
|
||||
|
||||
read(length) {
|
||||
if (this._position === 0 && length === undefined) {
|
||||
this._position = this._length;
|
||||
return this._buffer;
|
||||
}
|
||||
const position = this._position;
|
||||
this.skip(length !== undefined ? length : this._length - this._position);
|
||||
return this._buffer.slice(position, this._position);
|
||||
}
|
||||
|
||||
byte() {
|
||||
const position = this._position;
|
||||
this.skip(1);
|
||||
return this._buffer[position];
|
||||
}
|
||||
|
||||
int8() {
|
||||
const position = this._position;
|
||||
this.skip(1);
|
||||
return this._view.getInt8(position, true);
|
||||
}
|
||||
|
||||
int16() {
|
||||
const position = this._position;
|
||||
this.skip(2);
|
||||
return this._view.getInt16(position, true);
|
||||
}
|
||||
|
||||
int32() {
|
||||
const position = this._position;
|
||||
this.skip(4);
|
||||
return this._view.getInt32(position, true);
|
||||
}
|
||||
|
||||
int64() {
|
||||
const position = this._position;
|
||||
this.skip(8);
|
||||
return this._view.getInt64(position, true).toNumber();
|
||||
}
|
||||
|
||||
uint16() {
|
||||
const position = this._position;
|
||||
this.skip(2);
|
||||
return this._view.getUint16(position, true);
|
||||
}
|
||||
|
||||
uint32() {
|
||||
const position = this._position;
|
||||
this.skip(4);
|
||||
return this._view.getUint32(position, true);
|
||||
}
|
||||
|
||||
uint64() {
|
||||
const position = this._position;
|
||||
this.skip(8);
|
||||
return this._view.getUint64(position, true).toNumber();
|
||||
}
|
||||
|
||||
float32() {
|
||||
const position = this._position;
|
||||
this.skip(4);
|
||||
return this._view.getFloat32(position, true);
|
||||
}
|
||||
|
||||
float64() {
|
||||
const position = this._position;
|
||||
this.skip(8);
|
||||
return this._view.getFloat64(position, true);
|
||||
}
|
||||
|
||||
string() {
|
||||
const length = this.uint32();
|
||||
const position = this._position;
|
||||
this.skip(length);
|
||||
const data = this._buffer.subarray(position, this._position);
|
||||
return this._utf8.decode(data);
|
||||
}
|
||||
};
|
||||
|
||||
if (typeof window !== 'undefined' && typeof window.Long != 'undefined') {
|
||||
window.long = { Long: window.Long };
|
||||
window.Int64 = base.Int64;
|
||||
window.Uint64 = base.Uint64;
|
||||
}
|
||||
|
||||
if (typeof module !== 'undefined' && typeof module.exports === 'object') {
|
||||
module.exports.Int64 = base.Int64;
|
||||
module.exports.Uint64 = base.Uint64;
|
||||
module.exports.BinaryReader = base.BinaryReader;
|
||||
}
|
||||
@ -0,0 +1,315 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">
|
||||
<meta http-equiv="Content-Security-Policy" content="script-src 'self';">
|
||||
<title>Netron</title>
|
||||
<link rel="stylesheet" type="text/css" href="view-grapher.css">
|
||||
<link rel="stylesheet" type="text/css" href="view-sidebar.css">
|
||||
<style>
|
||||
html { touch-action: none; overflow: hidden; width: 100%; height: 100%; -ms-text-size-adjust: 100%; -webkit-text-size-adjust: 100%; text-rendering: optimizeLegibility; -webkit-text-rendering: optimizeLegibility; -moz-text-rendering: optimizeLegibility; -ms-text-rendering: optimizeLegibility; -o-text-rendering: optimizeLegibility; -webkit-font-smoothing: antialiased; -moz-font-smoothing: antialiased; -ms-font-smoothing: antialiased; -o-font-smoothing: antialiased; }
|
||||
body { touch-action: none; overflow: hidden; width: 100%; height: 100%; margin: 0; font-family: -apple-system, BlinkMacSystemFont, "Segoe WPC", "Segoe UI", "Ubuntu", "Droid Sans", sans-serif, "PingFang SC"; font-size: 12px; text-rendering: geometricPrecision; }
|
||||
button { font-family: -apple-system, BlinkMacSystemFont, "Segoe WPC", "Segoe UI", "Ubuntu", "Droid Sans", sans-serif, "PingFang SC"; }
|
||||
.center { position: absolute; margin: auto; top: 0; right: 0; bottom: 0; left: 0; user-select: none; -webkit-user-select: none; -moz-user-select: none; }
|
||||
.select { user-select: text; -webkit-user-select: text; -moz-user-select: text; }
|
||||
.open-file-dialog { display: none; }
|
||||
.graph { display: flex; height: 100%; width: 100%; overflow: auto; outline: none; touch-action: pan-x pan-y; }
|
||||
.canvas { margin: auto; flex-shrink: 0; text-rendering: geometricPrecision; user-select: none; -webkit-user-select: none; -moz-user-select: none; }
|
||||
.toolbar { position: absolute; top: 10px; left: 10px; padding: 0; margin: 0; user-select: none; -webkit-user-select: none; -moz-user-select: none; }
|
||||
.toolbar button:focus { outline: 0; }
|
||||
.toolbar-button { float: left; background: None; border-radius: 6px; border: 0; margin: 0; margin-right: 1px; padding: 0; fill: None; stroke: #777; cursor: pointer; width: 24px; height: 24px; }
|
||||
.toolbar-back-button { float: left; background: #777; border-top-left-radius: 6px; border-bottom-left-radius: 6px; border: 0px solid; border-color: #777; margin: 2px 0 2px 8px; padding: 0 8px 0 8px; cursor: pointer; height: 20px; color: #ffffff; font-size: 11px; line-height: 0; transition: 0.1s; }
|
||||
.toolbar-back-button:hover { background: #000000; border-color: #000000; }
|
||||
.toolbar-name-button { float: left; background: rgba(255, 255, 255, 0.95); border-top-right-radius: 6px; border-bottom-right-radius: 6px; border: 1px solid #777; color: #777; border-left: 1px; border-left-color: #ffffff; margin: 2px 0 2px 0; padding: 0 12px 0 6px; cursor: pointer; width: auto; height: 20px; font-size: 11px; line-height: 0; transition: 0.1s; }
|
||||
.toolbar-name-button:hover { color: #000000; }
|
||||
.icon .border { stroke: #fff; }
|
||||
.icon .stroke { stroke: #808080; }
|
||||
.icon:hover .stroke { stroke: #000000; }
|
||||
.dropdown { display: none; position: absolute; min-width: 225px; z-index: 1; border-radius: 4px; background-color: #f6f6f6; border: 1px solid rgba(0,0,0,.15); padding-top: 2px; padding-bottom: 2px; margin-left: 2px; overflow: hidden; }
|
||||
.dropdown button { display: block; border: none; border-radius: 0; background-color: transparent; color: black; width: 100%; text-align: left; padding: 4px 12px 5px 12px; white-space: no-wrap; font-size: 12px; }
|
||||
.dropdown button:hover { color: #ffffff; background-color: #2e6bd2; }
|
||||
.dropdown .separator { margin-top: 2px; margin-bottom: 2px; border-top: 1px; border-bottom: 0; border-style: solid; border-color: #e5e5e5; }
|
||||
.welcome { background-color: #ececec; color: #242424; }
|
||||
.welcome .logo { width: 582px; height: 128px; }
|
||||
.welcome .logo-text { top: -57px; width: 582px; transition: 0.1s; }
|
||||
.welcome .logo-name { top: -170px; width: 582px; transition: 0.1s; }
|
||||
.welcome .logo-icon { left: 248px; top: -18px; width: 106px; height: 106px; transition: 0.1s; }
|
||||
.welcome .logo-spinner { left: 248px; top: -18px; width: 106px; height: 106px; display: none; }
|
||||
.welcome .logo-stroke { stroke: #444444; }
|
||||
.welcome .logo-fill { fill: #444444; }
|
||||
.welcome .logo-border { stroke: #555555; }
|
||||
.welcome .logo-glyph { fill: #444444; }
|
||||
.welcome .logo-message { display: none; }
|
||||
.welcome .logo-github { display: none; }
|
||||
.welcome button { font-size: 12px; font-weight: bold; line-height: 1.25; text-align: center; vertical-align: middle; min-width: 60px; height: 32px; border-radius: 16px; transition: 0.1s; user-select: none; -webkit-user-select: none; -moz-user-select: none; color: #444444; background-color: #ececec; border: 1px solid #444444; }
|
||||
.welcome button:hover { color: #ececec; background-color: #444444; cursor: pointer; transition: 0.2s; }
|
||||
.welcome button:focus { outline: 0; }
|
||||
.welcome .open-file-button { top: 170px; left: -150px; width: 125px; opacity: 1; }
|
||||
.welcome .github-button { top: 170px; left: 150px; width: 125px; opacity: 1; }
|
||||
.welcome .consent-accept-button { top: 220px; left: 0px; width: 125px; display: none; opacity: 0; }
|
||||
.welcome .consent-message { top: 120px; left: 0px; font-size: 13px; text-align: center; line-height: 20px; color: #444444; display: none; opacity: 0; }
|
||||
.welcome .graph { display: none; opacity: 0; }
|
||||
.welcome.spinner .logo-spinner { display: block; -webkit-animation: orbit 0.5s infinite linear; animation: orbit 0.5s infinite linear; cursor: wait; }
|
||||
@-webkit-keyframes orbit { 0% { -webkit-transform: rotate(0deg); transform: rotate(0deg); } 100% { -webkit-transform: rotate(360deg); transform: rotate(360deg); } }
|
||||
@keyframes orbit { 0% { -webkit-transform: rotate(0deg); transform: rotate(0deg); } 100% { -webkit-transform: rotate(360deg); transform: rotate(360deg); } }
|
||||
.welcome.spinner .logo-spinner-stroke { stroke: #ececec; }
|
||||
.welcome.spinner .logo-name { display: none; }
|
||||
.welcome.spinner .open-file-button { opacity: 0; display: none; }
|
||||
.welcome.spinner .github-button { opacity: 0; display: none; }
|
||||
.welcome.consent .logo-name { display: none; }
|
||||
.welcome.consent .open-file-button { opacity: 0; display: none; }
|
||||
.welcome.consent .github-button { opacity: 0; display: none; }
|
||||
.welcome.consent .consent-accept-button { opacity: 1; display: block; }
|
||||
.welcome.consent .consent-message { opacity: 1; display: block; }
|
||||
.welcome.spinner .graph { display: flex; opacity: 0; }
|
||||
.welcome .toolbar { display: none; }
|
||||
.default { background-color: #ffffff; }
|
||||
.default .logo { display: none; }
|
||||
.default .graph { display: flex; opacity: 1; }
|
||||
.default .toolbar { display: table; }
|
||||
@media (prefers-color-scheme: dark) {
|
||||
:root { color-scheme: dark; }
|
||||
.default { background-color: #404040; }
|
||||
.graph { background-color: #404040; }
|
||||
.welcome { background-color: #1e1e1e; color: #888888; }
|
||||
.welcome .logo-stroke { stroke: #888888; }
|
||||
.welcome .logo-fill { fill: #888888; }
|
||||
.welcome .logo-border { stroke: #000000; }
|
||||
.welcome .logo-glyph { fill: #888888; }
|
||||
.welcome .logo-spinner-stroke { stroke: #ffffff; }
|
||||
.welcome .logo button { color: #888888; background-color: #1e1e1e; border-color: #888888; }
|
||||
.welcome .logo button:hover { color: #1e1e1e; background-color: #888888; }
|
||||
.welcome .consent-message { color: #888888; display: none; opacity: 0; }
|
||||
.icon .border { stroke: #1d1d1d; }
|
||||
.icon .stroke { stroke: #aaaaaa; }
|
||||
.icon:hover .stroke { stroke: #dfdfdf; }
|
||||
.dropdown { background-color: #373737; border-color: #000000; }
|
||||
.dropdown button { color: #ffffff; }
|
||||
.dropdown button:hover { color: #ffffff; background-color: #1d59d1; }
|
||||
.dropdown .separator { border-color: #5a5a5a; }
|
||||
.toolbar-back-button { background: #aaaaaa; border-color: #aaaaaa; color: #333333; }
|
||||
.toolbar-back-button:hover { background: #dfdfdf; border-color: #dfdfdf; }
|
||||
.toolbar-name-button { background: #404040; border-color: #aaaaaa; color: #cccccc; }
|
||||
.toolbar-name-button:hover { color: #dfdfdf; }
|
||||
}
|
||||
@media all and (max-width: 640px) {
|
||||
.welcome .logo { width: 240px; }
|
||||
.welcome .logo-text { opacity: 0; }
|
||||
.welcome .logo-name { opacity: 0; }
|
||||
.welcome .logo-icon { left: 0; top: 0; width: 128px; height: 128px; }
|
||||
.welcome .logo-spinner { left: 0; top: 0; width: 128px; height: 128px; }
|
||||
.welcome .logo .open-file-button { top: 180px; left: 0; }
|
||||
.welcome .logo .github-button { top: 270px; left: 0; }
|
||||
.welcome .logo .consent-message { top: 140px; }
|
||||
.welcome .logo .consent-accept-button { top: 310px; }
|
||||
.about .logo { border-radius: 0; border-left: 0px; border-right: 0px; width: 100%; padding-left: 0; padding-right: 0; }
|
||||
.about.desktop .logo { width: 320px; padding: 40px; }
|
||||
}
|
||||
@media only screen and (max-device-width: 1024px) {
|
||||
.toolbar-button { width: 32px; height: 32px; }
|
||||
.toolbar-back-button { margin-top: 6px; margin-bottom: 6px; }
|
||||
.toolbar-name-button { margin-top: 6px; margin-bottom: 6px; }
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body class="welcome spinner">
|
||||
<div id="graph" class="graph" tabindex="0">
|
||||
<svg id="canvas" class="canvas" preserveaspectratio="xMidYMid meet" width="100%" height="100%"></svg>
|
||||
</div>
|
||||
<div id="sidebar" class="sidebar"></div>
|
||||
<div id="toolbar" class="toolbar">
|
||||
<button id="menu-button" class="toolbar-button" title="Model Properties">
|
||||
<svg class="icon" viewbox="0 0 100 100">
|
||||
<rect class="border" x="12" y="12" width="76" height="76" rx="16" ry="16" stroke-width="8"></rect>
|
||||
<line class="border" x1="30" y1="37" x2="70" y2="37" stroke-width="8" stroke-linecap="round" stroke="#fff"></line>
|
||||
<line class="border" x1="30" y1="50" x2="70" y2="50" stroke-width="8" stroke-linecap="round" stroke="#fff"></line>
|
||||
<line class="border" x1="30" y1="63" x2="70" y2="63" stroke-width="8" stroke-linecap="round" stroke="#fff"></line>
|
||||
<rect class="stroke" x="12" y="12" width="76" height="76" rx="16" ry="16" stroke-width="4"></rect>
|
||||
<line class="stroke" x1="30" y1="37" x2="70" y2="37" stroke-width="4" stroke-linecap="round"></line>
|
||||
<line class="stroke" x1="30" y1="50" x2="70" y2="50" stroke-width="4" stroke-linecap="round"></line>
|
||||
<line class="stroke" x1="30" y1="63" x2="70" y2="63" stroke-width="4" stroke-linecap="round"></line>
|
||||
</svg>
|
||||
</button>
|
||||
<button id="zoom-in-button" class="toolbar-button" title="Zoom In">
|
||||
<svg class="icon" viewbox="0 0 100 100">
|
||||
<circle class="border" cx="50" cy="50" r="35" stroke-width="8" stroke="#fff"></circle>
|
||||
<line class="border" x1="50" y1="38" x2="50" y2="62" stroke-width="8" stroke-linecap="round" stroke="#fff"></line>
|
||||
<line class="border" x1="38" y1="50" x2="62" y2="50" stroke-width="8" stroke-linecap="round" stroke="#fff"></line>
|
||||
<line class="border" x1="78" y1="78" x2="82" y2="82" stroke-width="12" stroke-linecap="square" stroke="#fff"></line>
|
||||
<circle class="stroke" cx="50" cy="50" r="35" stroke-width="4"></circle>
|
||||
<line class="stroke" x1="50" y1="38" x2="50" y2="62" stroke-width="4" stroke-linecap="round"></line>
|
||||
<line class="stroke" x1="38" y1="50" x2="62" y2="50" stroke-width="4" stroke-linecap="round"></line>
|
||||
<line class="stroke" x1="78" y1="78" x2="82" y2="82" stroke-width="8" stroke-linecap="square"></line>
|
||||
</svg>
|
||||
</button>
|
||||
<button id="zoom-out-button" class="toolbar-button" title="Zoom Out">
|
||||
<svg class="icon" viewbox="0 0 100 100">
|
||||
<circle class="border" cx="50" cy="50" r="35" stroke-width="8" stroke="#fff"></circle>
|
||||
<line class="border" x1="38" y1="50" x2="62" y2="50" stroke-width="8" stroke-linecap="round" stroke="#fff"></line>
|
||||
<line class="border" x1="78" y1="78" x2="82" y2="82" stroke-width="12" stroke-linecap="square" stroke="#fff"></line>
|
||||
<circle class="stroke" cx="50" cy="50" r="35" stroke-width="4"></circle>
|
||||
<line class="stroke" x1="38" y1="50" x2="62" y2="50" stroke-width="4" stroke-linecap="round"></line>
|
||||
<line class="stroke" x1="78" y1="78" x2="82" y2="82" stroke-width="8" stroke-linecap="square"></line>
|
||||
</svg>
|
||||
</button>
|
||||
<button id="back-button" class="toolbar-back-button" title="Back">
|
||||
❮
|
||||
</button>
|
||||
<button id="name-button" class="toolbar-name-button" title="Name">
|
||||
</button>
|
||||
</div>
|
||||
<div class="center logo">
|
||||
<a href="https://github.com/lutzroeder/netron" target="blank_">
|
||||
<svg class="center logo-text" viewbox="0 0 5120 1024">
|
||||
<g transform="scale(9) translate(-44,-15)">
|
||||
<g transform="matrix(100,0,0,100,60.9965,126)">
|
||||
<path class="logo-glyph" d="M0.089,0L0.089,-0.745L0.595,-0.147L0.595,-0.715L0.656,-0.715L0.656,0.021L0.15,-0.578L0.15,0L0.089,0Z" style="fill-rule:nonzero;"/>
|
||||
</g>
|
||||
<g transform="matrix(100,0,0,100,164.341,126)">
|
||||
<path class="logo-glyph" d="M0.089,0L0.089,-0.715L0.443,-0.715L0.443,-0.654L0.154,-0.654L0.154,-0.43L0.443,-0.43L0.443,-0.369L0.154,-0.369L0.154,-0.061L0.443,-0.061L0.443,0L0.089,0Z" style="fill-rule:nonzero;"/>
|
||||
</g>
|
||||
<g transform="matrix(100,0,0,100,244.491,126)">
|
||||
<path class="logo-glyph" d="M0.216,0L0.216,-0.654L0.019,-0.654L0.019,-0.715L0.478,-0.715L0.478,-0.654L0.281,-0.654L0.281,0L0.216,0Z" style="fill-rule:nonzero;"/>
|
||||
</g>
|
||||
<g transform="matrix(100,0,0,100,323.031,126)">
|
||||
<path class="logo-glyph" d="M0.154,-0.658L0.154,-0.394L0.219,-0.394C0.28,-0.394 0.322,-0.404 0.346,-0.423C0.37,-0.442 0.382,-0.475 0.382,-0.522C0.382,-0.571 0.369,-0.606 0.345,-0.627C0.32,-0.648 0.278,-0.658 0.219,-0.658L0.154,-0.658ZM0.523,0L0.444,0L0.193,-0.341L0.154,-0.341L0.154,0L0.089,0L0.089,-0.715L0.22,-0.715C0.298,-0.715 0.356,-0.699 0.394,-0.667C0.433,-0.634 0.452,-0.585 0.452,-0.52C0.452,-0.464 0.436,-0.421 0.403,-0.389C0.37,-0.357 0.324,-0.341 0.266,-0.341L0.523,0Z" style="fill-rule:nonzero;"/>
|
||||
</g>
|
||||
<g transform="matrix(100,0,0,100,520.979,126)">
|
||||
<path class="logo-glyph" d="M0.089,0L0.089,-0.745L0.595,-0.147L0.595,-0.715L0.656,-0.715L0.656,0.021L0.15,-0.578L0.15,0L0.089,0Z" style="fill-rule:nonzero;"/>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
<svg class="center logo-icon" viewbox="0 0 1024 1024">
|
||||
<circle class="logo-stroke" cx="512" cy="512" r="431" fill="none" stroke-width="32"></circle>
|
||||
<circle class="logo-border" cx="512" cy="512" r="450" fill="none" stroke-width="6"></circle>
|
||||
<circle class="logo-border" cx="512" cy="512" r="412" fill="none" stroke-width="6"></circle>
|
||||
<line class="logo-stroke" x1="296" y1="392" x2="540" y2="280" stroke-width="12"></line>
|
||||
<line class="logo-stroke" x1="296" y1="632" x2="540" y2="280" stroke-width="12"></line>
|
||||
<line class="logo-stroke" x1="296" y1="392" x2="540" y2="435" stroke-width="12"></line>
|
||||
<line class="logo-stroke" x1="296" y1="632" x2="540" y2="435" stroke-width="12"></line>
|
||||
<line class="logo-stroke" x1="296" y1="392" x2="540" y2="590" stroke-width="12"></line>
|
||||
<line class="logo-stroke" x1="296" y1="632" x2="540" y2="590" stroke-width="12"></line>
|
||||
<line class="logo-stroke" x1="296" y1="392" x2="540" y2="744" stroke-width="12"></line>
|
||||
<line class="logo-stroke" x1="296" y1="632" x2="540" y2="744" stroke-width="12"></line>
|
||||
<line class="logo-stroke" x1="540" y1="280" x2="785" y2="512" stroke-width="12"></line>
|
||||
<line class="logo-stroke" x1="540" y1="590" x2="785" y2="512" stroke-width="12"></line>
|
||||
<line class="logo-stroke" x1="540" y1="435" x2="785" y2="512" stroke-width="12"></line>
|
||||
<line class="logo-stroke" x1="540" y1="744" x2="785" y2="512" stroke-width="12"></line>
|
||||
<g transform="translate(296, 392)">
|
||||
<circle class="logo-fill" cx="0" cy="0" r="51"></circle>
|
||||
<circle class="logo-border" cx="0" cy="0" r="51" fill="none" stroke-width="6"></circle>
|
||||
</g>
|
||||
<g transform="translate(296, 632)">
|
||||
<circle class="logo-fill" cx="0" cy="0" r="51"></circle>
|
||||
<circle class="logo-border" cx="0" cy="0" r="51" fill="none" stroke-width="6"></circle>
|
||||
</g>
|
||||
<g transform="translate(540, 280)">
|
||||
<circle class="logo-fill" cx="0" cy="0" r="51"></circle>
|
||||
<circle class="logo-border" cx="0" cy="0" r="51" fill="none" stroke-width="6"></circle>
|
||||
</g>
|
||||
<g transform="translate(540, 435)">
|
||||
<circle class="logo-fill" cx="0" cy="0" r="51"></circle>
|
||||
<circle class="logo-border" cx="0" cy="0" r="51" fill="none" stroke-width="6"></circle>
|
||||
</g>
|
||||
<g transform="translate(540, 590)">
|
||||
<circle class="logo-fill" cx="0" cy="0" r="51"></circle>
|
||||
<circle class="logo-border" cx="0" cy="0" r="51" fill="none" stroke-width="6"></circle>
|
||||
</g>
|
||||
<g transform="translate(540, 744)">
|
||||
<circle class="logo-fill" cx="0" cy="0" r="51"></circle>
|
||||
<circle class="logo-border" cx="0" cy="0" r="51" fill="none" stroke-width="6"></circle>
|
||||
</g>
|
||||
<g transform="translate(785, 512)">
|
||||
<circle class="logo-fill" cx="0" cy="0" r="51"></circle>
|
||||
<circle class="logo-border" cx="0" cy="0" r="51" fill="none" stroke-width="6"></circle>
|
||||
</g>
|
||||
</svg>
|
||||
<svg id="logo-spinner" class="center logo-spinner" viewbox="0 0 1024 1024">
|
||||
<g transform="translate(512, 512)" style="opacity: 1">
|
||||
<path class="logo-spinner-stroke" d="M-431,0 A-431,-431 0 0,1 0,-431" stroke-width="24" fill="None"></path>
|
||||
</g>
|
||||
</svg>
|
||||
</a>
|
||||
<a href="https://www.lutzroeder.com" target="blank_">
|
||||
<svg class="center logo-name" viewbox="0 0 5120 300">
|
||||
<g transform="scale(5.8) translate(20, 0)">
|
||||
<g transform="matrix(30,0,0,30,18.9123,38)">
|
||||
<path class="logo-glyph" d="M0.089,-0L0.089,-0.715L0.154,-0.715L0.154,-0.061L0.399,-0.061L0.399,-0L0.089,-0Z" style="fill-rule:nonzero;"/>
|
||||
</g>
|
||||
<g transform="matrix(30,0,0,30,46.7613,38)">
|
||||
<path class="logo-glyph" d="M0.086,-0.715L0.15,-0.715L0.15,-0.248C0.15,-0.177 0.166,-0.125 0.198,-0.091C0.23,-0.056 0.28,-0.039 0.346,-0.039C0.412,-0.039 0.46,-0.056 0.493,-0.091C0.525,-0.125 0.541,-0.177 0.541,-0.248L0.541,-0.715L0.606,-0.715L0.606,-0.269C0.606,-0.172 0.584,-0.1 0.542,-0.052C0.499,-0.005 0.433,0.019 0.346,0.019C0.259,0.019 0.193,-0.005 0.15,-0.052C0.107,-0.1 0.086,-0.172 0.086,-0.269L0.086,-0.715Z" style="fill-rule:nonzero;"/>
|
||||
</g>
|
||||
<g transform="matrix(30,0,0,30,83.5133,38)">
|
||||
<path class="logo-glyph" d="M0.216,-0L0.216,-0.654L0.019,-0.654L0.019,-0.715L0.478,-0.715L0.478,-0.654L0.281,-0.654L0.281,-0L0.216,-0Z" style="fill-rule:nonzero;"/>
|
||||
</g>
|
||||
<g transform="matrix(30,0,0,30,114.421,38)">
|
||||
<path class="logo-glyph" d="M0.012,-0L0.437,-0.656L0.074,-0.656L0.074,-0.715L0.548,-0.715L0.125,-0.06L0.505,-0.06L0.505,-0L0.012,-0Z" style="fill-rule:nonzero;"/>
|
||||
</g>
|
||||
<g transform="matrix(30,0,0,30,171.777,38)">
|
||||
<path class="logo-glyph" d="M0.154,-0.658L0.154,-0.394L0.219,-0.394C0.28,-0.394 0.322,-0.404 0.346,-0.423C0.37,-0.442 0.382,-0.475 0.382,-0.522C0.382,-0.571 0.369,-0.606 0.345,-0.627C0.32,-0.648 0.278,-0.658 0.219,-0.658L0.154,-0.658ZM0.523,-0L0.444,-0L0.193,-0.341L0.154,-0.341L0.154,-0L0.089,-0L0.089,-0.715L0.22,-0.715C0.298,-0.715 0.356,-0.699 0.394,-0.667C0.433,-0.634 0.452,-0.585 0.452,-0.52C0.452,-0.464 0.436,-0.421 0.403,-0.389C0.37,-0.357 0.324,-0.341 0.266,-0.341L0.523,-0Z" style="fill-rule:nonzero;"/>
|
||||
</g>
|
||||
<g transform="matrix(30,0,0,30,203.607,38)">
|
||||
<path class="logo-glyph" d="M0.437,-0.039C0.479,-0.039 0.519,-0.047 0.557,-0.063C0.595,-0.078 0.629,-0.101 0.659,-0.131C0.689,-0.161 0.712,-0.196 0.727,-0.234C0.743,-0.273 0.751,-0.313 0.751,-0.356C0.751,-0.399 0.743,-0.44 0.728,-0.478C0.712,-0.516 0.689,-0.55 0.659,-0.581C0.63,-0.611 0.596,-0.634 0.558,-0.649C0.52,-0.665 0.48,-0.673 0.437,-0.673C0.395,-0.673 0.355,-0.665 0.317,-0.649C0.28,-0.634 0.246,-0.611 0.216,-0.581C0.186,-0.55 0.163,-0.516 0.147,-0.478C0.132,-0.44 0.124,-0.399 0.124,-0.356C0.124,-0.313 0.132,-0.272 0.147,-0.234C0.163,-0.196 0.186,-0.161 0.216,-0.131C0.246,-0.101 0.279,-0.078 0.316,-0.062C0.354,-0.047 0.394,-0.039 0.437,-0.039ZM0.82,-0.356C0.82,-0.306 0.81,-0.258 0.791,-0.212C0.772,-0.167 0.744,-0.126 0.708,-0.091C0.671,-0.055 0.63,-0.028 0.583,-0.009C0.537,0.01 0.488,0.019 0.437,0.019C0.386,0.019 0.337,0.01 0.291,-0.009C0.245,-0.028 0.203,-0.055 0.167,-0.091C0.131,-0.127 0.103,-0.168 0.084,-0.213C0.065,-0.258 0.055,-0.306 0.055,-0.356C0.055,-0.407 0.065,-0.455 0.084,-0.501C0.103,-0.546 0.131,-0.587 0.167,-0.623C0.203,-0.659 0.244,-0.685 0.29,-0.704C0.335,-0.722 0.385,-0.731 0.437,-0.731C0.49,-0.731 0.539,-0.722 0.585,-0.703C0.631,-0.685 0.672,-0.658 0.708,-0.623C0.744,-0.587 0.772,-0.546 0.791,-0.501C0.81,-0.455 0.82,-0.407 0.82,-0.356Z" style="fill-rule:nonzero;"/>
|
||||
</g>
|
||||
<g transform="matrix(30,0,0,30,245.853,38)">
|
||||
<path class="logo-glyph" d="M0.089,-0L0.089,-0.715L0.443,-0.715L0.443,-0.654L0.154,-0.654L0.154,-0.43L0.443,-0.43L0.443,-0.369L0.154,-0.369L0.154,-0.061L0.443,-0.061L0.443,-0L0.089,-0Z" style="fill-rule:nonzero;"/>
|
||||
</g>
|
||||
<g transform="matrix(30,0,0,30,277.243,38)">
|
||||
<path class="logo-glyph" d="M0.154,-0.056L0.245,-0.056C0.319,-0.056 0.371,-0.06 0.402,-0.069C0.433,-0.077 0.459,-0.091 0.481,-0.111C0.511,-0.139 0.534,-0.174 0.549,-0.215C0.564,-0.257 0.572,-0.305 0.572,-0.358C0.572,-0.413 0.564,-0.461 0.549,-0.502C0.533,-0.544 0.51,-0.578 0.48,-0.605C0.457,-0.625 0.429,-0.64 0.396,-0.648C0.364,-0.657 0.306,-0.661 0.224,-0.661L0.154,-0.661L0.154,-0.056ZM0.089,-0L0.089,-0.715L0.2,-0.715C0.299,-0.715 0.37,-0.71 0.412,-0.7C0.453,-0.69 0.489,-0.674 0.519,-0.65C0.559,-0.618 0.589,-0.578 0.61,-0.528C0.631,-0.478 0.641,-0.421 0.641,-0.357C0.641,-0.293 0.631,-0.236 0.61,-0.186C0.589,-0.136 0.559,-0.096 0.52,-0.066C0.489,-0.042 0.454,-0.025 0.414,-0.015C0.374,-0.005 0.31,-0 0.222,-0L0.089,-0Z" style="fill-rule:nonzero;"/>
|
||||
</g>
|
||||
<g transform="matrix(30,0,0,30,314.142,38)">
|
||||
<path class="logo-glyph" d="M0.089,-0L0.089,-0.715L0.443,-0.715L0.443,-0.654L0.154,-0.654L0.154,-0.43L0.443,-0.43L0.443,-0.369L0.154,-0.369L0.154,-0.061L0.443,-0.061L0.443,-0L0.089,-0Z" style="fill-rule:nonzero;"/>
|
||||
</g>
|
||||
<g transform="matrix(30,0,0,30,345.532,38)">
|
||||
<path class="logo-glyph" d="M0.154,-0.658L0.154,-0.394L0.219,-0.394C0.28,-0.394 0.322,-0.404 0.346,-0.423C0.37,-0.442 0.382,-0.475 0.382,-0.522C0.382,-0.571 0.369,-0.606 0.345,-0.627C0.32,-0.648 0.278,-0.658 0.219,-0.658L0.154,-0.658ZM0.523,-0L0.444,-0L0.193,-0.341L0.154,-0.341L0.154,-0L0.089,-0L0.089,-0.715L0.22,-0.715C0.298,-0.715 0.356,-0.699 0.394,-0.667C0.433,-0.634 0.452,-0.585 0.452,-0.52C0.452,-0.464 0.436,-0.421 0.403,-0.389C0.37,-0.357 0.324,-0.341 0.266,-0.341L0.523,-0Z" style="fill-rule:nonzero;"/>
|
||||
</g>
|
||||
<g transform="matrix(30,0,0,30,376.911,38)">
|
||||
<path class="logo-glyph" d="M0.06,-0.468L0.155,-0.731L0.228,-0.699L0.1,-0.452L0.06,-0.468Z" style="fill-rule:nonzero;"/>
|
||||
</g>
|
||||
<g transform="matrix(30,0,0,30,401.549,38)">
|
||||
<path class="logo-glyph" d="M0.034,-0.12L0.09,-0.15C0.1,-0.115 0.118,-0.087 0.144,-0.068C0.169,-0.049 0.2,-0.039 0.236,-0.039C0.281,-0.039 0.316,-0.052 0.342,-0.079C0.367,-0.106 0.38,-0.143 0.38,-0.19C0.38,-0.224 0.371,-0.253 0.354,-0.276C0.337,-0.299 0.3,-0.325 0.244,-0.355C0.172,-0.393 0.124,-0.427 0.101,-0.456C0.077,-0.485 0.065,-0.519 0.065,-0.56C0.065,-0.611 0.082,-0.652 0.116,-0.684C0.151,-0.716 0.195,-0.732 0.25,-0.732C0.286,-0.732 0.317,-0.724 0.344,-0.709C0.37,-0.694 0.392,-0.671 0.408,-0.641L0.358,-0.611C0.347,-0.631 0.333,-0.647 0.314,-0.658C0.295,-0.668 0.272,-0.674 0.246,-0.674C0.211,-0.674 0.183,-0.663 0.162,-0.643C0.141,-0.622 0.131,-0.594 0.131,-0.559C0.131,-0.509 0.172,-0.462 0.255,-0.419C0.27,-0.411 0.281,-0.405 0.289,-0.401C0.35,-0.367 0.391,-0.336 0.411,-0.306C0.432,-0.276 0.442,-0.237 0.442,-0.19C0.442,-0.126 0.423,-0.075 0.386,-0.037C0.348,0 0.297,0.019 0.233,0.019C0.186,0.019 0.146,0.007 0.113,-0.016C0.079,-0.039 0.053,-0.074 0.034,-0.12Z" style="fill-rule:nonzero;"/>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
</a>
|
||||
<div class="center logo-message">
|
||||
<div style="height: 30px; text-align: center;">Version <span id="version" class="select">{version}</span></div>
|
||||
<div style="height: 30px; text-align: center;">Copyright © <a href="https://www.lutzroeder.com" target="blank_">Lutz Roeder</a></div>
|
||||
</div>
|
||||
<a id="logo-github" class="center logo-github" href="https://github.com/lutzroeder/netron" target="blank_">
|
||||
<svg viewbox="0 0 438.549 438.549">
|
||||
<path class="logo-fill" d="M409.132,114.573c-19.608-33.596-46.205-60.194-79.798-79.8C295.736,15.166,259.057,5.365,219.271,5.365
|
||||
c-39.781,0-76.472,9.804-110.063,29.408c-33.596,19.605-60.192,46.204-79.8,79.8C9.803,148.168,0,184.854,0,224.63
|
||||
c0,47.78,13.94,90.745,41.827,128.906c27.884,38.164,63.906,64.572,108.063,79.227c5.14,0.954,8.945,0.283,11.419-1.996
|
||||
c2.475-2.282,3.711-5.14,3.711-8.562c0-0.571-0.049-5.708-0.144-15.417c-0.098-9.709-0.144-18.179-0.144-25.406l-6.567,1.136
|
||||
c-4.187,0.767-9.469,1.092-15.846,1c-6.374-0.089-12.991-0.757-19.842-1.999c-6.854-1.231-13.229-4.086-19.13-8.559
|
||||
c-5.898-4.473-10.085-10.328-12.56-17.556l-2.855-6.57c-1.903-4.374-4.899-9.233-8.992-14.559
|
||||
c-4.093-5.331-8.232-8.945-12.419-10.848l-1.999-1.431c-1.332-0.951-2.568-2.098-3.711-3.429c-1.142-1.331-1.997-2.663-2.568-3.997
|
||||
c-0.572-1.335-0.098-2.43,1.427-3.289c1.525-0.859,4.281-1.276,8.28-1.276l5.708,0.853c3.807,0.763,8.516,3.042,14.133,6.851
|
||||
c5.614,3.806,10.229,8.754,13.846,14.842c4.38,7.806,9.657,13.754,15.846,17.847c6.184,4.093,12.419,6.136,18.699,6.136
|
||||
c6.28,0,11.704-0.476,16.274-1.423c4.565-0.952,8.848-2.383,12.847-4.285c1.713-12.758,6.377-22.559,13.988-29.41
|
||||
c-10.848-1.14-20.601-2.857-29.264-5.14c-8.658-2.286-17.605-5.996-26.835-11.14c-9.235-5.137-16.896-11.516-22.985-19.126
|
||||
c-6.09-7.614-11.088-17.61-14.987-29.979c-3.901-12.374-5.852-26.648-5.852-42.826c0-23.035,7.52-42.637,22.557-58.817
|
||||
c-7.044-17.318-6.379-36.732,1.997-58.24c5.52-1.715,13.706-0.428,24.554,3.853c10.85,4.283,18.794,7.952,23.84,10.994
|
||||
c5.046,3.041,9.089,5.618,12.135,7.708c17.705-4.947,35.976-7.421,54.818-7.421s37.117,2.474,54.823,7.421l10.849-6.849
|
||||
c7.419-4.57,16.18-8.758,26.262-12.565c10.088-3.805,17.802-4.853,23.134-3.138c8.562,21.509,9.325,40.922,2.279,58.24
|
||||
c15.036,16.18,22.559,35.787,22.559,58.817c0,16.178-1.958,30.497-5.853,42.966c-3.9,12.471-8.941,22.457-15.125,29.979
|
||||
c-6.191,7.521-13.901,13.85-23.131,18.986c-9.232,5.14-18.182,8.85-26.84,11.136c-8.662,2.286-18.415,4.004-29.263,5.146
|
||||
c9.894,8.562,14.842,22.077,14.842,40.539v60.237c0,3.422,1.19,6.279,3.572,8.562c2.379,2.279,6.136,2.95,11.276,1.995
|
||||
c44.163-14.653,80.185-41.062,108.068-79.226c27.88-38.161,41.825-81.126,41.825-128.906
|
||||
C438.536,184.851,428.728,148.168,409.132,114.573z"/>
|
||||
</svg>
|
||||
</a>
|
||||
<span class="center consent-message">This app uses cookies to report errors and anonymous usage information.</span>
|
||||
<button id="consent-accept-button" class="center consent-accept-button">Accept</button>
|
||||
<button id="open-file-button" class="center open-file-button" tabindex="0">Open Model…</button>
|
||||
<button id="github-button" class="center github-button">GitHub</button>
|
||||
<input type="file" id="open-file-dialog" class="open-file-dialog" multiple="false" accept="">
|
||||
<!-- Preload fonts to workaround Chrome SVG layout issue -->
|
||||
<div style="font-weight: normal; color: rgba(0, 0, 0, 0.01); user-select: none;">.</div>
|
||||
<div style="font-weight: bold; color: rgba(0, 0, 0, 0.01); user-select: none;">.</div>
|
||||
<div style="font-weight: bold; color: rgba(0, 0, 0, 0.01); user-select: none;">.</div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
@ -0,0 +1,730 @@
|
||||
|
||||
var host = host || {};
|
||||
|
||||
const electron = require('electron');
|
||||
const fs = require('fs');
|
||||
const http = require('http');
|
||||
const https = require('https');
|
||||
const process = require('process');
|
||||
const path = require('path');
|
||||
const querystring = require('querystring');
|
||||
|
||||
host.ElectronHost = class {
|
||||
|
||||
constructor() {
|
||||
process.on('uncaughtException', (err) => {
|
||||
this.exception(err, true);
|
||||
});
|
||||
this._document = window.document;
|
||||
this._window = window;
|
||||
this._window.eval = global.eval = () => {
|
||||
throw new Error('window.eval() not supported.');
|
||||
};
|
||||
this._window.addEventListener('unload', () => {
|
||||
if (typeof __coverage__ !== 'undefined') {
|
||||
const file = path.join('.nyc_output', path.basename(window.location.pathname, '.html')) + '.json';
|
||||
/* eslint-disable no-undef */
|
||||
fs.writeFileSync(file, JSON.stringify(__coverage__));
|
||||
/* eslint-enable no-undef */
|
||||
}
|
||||
});
|
||||
this._environment = electron.ipcRenderer.sendSync('get-environment', {});
|
||||
this._queue = [];
|
||||
}
|
||||
|
||||
get window() {
|
||||
return this._window;
|
||||
}
|
||||
|
||||
get document() {
|
||||
return this._document;
|
||||
}
|
||||
|
||||
get version() {
|
||||
return this._environment.version;
|
||||
}
|
||||
|
||||
get type() {
|
||||
return 'Electron';
|
||||
}
|
||||
|
||||
get agent() {
|
||||
return 'any';
|
||||
}
|
||||
|
||||
initialize(view) {
|
||||
this._view = view;
|
||||
electron.ipcRenderer.on('open', (_, data) => {
|
||||
this._openPath(data.path);
|
||||
});
|
||||
return new Promise((resolve /*, reject */) => {
|
||||
const accept = () => {
|
||||
if (this._environment.package) {
|
||||
this._telemetry = new host.Telemetry('UA-54146-13', this._getConfiguration('userId'), navigator.userAgent, this.type, this.version);
|
||||
}
|
||||
resolve();
|
||||
};
|
||||
const request = () => {
|
||||
this._view.show('welcome consent');
|
||||
const acceptButton = this.document.getElementById('consent-accept-button');
|
||||
if (acceptButton) {
|
||||
acceptButton.addEventListener('click', () => {
|
||||
this._setConfiguration('consent', Date.now());
|
||||
accept();
|
||||
});
|
||||
}
|
||||
};
|
||||
const time = this._getConfiguration('consent');
|
||||
if (time && (Date.now() - time) < 30 * 24 * 60 * 60 * 1000) {
|
||||
accept();
|
||||
}
|
||||
else {
|
||||
this._request('https://ipinfo.io/json', { 'Content-Type': 'application/json' }, 2000).then((text) => {
|
||||
try {
|
||||
const json = JSON.parse(text);
|
||||
const countries = ['AT', 'BE', 'BG', 'HR', 'CZ', 'CY', 'DK', 'EE', 'FI', 'FR', 'DE', 'EL', 'HU', 'IE', 'IT', 'LV', 'LT', 'LU', 'MT', 'NL', 'NO', 'PL', 'PT', 'SK', 'ES', 'SE', 'GB', 'UK', 'GR', 'EU', 'RO'];
|
||||
if (json && json.country && !countries.indexOf(json.country) !== -1) {
|
||||
this._setConfiguration('consent', Date.now());
|
||||
accept();
|
||||
}
|
||||
else {
|
||||
request();
|
||||
}
|
||||
}
|
||||
catch (err) {
|
||||
request();
|
||||
}
|
||||
}).catch(() => {
|
||||
request();
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
start() {
|
||||
if (this._queue) {
|
||||
const queue = this._queue;
|
||||
delete this._queue;
|
||||
if (queue.length > 0) {
|
||||
const path = queue.pop();
|
||||
this._openPath(path);
|
||||
}
|
||||
}
|
||||
|
||||
electron.ipcRenderer.on('export', (_, data) => {
|
||||
this._view.export(data.file);
|
||||
});
|
||||
electron.ipcRenderer.on('cut', () => {
|
||||
this._view.cut();
|
||||
});
|
||||
electron.ipcRenderer.on('copy', () => {
|
||||
this._view.copy();
|
||||
});
|
||||
electron.ipcRenderer.on('paste', () => {
|
||||
this._view.paste();
|
||||
});
|
||||
electron.ipcRenderer.on('selectall', () => {
|
||||
this._view.selectAll();
|
||||
});
|
||||
electron.ipcRenderer.on('toggle', (sender, name) => {
|
||||
this._view.toggle(name);
|
||||
this._update(Object.assign({}, this._view.options));
|
||||
});
|
||||
electron.ipcRenderer.on('zoom-in', () => {
|
||||
this.document.getElementById('zoom-in-button').click();
|
||||
});
|
||||
electron.ipcRenderer.on('zoom-out', () => {
|
||||
this.document.getElementById('zoom-out-button').click();
|
||||
});
|
||||
electron.ipcRenderer.on('reset-zoom', () => {
|
||||
this._view.resetZoom();
|
||||
});
|
||||
electron.ipcRenderer.on('show-properties', () => {
|
||||
this.document.getElementById('menu-button').click();
|
||||
});
|
||||
electron.ipcRenderer.on('find', () => {
|
||||
this._view.find();
|
||||
});
|
||||
this.document.getElementById('menu-button').addEventListener('click', () => {
|
||||
this._view.showModelProperties();
|
||||
});
|
||||
|
||||
const openFileButton = this.document.getElementById('open-file-button');
|
||||
if (openFileButton) {
|
||||
openFileButton.style.opacity = 1;
|
||||
openFileButton.addEventListener('click', () => {
|
||||
electron.ipcRenderer.send('open-file-dialog', {});
|
||||
});
|
||||
}
|
||||
const githubButton = this.document.getElementById('github-button');
|
||||
const githubLink = this.document.getElementById('logo-github');
|
||||
if (githubButton && githubLink) {
|
||||
githubButton.style.opacity = 1;
|
||||
githubButton.addEventListener('click', () => {
|
||||
this.openURL(githubLink.href);
|
||||
});
|
||||
}
|
||||
|
||||
this.document.addEventListener('dragover', (e) => {
|
||||
e.preventDefault();
|
||||
});
|
||||
this.document.addEventListener('drop', (e) => {
|
||||
e.preventDefault();
|
||||
});
|
||||
this.document.body.addEventListener('drop', (e) => {
|
||||
e.preventDefault();
|
||||
const paths = Array.from(e.dataTransfer.files).map(((file) => file.path));
|
||||
if (paths.length > 0) {
|
||||
electron.ipcRenderer.send('drop-paths', { paths: paths });
|
||||
}
|
||||
return false;
|
||||
});
|
||||
|
||||
this._view.show('welcome');
|
||||
}
|
||||
|
||||
environment(name) {
|
||||
return this._environment[name];
|
||||
}
|
||||
|
||||
error(message, detail) {
|
||||
electron.ipcRenderer.sendSync('show-message-box', {
|
||||
type: 'error',
|
||||
message: message,
|
||||
detail: detail,
|
||||
});
|
||||
}
|
||||
|
||||
confirm(message, detail) {
|
||||
const result = electron.ipcRenderer.sendSync('show-message-box', {
|
||||
type: 'question',
|
||||
message: message,
|
||||
detail: detail,
|
||||
buttons: ['Yes', 'No'],
|
||||
defaultId: 0,
|
||||
cancelId: 1
|
||||
});
|
||||
return result === 0;
|
||||
}
|
||||
|
||||
require(id) {
|
||||
try {
|
||||
return Promise.resolve(require(id));
|
||||
}
|
||||
catch (error) {
|
||||
return Promise.reject(error);
|
||||
}
|
||||
}
|
||||
|
||||
save(name, extension, defaultPath, callback) {
|
||||
const selectedFile = electron.ipcRenderer.sendSync('show-save-dialog', {
|
||||
title: 'Export Tensor',
|
||||
defaultPath: defaultPath,
|
||||
buttonLabel: 'Export',
|
||||
filters: [ { name: name, extensions: [ extension ] } ]
|
||||
});
|
||||
if (selectedFile) {
|
||||
callback(selectedFile);
|
||||
}
|
||||
}
|
||||
|
||||
export(file, blob) {
|
||||
const reader = new FileReader();
|
||||
reader.onload = (e) => {
|
||||
const data = new Uint8Array(e.target.result);
|
||||
fs.writeFile(file, data, null, (err) => {
|
||||
if (err) {
|
||||
this.exception(err, false);
|
||||
this.error('Error writing file.', err.message);
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
let err = null;
|
||||
if (!blob) {
|
||||
err = new Error("Export blob is '" + JSON.stringify(blob) + "'.");
|
||||
}
|
||||
else if (!(blob instanceof Blob)) {
|
||||
err = new Error("Export blob type is '" + (typeof blob) + "'.");
|
||||
}
|
||||
|
||||
if (err) {
|
||||
this.exception(err, false);
|
||||
this.error('Error exporting image.', err.message);
|
||||
}
|
||||
else {
|
||||
reader.readAsArrayBuffer(blob);
|
||||
}
|
||||
}
|
||||
|
||||
request(file, encoding, base) {
|
||||
return new Promise((resolve, reject) => {
|
||||
const pathname = path.join(base || __dirname, file);
|
||||
fs.stat(pathname, (err, stat) => {
|
||||
if (err && err.code === 'ENOENT') {
|
||||
reject(new Error("The file '" + file + "' does not exist."));
|
||||
}
|
||||
else if (err) {
|
||||
reject(err);
|
||||
}
|
||||
else if (!stat.isFile()) {
|
||||
reject(new Error("The path '" + file + "' is not a file."));
|
||||
}
|
||||
else if (stat && stat.size < 0x7ffff000) {
|
||||
fs.readFile(pathname, encoding, (err, data) => {
|
||||
if (err) {
|
||||
reject(err);
|
||||
}
|
||||
else {
|
||||
resolve(encoding ? data : new host.ElectronHost.BinaryStream(data));
|
||||
}
|
||||
});
|
||||
}
|
||||
else if (encoding) {
|
||||
reject(new Error("The file '" + file + "' size (" + stat.size.toString() + ") for encoding '" + encoding + "' is greater than 2 GB."));
|
||||
}
|
||||
else {
|
||||
resolve(new host.ElectronHost.FileStream(pathname, 0, stat.size, stat.mtimeMs));
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
openURL(url) {
|
||||
electron.shell.openExternal(url);
|
||||
}
|
||||
|
||||
exception(error, fatal) {
|
||||
if (this._telemetry && error && error.telemetry !== false) {
|
||||
try {
|
||||
const name = error && error.name ? error.name + ': ' : '';
|
||||
const message = error && error.message ? error.message : '(null)';
|
||||
const description = [ name + message ];
|
||||
if (error.stack) {
|
||||
const format = (file, line, column) => {
|
||||
return file.split('\\').join('/').split('/').pop() + ':' + line + ':' + column;
|
||||
};
|
||||
const match = error.stack.match(/\n {4}at (.*) \((.*):(\d*):(\d*)\)/);
|
||||
if (match) {
|
||||
description.push(match[1] + ' (' + format(match[2], match[3], match[4]) + ')');
|
||||
}
|
||||
else {
|
||||
const match = error.stack.match(/\n {4}at (.*):(\d*):(\d*)/);
|
||||
if (match) {
|
||||
description.push('(' + format(match[1], match[2], match[3]) + ')');
|
||||
}
|
||||
}
|
||||
}
|
||||
this._telemetry.exception(description.join(' @ '), fatal);
|
||||
}
|
||||
catch (e) {
|
||||
// continue regardless of error
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
screen(name) {
|
||||
if (this._telemetry) {
|
||||
try {
|
||||
this._telemetry.screenview(name);
|
||||
}
|
||||
catch (e) {
|
||||
// continue regardless of error
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
event(category, action, label, value) {
|
||||
if (this._telemetry) {
|
||||
try {
|
||||
this._telemetry.event(category, action, label, value);
|
||||
}
|
||||
catch (e) {
|
||||
// continue regardless of error
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
_context(location) {
|
||||
const basename = path.basename(location);
|
||||
const stat = fs.statSync(location);
|
||||
if (stat.isFile()) {
|
||||
const dirname = path.dirname(location);
|
||||
return this.request(basename, null, dirname).then((stream) => {
|
||||
return new host.ElectronHost.ElectronContext(this, dirname, basename, stream);
|
||||
});
|
||||
}
|
||||
else if (stat.isDirectory()) {
|
||||
const entries = new Map();
|
||||
const walk = (dir) => {
|
||||
for (const item of fs.readdirSync(dir)) {
|
||||
const pathname = path.join(dir, item);
|
||||
const stat = fs.statSync(pathname);
|
||||
if (stat.isDirectory()) {
|
||||
walk(pathname);
|
||||
}
|
||||
else if (stat.isFile()) {
|
||||
const stream = new host.ElectronHost.FileStream(pathname, 0, stat.size, stat.mtimeMs);
|
||||
const name = pathname.split(path.sep).join(path.posix.sep);
|
||||
entries.set(name, stream);
|
||||
}
|
||||
}
|
||||
};
|
||||
walk(location);
|
||||
return Promise.resolve(new host.ElectronHost.ElectronContext(this, location, basename, null, entries));
|
||||
}
|
||||
throw new Error("Unsupported path stat '" + JSON.stringify(stat) + "'.");
|
||||
}
|
||||
|
||||
_openPath(path) {
|
||||
if (this._queue) {
|
||||
this._queue.push(path);
|
||||
return;
|
||||
}
|
||||
if (path && this._view.accept(path)) {
|
||||
this._view.show('welcome spinner');
|
||||
this._context(path).then((context) => {
|
||||
this._view.open(context).then((model) => {
|
||||
this._view.show(null);
|
||||
const options = Object.assign({}, this._view.options);
|
||||
if (model) {
|
||||
options.path = path;
|
||||
}
|
||||
this._update(options);
|
||||
}).catch((error) => {
|
||||
const options = Object.assign({}, this._view.options);
|
||||
if (error) {
|
||||
this._view.error(error, null, null);
|
||||
options.path = null;
|
||||
}
|
||||
this._update(options);
|
||||
});
|
||||
}).catch((error) => {
|
||||
this._view.error(error, 'Error while reading file.', null);
|
||||
this._update({ path: null });
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
_request(location, headers, timeout) {
|
||||
return new Promise((resolve, reject) => {
|
||||
const url = new URL(location);
|
||||
const protocol = url.protocol === 'https:' ? https : http;
|
||||
const options = {};
|
||||
options.headers = headers;
|
||||
if (timeout) {
|
||||
options.timeout = timeout;
|
||||
}
|
||||
const request = protocol.request(location, options, (response) => {
|
||||
if (response.statusCode !== 200) {
|
||||
const err = new Error("The web request failed with status code " + response.statusCode + " at '" + location + "'.");
|
||||
err.type = 'error';
|
||||
err.url = location;
|
||||
err.status = response.statusCode;
|
||||
reject(err);
|
||||
}
|
||||
else {
|
||||
let data = '';
|
||||
response.on('data', (chunk) => {
|
||||
data += chunk;
|
||||
});
|
||||
response.on('err', (err) => {
|
||||
reject(err);
|
||||
});
|
||||
response.on('end', () => {
|
||||
resolve(data);
|
||||
});
|
||||
}
|
||||
});
|
||||
request.on("error", (err) => {
|
||||
reject(err);
|
||||
});
|
||||
request.on("timeout", () => {
|
||||
request.destroy();
|
||||
const error = new Error("The web request timed out at '" + location + "'.");
|
||||
error.type = 'timeout';
|
||||
error.url = url;
|
||||
reject(error);
|
||||
});
|
||||
request.end();
|
||||
});
|
||||
}
|
||||
|
||||
_getConfiguration(name) {
|
||||
return electron.ipcRenderer.sendSync('get-configuration', { name: name });
|
||||
}
|
||||
|
||||
_setConfiguration(name, value) {
|
||||
electron.ipcRenderer.sendSync('set-configuration', { name: name, value: value });
|
||||
}
|
||||
|
||||
_update(data) {
|
||||
electron.ipcRenderer.send('update', data);
|
||||
}
|
||||
};
|
||||
|
||||
host.Telemetry = class {
|
||||
|
||||
constructor(trackingId, clientId, userAgent, applicationName, applicationVersion) {
|
||||
this._params = {
|
||||
aip: '1', // anonymizeIp
|
||||
tid: trackingId,
|
||||
cid: clientId,
|
||||
ua: userAgent,
|
||||
an: applicationName,
|
||||
av: applicationVersion
|
||||
};
|
||||
}
|
||||
|
||||
screenview(screenName) {
|
||||
const params = Object.assign({}, this._params);
|
||||
params.cd = screenName;
|
||||
this._send('screenview', params);
|
||||
}
|
||||
|
||||
event(category, action, label, value) {
|
||||
const params = Object.assign({}, this._params);
|
||||
params.ec = category;
|
||||
params.ea = action;
|
||||
params.el = label;
|
||||
params.ev = value;
|
||||
this._send('event', params);
|
||||
}
|
||||
|
||||
exception(description, fatal) {
|
||||
const params = Object.assign({}, this._params);
|
||||
params.exd = description;
|
||||
if (fatal) {
|
||||
params.exf = '1';
|
||||
}
|
||||
this._send('exception', params);
|
||||
}
|
||||
|
||||
_send(type, params) {
|
||||
params.t = type;
|
||||
params.v = '1';
|
||||
for (const param in params) {
|
||||
if (params[param] === null || params[param] === undefined) {
|
||||
delete params[param];
|
||||
}
|
||||
}
|
||||
const body = querystring.stringify(params);
|
||||
const options = {
|
||||
method: 'POST',
|
||||
host: 'www.google-analytics.com',
|
||||
path: '/collect',
|
||||
headers: { 'Content-Length': Buffer.byteLength(body) }
|
||||
};
|
||||
const request = https.request(options, (response) => {
|
||||
response.on('error', (/* error */) => {});
|
||||
});
|
||||
request.setTimeout(5000, () => {
|
||||
request.destroy();
|
||||
});
|
||||
request.on('error', (/* error */) => {});
|
||||
request.write(body);
|
||||
request.end();
|
||||
}
|
||||
};
|
||||
|
||||
host.ElectronHost.BinaryStream = class {
|
||||
|
||||
constructor(buffer) {
|
||||
this._buffer = buffer;
|
||||
this._length = buffer.length;
|
||||
this._position = 0;
|
||||
}
|
||||
|
||||
get position() {
|
||||
return this._position;
|
||||
}
|
||||
|
||||
get length() {
|
||||
return this._length;
|
||||
}
|
||||
|
||||
stream(length) {
|
||||
const buffer = this.read(length);
|
||||
return new host.ElectronHost.BinaryStream(buffer.slice(0));
|
||||
}
|
||||
|
||||
seek(position) {
|
||||
this._position = position >= 0 ? position : this._length + position;
|
||||
if (this._position > this._buffer.length) {
|
||||
throw new Error('Expected ' + (this._position - this._buffer.length) + ' more bytes. The file might be corrupted. Unexpected end of file.');
|
||||
}
|
||||
}
|
||||
|
||||
skip(offset) {
|
||||
this._position += offset;
|
||||
if (this._position > this._buffer.length) {
|
||||
throw new Error('Expected ' + (this._position - this._buffer.length) + ' more bytes. The file might be corrupted. Unexpected end of file.');
|
||||
}
|
||||
}
|
||||
|
||||
peek(length) {
|
||||
if (this._position === 0 && length === undefined) {
|
||||
return this._buffer;
|
||||
}
|
||||
const position = this._position;
|
||||
this.skip(length !== undefined ? length : this._length - this._position);
|
||||
const end = this._position;
|
||||
this.seek(position);
|
||||
return this._buffer.subarray(position, end);
|
||||
}
|
||||
|
||||
read(length) {
|
||||
if (this._position === 0 && length === undefined) {
|
||||
this._position = this._length;
|
||||
return this._buffer;
|
||||
}
|
||||
const position = this._position;
|
||||
this.skip(length !== undefined ? length : this._length - this._position);
|
||||
return this._buffer.subarray(position, this._position);
|
||||
}
|
||||
|
||||
byte() {
|
||||
const position = this._position;
|
||||
this.skip(1);
|
||||
return this._buffer[position];
|
||||
}
|
||||
};
|
||||
|
||||
host.ElectronHost.FileStream = class {
|
||||
|
||||
constructor(file, start, length, mtime) {
|
||||
this._file = file;
|
||||
this._start = start;
|
||||
this._length = length;
|
||||
this._position = 0;
|
||||
this._mtime = mtime;
|
||||
}
|
||||
|
||||
get position() {
|
||||
return this._position;
|
||||
}
|
||||
|
||||
get length() {
|
||||
return this._length;
|
||||
}
|
||||
|
||||
stream(length) {
|
||||
const file = new host.ElectronHost.FileStream(this._file, this._position, length, this._mtime);
|
||||
this.skip(length);
|
||||
return file;
|
||||
}
|
||||
|
||||
seek(position) {
|
||||
this._position = position >= 0 ? position : this._length + position;
|
||||
}
|
||||
|
||||
skip(offset) {
|
||||
this._position += offset;
|
||||
if (this._position > this._length) {
|
||||
throw new Error('Expected ' + (this._position - this._length) + ' more bytes. The file might be corrupted. Unexpected end of file.');
|
||||
}
|
||||
}
|
||||
|
||||
peek(length) {
|
||||
length = length !== undefined ? length : this._length - this._position;
|
||||
if (length < 0x10000000) {
|
||||
const position = this._fill(length);
|
||||
this._position -= length;
|
||||
return this._buffer.subarray(position, position + length);
|
||||
}
|
||||
const position = this._position;
|
||||
this.skip(length);
|
||||
this.seek(position);
|
||||
const buffer = new Uint8Array(length);
|
||||
this._read(buffer, position);
|
||||
return buffer;
|
||||
}
|
||||
|
||||
read(length) {
|
||||
length = length !== undefined ? length : this._length - this._position;
|
||||
if (length < 0x10000000) {
|
||||
const position = this._fill(length);
|
||||
return this._buffer.subarray(position, position + length);
|
||||
}
|
||||
const position = this._position;
|
||||
this.skip(length);
|
||||
const buffer = new Uint8Array(length);
|
||||
this._read(buffer, position);
|
||||
return buffer;
|
||||
}
|
||||
|
||||
byte() {
|
||||
const position = this._fill(1);
|
||||
return this._buffer[position];
|
||||
}
|
||||
|
||||
_fill(length) {
|
||||
if (this._position + length > this._length) {
|
||||
throw new Error('Expected ' + (this._position + length - this._length) + ' more bytes. The file might be corrupted. Unexpected end of file.');
|
||||
}
|
||||
if (!this._buffer || this._position < this._offset || this._position + length > this._offset + this._buffer.length) {
|
||||
this._offset = this._position;
|
||||
this._buffer = new Uint8Array(Math.min(0x10000000, this._length - this._offset));
|
||||
this._read(this._buffer, this._offset);
|
||||
}
|
||||
const position = this._position;
|
||||
this._position += length;
|
||||
return position - this._offset;
|
||||
}
|
||||
|
||||
_read(buffer, offset) {
|
||||
const descriptor = fs.openSync(this._file, 'r');
|
||||
const stat = fs.statSync(this._file);
|
||||
if (stat.mtimeMs != this._mtime) {
|
||||
throw new Error("File '" + this._file + "' last modified time changed.");
|
||||
}
|
||||
try {
|
||||
fs.readSync(descriptor, buffer, 0, buffer.length, offset + this._start);
|
||||
}
|
||||
finally {
|
||||
fs.closeSync(descriptor);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
host.ElectronHost.ElectronHost = class {
|
||||
|
||||
constructor(host, folder, identifier, stream, entries) {
|
||||
this._host = host;
|
||||
this._folder = folder;
|
||||
this._identifier = identifier;
|
||||
this._stream = stream;
|
||||
this._entries = entries || new Map();
|
||||
}
|
||||
|
||||
get identifier() {
|
||||
return this._identifier;
|
||||
}
|
||||
|
||||
get stream() {
|
||||
return this._stream;
|
||||
}
|
||||
|
||||
get entries() {
|
||||
return this._entries;
|
||||
}
|
||||
|
||||
request(file, encoding, base) {
|
||||
return this._host.request(file, encoding, base === undefined ? this._folder : base);
|
||||
}
|
||||
|
||||
require(id) {
|
||||
return this._host.require(id);
|
||||
}
|
||||
|
||||
exception(error, fatal) {
|
||||
this._host.exception(error, fatal);
|
||||
}
|
||||
};
|
||||
|
||||
window.addEventListener('load', () => {
|
||||
global.protobuf = require('./protobuf');
|
||||
global.flatbuffers = require('./flatbuffers');
|
||||
const view = require('./view');
|
||||
window.__view__ = new view.View(new host.ElectronHost());
|
||||
});
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 34 KiB |
@ -0,0 +1,392 @@
|
||||
|
||||
|
||||
var flatbuffers = {};
|
||||
var json = json || require('./json');
|
||||
|
||||
flatbuffers.get = (name) => {
|
||||
flatbuffers._map = flatbuffers._map || new Map();
|
||||
if (!flatbuffers._map.has(name)) {
|
||||
flatbuffers._map.set(name, {});
|
||||
}
|
||||
return flatbuffers._map.get(name);
|
||||
};
|
||||
|
||||
flatbuffers.BinaryReader = class {
|
||||
|
||||
static open(data) {
|
||||
return new flatbuffers.BinaryReader(data);
|
||||
}
|
||||
|
||||
constructor(data) {
|
||||
const buffer = data instanceof Uint8Array ? data : data.peek();
|
||||
this._buffer = buffer;
|
||||
this._position = 0;
|
||||
this._dataView = new DataView(buffer.buffer, buffer.byteOffset, buffer.byteLength);
|
||||
}
|
||||
|
||||
get root() {
|
||||
return this.int32(this._position) + this._position;
|
||||
}
|
||||
|
||||
get identifier() {
|
||||
if (this._buffer.length >= 8) {
|
||||
const buffer = this._buffer.slice(4, 8);
|
||||
if (buffer.every((c) => c >= 32 && c <= 128)) {
|
||||
return String.fromCharCode(...buffer);
|
||||
}
|
||||
}
|
||||
return '';
|
||||
}
|
||||
|
||||
bool(offset) {
|
||||
return !!this.int8(offset);
|
||||
}
|
||||
|
||||
bool_(position, offset, defaultValue) {
|
||||
offset = this._offset(position, offset);
|
||||
return offset ? this.bool(position + offset) : defaultValue;
|
||||
}
|
||||
|
||||
int8(offset) {
|
||||
return this.uint8(offset) << 24 >> 24;
|
||||
}
|
||||
|
||||
int8_(position, offset, defaultValue) {
|
||||
offset = this._offset(position, offset);
|
||||
return offset ? this.int8(position + offset) : defaultValue;
|
||||
}
|
||||
|
||||
uint8(offset) {
|
||||
return this._buffer[offset];
|
||||
}
|
||||
|
||||
uint8_(position, offset, defaultValue) {
|
||||
offset = this._offset(position, offset);
|
||||
return offset ? this.uint8(position + offset) : defaultValue;
|
||||
}
|
||||
|
||||
int16(offset) {
|
||||
return this._dataView.getInt16(offset, true);
|
||||
}
|
||||
|
||||
int16_(position, offset, defaultValue) {
|
||||
offset = this._offset(position, offset);
|
||||
return offset ? this.int16(position + offset) : defaultValue;
|
||||
}
|
||||
|
||||
uint16(offset) {
|
||||
return this._dataView.getUint16(offset, true);
|
||||
}
|
||||
|
||||
uint16_(position, offset, defaultValue) {
|
||||
offset = this._offset(position, offset);
|
||||
return offset ? this.uint16(position + offset) : defaultValue;
|
||||
}
|
||||
|
||||
int32(offset) {
|
||||
return this._dataView.getInt32(offset, true);
|
||||
}
|
||||
|
||||
int32_(position, offset, defaultValue) {
|
||||
offset = this._offset(position, offset);
|
||||
return offset ? this.int32(position + offset) : defaultValue;
|
||||
}
|
||||
|
||||
uint32(offset) {
|
||||
return this._dataView.getUint32(offset, true);
|
||||
}
|
||||
|
||||
uint32_(position, offset, defaultValue) {
|
||||
offset = this._offset(position, offset);
|
||||
return offset ? this.int32(position + offset) : defaultValue;
|
||||
}
|
||||
|
||||
int64(offset) {
|
||||
return this._dataView.getInt64(offset, true);
|
||||
}
|
||||
|
||||
int64_(position, offset, defaultValue) {
|
||||
offset = this._offset(position, offset);
|
||||
return offset ? this.int64(position + offset) : defaultValue;
|
||||
}
|
||||
|
||||
uint64(offset) {
|
||||
return this._dataView.getUint64(offset, true);
|
||||
}
|
||||
|
||||
uint64_(position, offset, defaultValue) {
|
||||
offset = this._offset(position, offset);
|
||||
return offset ? this.uint64(position + offset) : defaultValue;
|
||||
}
|
||||
|
||||
float32(offset) {
|
||||
return this._dataView.getFloat32(offset, true);
|
||||
}
|
||||
|
||||
float32_(position, offset, defaultValue) {
|
||||
offset = this._offset(position, offset);
|
||||
return offset ? this.float32(position + offset) : defaultValue;
|
||||
}
|
||||
|
||||
float64(offset) {
|
||||
return this._dataView.getFloat64(offset, true);
|
||||
}
|
||||
|
||||
float64_(position, offset, defaultValue) {
|
||||
offset = this._offset(position, offset);
|
||||
return offset ? this.float64(position + offset) : defaultValue;
|
||||
}
|
||||
|
||||
string(offset, encoding) {
|
||||
offset += this.int32(offset);
|
||||
const length = this.int32(offset);
|
||||
var result = '';
|
||||
var i = 0;
|
||||
offset += 4;
|
||||
if (encoding === 1) {
|
||||
return this._buffer.subarray(offset, offset + length);
|
||||
}
|
||||
while (i < length) {
|
||||
var codePoint;
|
||||
// Decode UTF-8
|
||||
const a = this.uint8(offset + i++);
|
||||
if (a < 0xC0) {
|
||||
codePoint = a;
|
||||
}
|
||||
else {
|
||||
const b = this.uint8(offset + i++);
|
||||
if (a < 0xE0) {
|
||||
codePoint = ((a & 0x1F) << 6) | (b & 0x3F);
|
||||
}
|
||||
else {
|
||||
const c = this.uint8(offset + i++);
|
||||
if (a < 0xF0) {
|
||||
codePoint = ((a & 0x0F) << 12) | ((b & 0x3F) << 6) | (c & 0x3F);
|
||||
}
|
||||
else {
|
||||
const d = this.uint8(offset + i++);
|
||||
codePoint = ((a & 0x07) << 18) | ((b & 0x3F) << 12) | ((c & 0x3F) << 6) | (d & 0x3F);
|
||||
}
|
||||
}
|
||||
}
|
||||
// Encode UTF-16
|
||||
if (codePoint < 0x10000) {
|
||||
result += String.fromCharCode(codePoint);
|
||||
}
|
||||
else {
|
||||
codePoint -= 0x10000;
|
||||
result += String.fromCharCode((codePoint >> 10) + 0xD800, (codePoint & ((1 << 10) - 1)) + 0xDC00);
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
string_(position, offset, defaultValue) {
|
||||
offset = this._offset(position, offset);
|
||||
return offset ? this.string(position + offset) : defaultValue;
|
||||
}
|
||||
|
||||
bools_(position, offset) {
|
||||
offset = this._offset(position, offset);
|
||||
if (offset) {
|
||||
const length = this._length(position + offset);
|
||||
offset = this._vector(position + offset);
|
||||
const array = new Array(length);
|
||||
for (let i = 0; i < length; i++) {
|
||||
array[i] = this.uint8(offset + i + 4) ? true : false;
|
||||
}
|
||||
return array;
|
||||
}
|
||||
return [];
|
||||
}
|
||||
|
||||
int64s_(position, offset) {
|
||||
offset = this._offset(position, offset);
|
||||
if (offset) {
|
||||
const length = this._length(position + offset);
|
||||
offset = this._vector(position + offset);
|
||||
const array = new Array(length);
|
||||
for (let i = 0; i < length; i++) {
|
||||
array[i] = this.int64(offset + (i << 3));
|
||||
}
|
||||
return array;
|
||||
}
|
||||
return [];
|
||||
}
|
||||
|
||||
uint64s_(position, offset) {
|
||||
offset = this._offset(position, offset);
|
||||
if (offset) {
|
||||
const length = this._length(position + offset);
|
||||
offset = this._vector(position + offset);
|
||||
const array = new Array(length);
|
||||
for (let i = 0; i < length; i++) {
|
||||
array[i] = this.uint64(offset + (i << 3));
|
||||
}
|
||||
return array;
|
||||
}
|
||||
return [];
|
||||
}
|
||||
|
||||
strings_(position, offset) {
|
||||
offset = this._offset(position, offset);
|
||||
if (offset) {
|
||||
const length = this._length(position + offset);
|
||||
offset = this._vector(position + offset);
|
||||
const array = new Array(length);
|
||||
for (let i = 0; i < length; i++) {
|
||||
array[i] = this.string(offset + i * 4);
|
||||
}
|
||||
return array;
|
||||
}
|
||||
return [];
|
||||
}
|
||||
|
||||
struct(position, offset, decode) {
|
||||
offset = this._offset(position, offset);
|
||||
return offset ? decode(this, position + offset) : null;
|
||||
}
|
||||
|
||||
table(position, offset, decode) {
|
||||
offset = this._offset(position, offset);
|
||||
return offset ? decode(this, this._indirect(position + offset)) : null;
|
||||
}
|
||||
|
||||
union(position, offset, decode) {
|
||||
const type_offset = this._offset(position, offset);
|
||||
const type = type_offset ? this.uint8(position + type_offset) : 0;
|
||||
offset = this._offset(position, offset + 2);
|
||||
return offset ? decode(this, this._union(position + offset), type) : null;
|
||||
}
|
||||
|
||||
typedArray(position, offset, type) {
|
||||
offset = this._offset(position, offset);
|
||||
return offset ? new type(this._buffer.buffer, this._buffer.byteOffset + this._vector(position + offset), this._length(position + offset)) : new type(0);
|
||||
}
|
||||
|
||||
unionArray(/* position, offset, decode */) {
|
||||
throw new flatbuffers.Error('Not implemented.');
|
||||
}
|
||||
|
||||
structArray(position, offset, size, decode) {
|
||||
offset = this._offset(position, offset);
|
||||
const length = offset ? this._length(position + offset) : 0;
|
||||
const list = new Array(length);
|
||||
for (let i = 0; i < length; i++) {
|
||||
list[i] = decode(this, this._indirect(this._vector(position + offset) + i * 4));
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
tableArray(position, offset, decode) {
|
||||
offset = this._offset(position, offset);
|
||||
const length = offset ? this._length(position + offset) : 0;
|
||||
const list = new Array(length);
|
||||
for (let i = 0; i < length; i++) {
|
||||
list[i] = decode(this, this._indirect(this._vector(position + offset) + i * 4));
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
_offset(bb_pos, vtableOffset) {
|
||||
var vtable = bb_pos - this.int32(bb_pos);
|
||||
return vtableOffset < this.int16(vtable) ? this.int16(vtable + vtableOffset) : 0;
|
||||
}
|
||||
|
||||
_indirect(offset) {
|
||||
return offset + this.int32(offset);
|
||||
}
|
||||
|
||||
_vector(offset) {
|
||||
return offset + this.int32(offset) + 4;
|
||||
}
|
||||
|
||||
_length(offset) {
|
||||
return this.int32(offset + this.int32(offset));
|
||||
}
|
||||
|
||||
_union(offset) {
|
||||
return offset + this.int32(offset);
|
||||
}
|
||||
};
|
||||
|
||||
flatbuffers.TextReader = class {
|
||||
|
||||
static open(obj) {
|
||||
return new flatbuffers.TextReader(obj);
|
||||
}
|
||||
|
||||
constructor(obj) {
|
||||
this._root = obj;
|
||||
}
|
||||
|
||||
get root() {
|
||||
return this._root;
|
||||
}
|
||||
|
||||
value(obj, defaultValue) {
|
||||
return obj !== undefined ? obj : defaultValue;
|
||||
}
|
||||
|
||||
object(obj, decode) {
|
||||
return obj !== undefined ? decode(this, obj) : obj;
|
||||
}
|
||||
|
||||
array(obj) {
|
||||
if (Array.isArray(obj)) {
|
||||
const target = new Array(obj.length);
|
||||
for (let i = 0; i < obj.length; i++) {
|
||||
target[i] = obj[i];
|
||||
}
|
||||
return target;
|
||||
}
|
||||
if (!obj) {
|
||||
return [];
|
||||
}
|
||||
throw new flatbuffers.Error('Inalid value array.');
|
||||
}
|
||||
|
||||
typedArray(obj, type) {
|
||||
if (Array.isArray(obj)) {
|
||||
const target = new type(obj.length);
|
||||
for (let i = 0; i < obj.length; i++) {
|
||||
target[i] = obj[i];
|
||||
}
|
||||
return target;
|
||||
}
|
||||
if (!obj) {
|
||||
return new type(0);
|
||||
}
|
||||
throw new flatbuffers.Error('Inalid typed array.');
|
||||
}
|
||||
|
||||
objectArray(obj, decode) {
|
||||
if (Array.isArray(obj)) {
|
||||
const target = new Array(obj.length);
|
||||
for (let i = 0; i < obj.length; i++) {
|
||||
target[i] = decode(this, obj[i]);
|
||||
}
|
||||
return target;
|
||||
}
|
||||
if (!obj) {
|
||||
return [];
|
||||
}
|
||||
throw new flatbuffers.Error('Inalid object array.');
|
||||
}
|
||||
};
|
||||
|
||||
flatbuffers.Error = class extends Error {
|
||||
|
||||
constructor(message) {
|
||||
super(message);
|
||||
this.name = 'FlatBuffers Error';
|
||||
this.message = message;
|
||||
}
|
||||
};
|
||||
|
||||
if (typeof module !== "undefined" && typeof module.exports === "object") {
|
||||
module.exports.BinaryReader = flatbuffers.BinaryReader;
|
||||
module.exports.TextReader = flatbuffers.TextReader;
|
||||
module.exports.get = flatbuffers.get;
|
||||
}
|
||||
@ -0,0 +1,234 @@
|
||||
|
||||
var gzip = gzip || {};
|
||||
var zip = zip || require('./zip');
|
||||
|
||||
gzip.Archive = class {
|
||||
|
||||
static open(data) {
|
||||
const stream = data instanceof Uint8Array ? new gzip.BinaryReader(data) : data;
|
||||
const signature = [ 0x1f, 0x8b ];
|
||||
if (stream.length > 18 && stream.peek(2).every((value, index) => value === signature[index])) {
|
||||
return new gzip.Archive(stream);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
constructor(stream) {
|
||||
const position = stream.position;
|
||||
const entry = new gzip.Entry(stream);
|
||||
this._entries = new Map([ [ entry.name, entry.stream ] ]);
|
||||
stream.seek(position);
|
||||
}
|
||||
|
||||
get entries() {
|
||||
return this._entries;
|
||||
}
|
||||
};
|
||||
|
||||
gzip.Entry = class {
|
||||
|
||||
constructor(stream) {
|
||||
const signature = [ 0x1f, 0x8b ];
|
||||
if (stream.position + 2 > stream.length ||
|
||||
!stream.read(2).every((value, index) => value === signature[index])) {
|
||||
throw new gzip.Error('Invalid gzip signature.');
|
||||
}
|
||||
const string = () => {
|
||||
let content = '';
|
||||
while (stream.position < stream.length) {
|
||||
const value = stream.byte();
|
||||
if (value === 0x00) {
|
||||
break;
|
||||
}
|
||||
content += String.fromCharCode(value);
|
||||
}
|
||||
return content;
|
||||
};
|
||||
const reader = new gzip.BinaryReader(stream.read(8));
|
||||
const compressionMethod = reader.byte();
|
||||
if (compressionMethod != 8) {
|
||||
throw new gzip.Error("Invalid compression method '" + compressionMethod.toString() + "'.");
|
||||
}
|
||||
const flags = reader.byte();
|
||||
reader.uint32(); // MTIME
|
||||
reader.byte(); // XFL
|
||||
reader.byte(); // OS
|
||||
if ((flags & 4) != 0) { // FEXTRA
|
||||
const xlen = stream.byte() | (stream.byte() << 8);
|
||||
stream.skip(xlen);
|
||||
}
|
||||
this._name = (flags & 8) != 0 ? string() : ''; // FNAME
|
||||
if ((flags & 16) != 0) { // FCOMMENT
|
||||
string();
|
||||
}
|
||||
if ((flags & 1) != 0) { // FHCRC
|
||||
stream.skip(2);
|
||||
}
|
||||
this._stream = new gzip.InflaterStream(stream);
|
||||
}
|
||||
|
||||
get name() {
|
||||
return this._name;
|
||||
}
|
||||
|
||||
get stream() {
|
||||
return this._stream;
|
||||
}
|
||||
};
|
||||
|
||||
gzip.InflaterStream = class {
|
||||
|
||||
constructor(stream) {
|
||||
this._stream = stream.stream(stream.length - stream.position - 8);
|
||||
const reader = new gzip.BinaryReader(stream.read(8));
|
||||
reader.uint32(); // CRC32
|
||||
this._length = reader.uint32(); // ISIZE
|
||||
this._position = 0;
|
||||
}
|
||||
|
||||
get position() {
|
||||
return this._position;
|
||||
}
|
||||
|
||||
get length() {
|
||||
return this._length;
|
||||
}
|
||||
|
||||
seek(position) {
|
||||
if (this._buffer === undefined) {
|
||||
this._inflate();
|
||||
}
|
||||
this._position = position >= 0 ? position : this._length + position;
|
||||
}
|
||||
|
||||
skip(offset) {
|
||||
if (this._buffer === undefined) {
|
||||
this._inflate();
|
||||
}
|
||||
this._position += offset;
|
||||
}
|
||||
|
||||
stream(length) {
|
||||
return new gzip.BinaryReader(this.read(length));
|
||||
}
|
||||
|
||||
peek(length) {
|
||||
const position = this._position;
|
||||
length = length !== undefined ? length : this._length - this._position;
|
||||
this.skip(length);
|
||||
const end = this._position;
|
||||
this.seek(position);
|
||||
if (position === 0 && length === this._length) {
|
||||
return this._buffer;
|
||||
}
|
||||
return this._buffer.subarray(position, end);
|
||||
}
|
||||
|
||||
read(length) {
|
||||
const position = this._position;
|
||||
length = length !== undefined ? length : this._length - this._position;
|
||||
this.skip(length);
|
||||
if (position === 0 && length === this._length) {
|
||||
return this._buffer;
|
||||
}
|
||||
return this._buffer.subarray(position, this._position);
|
||||
}
|
||||
|
||||
byte() {
|
||||
const position = this._position;
|
||||
this.skip(1);
|
||||
return this._buffer[position];
|
||||
}
|
||||
|
||||
_inflate() {
|
||||
if (this._buffer === undefined) {
|
||||
const buffer = this._stream.peek();
|
||||
this._buffer = new zip.Inflater().inflateRaw(buffer, this._length);
|
||||
delete this._stream;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
gzip.BinaryReader = class {
|
||||
|
||||
constructor(buffer) {
|
||||
this._buffer = buffer;
|
||||
this._length = buffer.length;
|
||||
this._position = 0;
|
||||
this._view = new DataView(buffer.buffer, buffer.byteOffset, buffer.byteLength);
|
||||
}
|
||||
|
||||
get position() {
|
||||
return this._position;
|
||||
}
|
||||
|
||||
get length() {
|
||||
return this._length;
|
||||
}
|
||||
|
||||
create(buffer) {
|
||||
return new gzip.BinaryReader(buffer);
|
||||
}
|
||||
|
||||
stream(length) {
|
||||
return this.create(this.read(length));
|
||||
}
|
||||
|
||||
seek(position) {
|
||||
this._position = position >= 0 ? position : this._length + position;
|
||||
}
|
||||
|
||||
skip(offset) {
|
||||
this._position += offset;
|
||||
}
|
||||
|
||||
peek(length) {
|
||||
if (this._position === 0 && length === undefined) {
|
||||
return this._buffer;
|
||||
}
|
||||
const position = this._position;
|
||||
this.skip(length !== undefined ? length : this._length - this._position);
|
||||
const end = this._position;
|
||||
this.seek(position);
|
||||
return this._buffer.subarray(position, end);
|
||||
}
|
||||
|
||||
read(length) {
|
||||
if (this._position === 0 && length === undefined) {
|
||||
this._position = this._length;
|
||||
return this._buffer;
|
||||
}
|
||||
const position = this._position;
|
||||
this.skip(length !== undefined ? length : this._length - this._position);
|
||||
return this._buffer.subarray(position, this._position);
|
||||
}
|
||||
|
||||
byte() {
|
||||
const position = this._position;
|
||||
this.skip(1);
|
||||
return this._buffer[position];
|
||||
}
|
||||
|
||||
uint16() {
|
||||
const position = this._position;
|
||||
this.skip(2);
|
||||
return this._view.getUint16(position, true);
|
||||
}
|
||||
|
||||
uint32() {
|
||||
const position = this._position;
|
||||
this.skip(4);
|
||||
return this._view.getUint32(position, true);
|
||||
}
|
||||
};
|
||||
|
||||
gzip.Error = class extends Error {
|
||||
constructor(message) {
|
||||
super(message);
|
||||
this.name = 'Gzip Error';
|
||||
}
|
||||
};
|
||||
|
||||
if (typeof module !== 'undefined' && typeof module.exports === 'object') {
|
||||
module.exports.Archive = gzip.Archive;
|
||||
}
|
||||
@ -0,0 +1,374 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no, viewport-fit=cover">
|
||||
<meta http-equiv="Content-Security-Policy" content="script-src 'self' www.google-analytics.com;">
|
||||
<meta name="version" content="0.0.0">
|
||||
<title>Netron</title>
|
||||
<link rel="stylesheet" type="text/css" href="view-grapher.css">
|
||||
<link rel="stylesheet" type="text/css" href="view-sidebar.css">
|
||||
<link rel="shortcut icon" type="image/x-icon" href="favicon.ico">
|
||||
<link rel="icon" type="image/png" href="icon.png">
|
||||
<link rel="apple-touch-icon" type="image/png" href="icon.png">
|
||||
<link rel="apple-touch-icon-precomposed" type="image/png" href="icon.png">
|
||||
<link rel="fluid-icon" type="image/png" href="icon.png">
|
||||
<script type="text/javascript" src="dagre.js"></script>
|
||||
<script type="text/javascript" src="base.js"></script>
|
||||
<script type="text/javascript" src="text.js"></script>
|
||||
<script type="text/javascript" src="json.js"></script>
|
||||
<script type="text/javascript" src="xml.js"></script>
|
||||
<script type="text/javascript" src="python.js"></script>
|
||||
<script type="text/javascript" src="protobuf.js"></script>
|
||||
<script type="text/javascript" src="flatbuffers.js"></script>
|
||||
<script type="text/javascript" src="zip.js"></script>
|
||||
<script type="text/javascript" src="gzip.js"></script>
|
||||
<script type="text/javascript" src="tar.js"></script>
|
||||
<script type="text/javascript" src="view-grapher.js"></script>
|
||||
<script type="text/javascript" src="view-sidebar.js"></script>
|
||||
<script type="text/javascript" src="view.js"></script>
|
||||
<script type="text/javascript" src="index.js"></script>
|
||||
<style>
|
||||
html { touch-action: none; overflow: hidden; width: 100%; height: 100%; -ms-text-size-adjust: 100%; -webkit-text-size-adjust: 100%; text-rendering: optimizeLegibility; -webkit-text-rendering: optimizeLegibility; -moz-text-rendering: optimizeLegibility; -ms-text-rendering: optimizeLegibility; -o-text-rendering: optimizeLegibility; -webkit-font-smoothing: antialiased; -moz-font-smoothing: antialiased; -ms-font-smoothing: antialiased; -o-font-smoothing: antialiased; }
|
||||
body { touch-action: none; overflow: hidden; width: 100%; height: 100%; margin: 0; font-family: -apple-system, BlinkMacSystemFont, "Segoe WPC", "Segoe UI", "Ubuntu", "Droid Sans", sans-serif, "PingFang SC"; font-size: 12px; text-rendering: geometricPrecision; }
|
||||
button { font-family: -apple-system, BlinkMacSystemFont, "Segoe WPC", "Segoe UI", "Ubuntu", "Droid Sans", sans-serif, "PingFang SC"; }
|
||||
.center { position: absolute; margin: auto; top: 0; right: 0; bottom: 0; left: 0; user-select: none; -webkit-user-select: none; -moz-user-select: none; }
|
||||
.select { user-select: text; -webkit-user-select: text; -moz-user-select: text; }
|
||||
.open-file-dialog { display: none; }
|
||||
.transparent { width: 100%; height: 100%; background-color: #000000; display: none; opacity: 0; }
|
||||
.graph { display: flex; height: 100%; width: 100%; overflow: auto; outline: none; touch-action: pan-x pan-y; }
|
||||
.canvas { margin: auto; flex-shrink: 0; text-rendering: geometricPrecision; user-select: none; -webkit-user-select: none; -moz-user-select: none; }
|
||||
.toolbar { position: absolute; top: 10px; left: 10px; padding: 0; margin: 0; user-select: none; -webkit-user-select: none; -moz-user-select: none; }
|
||||
.toolbar button:focus { outline: 0; }
|
||||
.toolbar-button { background: None; border-radius: 6px; border: 0; margin: 0; padding: 0; fill: None; stroke: #777; cursor: pointer; width: 24px; height: 24px; }
|
||||
.toolbar-button { float: left; background: None; border-radius: 6px; border: 0; margin: 0; margin-right: 1px; padding: 0; fill: None; stroke: #777; cursor: pointer; width: 24px; height: 24px; }
|
||||
.toolbar-back-button { float: left; background: #777; border-top-left-radius: 6px; border-bottom-left-radius: 6px; border: 0px solid; border-color: #777; margin: 2px 0 2px 8px; padding: 0 8px 0 8px; cursor: pointer; height: 20px; color: #ffffff; font-size: 11px; line-height: 0; transition: 0.1s; }
|
||||
.toolbar-back-button:hover { background: #000000; border-color: #000000; }
|
||||
.toolbar-name-button { float: left; background: rgba(255, 255, 255, 0.95); border-top-right-radius: 6px; border-bottom-right-radius: 6px; border: 1px solid #777; color: #777; border-left: 1px; border-left-color: #ffffff; margin: 2px 0 2px 0; padding: 0 12px 0 6px; cursor: pointer; width: auto; height: 20px; font-size: 11px; line-height: 0; transition: 0.1s; }
|
||||
.toolbar-name-button:hover { color: #000000; }
|
||||
.icon .border { stroke: #fff; }
|
||||
.icon .stroke { stroke: #808080; }
|
||||
.icon:hover .stroke { stroke: #000000; }
|
||||
.dropdown { display: none; position: absolute; min-width: 225px; z-index: 1; border-radius: 4px; background-color: #f6f6f6; border: 1px solid rgba(0,0,0,.15); padding-top: 2px; padding-bottom: 2px; margin-left: 2px; overflow: hidden; }
|
||||
.dropdown button { display: block; border: none; border-radius: 0; background-color: transparent; color: black; width: 100%; text-align: left; padding: 4px 12px 5px 12px; white-space: no-wrap; font-size: 12px; }
|
||||
.dropdown button:hover { color: #ffffff; background-color: #2e6bd2; }
|
||||
.dropdown .separator { margin-top: 2px; margin-bottom: 2px; border-top: 1px; border-bottom: 0; border-style: solid; border-color: #e5e5e5; }
|
||||
.about { background-color: #ffffff; }
|
||||
.about { overflow: hidden; }
|
||||
.about .logo { background-color: #ececec; color: #242424; width: 320px; height: 170px; padding: 40px; opacity: 1.0; border-radius: 5px; border: 0.5px solid #cccccc; box-shadow: 0 0 30px #ddd; }
|
||||
.about.desktop .logo { border: None; border-radius: 0px; }
|
||||
.about.desktop .graph { display: none; opacity: 0; }
|
||||
.about.desktop .transparent { display: none; opacity: 0; }
|
||||
.about.desktop .toolbar { display: none; opacity: 0; }
|
||||
.about .logo-name { opacity: 0; }
|
||||
.about .logo-text { top: -130px; width: 320px; }
|
||||
.about .logo-icon { left: 136px; top: -108px; width: 60px; height: 60px; }
|
||||
.about .logo-stroke { stroke: #242424; }
|
||||
.about .logo-fill { fill: #242424; }
|
||||
.about .logo-border { stroke: #242424; }
|
||||
.about .logo-glyph { fill: #242424; }
|
||||
.about .logo-message { top: 112px; padding-left: 40px; padding-right: 40px; }
|
||||
.about a { text-decoration: none; color: #242424; }
|
||||
.about a:visited { color: inherit; }
|
||||
.about a:hover { color: #242424; }
|
||||
.about .logo-github { top: 130px; width: 24px; height: 24px; }
|
||||
.about .open-file-button { display: none; }
|
||||
.about .github-button { display: none; }
|
||||
.about .consent-message { display: none; }
|
||||
.about .consent-accept-button { display: none; }
|
||||
.about .graph { display: flex; opacity: 1; }
|
||||
.about .toolbar { display: block; opacity: 1; }
|
||||
.about .transparent { display: block; opacity: 0.5; }
|
||||
.welcome { background-color: #ececec; color: #242424; }
|
||||
.welcome .logo { width: 582px; height: 128px; }
|
||||
.welcome .logo-text { top: -57px; width: 582px; transition: 0.1s; }
|
||||
.welcome .logo-name { top: -170px; width: 582px; transition: 0.1s; }
|
||||
.welcome .logo-icon { left: 248px; top: -18px; width: 106px; height: 106px; transition: 0.1s; }
|
||||
.welcome .logo-spinner { left: 248px; top: -18px; width: 106px; height: 106px; display: none; }
|
||||
.welcome .logo-stroke { stroke: #444444; }
|
||||
.welcome .logo-fill { fill: #444444; }
|
||||
.welcome .logo-border { stroke: #555555; }
|
||||
.welcome .logo-glyph { fill: #444444; }
|
||||
.welcome .logo-message { display: none; }
|
||||
.welcome .logo-github { display: none; }
|
||||
.welcome button { font-size: 12px; font-weight: bold; line-height: 1.25; text-align: center; vertical-align: middle; min-width: 60px; height: 32px; border-radius: 16px; transition: 0.1s; user-select: none; -webkit-user-select: none; -moz-user-select: none; color: #444444; background-color: #ececec; border: 1px solid #444444; }
|
||||
.welcome button:hover { color: #ececec; background-color: #444444; cursor: pointer; transition: 0.2s; }
|
||||
.welcome button:focus { outline: 0; }
|
||||
.welcome .open-file-button { top: 170px; left: -150px; width: 125px; opacity: 1; }
|
||||
.welcome .github-button { top: 170px; left: 150px; width: 125px; opacity: 1; }
|
||||
.welcome .consent-accept-button { top: 220px; left: 0px; width: 125px; display: none; opacity: 0; }
|
||||
.welcome .consent-message { top: 120px; left: 0px; font-size: 13px; text-align: center; line-height: 20px; color: #444444; display: none; opacity: 0; }
|
||||
.welcome .graph { display: none; opacity: 0; }
|
||||
.welcome.spinner .logo-spinner { display: block; -webkit-animation: orbit 0.5s infinite linear; animation: orbit 0.5s infinite linear; cursor: wait; }
|
||||
@-webkit-keyframes orbit { 0% { -webkit-transform: rotate(0deg); transform: rotate(0deg); } 100% { -webkit-transform: rotate(360deg); transform: rotate(360deg); } }
|
||||
@keyframes orbit { 0% { -webkit-transform: rotate(0deg); transform: rotate(0deg); } 100% { -webkit-transform: rotate(360deg); transform: rotate(360deg); } }
|
||||
.welcome.spinner .logo-spinner-stroke { stroke: #ececec; }
|
||||
.welcome.spinner .logo-name { display: none; }
|
||||
.welcome.spinner .open-file-button { opacity: 0; display: none; }
|
||||
.welcome.spinner .github-button { opacity: 0; display: none; }
|
||||
.welcome.consent .logo-name { display: none; }
|
||||
.welcome.consent .open-file-button { opacity: 0; display: none; }
|
||||
.welcome.consent .github-button { opacity: 0; display: none; }
|
||||
.welcome.consent .consent-accept-button { opacity: 1; display: block; }
|
||||
.welcome.consent .consent-message { opacity: 1; display: block; }
|
||||
.welcome.spinner .graph { display: flex; opacity: 0; }
|
||||
.welcome .toolbar { display: none; }
|
||||
.default { background-color: #ffffff; }
|
||||
.default .logo { display: none; }
|
||||
.default .graph { display: flex; opacity: 1; }
|
||||
.default .toolbar { display: table; }
|
||||
@media (prefers-color-scheme: dark) {
|
||||
:root { color-scheme: dark; }
|
||||
.default { background-color: #404040; }
|
||||
.graph { background-color: #404040; }
|
||||
.about { background-color: #404040; }
|
||||
.about .logo { background-color: #2d2d2d; color: #dfdfdf; border-color: #000000; box-shadow: 0 0 30px #333; }
|
||||
.about a { color: #dfdfdf; }
|
||||
.about a:hover { color: #ffffff; }
|
||||
.about .logo-stroke { stroke: #dfdfdf; }
|
||||
.about .logo-fill { fill: #dfdfdf; }
|
||||
.about .logo-border { stroke: #dfdfdf; }
|
||||
.about .logo-glyph { fill: #dfdfdf; }
|
||||
.welcome { background-color: #1e1e1e; color: #888888; }
|
||||
.welcome .logo-stroke { stroke: #888888; }
|
||||
.welcome .logo-fill { fill: #888888; }
|
||||
.welcome .logo-border { stroke: #000000; }
|
||||
.welcome .logo-glyph { fill: #888888; }
|
||||
.welcome .logo-spinner-stroke { stroke: #ffffff; }
|
||||
.welcome .logo button { color: #888888; background-color: #1e1e1e; border-color: #888888; }
|
||||
.welcome .logo button:hover { color: #1e1e1e; background-color: #888888; }
|
||||
.welcome .consent-message { color: #888888; display: none; opacity: 0; }
|
||||
.icon .border { stroke: #1d1d1d; }
|
||||
.icon .stroke { stroke: #aaaaaa; }
|
||||
.icon:hover .stroke { stroke: #dfdfdf; }
|
||||
.dropdown { background-color: #373737; border-color: #000000; }
|
||||
.dropdown button { color: #ffffff; }
|
||||
.dropdown button:hover { color: #ffffff; background-color: #1d59d1; }
|
||||
.dropdown .separator { border-color: #5a5a5a; }
|
||||
.toolbar-back-button { background: #aaaaaa; border-color: #aaaaaa; color: #333333; }
|
||||
.toolbar-back-button:hover { background: #dfdfdf; border-color: #dfdfdf; }
|
||||
.toolbar-name-button { background: #404040; border-color: #aaaaaa; color: #cccccc; }
|
||||
.toolbar-name-button:hover { color: #dfdfdf; }
|
||||
}
|
||||
@media all and (max-width: 640px) {
|
||||
.welcome .logo { width: 240px; }
|
||||
.welcome .logo-text { opacity: 0; }
|
||||
.welcome .logo-name { opacity: 0; }
|
||||
.welcome .logo-icon { left: 0; top: 0; width: 128px; height: 128px; }
|
||||
.welcome .logo-spinner { left: 0; top: 0; width: 128px; height: 128px; }
|
||||
.welcome .logo .open-file-button { top: 180px; left: 0; }
|
||||
.welcome .logo .github-button { top: 270px; left: 0; }
|
||||
.welcome .logo .consent-message { top: 140px; }
|
||||
.welcome .logo .consent-accept-button { top: 310px; }
|
||||
.about .logo { border-radius: 0; border-left: 0px; border-right: 0px; width: 100%; padding-left: 0; padding-right: 0; }
|
||||
.about.desktop .logo { width: 320px; padding: 40px; }
|
||||
}
|
||||
@media only screen and (max-device-width: 1024px) {
|
||||
.toolbar-button { width: 32px; height: 32px; }
|
||||
.toolbar-back-button { margin-top: 6px; margin-bottom: 6px; }
|
||||
.toolbar-name-button { margin-top: 6px; margin-bottom: 6px; }
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body class="welcome spinner">
|
||||
<div id="graph" class="graph" tabindex="0">
|
||||
<svg id="canvas" class="canvas" preserveaspectratio="xMidYMid meet" width="100%" height="100%"></svg>
|
||||
</div>
|
||||
<div id="sidebar" class="sidebar"></div>
|
||||
<div id="toolbar" class="toolbar">
|
||||
<button id="menu-button" class="toolbar-button" title="Menu">
|
||||
<svg class="icon" viewbox="0 0 100 100">
|
||||
<rect class="border" x="12" y="12" width="76" height="76" rx="16" ry="16" stroke-width="8"></rect>
|
||||
<line class="border" x1="30" y1="37" x2="70" y2="37" stroke-width="8" stroke-linecap="round" stroke="#fff"></line>
|
||||
<line class="border" x1="30" y1="50" x2="70" y2="50" stroke-width="8" stroke-linecap="round" stroke="#fff"></line>
|
||||
<line class="border" x1="30" y1="63" x2="70" y2="63" stroke-width="8" stroke-linecap="round" stroke="#fff"></line>
|
||||
<rect class="stroke" x="12" y="12" width="76" height="76" rx="16" ry="16" stroke-width="4"></rect>
|
||||
<line class="stroke" x1="30" y1="37" x2="70" y2="37" stroke-width="4" stroke-linecap="round"></line>
|
||||
<line class="stroke" x1="30" y1="50" x2="70" y2="50" stroke-width="4" stroke-linecap="round"></line>
|
||||
<line class="stroke" x1="30" y1="63" x2="70" y2="63" stroke-width="4" stroke-linecap="round"></line>
|
||||
</svg>
|
||||
</button>
|
||||
<button id="zoom-in-button" class="toolbar-button" title="Zoom In">
|
||||
<svg class="icon" viewbox="0 0 100 100">
|
||||
<circle class="border" cx="50" cy="50" r="35" stroke-width="8" stroke="#fff"></circle>
|
||||
<line class="border" x1="50" y1="38" x2="50" y2="62" stroke-width="8" stroke-linecap="round" stroke="#fff"></line>
|
||||
<line class="border" x1="38" y1="50" x2="62" y2="50" stroke-width="8" stroke-linecap="round" stroke="#fff"></line>
|
||||
<line class="border" x1="78" y1="78" x2="82" y2="82" stroke-width="12" stroke-linecap="square" stroke="#fff"></line>
|
||||
<circle class="stroke" cx="50" cy="50" r="35" stroke-width="4"></circle>
|
||||
<line class="stroke" x1="50" y1="38" x2="50" y2="62" stroke-width="4" stroke-linecap="round"></line>
|
||||
<line class="stroke" x1="38" y1="50" x2="62" y2="50" stroke-width="4" stroke-linecap="round"></line>
|
||||
<line class="stroke" x1="78" y1="78" x2="82" y2="82" stroke-width="8" stroke-linecap="square"></line>
|
||||
</svg>
|
||||
</button>
|
||||
<button id="zoom-out-button" class="toolbar-button" title="Zoom Out">
|
||||
<svg class="icon" viewbox="0 0 100 100">
|
||||
<circle class="border" cx="50" cy="50" r="35" stroke-width="8" stroke="#fff"></circle>
|
||||
<line class="border" x1="38" y1="50" x2="62" y2="50" stroke-width="8" stroke-linecap="round" stroke="#fff"></line>
|
||||
<line class="border" x1="78" y1="78" x2="82" y2="82" stroke-width="12" stroke-linecap="square" stroke="#fff"></line>
|
||||
<circle class="stroke" cx="50" cy="50" r="35" stroke-width="4"></circle>
|
||||
<line class="stroke" x1="38" y1="50" x2="62" y2="50" stroke-width="4" stroke-linecap="round"></line>
|
||||
<line class="stroke" x1="78" y1="78" x2="82" y2="82" stroke-width="8" stroke-linecap="square"></line>
|
||||
</svg>
|
||||
</button>
|
||||
<button id="back-button" class="toolbar-back-button" title="Back">
|
||||
❮
|
||||
</button>
|
||||
<button id="name-button" class="toolbar-name-button" title="Name">
|
||||
</button>
|
||||
<div id="menu-dropdown" class="dropdown"></div>
|
||||
</div>
|
||||
<div id="transparent" class="transparent"></div>
|
||||
<div class="center logo">
|
||||
<a href="https://github.com/lutzroeder/netron" target="blank_">
|
||||
<svg class="center logo-text" viewbox="0 0 5120 1024">
|
||||
<g transform="scale(9) translate(-44,-15)">
|
||||
<g transform="matrix(100,0,0,100,60.9965,126)">
|
||||
<path class="logo-glyph" d="M0.089,0L0.089,-0.745L0.595,-0.147L0.595,-0.715L0.656,-0.715L0.656,0.021L0.15,-0.578L0.15,0L0.089,0Z" style="fill-rule:nonzero;"/>
|
||||
</g>
|
||||
<g transform="matrix(100,0,0,100,164.341,126)">
|
||||
<path class="logo-glyph" d="M0.089,0L0.089,-0.715L0.443,-0.715L0.443,-0.654L0.154,-0.654L0.154,-0.43L0.443,-0.43L0.443,-0.369L0.154,-0.369L0.154,-0.061L0.443,-0.061L0.443,0L0.089,0Z" style="fill-rule:nonzero;"/>
|
||||
</g>
|
||||
<g transform="matrix(100,0,0,100,244.491,126)">
|
||||
<path class="logo-glyph" d="M0.216,0L0.216,-0.654L0.019,-0.654L0.019,-0.715L0.478,-0.715L0.478,-0.654L0.281,-0.654L0.281,0L0.216,0Z" style="fill-rule:nonzero;"/>
|
||||
</g>
|
||||
<g transform="matrix(100,0,0,100,323.031,126)">
|
||||
<path class="logo-glyph" d="M0.154,-0.658L0.154,-0.394L0.219,-0.394C0.28,-0.394 0.322,-0.404 0.346,-0.423C0.37,-0.442 0.382,-0.475 0.382,-0.522C0.382,-0.571 0.369,-0.606 0.345,-0.627C0.32,-0.648 0.278,-0.658 0.219,-0.658L0.154,-0.658ZM0.523,0L0.444,0L0.193,-0.341L0.154,-0.341L0.154,0L0.089,0L0.089,-0.715L0.22,-0.715C0.298,-0.715 0.356,-0.699 0.394,-0.667C0.433,-0.634 0.452,-0.585 0.452,-0.52C0.452,-0.464 0.436,-0.421 0.403,-0.389C0.37,-0.357 0.324,-0.341 0.266,-0.341L0.523,0Z" style="fill-rule:nonzero;"/>
|
||||
</g>
|
||||
<g transform="matrix(100,0,0,100,520.979,126)">
|
||||
<path class="logo-glyph" d="M0.089,0L0.089,-0.745L0.595,-0.147L0.595,-0.715L0.656,-0.715L0.656,0.021L0.15,-0.578L0.15,0L0.089,0Z" style="fill-rule:nonzero;"/>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
<svg class="center logo-icon" viewbox="0 0 1024 1024">
|
||||
<circle class="logo-stroke" cx="512" cy="512" r="431" fill="none" stroke-width="32"></circle>
|
||||
<circle class="logo-border" cx="512" cy="512" r="450" fill="none" stroke-width="6"></circle>
|
||||
<circle class="logo-border" cx="512" cy="512" r="412" fill="none" stroke-width="6"></circle>
|
||||
<line class="logo-stroke" x1="296" y1="392" x2="540" y2="280" stroke-width="12"></line>
|
||||
<line class="logo-stroke" x1="296" y1="632" x2="540" y2="280" stroke-width="12"></line>
|
||||
<line class="logo-stroke" x1="296" y1="392" x2="540" y2="435" stroke-width="12"></line>
|
||||
<line class="logo-stroke" x1="296" y1="632" x2="540" y2="435" stroke-width="12"></line>
|
||||
<line class="logo-stroke" x1="296" y1="392" x2="540" y2="590" stroke-width="12"></line>
|
||||
<line class="logo-stroke" x1="296" y1="632" x2="540" y2="590" stroke-width="12"></line>
|
||||
<line class="logo-stroke" x1="296" y1="392" x2="540" y2="744" stroke-width="12"></line>
|
||||
<line class="logo-stroke" x1="296" y1="632" x2="540" y2="744" stroke-width="12"></line>
|
||||
<line class="logo-stroke" x1="540" y1="280" x2="785" y2="512" stroke-width="12"></line>
|
||||
<line class="logo-stroke" x1="540" y1="590" x2="785" y2="512" stroke-width="12"></line>
|
||||
<line class="logo-stroke" x1="540" y1="435" x2="785" y2="512" stroke-width="12"></line>
|
||||
<line class="logo-stroke" x1="540" y1="744" x2="785" y2="512" stroke-width="12"></line>
|
||||
<g transform="translate(296, 392)">
|
||||
<circle class="logo-fill" cx="0" cy="0" r="51"></circle>
|
||||
<circle class="logo-border" cx="0" cy="0" r="51" fill="none" stroke-width="6"></circle>
|
||||
</g>
|
||||
<g transform="translate(296, 632)">
|
||||
<circle class="logo-fill" cx="0" cy="0" r="51"></circle>
|
||||
<circle class="logo-border" cx="0" cy="0" r="51" fill="none" stroke-width="6"></circle>
|
||||
</g>
|
||||
<g transform="translate(540, 280)">
|
||||
<circle class="logo-fill" cx="0" cy="0" r="51"></circle>
|
||||
<circle class="logo-border" cx="0" cy="0" r="51" fill="none" stroke-width="6"></circle>
|
||||
</g>
|
||||
<g transform="translate(540, 435)">
|
||||
<circle class="logo-fill" cx="0" cy="0" r="51"></circle>
|
||||
<circle class="logo-border" cx="0" cy="0" r="51" fill="none" stroke-width="6"></circle>
|
||||
</g>
|
||||
<g transform="translate(540, 590)">
|
||||
<circle class="logo-fill" cx="0" cy="0" r="51"></circle>
|
||||
<circle class="logo-border" cx="0" cy="0" r="51" fill="none" stroke-width="6"></circle>
|
||||
</g>
|
||||
<g transform="translate(540, 744)">
|
||||
<circle class="logo-fill" cx="0" cy="0" r="51"></circle>
|
||||
<circle class="logo-border" cx="0" cy="0" r="51" fill="none" stroke-width="6"></circle>
|
||||
</g>
|
||||
<g transform="translate(785, 512)">
|
||||
<circle class="logo-fill" cx="0" cy="0" r="51"></circle>
|
||||
<circle class="logo-border" cx="0" cy="0" r="51" fill="none" stroke-width="6"></circle>
|
||||
</g>
|
||||
</svg>
|
||||
<svg id="logo-spinner" class="center logo-spinner" viewbox="0 0 1024 1024">
|
||||
<g transform="translate(512, 512)" style="opacity: 1">
|
||||
<path class="logo-spinner-stroke" d="M-431,0 A-431,-431 0 0,1 0,-431" stroke-width="24" fill="None"></path>
|
||||
</g>
|
||||
</svg>
|
||||
</a>
|
||||
<a href="https://www.lutzroeder.com" target="blank_">
|
||||
<svg class="center logo-name" viewbox="0 0 5120 300">
|
||||
<g transform="scale(5.8) translate(20, 0)">
|
||||
<g transform="matrix(30,0,0,30,18.9123,38)">
|
||||
<path class="logo-glyph" d="M0.089,-0L0.089,-0.715L0.154,-0.715L0.154,-0.061L0.399,-0.061L0.399,-0L0.089,-0Z" style="fill-rule:nonzero;"/>
|
||||
</g>
|
||||
<g transform="matrix(30,0,0,30,46.7613,38)">
|
||||
<path class="logo-glyph" d="M0.086,-0.715L0.15,-0.715L0.15,-0.248C0.15,-0.177 0.166,-0.125 0.198,-0.091C0.23,-0.056 0.28,-0.039 0.346,-0.039C0.412,-0.039 0.46,-0.056 0.493,-0.091C0.525,-0.125 0.541,-0.177 0.541,-0.248L0.541,-0.715L0.606,-0.715L0.606,-0.269C0.606,-0.172 0.584,-0.1 0.542,-0.052C0.499,-0.005 0.433,0.019 0.346,0.019C0.259,0.019 0.193,-0.005 0.15,-0.052C0.107,-0.1 0.086,-0.172 0.086,-0.269L0.086,-0.715Z" style="fill-rule:nonzero;"/>
|
||||
</g>
|
||||
<g transform="matrix(30,0,0,30,83.5133,38)">
|
||||
<path class="logo-glyph" d="M0.216,-0L0.216,-0.654L0.019,-0.654L0.019,-0.715L0.478,-0.715L0.478,-0.654L0.281,-0.654L0.281,-0L0.216,-0Z" style="fill-rule:nonzero;"/>
|
||||
</g>
|
||||
<g transform="matrix(30,0,0,30,114.421,38)">
|
||||
<path class="logo-glyph" d="M0.012,-0L0.437,-0.656L0.074,-0.656L0.074,-0.715L0.548,-0.715L0.125,-0.06L0.505,-0.06L0.505,-0L0.012,-0Z" style="fill-rule:nonzero;"/>
|
||||
</g>
|
||||
<g transform="matrix(30,0,0,30,171.777,38)">
|
||||
<path class="logo-glyph" d="M0.154,-0.658L0.154,-0.394L0.219,-0.394C0.28,-0.394 0.322,-0.404 0.346,-0.423C0.37,-0.442 0.382,-0.475 0.382,-0.522C0.382,-0.571 0.369,-0.606 0.345,-0.627C0.32,-0.648 0.278,-0.658 0.219,-0.658L0.154,-0.658ZM0.523,-0L0.444,-0L0.193,-0.341L0.154,-0.341L0.154,-0L0.089,-0L0.089,-0.715L0.22,-0.715C0.298,-0.715 0.356,-0.699 0.394,-0.667C0.433,-0.634 0.452,-0.585 0.452,-0.52C0.452,-0.464 0.436,-0.421 0.403,-0.389C0.37,-0.357 0.324,-0.341 0.266,-0.341L0.523,-0Z" style="fill-rule:nonzero;"/>
|
||||
</g>
|
||||
<g transform="matrix(30,0,0,30,203.607,38)">
|
||||
<path class="logo-glyph" d="M0.437,-0.039C0.479,-0.039 0.519,-0.047 0.557,-0.063C0.595,-0.078 0.629,-0.101 0.659,-0.131C0.689,-0.161 0.712,-0.196 0.727,-0.234C0.743,-0.273 0.751,-0.313 0.751,-0.356C0.751,-0.399 0.743,-0.44 0.728,-0.478C0.712,-0.516 0.689,-0.55 0.659,-0.581C0.63,-0.611 0.596,-0.634 0.558,-0.649C0.52,-0.665 0.48,-0.673 0.437,-0.673C0.395,-0.673 0.355,-0.665 0.317,-0.649C0.28,-0.634 0.246,-0.611 0.216,-0.581C0.186,-0.55 0.163,-0.516 0.147,-0.478C0.132,-0.44 0.124,-0.399 0.124,-0.356C0.124,-0.313 0.132,-0.272 0.147,-0.234C0.163,-0.196 0.186,-0.161 0.216,-0.131C0.246,-0.101 0.279,-0.078 0.316,-0.062C0.354,-0.047 0.394,-0.039 0.437,-0.039ZM0.82,-0.356C0.82,-0.306 0.81,-0.258 0.791,-0.212C0.772,-0.167 0.744,-0.126 0.708,-0.091C0.671,-0.055 0.63,-0.028 0.583,-0.009C0.537,0.01 0.488,0.019 0.437,0.019C0.386,0.019 0.337,0.01 0.291,-0.009C0.245,-0.028 0.203,-0.055 0.167,-0.091C0.131,-0.127 0.103,-0.168 0.084,-0.213C0.065,-0.258 0.055,-0.306 0.055,-0.356C0.055,-0.407 0.065,-0.455 0.084,-0.501C0.103,-0.546 0.131,-0.587 0.167,-0.623C0.203,-0.659 0.244,-0.685 0.29,-0.704C0.335,-0.722 0.385,-0.731 0.437,-0.731C0.49,-0.731 0.539,-0.722 0.585,-0.703C0.631,-0.685 0.672,-0.658 0.708,-0.623C0.744,-0.587 0.772,-0.546 0.791,-0.501C0.81,-0.455 0.82,-0.407 0.82,-0.356Z" style="fill-rule:nonzero;"/>
|
||||
</g>
|
||||
<g transform="matrix(30,0,0,30,245.853,38)">
|
||||
<path class="logo-glyph" d="M0.089,-0L0.089,-0.715L0.443,-0.715L0.443,-0.654L0.154,-0.654L0.154,-0.43L0.443,-0.43L0.443,-0.369L0.154,-0.369L0.154,-0.061L0.443,-0.061L0.443,-0L0.089,-0Z" style="fill-rule:nonzero;"/>
|
||||
</g>
|
||||
<g transform="matrix(30,0,0,30,277.243,38)">
|
||||
<path class="logo-glyph" d="M0.154,-0.056L0.245,-0.056C0.319,-0.056 0.371,-0.06 0.402,-0.069C0.433,-0.077 0.459,-0.091 0.481,-0.111C0.511,-0.139 0.534,-0.174 0.549,-0.215C0.564,-0.257 0.572,-0.305 0.572,-0.358C0.572,-0.413 0.564,-0.461 0.549,-0.502C0.533,-0.544 0.51,-0.578 0.48,-0.605C0.457,-0.625 0.429,-0.64 0.396,-0.648C0.364,-0.657 0.306,-0.661 0.224,-0.661L0.154,-0.661L0.154,-0.056ZM0.089,-0L0.089,-0.715L0.2,-0.715C0.299,-0.715 0.37,-0.71 0.412,-0.7C0.453,-0.69 0.489,-0.674 0.519,-0.65C0.559,-0.618 0.589,-0.578 0.61,-0.528C0.631,-0.478 0.641,-0.421 0.641,-0.357C0.641,-0.293 0.631,-0.236 0.61,-0.186C0.589,-0.136 0.559,-0.096 0.52,-0.066C0.489,-0.042 0.454,-0.025 0.414,-0.015C0.374,-0.005 0.31,-0 0.222,-0L0.089,-0Z" style="fill-rule:nonzero;"/>
|
||||
</g>
|
||||
<g transform="matrix(30,0,0,30,314.142,38)">
|
||||
<path class="logo-glyph" d="M0.089,-0L0.089,-0.715L0.443,-0.715L0.443,-0.654L0.154,-0.654L0.154,-0.43L0.443,-0.43L0.443,-0.369L0.154,-0.369L0.154,-0.061L0.443,-0.061L0.443,-0L0.089,-0Z" style="fill-rule:nonzero;"/>
|
||||
</g>
|
||||
<g transform="matrix(30,0,0,30,345.532,38)">
|
||||
<path class="logo-glyph" d="M0.154,-0.658L0.154,-0.394L0.219,-0.394C0.28,-0.394 0.322,-0.404 0.346,-0.423C0.37,-0.442 0.382,-0.475 0.382,-0.522C0.382,-0.571 0.369,-0.606 0.345,-0.627C0.32,-0.648 0.278,-0.658 0.219,-0.658L0.154,-0.658ZM0.523,-0L0.444,-0L0.193,-0.341L0.154,-0.341L0.154,-0L0.089,-0L0.089,-0.715L0.22,-0.715C0.298,-0.715 0.356,-0.699 0.394,-0.667C0.433,-0.634 0.452,-0.585 0.452,-0.52C0.452,-0.464 0.436,-0.421 0.403,-0.389C0.37,-0.357 0.324,-0.341 0.266,-0.341L0.523,-0Z" style="fill-rule:nonzero;"/>
|
||||
</g>
|
||||
<g transform="matrix(30,0,0,30,376.911,38)">
|
||||
<path class="logo-glyph" d="M0.06,-0.468L0.155,-0.731L0.228,-0.699L0.1,-0.452L0.06,-0.468Z" style="fill-rule:nonzero;"/>
|
||||
</g>
|
||||
<g transform="matrix(30,0,0,30,401.549,38)">
|
||||
<path class="logo-glyph" d="M0.034,-0.12L0.09,-0.15C0.1,-0.115 0.118,-0.087 0.144,-0.068C0.169,-0.049 0.2,-0.039 0.236,-0.039C0.281,-0.039 0.316,-0.052 0.342,-0.079C0.367,-0.106 0.38,-0.143 0.38,-0.19C0.38,-0.224 0.371,-0.253 0.354,-0.276C0.337,-0.299 0.3,-0.325 0.244,-0.355C0.172,-0.393 0.124,-0.427 0.101,-0.456C0.077,-0.485 0.065,-0.519 0.065,-0.56C0.065,-0.611 0.082,-0.652 0.116,-0.684C0.151,-0.716 0.195,-0.732 0.25,-0.732C0.286,-0.732 0.317,-0.724 0.344,-0.709C0.37,-0.694 0.392,-0.671 0.408,-0.641L0.358,-0.611C0.347,-0.631 0.333,-0.647 0.314,-0.658C0.295,-0.668 0.272,-0.674 0.246,-0.674C0.211,-0.674 0.183,-0.663 0.162,-0.643C0.141,-0.622 0.131,-0.594 0.131,-0.559C0.131,-0.509 0.172,-0.462 0.255,-0.419C0.27,-0.411 0.281,-0.405 0.289,-0.401C0.35,-0.367 0.391,-0.336 0.411,-0.306C0.432,-0.276 0.442,-0.237 0.442,-0.19C0.442,-0.126 0.423,-0.075 0.386,-0.037C0.348,0 0.297,0.019 0.233,0.019C0.186,0.019 0.146,0.007 0.113,-0.016C0.079,-0.039 0.053,-0.074 0.034,-0.12Z" style="fill-rule:nonzero;"/>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
</a>
|
||||
<div class="center logo-message">
|
||||
<div style="height: 30px; text-align: center;">Version <span id="version" class="select">{version}</span></div>
|
||||
<div style="height: 30px; text-align: center;">Copyright © <a href="https://www.lutzroeder.com" target="blank_">Lutz Roeder</a></div>
|
||||
</div>
|
||||
<a id="logo-github" class="center logo-github" href="https://github.com/lutzroeder/netron" target="blank_">
|
||||
<svg viewbox="0 0 438.549 438.549">
|
||||
<path class="logo-fill" d="M409.132,114.573c-19.608-33.596-46.205-60.194-79.798-79.8C295.736,15.166,259.057,5.365,219.271,5.365
|
||||
c-39.781,0-76.472,9.804-110.063,29.408c-33.596,19.605-60.192,46.204-79.8,79.8C9.803,148.168,0,184.854,0,224.63
|
||||
c0,47.78,13.94,90.745,41.827,128.906c27.884,38.164,63.906,64.572,108.063,79.227c5.14,0.954,8.945,0.283,11.419-1.996
|
||||
c2.475-2.282,3.711-5.14,3.711-8.562c0-0.571-0.049-5.708-0.144-15.417c-0.098-9.709-0.144-18.179-0.144-25.406l-6.567,1.136
|
||||
c-4.187,0.767-9.469,1.092-15.846,1c-6.374-0.089-12.991-0.757-19.842-1.999c-6.854-1.231-13.229-4.086-19.13-8.559
|
||||
c-5.898-4.473-10.085-10.328-12.56-17.556l-2.855-6.57c-1.903-4.374-4.899-9.233-8.992-14.559
|
||||
c-4.093-5.331-8.232-8.945-12.419-10.848l-1.999-1.431c-1.332-0.951-2.568-2.098-3.711-3.429c-1.142-1.331-1.997-2.663-2.568-3.997
|
||||
c-0.572-1.335-0.098-2.43,1.427-3.289c1.525-0.859,4.281-1.276,8.28-1.276l5.708,0.853c3.807,0.763,8.516,3.042,14.133,6.851
|
||||
c5.614,3.806,10.229,8.754,13.846,14.842c4.38,7.806,9.657,13.754,15.846,17.847c6.184,4.093,12.419,6.136,18.699,6.136
|
||||
c6.28,0,11.704-0.476,16.274-1.423c4.565-0.952,8.848-2.383,12.847-4.285c1.713-12.758,6.377-22.559,13.988-29.41
|
||||
c-10.848-1.14-20.601-2.857-29.264-5.14c-8.658-2.286-17.605-5.996-26.835-11.14c-9.235-5.137-16.896-11.516-22.985-19.126
|
||||
c-6.09-7.614-11.088-17.61-14.987-29.979c-3.901-12.374-5.852-26.648-5.852-42.826c0-23.035,7.52-42.637,22.557-58.817
|
||||
c-7.044-17.318-6.379-36.732,1.997-58.24c5.52-1.715,13.706-0.428,24.554,3.853c10.85,4.283,18.794,7.952,23.84,10.994
|
||||
c5.046,3.041,9.089,5.618,12.135,7.708c17.705-4.947,35.976-7.421,54.818-7.421s37.117,2.474,54.823,7.421l10.849-6.849
|
||||
c7.419-4.57,16.18-8.758,26.262-12.565c10.088-3.805,17.802-4.853,23.134-3.138c8.562,21.509,9.325,40.922,2.279,58.24
|
||||
c15.036,16.18,22.559,35.787,22.559,58.817c0,16.178-1.958,30.497-5.853,42.966c-3.9,12.471-8.941,22.457-15.125,29.979
|
||||
c-6.191,7.521-13.901,13.85-23.131,18.986c-9.232,5.14-18.182,8.85-26.84,11.136c-8.662,2.286-18.415,4.004-29.263,5.146
|
||||
c9.894,8.562,14.842,22.077,14.842,40.539v60.237c0,3.422,1.19,6.279,3.572,8.562c2.379,2.279,6.136,2.95,11.276,1.995
|
||||
c44.163-14.653,80.185-41.062,108.068-79.226c27.88-38.161,41.825-81.126,41.825-128.906
|
||||
C438.536,184.851,428.728,148.168,409.132,114.573z"/>
|
||||
</svg>
|
||||
</a>
|
||||
<span class="center consent-message">This app uses cookies to report errors and anonymous usage information.</span>
|
||||
<button id="consent-accept-button" class="center consent-accept-button">Accept</button>
|
||||
<button id="open-file-button" class="center open-file-button">Open Model…</button>
|
||||
<button id="github-button" class="center github-button">Download</button>
|
||||
<input type="file" id="open-file-dialog" class="open-file-dialog" multiple="false" accept=".onnx, .ort, .pb, .meta, .tflite, .lite, .tfl, .keras, .h5, .hd5, .hdf5, .json, .model, .mar, .params, .param, .armnn, .mnn, .ncnn, .tnnproto, .tmfile, .ms, .om, .nn, .uff, .rknn, .xmodel, .kmodel, .paddle, .pdmodel, .pdparams, .nb, .dnn, .cmf, .mlmodel, .mlpackage, .caffemodel, .pbtxt, .prototxt, .pkl, .pt, .pth, .ptl, .t7, .joblib, .cfg, .xml, .zip, .tar">
|
||||
<!-- Preload fonts to workaround Chrome SVG layout issue -->
|
||||
<div style="font-weight: normal; color: rgba(0, 0, 0, 0.01); user-select: none;">.</div>
|
||||
<div style="font-weight: bold; color: rgba(0, 0, 0, 0.01); user-select: none;">.</div>
|
||||
<div style="font-weight: bold; color: rgba(0, 0, 0, 0.01); user-select: none;">.</div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
@ -0,0 +1,566 @@
|
||||
|
||||
var json = json || {};
|
||||
var text = text || require('./text');
|
||||
|
||||
json.TextReader = class {
|
||||
|
||||
static open(data) {
|
||||
const decoder = text.Decoder.open(data);
|
||||
let state = 'start';
|
||||
for (let i = 0; i < 0x1000; i++) {
|
||||
const c = decoder.decode();
|
||||
if (c === undefined || c === '\0') {
|
||||
if (i === 0) {
|
||||
return null;
|
||||
}
|
||||
break;
|
||||
}
|
||||
if (c <= ' ') {
|
||||
if (c !== ' ' && c !== '\n' && c !== '\r' && c !== '\t') {
|
||||
return null;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
switch (state) {
|
||||
case 'start':
|
||||
if (c === '#') {
|
||||
state = 'comment';
|
||||
break;
|
||||
}
|
||||
if (c === '[') {
|
||||
state = 'list';
|
||||
break;
|
||||
}
|
||||
if (c === '{') {
|
||||
state = 'object';
|
||||
break;
|
||||
}
|
||||
if (c >= 'a' && c <= 'z' || c >= 'A' && c <= 'Z') {
|
||||
state = '';
|
||||
break;
|
||||
}
|
||||
return null;
|
||||
case 'list':
|
||||
if (c === '"' || c === '-' || c === '+' || c === '{' || c === '[' || (c >= '0' && c <= '9')) {
|
||||
state = '';
|
||||
break;
|
||||
}
|
||||
return null;
|
||||
case 'object':
|
||||
if (c != '"') {
|
||||
return null;
|
||||
}
|
||||
state = '';
|
||||
continue;
|
||||
}
|
||||
}
|
||||
return new json.TextReader(data);
|
||||
}
|
||||
|
||||
constructor(data) {
|
||||
this._data = data;
|
||||
this._escape = { '"': '"', '\\': '\\', '/': '/', b: '\b', f: '\f', n: '\n', r: '\r', t: '\t' };
|
||||
}
|
||||
|
||||
read() {
|
||||
const decoder = text.Decoder.open(this._data);
|
||||
const stack = [];
|
||||
this._decoder = decoder;
|
||||
this._position = 0;
|
||||
this._char = decoder.decode();
|
||||
this._whitespace();
|
||||
let obj = undefined;
|
||||
let first = true;
|
||||
for (;;) {
|
||||
if (Array.isArray(obj)) {
|
||||
this._whitespace();
|
||||
let c = this._char;
|
||||
if (c === ']') {
|
||||
this._next();
|
||||
this._whitespace();
|
||||
if (stack.length > 0) {
|
||||
obj = stack.pop();
|
||||
first = false;
|
||||
continue;
|
||||
}
|
||||
if (this._char !== undefined) {
|
||||
this._unexpected();
|
||||
}
|
||||
return obj;
|
||||
}
|
||||
if (!first) {
|
||||
if (this._char !== ',') {
|
||||
this._unexpected();
|
||||
}
|
||||
this._next();
|
||||
this._whitespace();
|
||||
c = this._char;
|
||||
}
|
||||
first = false;
|
||||
switch (c) {
|
||||
case '{': {
|
||||
this._next();
|
||||
stack.push(obj);
|
||||
const item = {};
|
||||
obj.push(item);
|
||||
obj = item;
|
||||
first = true;
|
||||
break;
|
||||
}
|
||||
case '[': {
|
||||
this._next();
|
||||
stack.push(obj);
|
||||
const item = [];
|
||||
obj.push(item);
|
||||
obj = item;
|
||||
first = true;
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
obj.push(c === '"' ? this._string() : this._literal());
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (obj instanceof Object) {
|
||||
this._whitespace();
|
||||
let c = this._char;
|
||||
if (c === '}') {
|
||||
this._next();
|
||||
this._whitespace();
|
||||
if (stack.length > 0) {
|
||||
obj = stack.pop();
|
||||
first = false;
|
||||
continue;
|
||||
}
|
||||
if (this._char !== undefined) {
|
||||
this._unexpected();
|
||||
}
|
||||
return obj;
|
||||
}
|
||||
if (!first) {
|
||||
if (this._char !== ',') {
|
||||
this._unexpected();
|
||||
}
|
||||
this._next();
|
||||
this._whitespace();
|
||||
c = this._char;
|
||||
}
|
||||
first = false;
|
||||
if (c === '"') {
|
||||
const key = this._string();
|
||||
switch (key) {
|
||||
case '__proto__':
|
||||
case 'constructor':
|
||||
case 'prototype':
|
||||
throw new json.Error("Invalid key '" + key + "'" + this._location());
|
||||
}
|
||||
this._whitespace();
|
||||
if (this._char !== ':') {
|
||||
this._unexpected();
|
||||
}
|
||||
this._next();
|
||||
this._whitespace();
|
||||
c = this._char;
|
||||
switch (c) {
|
||||
case '{': {
|
||||
this._next();
|
||||
stack.push(obj);
|
||||
const value = {};
|
||||
obj[key] = value;
|
||||
obj = value;
|
||||
first = true;
|
||||
break;
|
||||
}
|
||||
case '[': {
|
||||
this._next();
|
||||
stack.push(obj);
|
||||
const value = [];
|
||||
obj[key] = value;
|
||||
obj = value;
|
||||
first = true;
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
obj[key] = c === '"' ? this._string() : this._literal();
|
||||
break;
|
||||
}
|
||||
}
|
||||
this._whitespace();
|
||||
continue;
|
||||
}
|
||||
this._unexpected();
|
||||
}
|
||||
else {
|
||||
const c = this._char;
|
||||
switch (c) {
|
||||
case '{': {
|
||||
this._next();
|
||||
this._whitespace();
|
||||
obj = {};
|
||||
first = true;
|
||||
break;
|
||||
}
|
||||
case '[': {
|
||||
this._next();
|
||||
this._whitespace();
|
||||
obj = [];
|
||||
first = true;
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
const value = c === '"' ? this._string() : c >= '0' && c <= '9' ? this._number() : this._literal();
|
||||
this._whitespace();
|
||||
if (this._char !== undefined) {
|
||||
this._unexpected();
|
||||
}
|
||||
return value;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
_next() {
|
||||
if (this._char === undefined) {
|
||||
this._unexpected();
|
||||
}
|
||||
this._position = this._decoder.position;
|
||||
this._char = this._decoder.decode();
|
||||
}
|
||||
|
||||
_whitespace() {
|
||||
while (this._char === ' ' || this._char === '\n' || this._char === '\r' || this._char === '\t') {
|
||||
this._next();
|
||||
}
|
||||
}
|
||||
|
||||
_literal() {
|
||||
const c = this._char;
|
||||
if (c >= '0' && c <= '9') {
|
||||
return this._number();
|
||||
}
|
||||
switch (c) {
|
||||
case 't': this._expect('true'); return true;
|
||||
case 'f': this._expect('false'); return false;
|
||||
case 'n': this._expect('null'); return null;
|
||||
case 'N': this._expect('NaN'); return NaN;
|
||||
case 'I': this._expect('Infinity'); return Infinity;
|
||||
case '-': return this._number();
|
||||
}
|
||||
this._unexpected();
|
||||
}
|
||||
|
||||
_number() {
|
||||
let value = '';
|
||||
if (this._char === '-') {
|
||||
value = '-';
|
||||
this._next();
|
||||
}
|
||||
if (this._char === 'I') {
|
||||
this._expect('Infinity');
|
||||
return -Infinity;
|
||||
}
|
||||
const c = this._char;
|
||||
if (c < '0' || c > '9') {
|
||||
this._unexpected();
|
||||
}
|
||||
value += c;
|
||||
this._next();
|
||||
if (c === '0') {
|
||||
const n = this._char;
|
||||
if (n >= '0' && n <= '9') {
|
||||
this._unexpected();
|
||||
}
|
||||
}
|
||||
while (this._char >= '0' && this._char <= '9') {
|
||||
value += this._char;
|
||||
this._next();
|
||||
}
|
||||
if (this._char === '.') {
|
||||
value += '.';
|
||||
this._next();
|
||||
const n = this._char;
|
||||
if (n < '0' || n > '9') {
|
||||
this._unexpected();
|
||||
}
|
||||
while (this._char >= '0' && this._char <= '9') {
|
||||
value += this._char;
|
||||
this._next();
|
||||
}
|
||||
}
|
||||
if (this._char === 'e' || this._char === 'E') {
|
||||
value += this._char;
|
||||
this._next();
|
||||
const s = this._char;
|
||||
if (s === '-' || s === '+') {
|
||||
value += this._char;
|
||||
this._next();
|
||||
}
|
||||
const c = this._char;
|
||||
if (c < '0' || c > '9') {
|
||||
this._unexpected();
|
||||
}
|
||||
value += this._char;
|
||||
this._next();
|
||||
while (this._char >= '0' && this._char <= '9') {
|
||||
value += this._char;
|
||||
this._next();
|
||||
}
|
||||
}
|
||||
return +value;
|
||||
}
|
||||
|
||||
_string() {
|
||||
let value = '';
|
||||
this._next();
|
||||
while (this._char != '"') {
|
||||
if (this._char === '\\') {
|
||||
this._next();
|
||||
if (this._char === 'u') {
|
||||
this._next();
|
||||
let uffff = 0;
|
||||
for (let i = 0; i < 4; i ++) {
|
||||
const hex = parseInt(this._char, 16);
|
||||
if (!isFinite(hex)) {
|
||||
this._unexpected();
|
||||
}
|
||||
this._next();
|
||||
uffff = uffff * 16 + hex;
|
||||
}
|
||||
value += String.fromCharCode(uffff);
|
||||
}
|
||||
else if (this._escape[this._char]) {
|
||||
value += this._escape[this._char];
|
||||
this._next();
|
||||
}
|
||||
else {
|
||||
this._unexpected();
|
||||
}
|
||||
}
|
||||
else if (this._char < ' ') {
|
||||
this._unexpected();
|
||||
}
|
||||
else {
|
||||
value += this._char;
|
||||
this._next();
|
||||
}
|
||||
}
|
||||
this._next();
|
||||
return value;
|
||||
}
|
||||
|
||||
_expect(value) {
|
||||
for (let i = 0; i < value.length; i++) {
|
||||
if (value[i] !== this._char) {
|
||||
this._unexpected();
|
||||
}
|
||||
this._next();
|
||||
}
|
||||
}
|
||||
|
||||
_unexpected() {
|
||||
let c = this._char;
|
||||
if (c === undefined) {
|
||||
throw new json.Error('Unexpected end of JSON input.');
|
||||
}
|
||||
else if (c === '"') {
|
||||
c = 'string';
|
||||
}
|
||||
else if ((c >= '0' && c <= '9') || c === '-') {
|
||||
c = 'number';
|
||||
}
|
||||
else {
|
||||
if (c < ' ' || c > '\x7F') {
|
||||
const name = Object.keys(this._escape).filter((key) => this._escape[key] === c);
|
||||
c = (name.length === 1) ? '\\' + name : '\\u' + ('000' + c.charCodeAt(0).toString(16)).slice(-4);
|
||||
}
|
||||
c = "token '" + c + "'";
|
||||
}
|
||||
throw new json.Error('Unexpected ' + c + this._location());
|
||||
}
|
||||
|
||||
_location() {
|
||||
let line = 1;
|
||||
let column = 1;
|
||||
this._decoder.position = 0;
|
||||
let c;
|
||||
do {
|
||||
if (this._decoder.position === this._position) {
|
||||
return ' at ' + line.toString() + ':' + column.toString() + '.';
|
||||
}
|
||||
c = this._decoder.decode();
|
||||
if (c === '\n') {
|
||||
line++;
|
||||
column = 1;
|
||||
}
|
||||
else {
|
||||
column++;
|
||||
}
|
||||
}
|
||||
while (c !== undefined);
|
||||
return ' at ' + line.toString() + ':' + column.toString() + '.';
|
||||
}
|
||||
};
|
||||
|
||||
json.BinaryReader = class {
|
||||
|
||||
static open(data) {
|
||||
const buffer = data instanceof Uint8Array ? data : data.peek();
|
||||
return new json.BinaryReader(buffer);
|
||||
}
|
||||
|
||||
constructor(buffer) {
|
||||
this._buffer = buffer;
|
||||
}
|
||||
|
||||
read() {
|
||||
const buffer = this._buffer;
|
||||
const length = buffer.length;
|
||||
const view = new DataView(buffer.buffer, buffer.byteOffset, buffer.byteLength);
|
||||
const asciiDecoder = new TextDecoder('ascii');
|
||||
const utf8Decoder = new TextDecoder('utf-8');
|
||||
let position = 0;
|
||||
const skip = (offset) => {
|
||||
position += offset;
|
||||
if (position > length) {
|
||||
throw new json.Error('Expected ' + (position + length) + ' more bytes. The file might be corrupted. Unexpected end of file.', true);
|
||||
}
|
||||
};
|
||||
const header = () => {
|
||||
const start = position;
|
||||
skip(4);
|
||||
const size = view.getInt32(start, 4);
|
||||
if (size < 5 || start + size > length || buffer[start + size - 1] != 0x00) {
|
||||
throw new json.Error('Invalid file size.', true);
|
||||
}
|
||||
};
|
||||
header();
|
||||
const stack = [];
|
||||
let obj = {};
|
||||
for (;;) {
|
||||
skip(1);
|
||||
const type = buffer[position - 1];
|
||||
if (type == 0x00) {
|
||||
if (stack.length === 0) {
|
||||
break;
|
||||
}
|
||||
obj = stack.pop();
|
||||
continue;
|
||||
}
|
||||
const start = position;
|
||||
position = buffer.indexOf(0x00, start) + 1;
|
||||
const key = asciiDecoder.decode(buffer.subarray(start, position - 1));
|
||||
let value = null;
|
||||
switch (type) {
|
||||
case 0x01: { // float64
|
||||
const start = position;
|
||||
skip(8);
|
||||
value = view.getFloat64(start, true);
|
||||
break;
|
||||
}
|
||||
case 0x02: { // string
|
||||
skip(4);
|
||||
const size = view.getInt32(position - 4, true);
|
||||
const start = position;
|
||||
skip(size);
|
||||
value = utf8Decoder.decode(buffer.subarray(start, position - 1));
|
||||
if (buffer[position - 1] != '0x00') {
|
||||
throw new json.Error('String missing terminal 0.', true);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 0x03: { // object
|
||||
header();
|
||||
value = {};
|
||||
break;
|
||||
}
|
||||
case 0x04: { // array
|
||||
header();
|
||||
value = [];
|
||||
break;
|
||||
}
|
||||
case 0x05: { // bytes
|
||||
const start = position;
|
||||
skip(5);
|
||||
const size = view.getInt32(start, true);
|
||||
const subtype = buffer[start + 4];
|
||||
if (subtype !== 0x00) {
|
||||
throw new json.Error("Unknown binary subtype '" + subtype + "'.", true);
|
||||
}
|
||||
skip(size);
|
||||
value = buffer.subarray(start + 5, position);
|
||||
break;
|
||||
}
|
||||
case 0x08: { // boolean
|
||||
skip(1);
|
||||
value = buffer[position - 1];
|
||||
if (value > 1) {
|
||||
throw new json.Error("Invalid boolean value '" + value + "'.", true);
|
||||
}
|
||||
value = value === 1 ? true : false;
|
||||
break;
|
||||
}
|
||||
case 0x0A:
|
||||
value = null;
|
||||
break;
|
||||
case 0x10: {
|
||||
const start = position;
|
||||
skip(4);
|
||||
value = view.getInt32(start, true);
|
||||
break;
|
||||
}
|
||||
case 0x11: { // uint64
|
||||
const start = position;
|
||||
skip(8);
|
||||
value = view.getUint64(start, true).toNumber();
|
||||
break;
|
||||
}
|
||||
case 0x12: { // int64
|
||||
const start = position;
|
||||
skip(8);
|
||||
value = view.getInt64(start, true).toNumber();
|
||||
break;
|
||||
}
|
||||
default:
|
||||
throw new json.Error("Unknown value type '" + type + "'.", true);
|
||||
}
|
||||
if (Array.isArray(obj)) {
|
||||
if (obj.length !== parseInt(key, 10)) {
|
||||
throw new json.Error("Invalid array index '" + key + "'.", true);
|
||||
}
|
||||
obj.push(value);
|
||||
}
|
||||
else {
|
||||
switch (key) {
|
||||
case '__proto__':
|
||||
case 'constructor':
|
||||
case 'prototype':
|
||||
throw new json.Error("Invalid key '" + key + "' at " + position.toString() + "'.", true);
|
||||
}
|
||||
obj[key] = value;
|
||||
}
|
||||
if (type === 0x03 || type === 0x04) {
|
||||
stack.push(obj);
|
||||
obj = value;
|
||||
}
|
||||
}
|
||||
if (position !== length) {
|
||||
throw new json.Error("Unexpected data at '" + position.toString() + "'.", true);
|
||||
}
|
||||
return obj;
|
||||
}
|
||||
};
|
||||
|
||||
json.Error = class extends Error {
|
||||
|
||||
constructor(message, binary) {
|
||||
super(message);
|
||||
this.name = binary ? 'BSON Error' : 'JSON Error';
|
||||
}
|
||||
};
|
||||
|
||||
if (typeof module !== 'undefined' && typeof module.exports === 'object') {
|
||||
module.exports.TextReader = json.TextReader;
|
||||
module.exports.BinaryReader = json.BinaryReader;
|
||||
}
|
||||
@ -0,0 +1,567 @@
|
||||
|
||||
// Experimental
|
||||
|
||||
var numpy = numpy || {};
|
||||
var python = python || require('./python');
|
||||
|
||||
numpy.ModelFactory = class {
|
||||
|
||||
match(context) {
|
||||
const stream = context.stream;
|
||||
const signature = [ 0x93, 0x4E, 0x55, 0x4D, 0x50, 0x59 ];
|
||||
if (signature.length <= stream.length && stream.peek(signature.length).every((value, index) => value === signature[index])) {
|
||||
return { name: 'npy' };
|
||||
}
|
||||
const entries = context.entries('zip');
|
||||
if (entries.size > 0 && Array.from(entries.keys()).every((name) => name.endsWith('.npy'))) {
|
||||
return { name: 'npz', value: entries };
|
||||
}
|
||||
const obj = context.open('pkl');
|
||||
if (obj) {
|
||||
if (numpy.Utility.isTensor(obj)) {
|
||||
return { name: 'numpy.ndarray', value: obj };
|
||||
}
|
||||
if (Array.isArray(obj) && obj.every((obj) => obj && obj.__class__ && obj.__class__.__name__ === 'Network' && (obj.__class__.__module__ === 'dnnlib.tflib.network' || obj.__class__.__module__ === 'tfutil'))) {
|
||||
return { name: 'dnnlib.tflib.network', value: obj };
|
||||
}
|
||||
const weights = numpy.Utility.weights(obj);
|
||||
if (weights) {
|
||||
return { name: 'pickle', value: weights };
|
||||
}
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
|
||||
open(context, match) {
|
||||
let format = '';
|
||||
const graphs = [];
|
||||
switch (match.name) {
|
||||
case 'npy': {
|
||||
format = 'NumPy Array';
|
||||
const execution = new python.Execution(null);
|
||||
const stream = context.stream;
|
||||
const buffer = stream.peek();
|
||||
const bytes = execution.invoke('io.BytesIO', [ buffer ]);
|
||||
const array = execution.invoke('numpy.load', [ bytes ]);
|
||||
const layer = { type: 'numpy.ndarray', parameters: [ { name: 'value', tensor: { name: '', array: array } } ] };
|
||||
graphs.push({ layers: [ layer ] });
|
||||
break;
|
||||
}
|
||||
case 'npz': {
|
||||
format = 'NumPy Zip';
|
||||
const layers = new Map();
|
||||
const execution = new python.Execution(null);
|
||||
for (const entry of match.value) {
|
||||
if (!entry[0].endsWith('.npy')) {
|
||||
throw new numpy.Error("Invalid file name '" + entry.name + "'.");
|
||||
}
|
||||
const name = entry[0].replace(/\.npy$/, '');
|
||||
const parts = name.split('/');
|
||||
const parameterName = parts.pop();
|
||||
const groupName = parts.join('/');
|
||||
if (!layers.has(groupName)) {
|
||||
layers.set(groupName, { name: groupName, parameters: [] });
|
||||
}
|
||||
const layer = layers.get(groupName);
|
||||
const stream = entry[1];
|
||||
const buffer = stream.peek();
|
||||
const bytes = execution.invoke('io.BytesIO', [ buffer ]);
|
||||
let array = execution.invoke('numpy.load', [ bytes ]);
|
||||
if (array.dtype.byteorder === '|' && array.dtype.itemsize !== 1) {
|
||||
if (array.dtype.kind !== 'O') {
|
||||
throw new numpy.Error("Invalid data type '" + array.dataType + "'.");
|
||||
}
|
||||
const unpickler = python.Unpickler.open(array.data);
|
||||
array = unpickler.load((name, args) => execution.invoke(name, args));
|
||||
}
|
||||
layer.parameters.push({
|
||||
name: parameterName,
|
||||
tensor: { name: name, array: array }
|
||||
});
|
||||
}
|
||||
graphs.push({ layers: Array.from(layers.values()) });
|
||||
break;
|
||||
}
|
||||
case 'pickle': {
|
||||
format = 'NumPy Weights';
|
||||
const layers = new Map();
|
||||
const weights = match.value;
|
||||
let separator = '.';
|
||||
if (Array.from(weights.keys()).filter((key) => key.indexOf('_') !== -1) &&
|
||||
Array.from(weights.keys()).every((key) => key.indexOf('_') > key.indexOf('.'))) {
|
||||
separator = '_';
|
||||
}
|
||||
for (const pair of weights) {
|
||||
const name = pair[0];
|
||||
const array = pair[1];
|
||||
const parts = name.split(separator);
|
||||
const parameterName = parts.length > 1 ? parts.pop() : '?';
|
||||
const layerName = parts.join(separator);
|
||||
if (!layers.has(layerName)) {
|
||||
layers.set(layerName, { name: layerName, parameters: [] });
|
||||
}
|
||||
const layer = layers.get(layerName);
|
||||
layer.parameters.push({
|
||||
name: parameterName,
|
||||
tensor: { name: name, array: array }
|
||||
});
|
||||
}
|
||||
graphs.push({ layers: Array.from(layers.values()) });
|
||||
break;
|
||||
}
|
||||
case 'numpy.ndarray': {
|
||||
format = 'NumPy NDArray';
|
||||
const layer = {
|
||||
type: 'numpy.ndarray',
|
||||
parameters: [ { name: 'value', tensor: { name: '', array: match.value } } ]
|
||||
};
|
||||
graphs.push({ layers: [ layer ] });
|
||||
break;
|
||||
}
|
||||
case 'dnnlib.tflib.network': {
|
||||
format = 'dnnlib';
|
||||
for (const obj of match.value) {
|
||||
const layers = new Map();
|
||||
for (const entry of obj.variables) {
|
||||
const name = entry[0];
|
||||
const value = entry[1];
|
||||
if (numpy.Utility.isTensor(value)) {
|
||||
const parts = name.split('/');
|
||||
const parameterName = parts.length > 1 ? parts.pop() : '?';
|
||||
const layerName = parts.join('/');
|
||||
if (!layers.has(layerName)) {
|
||||
layers.set(layerName, { name: layerName, parameters: [] });
|
||||
}
|
||||
const layer = layers.get(layerName);
|
||||
layer.parameters.push({
|
||||
name: parameterName,
|
||||
tensor: { name: name, array: value }
|
||||
});
|
||||
}
|
||||
}
|
||||
graphs.push({ name: obj.name, layers: Array.from(layers.values()) });
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
const model = new numpy.Model(format, graphs);
|
||||
return Promise.resolve(model);
|
||||
}
|
||||
};
|
||||
|
||||
numpy.Model = class {
|
||||
|
||||
constructor(format, graphs) {
|
||||
this._format = format;
|
||||
this._graphs = graphs.map((graph) => new numpy.Graph(graph));
|
||||
}
|
||||
|
||||
get format() {
|
||||
return this._format;
|
||||
}
|
||||
|
||||
get graphs() {
|
||||
return this._graphs;
|
||||
}
|
||||
};
|
||||
|
||||
numpy.Graph = class {
|
||||
|
||||
constructor(graph) {
|
||||
this._name = graph.name || '';
|
||||
this._nodes = graph.layers.map((layer) => new numpy.Node(layer));
|
||||
}
|
||||
|
||||
get name() {
|
||||
return this._name;
|
||||
}
|
||||
|
||||
get inputs() {
|
||||
return [];
|
||||
}
|
||||
|
||||
get outputs() {
|
||||
return [];
|
||||
}
|
||||
|
||||
get nodes() {
|
||||
return this._nodes;
|
||||
}
|
||||
};
|
||||
|
||||
numpy.Parameter = class {
|
||||
|
||||
constructor(name, args) {
|
||||
this._name = name;
|
||||
this._arguments = args;
|
||||
}
|
||||
|
||||
get name() {
|
||||
return this._name;
|
||||
}
|
||||
|
||||
get visible() {
|
||||
return true;
|
||||
}
|
||||
|
||||
get arguments() {
|
||||
return this._arguments;
|
||||
}
|
||||
};
|
||||
|
||||
numpy.Argument = class {
|
||||
|
||||
constructor(name, initializer) {
|
||||
if (typeof name !== 'string') {
|
||||
throw new numpy.Error("Invalid argument identifier '" + JSON.stringify(name) + "'.");
|
||||
}
|
||||
this._name = name;
|
||||
this._initializer = initializer || null;
|
||||
}
|
||||
|
||||
get name() {
|
||||
return this._name;
|
||||
}
|
||||
|
||||
get type() {
|
||||
return this._initializer.type;
|
||||
}
|
||||
|
||||
get initializer() {
|
||||
return this._initializer;
|
||||
}
|
||||
};
|
||||
|
||||
numpy.Node = class {
|
||||
|
||||
constructor(layer) {
|
||||
this._name = layer.name || '';
|
||||
this._type = { name: layer.type || 'Module' };
|
||||
this._inputs = [];
|
||||
for (const parameter of layer.parameters) {
|
||||
const initializer = new numpy.Tensor(parameter.tensor.array);
|
||||
this._inputs.push(new numpy.Parameter(parameter.name, [
|
||||
new numpy.Argument(parameter.tensor.name || '', initializer)
|
||||
]));
|
||||
}
|
||||
}
|
||||
|
||||
get type() {
|
||||
return this._type;
|
||||
}
|
||||
|
||||
get name() {
|
||||
return this._name;
|
||||
}
|
||||
|
||||
get inputs() {
|
||||
return this._inputs;
|
||||
}
|
||||
|
||||
get outputs() {
|
||||
return [];
|
||||
}
|
||||
|
||||
get attributes() {
|
||||
return [];
|
||||
}
|
||||
};
|
||||
|
||||
numpy.Tensor = class {
|
||||
|
||||
constructor(array) {
|
||||
this._type = new numpy.TensorType(array.dtype.name, new numpy.TensorShape(array.shape));
|
||||
this._data = array.tobytes();
|
||||
this._byteorder = array.dtype.byteorder;
|
||||
this._itemsize = array.dtype.itemsize;
|
||||
}
|
||||
|
||||
get type(){
|
||||
return this._type;
|
||||
}
|
||||
|
||||
get state() {
|
||||
return this._context().state;
|
||||
}
|
||||
|
||||
get value() {
|
||||
const context = this._context();
|
||||
if (context.state) {
|
||||
return null;
|
||||
}
|
||||
context.limit = Number.MAX_SAFE_INTEGER;
|
||||
return this._decode(context, 0);
|
||||
}
|
||||
|
||||
toString() {
|
||||
const context = this._context();
|
||||
if (context.state) {
|
||||
return '';
|
||||
}
|
||||
context.limit = 10000;
|
||||
const value = this._decode(context, 0);
|
||||
return numpy.Tensor._stringify(value, '', ' ');
|
||||
}
|
||||
|
||||
_context() {
|
||||
const context = {};
|
||||
context.index = 0;
|
||||
context.count = 0;
|
||||
context.state = null;
|
||||
if (this._byteorder !== '<' && this._byteorder !== '>' && this._type.dataType !== 'uint8' && this._type.dataType !== 'int8') {
|
||||
context.state = 'Tensor byte order is not supported.';
|
||||
return context;
|
||||
}
|
||||
if (!this._data || this._data.length == 0) {
|
||||
context.state = 'Tensor data is empty.';
|
||||
return context;
|
||||
}
|
||||
context.itemSize = this._itemsize;
|
||||
context.dimensions = this._type.shape.dimensions;
|
||||
context.dataType = this._type.dataType;
|
||||
context.littleEndian = this._byteorder == '<';
|
||||
context.data = this._data;
|
||||
context.rawData = new DataView(this._data.buffer, this._data.byteOffset, this._data.byteLength);
|
||||
return context;
|
||||
}
|
||||
|
||||
_decode(context, dimension) {
|
||||
const littleEndian = context.littleEndian;
|
||||
const shape = context.dimensions.length == 0 ? [ 1 ] : context.dimensions;
|
||||
const results = [];
|
||||
const size = shape[dimension];
|
||||
if (dimension == shape.length - 1) {
|
||||
for (let i = 0; i < size; i++) {
|
||||
if (context.count > context.limit) {
|
||||
results.push('...');
|
||||
return results;
|
||||
}
|
||||
if (context.rawData) {
|
||||
switch (context.dataType) {
|
||||
case 'float16':
|
||||
results.push(context.rawData.getFloat16(context.index, littleEndian));
|
||||
break;
|
||||
case 'float32':
|
||||
results.push(context.rawData.getFloat32(context.index, littleEndian));
|
||||
break;
|
||||
case 'float64':
|
||||
results.push(context.rawData.getFloat64(context.index, littleEndian));
|
||||
break;
|
||||
case 'int8':
|
||||
results.push(context.rawData.getInt8(context.index, littleEndian));
|
||||
break;
|
||||
case 'int16':
|
||||
results.push(context.rawData.getInt16(context.index, littleEndian));
|
||||
break;
|
||||
case 'int32':
|
||||
results.push(context.rawData.getInt32(context.index, littleEndian));
|
||||
break;
|
||||
case 'int64':
|
||||
results.push(context.rawData.getInt64(context.index, littleEndian));
|
||||
break;
|
||||
case 'uint8':
|
||||
results.push(context.rawData.getUint8(context.index, littleEndian));
|
||||
break;
|
||||
case 'uint16':
|
||||
results.push(context.rawData.getUint16(context.index, littleEndian));
|
||||
break;
|
||||
case 'uint32':
|
||||
results.push(context.rawData.getUint32(context.index, littleEndian));
|
||||
break;
|
||||
}
|
||||
context.index += context.itemSize;
|
||||
context.count++;
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
for (let j = 0; j < size; j++) {
|
||||
if (context.count > context.limit) {
|
||||
results.push('...');
|
||||
return results;
|
||||
}
|
||||
results.push(this._decode(context, dimension + 1));
|
||||
}
|
||||
}
|
||||
if (context.dimensions.length == 0) {
|
||||
return results[0];
|
||||
}
|
||||
return results;
|
||||
}
|
||||
|
||||
static _stringify(value, indentation, indent) {
|
||||
if (Array.isArray(value)) {
|
||||
const result = [];
|
||||
result.push(indentation + '[');
|
||||
const items = value.map((item) => numpy.Tensor._stringify(item, indentation + indent, indent));
|
||||
if (items.length > 0) {
|
||||
result.push(items.join(',\n'));
|
||||
}
|
||||
result.push(indentation + ']');
|
||||
return result.join('\n');
|
||||
}
|
||||
if (typeof value == 'string') {
|
||||
return indentation + value;
|
||||
}
|
||||
if (value == Infinity) {
|
||||
return indentation + 'Infinity';
|
||||
}
|
||||
if (value == -Infinity) {
|
||||
return indentation + '-Infinity';
|
||||
}
|
||||
if (isNaN(value)) {
|
||||
return indentation + 'NaN';
|
||||
}
|
||||
return indentation + value.toString();
|
||||
}
|
||||
};
|
||||
|
||||
numpy.TensorType = class {
|
||||
|
||||
constructor(dataType, shape) {
|
||||
this._dataType = dataType;
|
||||
this._shape = shape;
|
||||
}
|
||||
|
||||
get dataType() {
|
||||
return this._dataType || '?';
|
||||
}
|
||||
|
||||
get shape() {
|
||||
return this._shape;
|
||||
}
|
||||
|
||||
toString() {
|
||||
return this.dataType + this._shape.toString();
|
||||
}
|
||||
};
|
||||
|
||||
numpy.TensorShape = class {
|
||||
|
||||
constructor(dimensions) {
|
||||
this._dimensions = dimensions;
|
||||
}
|
||||
|
||||
get dimensions() {
|
||||
return this._dimensions;
|
||||
}
|
||||
|
||||
toString() {
|
||||
if (!this._dimensions || this._dimensions.length == 0) {
|
||||
return '';
|
||||
}
|
||||
return '[' + this._dimensions.join(',') + ']';
|
||||
}
|
||||
};
|
||||
|
||||
numpy.Utility = class {
|
||||
|
||||
static isTensor(obj) {
|
||||
return obj && obj.__class__ &&
|
||||
((obj.__class__.__module__ === 'numpy' && obj.__class__.__name__ === 'ndarray') ||
|
||||
(obj.__class__.__module__ === 'numpy.core.memmap' && obj.__class__.__name__ === 'memmap'));
|
||||
}
|
||||
|
||||
static weights(obj) {
|
||||
const dict = (obj, key) => {
|
||||
const dict = key === '' ? obj : obj[key];
|
||||
if (dict) {
|
||||
const weights = new Map();
|
||||
if (dict instanceof Map) {
|
||||
for (const pair of dict) {
|
||||
const key = pair[0];
|
||||
const obj = pair[1];
|
||||
if (numpy.Utility.isTensor(obj)) {
|
||||
weights.set(key, obj);
|
||||
continue;
|
||||
}
|
||||
else if (obj instanceof Map && Array.from(obj).every((pair) => numpy.Utility.isTensor(pair[1]))) {
|
||||
for (const pair of obj) {
|
||||
weights.set(key + '.' + pair[0], pair[1]);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
else if (key === '_metadata') {
|
||||
continue;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
return weights;
|
||||
}
|
||||
else if (!Array.isArray(dict)) {
|
||||
const set = new Set([ 'weight_order', 'lr', 'model_iter', '__class__' ]);
|
||||
for (const entry of Object.entries(dict)) {
|
||||
const key = entry[0];
|
||||
const value = entry[1];
|
||||
if (key) {
|
||||
if (numpy.Utility.isTensor(value)) {
|
||||
weights.set(key, value);
|
||||
continue;
|
||||
}
|
||||
if (set.has(key)) {
|
||||
continue;
|
||||
}
|
||||
if (value && !Array.isArray(value) && Object.entries(value).every((entry) => numpy.Utility.isTensor(entry[1]))) {
|
||||
const name = key;
|
||||
for (const entry of Object.entries(value)) {
|
||||
weights.set(name + '.' + entry[0], entry[1]);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
return weights;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
};
|
||||
const list = (obj, key) => {
|
||||
const list = key === '' ? obj : obj[key];
|
||||
if (list && Array.isArray(list)) {
|
||||
const weights = new Map();
|
||||
for (let i = 0; i < list.length; i++) {
|
||||
const obj = list[i];
|
||||
if (numpy.Utility.isTensor(obj)) {
|
||||
weights.set(i.toString(), obj);
|
||||
continue;
|
||||
}
|
||||
else if (obj instanceof Map && Array.from(obj).every((pair) => numpy.Utility.isTensor(pair[1]))) {
|
||||
for (const pair of obj) {
|
||||
weights.set(i.toString() + '.' + pair[0], pair[1]);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
return weights;
|
||||
}
|
||||
};
|
||||
const keys = [ '', 'blobs', 'model' ];
|
||||
for (const key of keys) {
|
||||
const weights = dict(obj, key);
|
||||
if (weights && weights.size > 0) {
|
||||
return weights;
|
||||
}
|
||||
}
|
||||
for (const key of keys) {
|
||||
const weights = list(obj, key);
|
||||
if (weights) {
|
||||
return weights;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
};
|
||||
|
||||
numpy.Error = class extends Error {
|
||||
|
||||
constructor(message) {
|
||||
super(message);
|
||||
this.name = 'Error loading Chainer model.';
|
||||
}
|
||||
};
|
||||
|
||||
if (typeof module !== 'undefined' && typeof module.exports === 'object') {
|
||||
module.exports.ModelFactory = numpy.ModelFactory;
|
||||
}
|
||||
File diff suppressed because one or more lines are too long
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,401 @@
|
||||
var $root = flatbuffers.get('ort');
|
||||
|
||||
$root.onnxruntime = $root.onnxruntime || {};
|
||||
|
||||
$root.onnxruntime.fbs = $root.onnxruntime.fbs || {};
|
||||
|
||||
$root.onnxruntime.fbs.AttributeType = {
|
||||
UNDEFINED: 0,
|
||||
FLOAT: 1,
|
||||
INT: 2,
|
||||
STRING: 3,
|
||||
TENSOR: 4,
|
||||
GRAPH: 5,
|
||||
FLOATS: 6,
|
||||
INTS: 7,
|
||||
STRINGS: 8,
|
||||
TENSORS: 9,
|
||||
GRAPHS: 10,
|
||||
SPARSE_TENSOR: 11,
|
||||
SPARSE_TENSORS: 12
|
||||
};
|
||||
|
||||
$root.onnxruntime.fbs.Shape = class Shape {
|
||||
|
||||
static decode(reader, position) {
|
||||
const $ = new $root.onnxruntime.fbs.Shape();
|
||||
$.dim = reader.tableArray(position, 4, $root.onnxruntime.fbs.Dimension.decode);
|
||||
return $;
|
||||
}
|
||||
};
|
||||
|
||||
$root.onnxruntime.fbs.Dimension = class Dimension {
|
||||
|
||||
static decode(reader, position) {
|
||||
const $ = new $root.onnxruntime.fbs.Dimension();
|
||||
$.value = reader.table(position, 4, $root.onnxruntime.fbs.DimensionValue.decode);
|
||||
$.denotation = reader.string_(position, 6, null);
|
||||
return $;
|
||||
}
|
||||
};
|
||||
|
||||
$root.onnxruntime.fbs.DimensionValueType = {
|
||||
UNKNOWN: 0,
|
||||
VALUE: 1,
|
||||
PARAM: 2
|
||||
};
|
||||
|
||||
$root.onnxruntime.fbs.DimensionValue = class DimensionValue {
|
||||
|
||||
static decode(reader, position) {
|
||||
const $ = new $root.onnxruntime.fbs.DimensionValue();
|
||||
$.dim_type = reader.int8_(position, 4, 0);
|
||||
$.dim_value = reader.int64_(position, 6, 0);
|
||||
$.dim_param = reader.string_(position, 8, null);
|
||||
return $;
|
||||
}
|
||||
};
|
||||
|
||||
$root.onnxruntime.fbs.TensorDataType = {
|
||||
UNDEFINED: 0,
|
||||
FLOAT: 1,
|
||||
UINT8: 2,
|
||||
INT8: 3,
|
||||
UINT16: 4,
|
||||
INT16: 5,
|
||||
INT32: 6,
|
||||
INT64: 7,
|
||||
STRING: 8,
|
||||
BOOL: 9,
|
||||
FLOAT16: 10,
|
||||
DOUBLE: 11,
|
||||
UINT32: 12,
|
||||
UINT64: 13,
|
||||
COMPLEX64: 14,
|
||||
COMPLEX128: 15,
|
||||
BFLOAT16: 16
|
||||
};
|
||||
|
||||
$root.onnxruntime.fbs.TensorTypeAndShape = class TensorTypeAndShape {
|
||||
|
||||
static decode(reader, position) {
|
||||
const $ = new $root.onnxruntime.fbs.TensorTypeAndShape();
|
||||
$.elem_type = reader.int32_(position, 4, 0);
|
||||
$.shape = reader.table(position, 6, $root.onnxruntime.fbs.Shape.decode);
|
||||
return $;
|
||||
}
|
||||
};
|
||||
|
||||
$root.onnxruntime.fbs.MapType = class MapType {
|
||||
|
||||
static decode(reader, position) {
|
||||
const $ = new $root.onnxruntime.fbs.MapType();
|
||||
$.key_type = reader.int32_(position, 4, 0);
|
||||
$.value_type = reader.table(position, 6, $root.onnxruntime.fbs.TypeInfo.decode);
|
||||
return $;
|
||||
}
|
||||
};
|
||||
|
||||
$root.onnxruntime.fbs.SequenceType = class SequenceType {
|
||||
|
||||
static decode(reader, position) {
|
||||
const $ = new $root.onnxruntime.fbs.SequenceType();
|
||||
$.elem_type = reader.table(position, 4, $root.onnxruntime.fbs.TypeInfo.decode);
|
||||
return $;
|
||||
}
|
||||
};
|
||||
|
||||
$root.onnxruntime.fbs.NodeType = {
|
||||
Primitive: 0,
|
||||
Fused: 1
|
||||
};
|
||||
|
||||
$root.onnxruntime.fbs.EdgeEnd = class EdgeEnd {
|
||||
|
||||
static decode(reader, position) {
|
||||
const $ = new $root.onnxruntime.fbs.EdgeEnd();
|
||||
$.node_index = reader.uint32(position + 0);
|
||||
$.src_arg_index = reader.int32(position + 4);
|
||||
$.dst_arg_index = reader.int32(position + 8);
|
||||
return $;
|
||||
}
|
||||
};
|
||||
|
||||
$root.onnxruntime.fbs.NodeEdge = class NodeEdge {
|
||||
|
||||
static decode(reader, position) {
|
||||
const $ = new $root.onnxruntime.fbs.NodeEdge();
|
||||
$.node_index = reader.uint32_(position, 4, 0);
|
||||
$.input_edges = reader.structArray(position, 6, undefined,$root.onnxruntime.fbs.EdgeEnd.decode);
|
||||
$.output_edges = reader.structArray(position, 8, undefined,$root.onnxruntime.fbs.EdgeEnd.decode);
|
||||
return $;
|
||||
}
|
||||
};
|
||||
|
||||
$root.onnxruntime.fbs.Node = class Node {
|
||||
|
||||
static decode(reader, position) {
|
||||
const $ = new $root.onnxruntime.fbs.Node();
|
||||
$.name = reader.string_(position, 4, null);
|
||||
$.doc_string = reader.string_(position, 6, null);
|
||||
$.domain = reader.string_(position, 8, null);
|
||||
$.since_version = reader.int32_(position, 10, 0);
|
||||
$.index = reader.uint32_(position, 12, 0);
|
||||
$.op_type = reader.string_(position, 14, null);
|
||||
$.type = reader.int32_(position, 16, 0);
|
||||
$.execution_provider_type = reader.string_(position, 18, null);
|
||||
$.inputs = reader.strings_(position, 20);
|
||||
$.outputs = reader.strings_(position, 22);
|
||||
$.attributes = reader.tableArray(position, 24, $root.onnxruntime.fbs.Attribute.decode);
|
||||
$.input_arg_counts = reader.typedArray(position, 26, Int32Array);
|
||||
$.implicit_inputs = reader.strings_(position, 28);
|
||||
return $;
|
||||
}
|
||||
};
|
||||
|
||||
$root.onnxruntime.fbs.ValueInfo = class ValueInfo {
|
||||
|
||||
static decode(reader, position) {
|
||||
const $ = new $root.onnxruntime.fbs.ValueInfo();
|
||||
$.name = reader.string_(position, 4, null);
|
||||
$.doc_string = reader.string_(position, 6, null);
|
||||
$.type = reader.table(position, 8, $root.onnxruntime.fbs.TypeInfo.decode);
|
||||
return $;
|
||||
}
|
||||
};
|
||||
|
||||
$root.onnxruntime.fbs.TypeInfoValue = class {
|
||||
|
||||
static decode(reader, position, type) {
|
||||
switch (type) {
|
||||
case 1: return $root.onnxruntime.fbs.TensorTypeAndShape.decode(reader, position);
|
||||
case 2: return $root.onnxruntime.fbs.SequenceType.decode(reader, position);
|
||||
case 3: return $root.onnxruntime.fbs.MapType.decode(reader, position);
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
|
||||
static decodeText(reader, json, type) {
|
||||
switch (type) {
|
||||
case 'TensorTypeAndShape': return $root.onnxruntime.fbs.TensorTypeAndShape.decodeText(reader, json);
|
||||
case 'SequenceType': return $root.onnxruntime.fbs.SequenceType.decodeText(reader, json);
|
||||
case 'MapType': return $root.onnxruntime.fbs.MapType.decodeText(reader, json);
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
};
|
||||
|
||||
$root.onnxruntime.fbs.TypeInfo = class TypeInfo {
|
||||
|
||||
static decode(reader, position) {
|
||||
const $ = new $root.onnxruntime.fbs.TypeInfo();
|
||||
$.denotation = reader.string_(position, 4, null);
|
||||
$.value = reader.union(position, 6, $root.onnxruntime.fbs.TypeInfoValue.decode);
|
||||
return $;
|
||||
}
|
||||
};
|
||||
|
||||
$root.onnxruntime.fbs.OperatorSetId = class OperatorSetId {
|
||||
|
||||
static decode(reader, position) {
|
||||
const $ = new $root.onnxruntime.fbs.OperatorSetId();
|
||||
$.domain = reader.string_(position, 4, null);
|
||||
$.version = reader.int64_(position, 6, 0);
|
||||
return $;
|
||||
}
|
||||
};
|
||||
|
||||
$root.onnxruntime.fbs.Tensor = class Tensor {
|
||||
|
||||
static decode(reader, position) {
|
||||
const $ = new $root.onnxruntime.fbs.Tensor();
|
||||
$.name = reader.string_(position, 4, null);
|
||||
$.doc_string = reader.string_(position, 6, null);
|
||||
$.dims = reader.int64s_(position, 8);
|
||||
$.data_type = reader.int32_(position, 10, 0);
|
||||
$.raw_data = reader.typedArray(position, 12, Uint8Array);
|
||||
$.string_data = reader.strings_(position, 14);
|
||||
return $;
|
||||
}
|
||||
};
|
||||
|
||||
$root.onnxruntime.fbs.SparseTensor = class SparseTensor {
|
||||
|
||||
static decode(reader, position) {
|
||||
const $ = new $root.onnxruntime.fbs.SparseTensor();
|
||||
$.values = reader.table(position, 4, $root.onnxruntime.fbs.Tensor.decode);
|
||||
$.indices = reader.table(position, 6, $root.onnxruntime.fbs.Tensor.decode);
|
||||
$.dims = reader.int64s_(position, 8);
|
||||
return $;
|
||||
}
|
||||
};
|
||||
|
||||
$root.onnxruntime.fbs.Attribute = class Attribute {
|
||||
|
||||
static decode(reader, position) {
|
||||
const $ = new $root.onnxruntime.fbs.Attribute();
|
||||
$.name = reader.string_(position, 4, null);
|
||||
$.doc_string = reader.string_(position, 6, null);
|
||||
$.type = reader.int32_(position, 8, 0);
|
||||
$.f = reader.float32_(position, 10, 0);
|
||||
$.i = reader.int64_(position, 12, 0);
|
||||
$.s = reader.string_(position, 14, null);
|
||||
$.t = reader.table(position, 16, $root.onnxruntime.fbs.Tensor.decode);
|
||||
$.g = reader.table(position, 18, $root.onnxruntime.fbs.Graph.decode);
|
||||
$.floats = reader.typedArray(position, 20, Float32Array);
|
||||
$.ints = reader.int64s_(position, 22);
|
||||
$.strings = reader.strings_(position, 24);
|
||||
$.tensors = reader.tableArray(position, 26, $root.onnxruntime.fbs.Tensor.decode);
|
||||
$.graphs = reader.tableArray(position, 28, $root.onnxruntime.fbs.Graph.decode);
|
||||
return $;
|
||||
}
|
||||
};
|
||||
|
||||
$root.onnxruntime.fbs.NodesToOptimizeIndices = class NodesToOptimizeIndices {
|
||||
|
||||
static decode(reader, position) {
|
||||
const $ = new $root.onnxruntime.fbs.NodesToOptimizeIndices();
|
||||
$.node_indices = reader.typedArray(position, 4, Uint32Array);
|
||||
$.num_inputs = reader.uint32_(position, 6, 0);
|
||||
$.num_outputs = reader.uint32_(position, 8, 0);
|
||||
$.has_variadic_input = reader.bool_(position, 10, false);
|
||||
$.has_variadic_output = reader.bool_(position, 12, false);
|
||||
$.num_variadic_inputs = reader.uint32_(position, 14, 0);
|
||||
$.num_variadic_outputs = reader.uint32_(position, 16, 0);
|
||||
return $;
|
||||
}
|
||||
};
|
||||
|
||||
$root.onnxruntime.fbs.NodeIndexAndKernelDefHash = class NodeIndexAndKernelDefHash {
|
||||
|
||||
static decode(reader, position) {
|
||||
const $ = new $root.onnxruntime.fbs.NodeIndexAndKernelDefHash();
|
||||
$.node_index = reader.uint32_(position, 4, 0);
|
||||
$.kernel_def_hash = reader.uint64_(position, 6, 0);
|
||||
return $;
|
||||
}
|
||||
};
|
||||
|
||||
$root.onnxruntime.fbs.RuntimeOptimizationRecord = class RuntimeOptimizationRecord {
|
||||
|
||||
static decode(reader, position) {
|
||||
const $ = new $root.onnxruntime.fbs.RuntimeOptimizationRecord();
|
||||
$.action_id = reader.string_(position, 4, null);
|
||||
$.nodes_to_optimize_indices = reader.table(position, 6, $root.onnxruntime.fbs.NodesToOptimizeIndices.decode);
|
||||
$.produced_nodes = reader.tableArray(position, 8, $root.onnxruntime.fbs.NodeIndexAndKernelDefHash.decode);
|
||||
return $;
|
||||
}
|
||||
};
|
||||
|
||||
$root.onnxruntime.fbs.RuntimeOptimizationRecordContainerEntry = class RuntimeOptimizationRecordContainerEntry {
|
||||
|
||||
static decode(reader, position) {
|
||||
const $ = new $root.onnxruntime.fbs.RuntimeOptimizationRecordContainerEntry();
|
||||
$.optimizer_name = reader.string_(position, 4, null);
|
||||
$.runtime_optimization_records = reader.tableArray(position, 6, $root.onnxruntime.fbs.RuntimeOptimizationRecord.decode);
|
||||
return $;
|
||||
}
|
||||
};
|
||||
|
||||
$root.onnxruntime.fbs.RuntimeOptimizations = class RuntimeOptimizations {
|
||||
|
||||
static decode(reader, position) {
|
||||
const $ = new $root.onnxruntime.fbs.RuntimeOptimizations();
|
||||
$.records = reader.tableArray(position, 4, $root.onnxruntime.fbs.RuntimeOptimizationRecordContainerEntry.decode);
|
||||
return $;
|
||||
}
|
||||
};
|
||||
|
||||
$root.onnxruntime.fbs.Graph = class Graph {
|
||||
|
||||
static decode(reader, position) {
|
||||
const $ = new $root.onnxruntime.fbs.Graph();
|
||||
$.initializers = reader.tableArray(position, 4, $root.onnxruntime.fbs.Tensor.decode);
|
||||
$.node_args = reader.tableArray(position, 6, $root.onnxruntime.fbs.ValueInfo.decode);
|
||||
$.nodes = reader.tableArray(position, 8, $root.onnxruntime.fbs.Node.decode);
|
||||
$.max_node_index = reader.uint32_(position, 10, 0);
|
||||
$.node_edges = reader.tableArray(position, 12, $root.onnxruntime.fbs.NodeEdge.decode);
|
||||
$.inputs = reader.strings_(position, 14);
|
||||
$.outputs = reader.strings_(position, 16);
|
||||
$.sparse_initializers = reader.tableArray(position, 18, $root.onnxruntime.fbs.SparseTensor.decode);
|
||||
$.runtime_optimizations = reader.table(position, 20, $root.onnxruntime.fbs.RuntimeOptimizations.decode);
|
||||
return $;
|
||||
}
|
||||
};
|
||||
|
||||
$root.onnxruntime.fbs.StringStringEntry = class StringStringEntry {
|
||||
|
||||
static decode(reader, position) {
|
||||
const $ = new $root.onnxruntime.fbs.StringStringEntry();
|
||||
$.key = reader.string_(position, 4, null);
|
||||
$.value = reader.string_(position, 6, null);
|
||||
return $;
|
||||
}
|
||||
};
|
||||
|
||||
$root.onnxruntime.fbs.Model = class Model {
|
||||
|
||||
static decode(reader, position) {
|
||||
const $ = new $root.onnxruntime.fbs.Model();
|
||||
$.ir_version = reader.int64_(position, 4, 0);
|
||||
$.opset_import = reader.tableArray(position, 6, $root.onnxruntime.fbs.OperatorSetId.decode);
|
||||
$.producer_name = reader.string_(position, 8, null);
|
||||
$.producer_version = reader.string_(position, 10, null);
|
||||
$.domain = reader.string_(position, 12, null);
|
||||
$.model_version = reader.int64_(position, 14, 0);
|
||||
$.doc_string = reader.string_(position, 16, null);
|
||||
$.graph = reader.table(position, 18, $root.onnxruntime.fbs.Graph.decode);
|
||||
$.graph_doc_string = reader.string_(position, 20, null);
|
||||
$.metadata_props = reader.tableArray(position, 22, $root.onnxruntime.fbs.StringStringEntry.decode);
|
||||
return $;
|
||||
}
|
||||
};
|
||||
|
||||
$root.onnxruntime.fbs.KernelCreateInfos = class KernelCreateInfos {
|
||||
|
||||
static decode(reader, position) {
|
||||
const $ = new $root.onnxruntime.fbs.KernelCreateInfos();
|
||||
$.node_indices = reader.typedArray(position, 4, Uint32Array);
|
||||
$.kernel_def_hashes = reader.uint64s_(position, 6);
|
||||
return $;
|
||||
}
|
||||
};
|
||||
|
||||
$root.onnxruntime.fbs.SubGraphSessionState = class SubGraphSessionState {
|
||||
|
||||
static decode(reader, position) {
|
||||
const $ = new $root.onnxruntime.fbs.SubGraphSessionState();
|
||||
$.graph_id = reader.string_(position, 4, null);
|
||||
$.session_state = reader.table(position, 6, $root.onnxruntime.fbs.SessionState.decode);
|
||||
return $;
|
||||
}
|
||||
};
|
||||
|
||||
$root.onnxruntime.fbs.SessionState = class SessionState {
|
||||
|
||||
static decode(reader, position) {
|
||||
const $ = new $root.onnxruntime.fbs.SessionState();
|
||||
$.kernels = reader.table(position, 4, $root.onnxruntime.fbs.KernelCreateInfos.decode);
|
||||
$.sub_graph_session_states = reader.tableArray(position, 6, $root.onnxruntime.fbs.SubGraphSessionState.decode);
|
||||
return $;
|
||||
}
|
||||
};
|
||||
|
||||
$root.onnxruntime.fbs.InferenceSession = class InferenceSession {
|
||||
|
||||
static identifier(reader) {
|
||||
return reader.identifier === 'ORTM';
|
||||
}
|
||||
|
||||
static create(reader) {
|
||||
return $root.onnxruntime.fbs.InferenceSession.decode(reader, reader.root);
|
||||
}
|
||||
|
||||
static decode(reader, position) {
|
||||
const $ = new $root.onnxruntime.fbs.InferenceSession();
|
||||
$.ort_version = reader.string_(position, 4, null);
|
||||
$.model = reader.table(position, 6, $root.onnxruntime.fbs.Model.decode);
|
||||
$.session_state = reader.table(position, 8, $root.onnxruntime.fbs.SessionState.decode);
|
||||
return $;
|
||||
}
|
||||
};
|
||||
@ -0,0 +1,189 @@
|
||||
|
||||
// Experimental
|
||||
|
||||
var pickle = pickle || {};
|
||||
var python = python || require('./python');
|
||||
var zip = zip || require('./zip');
|
||||
|
||||
pickle.ModelFactory = class {
|
||||
|
||||
match(context) {
|
||||
const stream = context.stream;
|
||||
const signature = [ 0x80, undefined, 0x8a, 0x0a, 0x6c, 0xfc, 0x9c, 0x46, 0xf9, 0x20, 0x6a, 0xa8, 0x50, 0x19 ];
|
||||
if (signature.length <= stream.length && stream.peek(signature.length).every((value, index) => signature[index] === undefined || signature[index] === value)) {
|
||||
// Reject PyTorch models with .pkl file extension.
|
||||
return undefined;
|
||||
}
|
||||
const obj = context.open('pkl');
|
||||
if (obj !== undefined) {
|
||||
return 'pickle';
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
|
||||
open(context) {
|
||||
return new Promise((resolve) => {
|
||||
let format = 'Pickle';
|
||||
const obj = context.open('pkl');
|
||||
if (obj === null || obj === undefined) {
|
||||
context.exception(new pickle.Error("Unknown Pickle null object in '" + context.identifier + "'."));
|
||||
}
|
||||
else if (Array.isArray(obj)) {
|
||||
if (obj.length > 0 && obj[0] && obj.every((item) => item && item.__class__ && obj[0].__class__ && item.__class__.__module__ === obj[0].__class__.__module__ && item.__class__.__name__ === obj[0].__class__.__name__)) {
|
||||
const type = obj[0].__class__.__module__ + "." + obj[0].__class__.__name__;
|
||||
context.exception(new pickle.Error("Unknown Pickle '" + type + "' array object in '" + context.identifier + "'."));
|
||||
}
|
||||
else {
|
||||
context.exception(new pickle.Error("Unknown Pickle array object in '" + context.identifier + "'."));
|
||||
}
|
||||
}
|
||||
else if (obj && obj.__class__) {
|
||||
const formats = new Map([
|
||||
[ 'cuml.ensemble.randomforestclassifier.RandomForestClassifier', 'cuML' ]
|
||||
]);
|
||||
const type = obj.__class__.__module__ + "." + obj.__class__.__name__;
|
||||
if (formats.has(type)) {
|
||||
format = formats.get(type);
|
||||
}
|
||||
else {
|
||||
context.exception(new pickle.Error("Unknown Pickle type '" + type + "' in '" + context.identifier + "'."));
|
||||
}
|
||||
}
|
||||
else {
|
||||
context.exception(new pickle.Error("Unknown Pickle object in '" + context.identifier + "'."));
|
||||
}
|
||||
resolve(new pickle.Model(obj, format));
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
pickle.Model = class {
|
||||
|
||||
constructor(value, format) {
|
||||
this._format = format;
|
||||
this._graphs = [ new pickle.Graph(value) ];
|
||||
}
|
||||
|
||||
get format() {
|
||||
return this._format;
|
||||
}
|
||||
|
||||
get graphs() {
|
||||
return this._graphs;
|
||||
}
|
||||
};
|
||||
|
||||
pickle.Graph = class {
|
||||
|
||||
constructor(obj) {
|
||||
this._inputs = [];
|
||||
this._outputs = [];
|
||||
this._nodes = [];
|
||||
|
||||
if (Array.isArray(obj) && obj.every((item) => item.__class__)) {
|
||||
for (const item of obj) {
|
||||
this._nodes.push(new pickle.Node(item));
|
||||
}
|
||||
}
|
||||
else if (obj && obj instanceof Map) {
|
||||
for (const entry of obj) {
|
||||
this._nodes.push(new pickle.Node(entry[1], entry[0]));
|
||||
}
|
||||
}
|
||||
else if (obj && obj.__class__) {
|
||||
this._nodes.push(new pickle.Node(obj));
|
||||
}
|
||||
else if (obj && Object(obj) === obj) {
|
||||
this._nodes.push(new pickle.Node(obj));
|
||||
}
|
||||
}
|
||||
|
||||
get inputs() {
|
||||
return this._inputs;
|
||||
}
|
||||
|
||||
get outputs() {
|
||||
return this._outputs;
|
||||
}
|
||||
|
||||
get nodes() {
|
||||
return this._nodes;
|
||||
}
|
||||
};
|
||||
|
||||
pickle.Node = class {
|
||||
|
||||
constructor(obj, name) {
|
||||
this._name = name || '';
|
||||
this._inputs = [];
|
||||
this._outputs = [];
|
||||
this._attributes = [];
|
||||
if (Array.isArray(obj)) {
|
||||
this._type = { name: 'List' };
|
||||
this._attributes.push(new pickle.Attribute('value', obj));
|
||||
}
|
||||
else {
|
||||
const type = obj.__class__ ? obj.__class__.__module__ + '.' + obj.__class__.__name__ : 'Object';
|
||||
this._type = { name: type };
|
||||
for (const key of Object.keys(obj)) {
|
||||
const value = obj[key];
|
||||
this._attributes.push(new pickle.Attribute(key, value));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
get type() {
|
||||
return this._type;
|
||||
}
|
||||
|
||||
get name() {
|
||||
return this._name;
|
||||
}
|
||||
|
||||
get inputs() {
|
||||
return this._inputs;
|
||||
}
|
||||
|
||||
get outputs() {
|
||||
return this._outputs;
|
||||
}
|
||||
|
||||
get attributes() {
|
||||
return this._attributes;
|
||||
}
|
||||
};
|
||||
|
||||
pickle.Attribute = class {
|
||||
|
||||
constructor(name, value) {
|
||||
this._name = name;
|
||||
this._value = value;
|
||||
if (value && value.__class__) {
|
||||
this._type = value.__class__.__module__ + '.' + value.__class__.__name__;
|
||||
}
|
||||
}
|
||||
|
||||
get name() {
|
||||
return this._name;
|
||||
}
|
||||
|
||||
get value() {
|
||||
return this._value;
|
||||
}
|
||||
|
||||
get type() {
|
||||
return this._type;
|
||||
}
|
||||
};
|
||||
|
||||
pickle.Error = class extends Error {
|
||||
|
||||
constructor(message) {
|
||||
super(message);
|
||||
this.name = 'Error loading Pickle model.';
|
||||
}
|
||||
};
|
||||
|
||||
if (typeof module !== 'undefined' && typeof module.exports === 'object') {
|
||||
module.exports.ModelFactory = pickle.ModelFactory;
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,298 @@
|
||||
|
||||
import codecs
|
||||
import errno
|
||||
import os
|
||||
import random
|
||||
import re
|
||||
import socket
|
||||
import sys
|
||||
import threading
|
||||
import webbrowser
|
||||
import time
|
||||
|
||||
from .__version__ import __version__
|
||||
|
||||
if sys.version_info[0] > 2:
|
||||
from urllib.parse import urlparse
|
||||
from urllib.parse import unquote
|
||||
from http.server import HTTPServer
|
||||
from http.server import BaseHTTPRequestHandler
|
||||
from socketserver import ThreadingMixIn
|
||||
else:
|
||||
from urlparse import urlparse
|
||||
from urlparse import unquote
|
||||
from BaseHTTPServer import HTTPServer
|
||||
from BaseHTTPServer import BaseHTTPRequestHandler
|
||||
from SocketServer import ThreadingMixIn
|
||||
|
||||
class HTTPRequestHandler(BaseHTTPRequestHandler):
|
||||
def handler(self):
|
||||
if not hasattr(self, 'mime_types_map'):
|
||||
self.mime_types_map = {
|
||||
'.html': 'text/html',
|
||||
'.js': 'text/javascript',
|
||||
'.css': 'text/css',
|
||||
'.png': 'image/png',
|
||||
'.gif': 'image/gif',
|
||||
'.jpg': 'image/jpeg',
|
||||
'.ico': 'image/x-icon',
|
||||
'.json': 'application/json',
|
||||
'.pb': 'application/octet-stream',
|
||||
'.ttf': 'font/truetype',
|
||||
'.otf': 'font/opentype',
|
||||
'.eot': 'application/vnd.ms-fontobject',
|
||||
'.woff': 'font/woff',
|
||||
'.woff2': 'application/font-woff2',
|
||||
'.svg': 'image/svg+xml'
|
||||
}
|
||||
pathname = urlparse(self.path).path
|
||||
folder = os.path.dirname(os.path.realpath(__file__))
|
||||
location = folder + pathname
|
||||
status_code = 0
|
||||
headers = {}
|
||||
buffer = None
|
||||
data = '/data/'
|
||||
if status_code == 0:
|
||||
if pathname == '/':
|
||||
meta = []
|
||||
meta.append('<meta name="type" content="Python">')
|
||||
meta.append('<meta name="version" content="' + __version__ + '">')
|
||||
if self.file:
|
||||
meta.append('<meta name="file" content="/data/' + self.file + '">')
|
||||
with codecs.open(location + 'index.html', mode="r", encoding="utf-8") as open_file:
|
||||
buffer = open_file.read()
|
||||
buffer = re.sub(r'<meta name="version" content="\d+.\d+.\d+">', '\n'.join(meta), buffer)
|
||||
buffer = buffer.encode('utf-8')
|
||||
headers['Content-Type'] = 'text/html'
|
||||
headers['Content-Length'] = len(buffer)
|
||||
status_code = 200
|
||||
elif pathname.startswith(data):
|
||||
file = pathname[len(data):]
|
||||
if file == self.file and self.data:
|
||||
buffer = self.data
|
||||
else:
|
||||
file = self.folder + '/' + unquote(file)
|
||||
status_code = 404
|
||||
if os.path.exists(file):
|
||||
with open(file, 'rb') as binary:
|
||||
buffer = binary.read()
|
||||
if buffer:
|
||||
headers['Content-Type'] = 'application/octet-stream'
|
||||
headers['Content-Length'] = len(buffer)
|
||||
status_code = 200
|
||||
else:
|
||||
if os.path.exists(location) and not os.path.isdir(location):
|
||||
extension = os.path.splitext(location)[1]
|
||||
content_type = self.mime_types_map[extension]
|
||||
if content_type:
|
||||
with open(location, 'rb') as binary:
|
||||
buffer = binary.read()
|
||||
headers['Content-Type'] = content_type
|
||||
headers['Content-Length'] = len(buffer)
|
||||
status_code = 200
|
||||
else:
|
||||
status_code = 404
|
||||
if self.log:
|
||||
sys.stdout.write(str(status_code) + ' ' + self.command + ' ' + self.path + '\n')
|
||||
sys.stdout.flush()
|
||||
self.send_response(status_code)
|
||||
for key in headers:
|
||||
self.send_header(key, headers[key])
|
||||
self.end_headers()
|
||||
if self.command != 'HEAD':
|
||||
if status_code == 404 and buffer is None:
|
||||
self.wfile.write(bytes(status_code))
|
||||
elif (status_code in (200, 404)) and buffer is not None:
|
||||
self.wfile.write(buffer)
|
||||
def do_GET(self):
|
||||
self.handler()
|
||||
def do_HEAD(self):
|
||||
self.handler()
|
||||
def log_message(self, format, *args):
|
||||
return
|
||||
|
||||
class ThreadedHTTPServer(ThreadingMixIn, HTTPServer):
|
||||
pass
|
||||
|
||||
class HTTPServerThread(threading.Thread):
|
||||
def __init__(self, data, file, address, log):
|
||||
threading.Thread.__init__(self)
|
||||
self.address = address
|
||||
self.url = 'http://' + address[0] + ':' + str(address[1])
|
||||
self.file = file
|
||||
self.server = ThreadedHTTPServer(address, HTTPRequestHandler)
|
||||
self.server.timeout = 0.25
|
||||
if file:
|
||||
self.server.RequestHandlerClass.folder = os.path.dirname(file) if os.path.dirname(file) else '.'
|
||||
self.server.RequestHandlerClass.file = os.path.basename(file)
|
||||
else:
|
||||
self.server.RequestHandlerClass.folder = ''
|
||||
self.server.RequestHandlerClass.file = ''
|
||||
self.server.RequestHandlerClass.data = data
|
||||
self.server.RequestHandlerClass.log = log
|
||||
self.terminate_event = threading.Event()
|
||||
self.terminate_event.set()
|
||||
self.stop_event = threading.Event()
|
||||
|
||||
def run(self):
|
||||
self.stop_event.clear()
|
||||
self.terminate_event.clear()
|
||||
try:
|
||||
while not self.stop_event.is_set():
|
||||
self.server.handle_request()
|
||||
except Exception:
|
||||
pass
|
||||
self.terminate_event.set()
|
||||
self.stop_event.clear()
|
||||
|
||||
def stop(self):
|
||||
if self.alive():
|
||||
sys.stdout.write("Stopping " + self.url + "\n")
|
||||
self.stop_event.set()
|
||||
self.server.server_close()
|
||||
self.terminate_event.wait(1000)
|
||||
|
||||
def alive(self):
|
||||
return not self.terminate_event.is_set()
|
||||
|
||||
_thread_list = []
|
||||
|
||||
def _add_thread(thread):
|
||||
global _thread_list
|
||||
_thread_list.append(thread)
|
||||
|
||||
def _update_thread_list(address=None):
|
||||
global _thread_list
|
||||
_thread_list = [ thread for thread in _thread_list if thread.alive() ]
|
||||
threads = _thread_list
|
||||
if address is not None:
|
||||
address = _make_address(address)
|
||||
if address[1] is None:
|
||||
threads = [ thread for thread in threads if address[0] == thread.address[0] ]
|
||||
else:
|
||||
threads = [ thread for thread in threads if address[0] == thread.address[0] and address[1] == thread.address[1] ]
|
||||
return threads
|
||||
|
||||
def _make_address(address):
|
||||
if address is None or isinstance(address, int):
|
||||
port = address
|
||||
address = ('localhost', port)
|
||||
if isinstance(address, tuple) and len(address) == 2:
|
||||
host = address[0]
|
||||
port = address[1]
|
||||
if isinstance(host, str) and (port is None or isinstance(port, int)):
|
||||
return address
|
||||
raise ValueError('Invalid address.')
|
||||
|
||||
def _make_port(address):
|
||||
if address[1] is None or address[1] == 0:
|
||||
ports = []
|
||||
if address[1] != 0:
|
||||
ports.append(8080)
|
||||
ports.append(8081)
|
||||
rnd = random.Random()
|
||||
for _ in range(4):
|
||||
port = rnd.randrange(15000, 25000)
|
||||
if port not in ports:
|
||||
ports.append(port)
|
||||
ports.append(0)
|
||||
for port in ports:
|
||||
temp_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
|
||||
temp_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
|
||||
temp_socket.settimeout(1)
|
||||
try:
|
||||
temp_socket.bind((address[0], port))
|
||||
sockname = temp_socket.getsockname()
|
||||
address = (address[0], sockname[1])
|
||||
return address
|
||||
except:
|
||||
pass
|
||||
finally:
|
||||
temp_socket.close()
|
||||
if isinstance(address[1], int):
|
||||
return address
|
||||
raise ValueError('Failed to allocate port.')
|
||||
|
||||
def stop(address=None):
|
||||
'''Stop serving model at address.
|
||||
|
||||
Args:
|
||||
address (tuple, optional): A (host, port) tuple, or a port number.
|
||||
'''
|
||||
threads = _update_thread_list(address)
|
||||
for thread in threads:
|
||||
thread.stop()
|
||||
_update_thread_list()
|
||||
|
||||
def status(adrress=None):
|
||||
'''Is model served at address.
|
||||
|
||||
Args:
|
||||
address (tuple, optional): A (host, port) tuple, or a port number.
|
||||
'''
|
||||
threads = _update_thread_list(adrress)
|
||||
return len(threads) > 0
|
||||
|
||||
def wait():
|
||||
'''Wait for console exit and stop all model servers.'''
|
||||
try:
|
||||
while len(_update_thread_list()) > 0:
|
||||
time.sleep(1000)
|
||||
except (KeyboardInterrupt, SystemExit):
|
||||
sys.stdout.write('\n')
|
||||
sys.stdout.flush()
|
||||
stop()
|
||||
|
||||
def serve(file, data, address=None, browse=False, log=False):
|
||||
'''Start serving model from file or data buffer at address and open in web browser.
|
||||
|
||||
Args:
|
||||
file (string): Model file to serve. Required to detect format.
|
||||
data (bytes): Model data to serve. None will load data from file.
|
||||
log (bool, optional): Log details to console. Default: False
|
||||
browse (bool, optional): Launch web browser. Default: True
|
||||
address (tuple, optional): A (host, port) tuple, or a port number.
|
||||
|
||||
Returns:
|
||||
A (host, port) address tuple.
|
||||
'''
|
||||
if not data and file and not os.path.exists(file):
|
||||
raise FileNotFoundError(errno.ENOENT, os.strerror(errno.ENOENT), file)
|
||||
|
||||
_update_thread_list()
|
||||
address = _make_address(address)
|
||||
if isinstance(address[1], int) and address[1] != 0:
|
||||
stop(address)
|
||||
else:
|
||||
address = _make_port(address)
|
||||
_update_thread_list()
|
||||
|
||||
thread = HTTPServerThread(data, file, address, log)
|
||||
thread.start()
|
||||
while not thread.alive():
|
||||
time.sleep(10)
|
||||
_add_thread(thread)
|
||||
|
||||
if file:
|
||||
sys.stdout.write("Serving '" + file + "' at " + thread.url + "\n")
|
||||
else:
|
||||
sys.stdout.write("Serving at " + thread.url + "\n")
|
||||
sys.stdout.flush()
|
||||
if browse:
|
||||
webbrowser.open(thread.url)
|
||||
|
||||
return address
|
||||
|
||||
def start(file=None, address=None, browse=True, log=False):
|
||||
'''Start serving model file at address and open in web browser.
|
||||
|
||||
Args:
|
||||
file (string): Model file to serve.
|
||||
log (bool, optional): Log details to console. Default: False
|
||||
browse (bool, optional): Launch web browser, Default: True
|
||||
address (tuple, optional): A (host, port) tuple, or a port number.
|
||||
|
||||
Returns:
|
||||
A (host, port) address tuple.
|
||||
'''
|
||||
return serve(file, None, browse=browse, address=address, log=log)
|
||||
@ -0,0 +1,171 @@
|
||||
|
||||
var tar = tar || {};
|
||||
|
||||
tar.Archive = class {
|
||||
|
||||
static open(data) {
|
||||
const stream = data instanceof Uint8Array ? new tar.BinaryReader(data) : data;
|
||||
if (stream.length > 512) {
|
||||
const buffer = stream.peek(512);
|
||||
const sum = buffer.map((value, index) => (index >= 148 && index < 156) ? 32 : value).reduce((a, b) => a + b, 0);
|
||||
let checksum = '';
|
||||
for (let i = 148; i < 156 && buffer[i] !== 0x00; i++) {
|
||||
checksum += String.fromCharCode(buffer[i]);
|
||||
}
|
||||
checksum = parseInt(checksum, 8);
|
||||
if (!isNaN(checksum) && sum === checksum) {
|
||||
return new tar.Archive(stream);
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
constructor(stream) {
|
||||
this._entries = new Map();
|
||||
const position = stream.position;
|
||||
while (stream.position < stream.length) {
|
||||
const entry = new tar.Entry(stream);
|
||||
if (entry.type === '0' || entry.type === '1' || entry.type === '2') {
|
||||
this._entries.set(entry.name, entry.stream);
|
||||
}
|
||||
if (stream.position + 512 > stream.length ||
|
||||
stream.peek(512).every((value) => value === 0x00)) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
stream.seek(position);
|
||||
}
|
||||
|
||||
get entries() {
|
||||
return this._entries;
|
||||
}
|
||||
};
|
||||
|
||||
tar.Entry = class {
|
||||
|
||||
constructor(stream) {
|
||||
const buffer = stream.read(512);
|
||||
const reader = new tar.BinaryReader(buffer);
|
||||
const sum = buffer.map((value, index) => (index >= 148 && index < 156) ? 32 : value).reduce((a, b) => a + b, 0);
|
||||
let checksum = '';
|
||||
for (let i = 148; i < 156 && buffer[i] !== 0x00; i++) {
|
||||
checksum += String.fromCharCode(buffer[i]);
|
||||
}
|
||||
checksum = parseInt(checksum, 8);
|
||||
if (isNaN(checksum) || sum !== checksum) {
|
||||
throw new tar.Error('Invalid tar archive.');
|
||||
}
|
||||
this._name = reader.string(100);
|
||||
reader.string(8); // file mode
|
||||
reader.string(8); // owner
|
||||
reader.string(8); // group
|
||||
const size = parseInt(reader.string(12).trim(), 8);
|
||||
reader.string(12); // timestamp
|
||||
reader.string(8); // checksum
|
||||
this._type = reader.string(1);
|
||||
reader.string(100); // name of linked file
|
||||
if (reader.string(6) === 'ustar') {
|
||||
reader.string(2); // ustar version
|
||||
reader.string(32); // owner user name
|
||||
reader.string(32); // owner group name
|
||||
reader.string(8); // device major number
|
||||
reader.string(8); // device number number
|
||||
this._name = reader.string(155) + this._name;
|
||||
}
|
||||
this._stream = stream.stream(size);
|
||||
stream.read(((size % 512) != 0) ? (512 - (size % 512)) : 0);
|
||||
}
|
||||
|
||||
get type() {
|
||||
return this._type;
|
||||
}
|
||||
|
||||
get name() {
|
||||
return this._name;
|
||||
}
|
||||
|
||||
get stream() {
|
||||
return this._stream;
|
||||
}
|
||||
};
|
||||
|
||||
tar.BinaryReader = class {
|
||||
|
||||
constructor(buffer) {
|
||||
this._buffer = buffer;
|
||||
this._length = buffer.length;
|
||||
this._position = 0;
|
||||
this._view = new DataView(buffer.buffer, buffer.byteOffset, buffer.byteLength);
|
||||
}
|
||||
|
||||
get position() {
|
||||
return this._position;
|
||||
}
|
||||
|
||||
get length() {
|
||||
return this._length;
|
||||
}
|
||||
|
||||
create(buffer) {
|
||||
return new tar.BinaryReader(buffer);
|
||||
}
|
||||
|
||||
stream(length) {
|
||||
return this.create(this.read(length));
|
||||
}
|
||||
|
||||
seek(position) {
|
||||
this._position = position >= 0 ? position : this._length + position;
|
||||
}
|
||||
|
||||
skip(offset) {
|
||||
this._position += offset;
|
||||
}
|
||||
|
||||
peek(length) {
|
||||
if (this._position === 0 && length === undefined) {
|
||||
return this._buffer;
|
||||
}
|
||||
const position = this._position;
|
||||
this.skip(length !== undefined ? length : this._length - this._position);
|
||||
const end = this._position;
|
||||
this.seek(position);
|
||||
return this._buffer.subarray(position, end);
|
||||
}
|
||||
|
||||
read(length) {
|
||||
if (this._position === 0 && length === undefined) {
|
||||
this._position = this._length;
|
||||
return this._buffer;
|
||||
}
|
||||
const position = this._position;
|
||||
this.skip(length !== undefined ? length : this._length - this._position);
|
||||
return this._buffer.subarray(position, this._position);
|
||||
}
|
||||
|
||||
string(length) {
|
||||
const buffer = this.read(length);
|
||||
let position = 0;
|
||||
let content = '';
|
||||
for (let i = 0; i < length; i++) {
|
||||
const c = buffer[position++];
|
||||
if (c === 0) {
|
||||
break;
|
||||
}
|
||||
content += String.fromCharCode(c);
|
||||
}
|
||||
return content;
|
||||
}
|
||||
};
|
||||
|
||||
tar.Error = class extends Error {
|
||||
|
||||
constructor(message) {
|
||||
super(message);
|
||||
this.name = 'tar Error';
|
||||
}
|
||||
};
|
||||
|
||||
if (typeof module !== 'undefined' && typeof module.exports === 'object') {
|
||||
module.exports.Archive = tar.Archive;
|
||||
}
|
||||
@ -0,0 +1,292 @@
|
||||
|
||||
var text = text || {};
|
||||
|
||||
text.Decoder = class {
|
||||
|
||||
static open(data, encoding) {
|
||||
if (typeof data === 'string') {
|
||||
return new text.Decoder.String(data);
|
||||
}
|
||||
const assert = (encoding, condition) => {
|
||||
if (encoding && encoding !== condition) {
|
||||
throw new text.Error("Invalid encoding '" + encoding + "'.");
|
||||
}
|
||||
};
|
||||
const buffer = data instanceof Uint8Array ? data : data.peek();
|
||||
const length = buffer.length;
|
||||
if (length >= 3 && buffer[0] === 0xef && buffer[1] === 0xbb && buffer[2] === 0xbf) {
|
||||
assert(encoding, 'utf-8');
|
||||
return new text.Decoder.Utf8(buffer, 3, true);
|
||||
}
|
||||
if (length >= 2 && buffer[0] === 0xff && buffer[1] === 0xfe) {
|
||||
assert(encoding, 'utf-16');
|
||||
return new text.Decoder.Utf16LE(buffer, 2);
|
||||
}
|
||||
if (length >= 2 && buffer[0] === 0xfe && buffer[1] === 0xff) {
|
||||
assert(encoding, 'utf-16');
|
||||
return new text.Decoder.Utf16BE(buffer, 2);
|
||||
}
|
||||
if (length >= 4 && buffer[0] === 0x00 && buffer[1] === 0x00 && buffer[2] === 0xfe && buffer[3] === 0xff) {
|
||||
throw new text.Error("Unsupported UTF-32 big-endian encoding.");
|
||||
}
|
||||
if (length >= 4 && buffer[0] === 0xff && buffer[1] === 0xfe && buffer[2] === 0x00 && buffer[3] === 0x00) {
|
||||
throw new text.Error("Unsupported UTF-32 little-endian encoding.");
|
||||
}
|
||||
if (length >= 5 && buffer[0] === 0x2B && buffer[1] === 0x2F && buffer[2] === 0x76 && buffer[3] === 0x38 && buffer[4] === 0x2D) {
|
||||
throw new text.Error("Unsupported UTF-7 encoding.");
|
||||
}
|
||||
if (length >= 4 && buffer[0] === 0x2B && buffer[1] === 0x2F && buffer[2] === 0x76 && (buffer[3] === 0x38 || buffer[3] === 0x39 || buffer[3] === 0x2B || buffer[3] === 0x2F)) {
|
||||
throw new text.Error("Unsupported UTF-7 encoding.");
|
||||
}
|
||||
if (length >= 4 && buffer[0] === 0x84 && buffer[1] === 0x31 && buffer[2] === 0x95 && buffer[3] === 0x33) {
|
||||
throw new text.Error("Unsupported GB-18030 encoding.");
|
||||
}
|
||||
if (length > 4 && (length % 2) == 0 && (buffer[0] === 0x00 || buffer[1] === 0x00 || buffer[2] === 0x00 || buffer[3] === 0x00)) {
|
||||
const lo = new Uint32Array(256);
|
||||
const hi = new Uint32Array(256);
|
||||
for (let i = 0; i < length; i += 2) {
|
||||
lo[buffer[i]]++;
|
||||
hi[buffer[i + 1]]++;
|
||||
}
|
||||
if (lo[0x00] === 0 && (hi[0x00] / (length >> 1)) > 0.5) {
|
||||
assert(encoding, 'utf-16');
|
||||
return new text.Decoder.Utf16LE(buffer, 0);
|
||||
}
|
||||
if (hi[0x00] === 0 && (lo[0x00] / (length >> 1)) > 0.5) {
|
||||
assert(encoding, 'utf-16');
|
||||
return new text.Decoder.Utf16BE(buffer, 0);
|
||||
}
|
||||
}
|
||||
if (encoding && (encoding.startsWith('iso-8859-') || encoding.startsWith('latin-'))) {
|
||||
return new text.Decoder.Latin1(buffer, 0);
|
||||
}
|
||||
assert(encoding, 'utf-8');
|
||||
return new text.Decoder.Utf8(buffer, 0, encoding === 'utf-8');
|
||||
}
|
||||
};
|
||||
|
||||
text.Decoder.String = class {
|
||||
|
||||
constructor(buffer) {
|
||||
this.buffer = buffer ? buffer.match(/[\uD800-\uDBFF][\uDC00-\uDFFF]|[^\uD800-\uDFFF]/g) : [];
|
||||
this.position = 0;
|
||||
this.length = this.buffer.length;
|
||||
}
|
||||
|
||||
get encoding() {
|
||||
return null;
|
||||
}
|
||||
|
||||
decode() {
|
||||
if (this.position < this.length) {
|
||||
return this.buffer[this.position++];
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
};
|
||||
|
||||
text.Decoder.Utf8 = class {
|
||||
|
||||
constructor(buffer, position, fatal) {
|
||||
this.position = position || 0;
|
||||
this.buffer = buffer;
|
||||
this.fatal = fatal;
|
||||
}
|
||||
|
||||
get encoding() {
|
||||
return 'utf-8';
|
||||
}
|
||||
|
||||
decode() {
|
||||
const c = this.buffer[this.position];
|
||||
if (c === undefined) {
|
||||
return c;
|
||||
}
|
||||
this.position++;
|
||||
if (c < 0x80) {
|
||||
return String.fromCodePoint(c);
|
||||
}
|
||||
if (c >= 0xC2 && c <= 0xDF) {
|
||||
if (this.buffer[this.position] !== undefined) {
|
||||
const c2 = this.buffer[this.position];
|
||||
this.position++;
|
||||
return String.fromCharCode(((c & 0x1F) << 6) | (c2 & 0x3F));
|
||||
}
|
||||
}
|
||||
if (c >= 0xE0 && c <= 0xEF) {
|
||||
if (this.buffer[this.position + 1] !== undefined) {
|
||||
const c2 = this.buffer[this.position];
|
||||
if ((c !== 0xE0 || c2 >= 0xA0) && (c !== 0xED || c2 <= 0x9f)) {
|
||||
const c3 = this.buffer[this.position + 1];
|
||||
if (c3 >= 0x80 && c3 < 0xFB) {
|
||||
this.position += 2;
|
||||
return String.fromCharCode(((c & 0x0F) << 12) | ((c2 & 0x3F) << 6) | ((c3 & 0x3F) << 0));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (c >= 0xF0 && c <= 0xF4) {
|
||||
if (this.buffer[this.position + 2] !== undefined) {
|
||||
const c2 = this.buffer[this.position];
|
||||
if (c2 >= 0x80 && c2 <= 0xBF) {
|
||||
const c3 = this.buffer[this.position + 1];
|
||||
if (c3 >= 0x80 && c3 <= 0xBF) {
|
||||
const c4 = this.buffer[this.position + 2];
|
||||
if (c4 >= 0x80 && c4 <= 0xBF) {
|
||||
this.position += 3;
|
||||
return String.fromCodePoint(((c & 0x07) << 18) | ((c2 & 0x3F) << 12) | ((c3 & 0x3F) << 6) | (c4 & 0x3F));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (this.fatal) {
|
||||
throw new text.Error('Invalid utf-8 character.');
|
||||
}
|
||||
return String.fromCharCode(0xfffd);
|
||||
}
|
||||
};
|
||||
|
||||
text.Decoder.Latin1 = class {
|
||||
|
||||
constructor(buffer, position) {
|
||||
this.position = position || 0;
|
||||
this.buffer = buffer;
|
||||
}
|
||||
|
||||
get encoding() {
|
||||
return 'latin-1';
|
||||
}
|
||||
|
||||
decode() {
|
||||
const c = this.buffer[this.position];
|
||||
if (c === undefined) {
|
||||
return c;
|
||||
}
|
||||
this.position++;
|
||||
return String.fromCodePoint(c);
|
||||
}
|
||||
};
|
||||
|
||||
text.Decoder.Utf16LE = class {
|
||||
|
||||
constructor(buffer, position) {
|
||||
this.buffer = buffer;
|
||||
this.position = position || 0;
|
||||
this.length = buffer.length;
|
||||
}
|
||||
|
||||
get encoding() {
|
||||
return 'utf-16';
|
||||
}
|
||||
|
||||
decode() {
|
||||
if (this.position + 1 < this.length) {
|
||||
const c = this.buffer[this.position++] | (this.buffer[this.position++] << 8);
|
||||
if (c < 0xD800 || c >= 0xDFFF) {
|
||||
return String.fromCharCode(c);
|
||||
}
|
||||
if (c >= 0xD800 && c < 0xDBFF) {
|
||||
if (this._position + 1 < this._length) {
|
||||
const c2 = this._buffer[this._position++] | (this._buffer[this._position++] << 8);
|
||||
if (c >= 0xDC00 || c < 0xDFFF) {
|
||||
return String.fromCodePoint(0x10000 + ((c & 0x3ff) << 10) + (c2 & 0x3ff));
|
||||
}
|
||||
}
|
||||
}
|
||||
return String.fromCharCode(0xfffd);
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
};
|
||||
|
||||
text.Decoder.Utf16BE = class {
|
||||
|
||||
constructor(buffer, position) {
|
||||
this.buffer = buffer;
|
||||
this.position = position || 0;
|
||||
this.length = buffer.length;
|
||||
}
|
||||
|
||||
get encoding() {
|
||||
return 'utf-16';
|
||||
}
|
||||
|
||||
decode() {
|
||||
if (this.position + 1 < this.length) {
|
||||
const c = (this.buffer[this.position++] << 8) | this.buffer[this.position++];
|
||||
if (c < 0xD800 || c >= 0xDFFF) {
|
||||
return String.fromCharCode(c);
|
||||
}
|
||||
if (c >= 0xD800 && c < 0xDBFF) {
|
||||
if (this._position + 1 < this._length) {
|
||||
const c2 = (this._buffer[this._position++] << 8) | this._buffer[this._position++];
|
||||
if (c >= 0xDC00 || c < 0xDFFF) {
|
||||
return String.fromCodePoint(0x10000 + ((c & 0x3ff) << 10) + (c2 & 0x3ff));
|
||||
}
|
||||
}
|
||||
}
|
||||
return String.fromCharCode(0xfffd);
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
};
|
||||
|
||||
text.Reader = class {
|
||||
|
||||
constructor(data, length) {
|
||||
this._decoder = text.Decoder.open(data);
|
||||
this._position = 0;
|
||||
this._length = length || Number.MAX_SAFE_INTEGER;
|
||||
}
|
||||
|
||||
static open(data, length) {
|
||||
return new text.Reader(data, length);
|
||||
}
|
||||
|
||||
read() {
|
||||
if (this._position >= this._length) {
|
||||
return undefined;
|
||||
}
|
||||
let line = '';
|
||||
let buffer = null;
|
||||
for (;;) {
|
||||
const c = this._decoder.decode();
|
||||
if (c === undefined) {
|
||||
this._length = this._position;
|
||||
break;
|
||||
}
|
||||
this._position++;
|
||||
if (this._position > this._length) {
|
||||
break;
|
||||
}
|
||||
if (c === '\n') {
|
||||
break;
|
||||
}
|
||||
line += c;
|
||||
if (line.length >= 32) {
|
||||
buffer = buffer || [];
|
||||
buffer.push(line);
|
||||
line = '';
|
||||
}
|
||||
}
|
||||
if (buffer) {
|
||||
buffer.push(line);
|
||||
return buffer.join('');
|
||||
}
|
||||
return line;
|
||||
}
|
||||
};
|
||||
|
||||
text.Error = class extends Error {
|
||||
|
||||
constructor(message) {
|
||||
super(message);
|
||||
this.name = 'Text Error';
|
||||
}
|
||||
};
|
||||
|
||||
if (typeof module !== 'undefined' && typeof module.exports === 'object') {
|
||||
module.exports.Decoder = text.Decoder;
|
||||
module.exports.Reader = text.Reader;
|
||||
}
|
||||
@ -0,0 +1,136 @@
|
||||
|
||||
.node path { stroke: #333; fill: none; stroke-width: 1px; }
|
||||
.node line { stroke: #333; fill: none; stroke-width: 1px; }
|
||||
|
||||
.node-item path { stroke-width: 0; stroke: #000; fill: #fff; }
|
||||
.node-item text { font-family: -apple-system, BlinkMacSystemFont, "Segoe WPC", "Segoe UI", "Ubuntu", "Droid Sans", sans-serif, "PingFang SC"; font-size: 11px; text-rendering: geometricPrecision; }
|
||||
|
||||
.node-item-function path { fill: #fff; }
|
||||
.node-item-function text { fill: #000; }
|
||||
.node-item-function:hover { cursor: pointer; }
|
||||
.node-item-function:hover path { fill: #eee; }
|
||||
|
||||
.node-item-type path { fill: #000; }
|
||||
.node-item-type text { fill: #fff; }
|
||||
.node-item-type:hover { cursor: pointer; }
|
||||
.node-item-type:hover path { fill: #fff; }
|
||||
.node-item-type:hover text { fill: #000; }
|
||||
|
||||
.node-item-type-constant path { fill: #eee; }
|
||||
.node-item-type-constant text { fill: #000; }
|
||||
.node-item-type-constant:hover path { fill: #fff; }
|
||||
|
||||
.node-item-type-control path { fill: #eee; }
|
||||
.node-item-type-control text { fill: #000; }
|
||||
.node-item-type-control:hover path { fill: #fff; }
|
||||
|
||||
.node-item-type-layer path { fill: rgb(51, 85, 136); }
|
||||
.node-item-type-wrapper path { fill: rgb(238, 238, 238); }
|
||||
.node-item-type-wrapper text { fill: rgb(0, 0, 0) }
|
||||
.node-item-type-activation path { fill: rgb(112, 41, 33); }
|
||||
.node-item-type-pool path { fill: rgb(51, 85, 51); }
|
||||
.node-item-type-normalization path { fill: rgb(51, 85, 68); }
|
||||
.node-item-type-dropout path { fill: rgb(69, 71, 112); }
|
||||
.node-item-type-shape path { fill: rgb(108, 79, 71); }
|
||||
.node-item-type-tensor path { fill: rgb(89, 66, 59); }
|
||||
.node-item-type-transform path { fill: rgb(51, 85, 68); }
|
||||
.node-item-type-data path { fill: rgb(85, 85, 85); }
|
||||
.node-item-type-quantization path { fill: rgb(80, 40, 0); }
|
||||
.node-item-type-custom path { fill: rgb(128, 128, 128); }
|
||||
|
||||
.node-item-input path { fill: #fff; }
|
||||
.node-item-input:hover { cursor: pointer; }
|
||||
.node-item-input:hover path { fill: #fff; }
|
||||
|
||||
.node-item-constant path { fill: #eee; }
|
||||
.node-item-constant:hover { cursor: pointer; }
|
||||
.node-item-constant:hover path { fill: #fff; }
|
||||
|
||||
.node-item-undefined path { fill: #f00; }
|
||||
.node-item-undefined:hover { cursor: pointer; }
|
||||
.node-item-undefined:hover path { fill: #fff; }
|
||||
|
||||
.node-attribute:hover { cursor: pointer; }
|
||||
.node-attribute text { font-family: -apple-system, BlinkMacSystemFont, "Segoe WPC", "Segoe UI", "Ubuntu", "Droid Sans", sans-serif, "PingFang SC"; font-size: 9px; font-weight: normal; text-rendering: geometricPrecision; }
|
||||
.node-attribute path { fill: #fff; stroke-width: 0; stroke: #000; }
|
||||
.node-attribute:hover path { fill: #f6f6f6; }
|
||||
|
||||
.graph-item-input path { fill: #eee; }
|
||||
.graph-item-input:hover { cursor: pointer; }
|
||||
.graph-item-input:hover path { fill: #fff; }
|
||||
|
||||
.graph-item-output path { fill: #eee; }
|
||||
.graph-item-output:hover { cursor: pointer; }
|
||||
.graph-item-output:hover path { fill: #fff; }
|
||||
|
||||
.edge-label { font-family: -apple-system, BlinkMacSystemFont, "Segoe WPC", "Segoe UI", "Ubuntu", "Droid Sans", sans-serif, "PingFang SC"; font-size: 10px; }
|
||||
.edge-path { stroke: #000; stroke-width: 1px; fill: none; marker-end: url("#arrowhead-vee"); }
|
||||
#arrowhead-vee { fill: #000; }
|
||||
.edge-path-control-dependency { stroke-dasharray: 3, 2; }
|
||||
|
||||
.cluster rect { stroke: #000; fill: #000; fill-opacity: 0.02; stroke-opacity: 0.06; stroke-width: 1px; }
|
||||
|
||||
.select .node.border { stroke: #e00; stroke-width: 2px; }
|
||||
.select.edge-path { stroke: #e00; stroke-width: 2px; marker-end: url("#arrowhead-vee-select"); }
|
||||
#arrowhead-vee-select { fill: #e00; }
|
||||
|
||||
@keyframes pulse { from { stroke-dashoffset: 100px; } to { stroke-dashoffset: 0; } }
|
||||
|
||||
@media (prefers-color-scheme: dark) {
|
||||
|
||||
.edge-label { fill: #b2b2b2; }
|
||||
.edge-path { stroke: #888; }
|
||||
#arrowhead-vee { fill: #888; }
|
||||
|
||||
.node path { stroke: #1d1d1d; }
|
||||
.node line { stroke: #1d1d1d; }
|
||||
|
||||
.select .node.border { stroke: #b00; }
|
||||
.select.edge-path { stroke: #b00; }
|
||||
#arrowhead-vee-select { fill: #b00 }
|
||||
|
||||
.node-item-function path { fill: #404040; }
|
||||
.node-item-function text { fill: #dfdfdfdf; }
|
||||
.node-item-function:hover { cursor: pointer; }
|
||||
.node-item-function:hover path { fill: #666666; }
|
||||
|
||||
.node-item-type path { fill: #303030; }
|
||||
.node-item-type text { fill: #dfdfdf; }
|
||||
.node-item-type:hover { cursor: pointer; }
|
||||
.node-item-type:hover path { fill: #808080; }
|
||||
.node-item-type:hover text { fill: #dfdfdf; }
|
||||
|
||||
.node-item path { stroke: #fff; }
|
||||
.node-item text { fill: #dfdfdf; }
|
||||
|
||||
.node-attribute text { fill: #b2b2b2; }
|
||||
.node-attribute path { fill: #2d2d2d; }
|
||||
.node-attribute:hover path { fill: #666666; }
|
||||
|
||||
.graph-item-input path { fill: #404040; }
|
||||
.graph-item-input:hover { cursor: pointer; }
|
||||
.graph-item-input:hover path { fill: #666666; }
|
||||
|
||||
.graph-item-output path { fill: #404040; }
|
||||
.graph-item-output:hover { cursor: pointer; }
|
||||
.graph-item-output:hover path { fill: #666666; }
|
||||
|
||||
.node-item-input path { fill: #404040; }
|
||||
.node-item-input:hover path { fill: #666666; }
|
||||
.node-item-constant path { fill: #4b4b4b; }
|
||||
.node-item-constant:hover path { fill: #666666; }
|
||||
|
||||
.node-item-type-layer path { fill: rgba(51, 85, 136, 0.7); }
|
||||
.node-item-type-activation path { fill: rgba(75, 27, 22, 0.7); }
|
||||
.node-item-type-activation path { fill: rgba(75, 27, 22, 0.7); }
|
||||
.node-item-type-pool path { fill: rgba(51, 85, 51, 0.7); }
|
||||
.node-item-type-pool path { fill: rgba(51, 85, 51, 0.7); }
|
||||
.node-item-type-normalization path { fill: rgba(51, 85, 68, 0.7); }
|
||||
.node-item-type-dropout path { fill: rgba(69, 71, 112, 0.7); }
|
||||
.node-item-type-shape path { fill: rgba(108, 79, 71, 0.7); }
|
||||
.node-item-type-tensor path { fill: rgba(89, 66, 59, 0.7); }
|
||||
.node-item-type-transform path { fill: rgba(51, 85, 68, 0.7); }
|
||||
.node-item-type-data path { fill: rgba(85, 85, 85, 0.7); }
|
||||
.node-item-type-quantization path { fill: rgb(80, 40, 0, 0.7); }
|
||||
.node-item-type-custom path { fill: rgb(64, 64, 64, 0.7); }
|
||||
}
|
||||
@ -0,0 +1,89 @@
|
||||
|
||||
.sidebar { font-family: -apple-system, BlinkMacSystemFont, "Segoe WPC", "Segoe UI", "Ubuntu", "Droid Sans", sans-serif; font-size: 12px; height: 100%; width: 0; position: fixed; transition: 0.2s; z-index: 1; top: 0; right: 0; background-color: #ececec; color: #242424; overflow: hidden; border-left: 1px solid #ccc; }
|
||||
.sidebar-title { font-weight: bold; font-size: 12px; letter-spacing: 0.5px; height: 20px; margin: 0; padding: 20px; user-select: none; -webkit-user-select: none; -moz-user-select: none; }
|
||||
.sidebar-closebutton { padding: 8px 8px 8px 32px; text-decoration: none; font-size: 25px; color: #777777; opacity: 1.0; display: block; transition: 0.2s; position: absolute; top: 0; right: 15px; margin-left: 50px; user-select: none; -webkit-user-select: none; -moz-user-select: none; }
|
||||
.sidebar-closebutton:hover { color: #242424; }
|
||||
.sidebar-content { padding-left: 20px; padding-right: 20px; margin-bottom: 20px; overflow-y: auto; height: calc(100vh - 60px); }
|
||||
|
||||
.sidebar-view-title { font-weight: bold; font-size: 11px; line-height: 1.25; border-bottom: 1px solid #ececec; padding-bottom: 0.3em; margin-top: 0; margin-bottom: 16px; color: #333; user-select: none; -webkit-user-select: none; -moz-user-select: none; cursor: default; }
|
||||
.sidebar-view-title-button { display: inline-block; color: #888; text-align: center; vertical-align: middle; font-weight: bold; width: 12px; height: 12px; font-size: 10px; line-height: 12px; border-radius: 50%; transform: translateY(-1px); padding: 1px; background: transparent; border: 1px solid #aaa; text-decoration: none; cursor: pointer; user-select: none; -webkit-user-select: none; -moz-user-select: none; }
|
||||
.sidebar-view-title-button:hover { color: #333; border: 1px solid #333; }
|
||||
.sidebar-view-header { font-weight: bold; font-size: 11px; text-transform: uppercase; line-height: 1.25; margin-top: 16px; margin-bottom: 16px; border-bottom: 1px solid #ececec; display: block; user-select: none; -webkit-user-select: none; -moz-user-select: none; cursor: default; }
|
||||
.sidebar-view-item { margin-bottom: 0px; display: block; }
|
||||
.sidebar-view-item-name { float: left; font-size: 11px; min-width: 95px; max-width: 95px; padding-right: 5px; padding-top: 7px; display: block; }
|
||||
.sidebar-view-item-name input { color: #777; font-family: inherit; font-size: inherit; color: inherit; background-color: inherit; width: 100%; text-align: right; margin: 0; padding: 0; border: 0; outline: none; text-overflow: ellipsis; }
|
||||
.sidebar-view-item-value-list { margin: 0; margin-left: 105px; overflow: hidden; display: block; padding: 0; }
|
||||
.sidebar-view-item-value { font-size: 11px; background-color: #fcfcfc; border-radius: 2px; border: 1px solid #fcfcfc; margin-top: 3px; margin-bottom: 3px; overflow: auto; }
|
||||
.sidebar-view-item-value-dark { background-color: #f8f8f8; border: 1px solid #f8f8f8; }
|
||||
.sidebar-view-item-value b { font-weight: bold; }
|
||||
.sidebar-view-item-value code { font-family: 'SFMono-Regular', Consolas, 'Liberation Mono', Menlo, Courier, monospace; overflow: auto; white-space: pre-wrap; word-wrap: break-word; }
|
||||
.sidebar-view-item-value pre { font-family: 'SFMono-Regular', Consolas, 'Liberation Mono', Menlo, Courier, monospace; margin: 0; overflow: auto; white-space: pre; word-wrap: normal; display: block; }
|
||||
.sidebar-view-item-value-line { padding: 4px 6px 4px 6px; }
|
||||
.sidebar-view-item-value-line-link { padding: 4px 6px 4px 6px; cursor: default; }
|
||||
.sidebar-view-item-value-line-link:hover { text-decoration: underline; }
|
||||
.sidebar-view-item-value-line-border { padding: 4px 6px 4px 6px; border-top: 1px solid rgba(27, 31, 35, 0.05); }
|
||||
.sidebar-view-item-value-line-content { white-space: pre; word-wrap: normal; overflow: auto; display: block; }
|
||||
.sidebar-view-item-value-expander { font-family: 'SFMono-Regular', Consolas, 'Liberation Mono', Menlo, Courier, monospace; float: right; color: #aaa; cursor: pointer; user-select: none; -webkit-user-select: none; -moz-user-select: none; padding: 4px 6px 4px 6px; }
|
||||
.sidebar-view-item-value-expander:hover { color: #000; }
|
||||
.sidebar-view-item-select {
|
||||
font-family: inherit; font-size: 12px;
|
||||
background-color: #fcfcfc; border: #fcfcfc; color: #333;
|
||||
border-radius: 2px; width: 100%; height: 23px; padding: 3px 12px 3px 7px;
|
||||
margin-top: 3px; margin-bottom: 3px; box-sizing: border-box; outline: none;
|
||||
-moz-box-sizing: border-box; -webkit-appearance: none; -moz-appearance: none;
|
||||
background-image: linear-gradient(45deg, transparent 50%, #333 50%), linear-gradient(135deg, #333 50%, transparent 50%);
|
||||
background-position: calc(100% - 12px) calc(10px), calc(100% - 7px) calc(10px);
|
||||
background-size: 5px 5px, 5px 5px;
|
||||
background-repeat: no-repeat;
|
||||
}
|
||||
.sidebar-view-separator { margin-bottom: 20px; }
|
||||
|
||||
.sidebar-view-find input[type=text] { font-family: inherit; font-size: 13px; padding: 4px 6px 4px 6px; background: #fff; border-radius: 4px; border: 1px solid #ccc; outline: 0; }
|
||||
.sidebar-view-find ol { list-style-type: none; overflow-y: auto; margin: 8px 0 20px 0; padding: 0; }
|
||||
.sidebar-view-find li { font-family: 'SFMono-Regular', Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 12px; margin: 0; padding: 5px 8px 5px 8px; outline: 0; white-space: nowrap; user-select: none; -webkit-user-select: none; -moz-user-select: none; }
|
||||
.sidebar-view-find li:not(:first-child) { border-top: 1px solid #f0f0f0; }
|
||||
.sidebar-view-find li:hover { background: #eee; }
|
||||
|
||||
.sidebar-view-documentation { font-size: 13px; line-height: 1.5; margin: 0; }
|
||||
.sidebar-view-documentation h1 { font-weight: bold; font-size: 13px; line-height: 1.25; border-bottom: 1px solid #e8e8e8; padding-bottom: 0.3em; margin-top: 0; margin-bottom: 16px; }
|
||||
.sidebar-view-documentation h2 { font-weight: bold; font-size: 11px; line-height: 1.25; margin-top: 20px; margin-bottom: 16px; text-transform: uppercase; border: 0; }
|
||||
.sidebar-view-documentation h3 { font-weight: bold; font-size: 11px; line-height: 1.25; }
|
||||
.sidebar-view-documentation p { margin-top: 4px; margin-bottom: 4px; margin-left: 0px; }
|
||||
.sidebar-view-documentation a { color: #237; }
|
||||
.sidebar-view-documentation code { font-family: 'SFMono-Regular', Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 12px; background-color: rgba(27, 31, 35, 0.05); padding: 0.2em 0.4em; margin: 0; border-radius: 3px; }
|
||||
.sidebar-view-documentation pre { font-family: 'SFMono-Regular', Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 12px; padding: 16px; overflow: auto; line-height: 1.45; background-color: rgba(27, 31, 35, 0.05); border-radius: 3px; }
|
||||
.sidebar-view-documentation pre code { font-size: 13px; padding: 16px; line-height: 1.45; background-color: transparent; padding: 0; border-radius: 0; }
|
||||
.sidebar-view-documentation tt { font-family: 'SFMono-Regular', Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-weight: bold; font-size: 90%; background-color: rgba(27, 31, 35, 0.05); border-radius: 3px; padding: 0.2em 0.4em; margin: 0; }
|
||||
.sidebar-view-documentation dl dt { font-size: 13px; font-weight: bold; padding: 0; margin-top: 16px; margin-left: 0px; }
|
||||
.sidebar-view-documentation dd { padding: 0 16px; margin-left: 0; margin-bottom: 16px; }
|
||||
.sidebar-view-documentation ul { margin-top: 6px; margin-bottom: 6px; padding-left: 20px; }
|
||||
.sidebar-view-documentation blockquote { margin-left: 15px; margin-right: 15px; }
|
||||
|
||||
@media (prefers-color-scheme: dark) {
|
||||
.sidebar html { color: #dfdfdf; }
|
||||
.sidebar { background-color: #2d2d2d; color: #dfdfdf; border-left: 1px solid #000; }
|
||||
.sidebar-closebutton { padding: 8px 8px 8px 32px; text-decoration: none; font-size: 25px; color: #777777; opacity: 1.0; display: block; transition: 0.2s; position: absolute; top: 0; right: 15px; margin-left: 50px; user-select: none; -webkit-user-select: none; -moz-user-select: none; }
|
||||
.sidebar-closebutton:hover { color: #ffffff; }
|
||||
.sidebar-view-item-value { background-color: #383838; border-color: #383838; }
|
||||
.sidebar-view-item-value-dark { background-color: #3e3e3e; border-color: #3e3e3e; }
|
||||
.sidebar-view-item-value-line-border { border-color: rgba(0, 0, 0, 0.09); }
|
||||
.sidebar-view-item-select { background-color: #383838; border: #383838; color: #dfdfdf; background-image: linear-gradient(45deg, transparent 50%, #aaa 50%), linear-gradient(135deg, #aaa 50%, transparent 50%); }
|
||||
|
||||
.sidebar-view-title { border-bottom-color: #2d2d2d; color: #dfdfdf; }
|
||||
.sidebar-view-title-button { color: #888888; border-color: #888888; }
|
||||
.sidebar-view-title-button:hover { color: #dfdfdf; border-color: #dfdfdf; }
|
||||
.sidebar-view-header { border-bottom-color: #2d2d2d; color: #dfdfdf; }
|
||||
|
||||
.sidebar-view-documentation h1 { border-bottom: 1px solid #424242; color: #dfdfdf; }
|
||||
.sidebar-view-documentation h2 { color: #dfdfdf; }
|
||||
.sidebar-view-documentation p { color: #aaaaaa; }
|
||||
.sidebar-view-documentation a { color: #6688aa; }
|
||||
.sidebar-view-documentation tt { background-color:#1e1e1e; }
|
||||
.sidebar-view-documentation code { background-color: #1e1e1e; }
|
||||
.sidebar-view-documentation pre { background-color: #1e1e1e; }
|
||||
|
||||
.sidebar-view-find input[type=text] { background: #383838; color: #dfdfdf; border-color: #424242; }
|
||||
.sidebar-view-find li:not(:first-child) { border-top: 1px solid #2a2a2a; }
|
||||
.sidebar-view-find li:hover { background: #383838; }
|
||||
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,256 @@
|
||||
|
||||
// Experimental
|
||||
|
||||
var weka = weka || {};
|
||||
var json = json || require('./json');
|
||||
var java = {};
|
||||
|
||||
weka.ModelFactory = class {
|
||||
|
||||
match(context) {
|
||||
try {
|
||||
const stream = context.stream;
|
||||
if (stream.length >= 5) {
|
||||
const signature = [ 0xac, 0xed ];
|
||||
if (stream.peek(2).every((value, index) => value === signature[index])) {
|
||||
const reader = new java.io.InputObjectStream(stream);
|
||||
const obj = reader.read();
|
||||
if (obj && obj.$class && obj.$class.name) {
|
||||
return 'weka';
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (err) {
|
||||
// continue regardless of error
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
|
||||
open(context) {
|
||||
return Promise.resolve().then(() => {
|
||||
const reader = new java.io.InputObjectStream(context.stream);
|
||||
const obj = reader.read();
|
||||
throw new weka.Error("Unsupported type '" + obj.$class.name + "'.");
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
weka.Error = class extends Error {
|
||||
|
||||
constructor(message) {
|
||||
super(message);
|
||||
this.name = 'Error loading Weka model.';
|
||||
}
|
||||
};
|
||||
|
||||
java.io = {};
|
||||
|
||||
java.io.InputObjectStream = class {
|
||||
|
||||
constructor(stream) {
|
||||
// Object Serialization Stream Protocol
|
||||
// https://www.cis.upenn.edu/~bcpierce/courses/629/jdkdocs/guide/serialization/spec/protocol.doc.html
|
||||
if (stream.length < 5) {
|
||||
throw new java.io.Error('Invalid stream size');
|
||||
}
|
||||
const signature = [ 0xac, 0xed ];
|
||||
if (!stream.peek(2).every((value, index) => value === signature[index])) {
|
||||
throw new java.io.Error('Invalid stream signature');
|
||||
}
|
||||
this._reader = new java.io.InputObjectStream.BinaryReader(stream.peek());
|
||||
this._references = [];
|
||||
this._reader.skip(2);
|
||||
const version = this._reader.uint16();
|
||||
if (version !== 0x0005) {
|
||||
throw new java.io.Error("Unsupported version '" + version + "'.");
|
||||
}
|
||||
}
|
||||
|
||||
read() {
|
||||
return this._object();
|
||||
}
|
||||
|
||||
_object() {
|
||||
const code = this._reader.byte();
|
||||
switch (code) {
|
||||
case 0x73: { // TC_OBJECT
|
||||
const obj = {};
|
||||
obj.$class = this._classDesc();
|
||||
this._newHandle(obj);
|
||||
this._classData(obj);
|
||||
return obj;
|
||||
}
|
||||
case 0x74: { // TC_STRING
|
||||
return this._newString(false);
|
||||
}
|
||||
}
|
||||
throw new java.io.Error("Unsupported code '" + code + "'.");
|
||||
}
|
||||
|
||||
_classDesc() {
|
||||
const code = this._reader.byte();
|
||||
switch (code) {
|
||||
case 0x72: // TC_CLASSDESC
|
||||
this._reader.skip(-1);
|
||||
return this._newClassDesc();
|
||||
case 0x71: // TC_REFERENCE
|
||||
return this._references[this._reader.uint32() - 0x7e0000];
|
||||
case 0x70: // TC_NULL
|
||||
this._reader.byte();
|
||||
return null;
|
||||
}
|
||||
throw new java.io.Error("Unsupported code '" + code + "'.");
|
||||
}
|
||||
|
||||
_newClassDesc() {
|
||||
const code = this._reader.byte();
|
||||
switch (code) {
|
||||
case 0x72: { // TC_CLASSDESC
|
||||
const classDesc = {};
|
||||
classDesc.name = this._reader.string(),
|
||||
classDesc.id = this._reader.uint64().toString();
|
||||
this._newHandle(classDesc);
|
||||
classDesc.flags = this._reader.byte();
|
||||
classDesc.fields = [];
|
||||
const count = this._reader.uint16();
|
||||
for (let i = 0; i < count; i++) {
|
||||
const field = {};
|
||||
field.type = String.fromCharCode(this._reader.byte());
|
||||
field.name = this._reader.string();
|
||||
if (field.type === '[' || field.type === 'L') {
|
||||
field.classname = this._object();
|
||||
}
|
||||
classDesc.fields.push(field);
|
||||
}
|
||||
if (this._reader.byte() !== 0x78) {
|
||||
throw new java.io.Error('Expected TC_ENDBLOCKDATA.');
|
||||
}
|
||||
classDesc.superClass = this._classDesc();
|
||||
return classDesc;
|
||||
}
|
||||
case 0x7D: // TC_PROXYCLASSDESC
|
||||
break;
|
||||
}
|
||||
throw new java.io.Error("Unsupported code '" + code + "'.");
|
||||
}
|
||||
|
||||
_classData(/* obj */) {
|
||||
/*
|
||||
const classname = obj.$class.name;
|
||||
let flags = obj.$class.flags;
|
||||
let superClass = obj.$class.superClass;
|
||||
while (superClass) {
|
||||
flags |= superClass.flags;
|
||||
superClass = superClass.superClass;
|
||||
}
|
||||
if (flags & 0x02) { // SC_SERIALIZABLE
|
||||
debugger;
|
||||
var customObject = objects[classname];
|
||||
var hasReadObjectMethod = customObject && customObject.readObject;
|
||||
if (flags & 0x01) { // SC_WRITE_METHOD
|
||||
if (!hasReadObjectMethod) {
|
||||
throw new Error('Class "'+ classname + '" dose not implement readObject()');
|
||||
}
|
||||
customObject.readObject(this, obj);
|
||||
if (this._reader.byte() !== 0x78) { // TC_ENDBLOCKDATA
|
||||
throw new java.io.Error('Expected TC_ENDBLOCKDATA.');
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (hasReadObjectMethod) {
|
||||
customObject.readObject(this, obj);
|
||||
if (this._reader.byte() !== 0x78) { // TC_ENDBLOCKDATA
|
||||
throw new java.io.Error('Expected TC_ENDBLOCKDATA.');
|
||||
}
|
||||
}
|
||||
else {
|
||||
this._nowrclass(obj);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (flags & 0x04) { // SC_EXTERNALIZABLE
|
||||
if (flags & 0x08) { // SC_BLOCK_DATA
|
||||
this._objectAnnotation(obj);
|
||||
}
|
||||
else {
|
||||
this._externalContents();
|
||||
}
|
||||
}
|
||||
else {
|
||||
throw new Error('Illegal flags: ' + flags);
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
_newString(long) {
|
||||
const value = this._reader.string(long);
|
||||
this._newHandle(value);
|
||||
return value;
|
||||
}
|
||||
|
||||
_newHandle(obj) {
|
||||
this._references.push(obj);
|
||||
}
|
||||
};
|
||||
|
||||
java.io.InputObjectStream.BinaryReader = class {
|
||||
|
||||
constructor(buffer) {
|
||||
this._buffer = buffer;
|
||||
this._position = 0;
|
||||
this._length = buffer.length;
|
||||
this._view = new DataView(buffer.buffer, buffer.byteOffset, buffer.byteLength);
|
||||
this._decoder = new TextDecoder('utf-8');
|
||||
}
|
||||
|
||||
skip(offset) {
|
||||
this._position += offset;
|
||||
if (this._position > this._end) {
|
||||
throw new java.io.Error('Expected ' + (this._position - this._end) + ' more bytes. The file might be corrupted. Unexpected end of file.');
|
||||
}
|
||||
}
|
||||
|
||||
byte() {
|
||||
const position = this._position;
|
||||
this.skip(1);
|
||||
return this._buffer[position];
|
||||
}
|
||||
|
||||
uint16() {
|
||||
const position = this._position;
|
||||
this.skip(2);
|
||||
return this._view.getUint16(position, false);
|
||||
}
|
||||
|
||||
uint32() {
|
||||
const position = this._position;
|
||||
this.skip(4);
|
||||
return this._view.getUint32(position, false);
|
||||
}
|
||||
|
||||
uint64() {
|
||||
const position = this._position;
|
||||
this.skip(8);
|
||||
return this._view.getUint64(position, false);
|
||||
}
|
||||
|
||||
string(long) {
|
||||
const size = long ? this.uint64().toNumber() : this.uint16();
|
||||
const position = this._position;
|
||||
this.skip(size);
|
||||
return this._decoder.decode(this._buffer.subarray(position, this._position));
|
||||
}
|
||||
};
|
||||
|
||||
java.io.Error = class extends Error {
|
||||
|
||||
constructor(message) {
|
||||
super(message);
|
||||
this.name = 'Error loading Object Serialization Stream Protocol.';
|
||||
}
|
||||
};
|
||||
|
||||
if (typeof module !== 'undefined' && typeof module.exports === 'object') {
|
||||
module.exports.ModelFactory = weka.ModelFactory;
|
||||
}
|
||||
@ -0,0 +1,713 @@
|
||||
|
||||
var zip = zip || {};
|
||||
var zlib = zlib || {};
|
||||
|
||||
zip.Archive = class {
|
||||
|
||||
static open(data) {
|
||||
const stream = data instanceof Uint8Array ? new zip.BinaryReader(data) : data;
|
||||
if (stream.length > 2) {
|
||||
const buffer = stream.peek(2);
|
||||
if (buffer[0] === 0x78) { // zlib
|
||||
const check = (buffer[0] << 8) + buffer[1];
|
||||
if (check % 31 === 0) {
|
||||
return new zlib.Archive(stream);
|
||||
}
|
||||
}
|
||||
const signature = buffer[0] === 0x50 && buffer[1] === 0x4B;
|
||||
const position = stream.position;
|
||||
const seek = (content) => {
|
||||
let position = stream.length;
|
||||
do {
|
||||
position = Math.max(0, position - 66000);
|
||||
stream.seek(position);
|
||||
const length = Math.min(stream.length - position, 66000 + 4);
|
||||
const buffer = stream.read(length);
|
||||
for (let i = buffer.length - 4; i >= 0; i--) {
|
||||
if (content[0] === buffer[i] && content[1] === buffer[i + 1] && content[2] === buffer[i + 2] && content[3] === buffer[i + 3]) {
|
||||
stream.seek(position + i + 4);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
if (!signature) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
while (position > 0);
|
||||
return false;
|
||||
};
|
||||
if (!seek([ 0x50, 0x4B, 0x05, 0x06 ])) {
|
||||
stream.seek(position);
|
||||
if (!signature) {
|
||||
return null;
|
||||
}
|
||||
throw new zip.Error('End of Zip central directory not found.');
|
||||
}
|
||||
const reader = new zip.BinaryReader(stream.read(16));
|
||||
reader.skip(12);
|
||||
let offset = reader.uint32(); // central directory offset
|
||||
if (offset > stream.length) {
|
||||
if (!seek([ 0x50, 0x4B, 0x06, 0x06 ])) {
|
||||
stream.seek(position);
|
||||
throw new zip.Error('End of Zip64 central directory not found.');
|
||||
}
|
||||
const reader = new zip.BinaryReader(stream.read(52));
|
||||
reader.skip(44);
|
||||
offset = reader.uint32();
|
||||
if (reader.uint32() !== 0) {
|
||||
stream.seek(position);
|
||||
throw new zip.Error('Zip 64-bit central directory offset not supported.');
|
||||
}
|
||||
}
|
||||
if (offset > stream.length) {
|
||||
stream.seek(position);
|
||||
throw new zip.Error('Invalid Zip central directory offset.');
|
||||
}
|
||||
stream.seek(offset);
|
||||
const archive = new zip.Archive(stream);
|
||||
stream.seek(position);
|
||||
return archive;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
constructor(stream) {
|
||||
this._entries = new Map();
|
||||
const headers = [];
|
||||
const signature = [ 0x50, 0x4B, 0x01, 0x02 ];
|
||||
while (stream.position + 4 < stream.length && stream.read(4).every((value, index) => value === signature[index])) {
|
||||
const header = {};
|
||||
const reader = new zip.BinaryReader(stream.read(42));
|
||||
reader.uint16(); // version made by
|
||||
reader.skip(2); // version needed to extract
|
||||
const flags = reader.uint16();
|
||||
if ((flags & 1) == 1) {
|
||||
throw new zip.Error('Encrypted Zip entries not supported.');
|
||||
}
|
||||
header.encoding = flags & 0x800 ? 'utf-8' : 'ascii';
|
||||
header.compressionMethod = reader.uint16();
|
||||
reader.uint32(); // date
|
||||
reader.uint32(); // crc32
|
||||
header.compressedSize = reader.uint32();
|
||||
header.size = reader.uint32();
|
||||
header.nameLength = reader.uint16(); // file name length
|
||||
const extraDataLength = reader.uint16();
|
||||
const commentLength = reader.uint16();
|
||||
header.disk = reader.uint16(); // disk number start
|
||||
reader.uint16(); // internal file attributes
|
||||
reader.uint32(); // external file attributes
|
||||
header.localHeaderOffset = reader.uint32();
|
||||
const nameBuffer = stream.read(header.nameLength);
|
||||
const decoder = new TextDecoder(header.encoding);
|
||||
header.name = decoder.decode(nameBuffer);
|
||||
const extraData = stream.read(extraDataLength);
|
||||
if (extraData.length > 0) {
|
||||
const reader = new zip.BinaryReader(extraData);
|
||||
while (reader.position < reader.length) {
|
||||
const type = reader.uint16();
|
||||
const length = reader.uint16();
|
||||
switch (type) {
|
||||
case 0x0001:
|
||||
if (header.size === 0xffffffff) {
|
||||
header.size = reader.uint32();
|
||||
if (reader.uint32() !== 0) {
|
||||
throw new zip.Error('Zip 64-bit offset not supported.');
|
||||
}
|
||||
}
|
||||
if (header.compressedSize === 0xffffffff) {
|
||||
header.compressedSize = reader.uint32();
|
||||
if (reader.uint32() !== 0) {
|
||||
throw new zip.Error('Zip 64-bit offset not supported.');
|
||||
}
|
||||
}
|
||||
if (header.localHeaderOffset === 0xffffffff) {
|
||||
header.localHeaderOffset = reader.uint32();
|
||||
if (reader.uint32() !== 0) {
|
||||
throw new zip.Error('Zip 64-bit offset not supported.');
|
||||
}
|
||||
}
|
||||
if (header.disk === 0xffff) {
|
||||
header.disk = reader.uint32();
|
||||
}
|
||||
break;
|
||||
default:
|
||||
reader.skip(length);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
stream.read(commentLength); // comment
|
||||
headers.push(header);
|
||||
}
|
||||
for (const header of headers) {
|
||||
if (header.size === 0 && header.name.endsWith('/')) {
|
||||
continue;
|
||||
}
|
||||
const entry = new zip.Entry(stream, header);
|
||||
this._entries.set(entry.name, entry.stream);
|
||||
}
|
||||
}
|
||||
|
||||
get entries() {
|
||||
return this._entries;
|
||||
}
|
||||
};
|
||||
|
||||
zip.Entry = class {
|
||||
|
||||
constructor(stream, header) {
|
||||
stream.seek(header.localHeaderOffset);
|
||||
const signature = [ 0x50, 0x4B, 0x03, 0x04 ];
|
||||
if (stream.position + 4 > stream.length || !stream.read(4).every((value, index) => value === signature[index])) {
|
||||
throw new zip.Error('Invalid Zip local file header signature.');
|
||||
}
|
||||
const reader = new zip.BinaryReader(stream.read(26));
|
||||
reader.skip(22);
|
||||
header.nameLength = reader.uint16();
|
||||
const extraDataLength = reader.uint16();
|
||||
header.nameBuffer = stream.read(header.nameLength);
|
||||
stream.skip(extraDataLength);
|
||||
const decoder = new TextDecoder(header.encoding);
|
||||
this._name = decoder.decode(header.nameBuffer);
|
||||
this._stream = stream.stream(header.compressedSize);
|
||||
switch (header.compressionMethod) {
|
||||
case 0: { // stored
|
||||
if (header.size !== header.compressedSize) {
|
||||
throw new zip.Error('Invalid compression size.');
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 8: { // deflate
|
||||
this._stream = new zip.InflaterStream(this._stream, header.size);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
throw new zip.Error('Invalid compression method.');
|
||||
}
|
||||
}
|
||||
|
||||
get name() {
|
||||
return this._name;
|
||||
}
|
||||
|
||||
get stream() {
|
||||
return this._stream;
|
||||
}
|
||||
};
|
||||
|
||||
zip.Inflater = class {
|
||||
|
||||
inflateRaw(data, length) {
|
||||
let buffer = null;
|
||||
if (typeof process === 'object' && typeof process.versions == 'object' && typeof process.versions.node !== 'undefined') {
|
||||
buffer = require('zlib').inflateRawSync(data);
|
||||
}
|
||||
else {
|
||||
const reader = new zip.BitReader(data);
|
||||
const writer = length === undefined ? new zip.BlockWriter() : new zip.BufferWriter(length);
|
||||
if (!zip.Inflater._staticLengthTree) {
|
||||
zip.Inflater._codeLengths = new Uint8Array(19);
|
||||
zip.Inflater._codeOrder = [ 16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15 ];
|
||||
zip.Inflater._lengthBase = [ 24, 32, 40, 48, 56, 64, 72, 80, 89, 105, 121, 137, 154, 186, 218, 250, 283, 347, 411, 475, 540, 668, 796, 924, 1053, 1309, 1565, 1821, 2064, 7992, 7992, 7992 ];
|
||||
zip.Inflater._distanceBase = [ 16, 32, 48, 64, 81, 113, 146, 210, 275, 403, 532, 788, 1045, 1557, 2070, 3094, 4119, 6167, 8216, 12312, 16409, 24601, 32794, 49178, 65563, 98331, 131100, 196636, 262173, 393245, 1048560, 1048560 ];
|
||||
}
|
||||
let type;
|
||||
do {
|
||||
type = reader.bits(3);
|
||||
switch (type >>> 1) {
|
||||
case 0: { // uncompressed block
|
||||
this._copyUncompressedBlock(reader, writer);
|
||||
break;
|
||||
}
|
||||
case 1: { // block with fixed huffman trees
|
||||
if (!zip.Inflater._staticLengthTree) {
|
||||
zip.Inflater._staticLengthTree = zip.HuffmanTree.create(new Uint8Array([].concat.apply([], [[144, 8], [112, 9], [24, 7], [8, 8]].map((x) => [...Array(x[0])].map(() => x[1])))));
|
||||
zip.Inflater._staticDistanceTree = zip.HuffmanTree.create(new Uint8Array([...Array(32)].map(() => 5)));
|
||||
}
|
||||
this._lengthTree = zip.Inflater._staticLengthTree;
|
||||
this._distanceTree = zip.Inflater._staticDistanceTree;
|
||||
this._inflateBlock(reader, writer);
|
||||
break;
|
||||
}
|
||||
case 2: { // block with dynamic huffman trees
|
||||
this._decodeTrees(reader);
|
||||
this._inflateBlock(reader, writer);
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
throw new zip.Error('Unknown block type.');
|
||||
}
|
||||
}
|
||||
} while ((type & 1) == 0);
|
||||
if (length !== undefined && length !== writer.length) {
|
||||
throw new zip.Error('Invalid uncompressed size.');
|
||||
}
|
||||
buffer = writer.toBuffer();
|
||||
}
|
||||
if (length !== undefined && length !== buffer.length) {
|
||||
throw new zip.Error('Invalid uncompressed size.');
|
||||
}
|
||||
return buffer;
|
||||
}
|
||||
|
||||
_copyUncompressedBlock(reader, writer) {
|
||||
const length = reader.uint16();
|
||||
const inverseLength = reader.uint16();
|
||||
if (length !== (~inverseLength & 0xffff)) {
|
||||
throw new zip.Error('Invalid uncompressed block length.');
|
||||
}
|
||||
writer.write(reader.read(length));
|
||||
}
|
||||
|
||||
_decodeTrees(reader) {
|
||||
const hlit = reader.bits(5) + 257;
|
||||
const hdist = reader.bits(5) + 1;
|
||||
const hclen = reader.bits(4) + 4;
|
||||
const codeLengths = zip.Inflater._codeLengths;
|
||||
for (let i = 0; i < codeLengths.length; i++) {
|
||||
codeLengths[i] = 0;
|
||||
}
|
||||
const codeOrder = zip.Inflater._codeOrder;
|
||||
for (let i = 0; i < hclen; i++) {
|
||||
codeLengths[codeOrder[i]] = reader.bits(3);
|
||||
}
|
||||
const codeTree = zip.HuffmanTree.create(codeLengths);
|
||||
const codeMask = codeTree.length - 1;
|
||||
const lengths = new Uint8Array(hlit + hdist);
|
||||
let value = 0;
|
||||
let length = 0;
|
||||
for (let i = 0; i < hlit + hdist;) {
|
||||
const code = codeTree[reader.bits16() & codeMask];
|
||||
reader.position += code & 0x0f;
|
||||
const literal = code >>> 4;
|
||||
switch (literal) {
|
||||
case 16: length = reader.bits(2) + 3; break;
|
||||
case 17: length = reader.bits(3) + 3; value = 0; break;
|
||||
case 18: length = reader.bits(7) + 11; value = 0; break;
|
||||
default: length = 1; value = literal; break;
|
||||
}
|
||||
for (; length > 0; length--) {
|
||||
lengths[i++] = value;
|
||||
}
|
||||
}
|
||||
this._lengthTree = zip.HuffmanTree.create(lengths.subarray(0, hlit));
|
||||
this._distanceTree = zip.HuffmanTree.create(lengths.subarray(hlit, hlit + hdist));
|
||||
}
|
||||
|
||||
_inflateBlock(reader, writer) {
|
||||
const lengthTree = this._lengthTree;
|
||||
const distanceTree = this._distanceTree;
|
||||
const lengthMask = lengthTree.length - 1;
|
||||
const distanceMask = distanceTree.length - 1;
|
||||
const buffer = writer.buffer;
|
||||
const threshold = writer.threshold !== undefined ? writer.threshold : writer.length;
|
||||
let position = writer.position;
|
||||
for (;;) {
|
||||
if (position > threshold) {
|
||||
position = writer.push(position);
|
||||
}
|
||||
const code = lengthTree[reader.bits16() & lengthMask];
|
||||
reader.position += code & 0x0f;
|
||||
const literal = code >>> 4;
|
||||
if (literal < 256) {
|
||||
buffer[position++] = literal;
|
||||
}
|
||||
else if (literal === 256) {
|
||||
writer.push(position);
|
||||
return;
|
||||
}
|
||||
else {
|
||||
let length = literal - 254;
|
||||
if (literal > 264) {
|
||||
const lengthBase = zip.Inflater._lengthBase[literal - 257];
|
||||
length = (lengthBase >>> 3) + reader.bits(lengthBase & 0x07);
|
||||
}
|
||||
const code = distanceTree[reader.bits16() & distanceMask];
|
||||
reader.position += code & 0x0f;
|
||||
const distanceBase = zip.Inflater._distanceBase[code >>> 4];
|
||||
const bits = distanceBase & 0x0f;
|
||||
const distance = (distanceBase >>> 4) + (reader.bits16() & ((1 << bits) - 1));
|
||||
reader.position += bits;
|
||||
let offset = position - distance;
|
||||
for (let i = 0; i < length; i++) {
|
||||
buffer[position++] = buffer[offset++];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
zip.HuffmanTree = class {
|
||||
|
||||
static create(tree) {
|
||||
let bits = tree[0];
|
||||
for (let i = 1; i < tree.length; ++i) {
|
||||
if (tree[i] > bits) {
|
||||
bits = tree[i];
|
||||
}
|
||||
}
|
||||
// Algorithm from https://github.com/photopea/UZIP.js
|
||||
let rev15 = zip.HuffmanTree._rev15;
|
||||
if (!rev15) {
|
||||
const length = 1 << 15;
|
||||
rev15 = new Uint16Array(length);
|
||||
for (let i = 0; i < length; i++) {
|
||||
let x = i;
|
||||
x = (((x & 0xaaaaaaaa) >>> 1) | ((x & 0x55555555) << 1));
|
||||
x = (((x & 0xcccccccc) >>> 2) | ((x & 0x33333333) << 2));
|
||||
x = (((x & 0xf0f0f0f0) >>> 4) | ((x & 0x0f0f0f0f) << 4));
|
||||
x = (((x & 0xff00ff00) >>> 8) | ((x & 0x00ff00ff) << 8));
|
||||
rev15[i] = (((x >>> 16) | (x << 16))) >>> 17;
|
||||
}
|
||||
zip.HuffmanTree._rev15 = rev15;
|
||||
zip.HuffmanTree._bitLengthCounts = new Uint16Array(16);
|
||||
zip.HuffmanTree._nextCodes = new Uint16Array(16);
|
||||
}
|
||||
const length = tree.length;
|
||||
const bitLengthCounts = zip.HuffmanTree._bitLengthCounts;
|
||||
for (let i = 0; i < 16; i++) {
|
||||
bitLengthCounts[i] = 0;
|
||||
}
|
||||
for (let i = 0; i < length; i++) {
|
||||
bitLengthCounts[tree[i]]++;
|
||||
}
|
||||
const nextCodes = zip.HuffmanTree._nextCodes;
|
||||
let code = 0;
|
||||
bitLengthCounts[0] = 0;
|
||||
for (let i = 0; i < bits; i++) {
|
||||
code = (code + bitLengthCounts[i]) << 1;
|
||||
nextCodes[i + 1] = code;
|
||||
}
|
||||
const codes = new Uint16Array(length);
|
||||
for (let i = 0; i < length; i++) {
|
||||
const index = tree[i];
|
||||
if (index !== 0) {
|
||||
codes[i] = nextCodes[index];
|
||||
nextCodes[index]++;
|
||||
}
|
||||
}
|
||||
const shift = 15 - bits;
|
||||
const table = new Uint16Array(1 << bits);
|
||||
for (let i = 0; i < length; i++) {
|
||||
const c = tree[i];
|
||||
if (c !== 0) {
|
||||
const value = (i << 4) | c;
|
||||
const rest = bits - c;
|
||||
let index = codes[i] << rest;
|
||||
const max = index + (1 << rest);
|
||||
for (; index != max; index++) {
|
||||
table[rev15[index] >>> shift] = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
return table;
|
||||
}
|
||||
};
|
||||
|
||||
zip.BitReader = class {
|
||||
|
||||
constructor(buffer) {
|
||||
this.buffer = buffer;
|
||||
this.position = 0;
|
||||
}
|
||||
|
||||
bits(count) {
|
||||
const offset = (this.position / 8) >> 0;
|
||||
const shift = (this.position & 7);
|
||||
this.position += count;
|
||||
return ((this.buffer[offset] | (this.buffer[offset + 1] << 8)) >>> shift) & ((1 << count) - 1);
|
||||
}
|
||||
|
||||
bits16() {
|
||||
const offset = (this.position / 8) >> 0;
|
||||
return ((this.buffer[offset] | (this.buffer[offset + 1] << 8) | (this.buffer[offset + 2] << 16)) >>> (this.position & 7));
|
||||
}
|
||||
|
||||
read(length) {
|
||||
this.position = (this.position + 7) & ~7; // align
|
||||
const offset = (this.position / 8) >> 0;
|
||||
this.position += length * 8;
|
||||
return this.buffer.subarray(offset, offset + length);
|
||||
}
|
||||
|
||||
uint16() {
|
||||
this.position = (this.position + 7) & ~7; // align
|
||||
const offset = (this.position / 8) >> 0;
|
||||
this.position += 16;
|
||||
return this.buffer[offset] | (this.buffer[offset + 1] << 8);
|
||||
}
|
||||
};
|
||||
|
||||
zip.BlockWriter = class {
|
||||
|
||||
constructor() {
|
||||
this.blocks = [];
|
||||
this.buffer = new Uint8Array(65536);
|
||||
this.position = 0;
|
||||
this.length = 0;
|
||||
this.threshold = 0xf400;
|
||||
}
|
||||
|
||||
push(position) {
|
||||
this.blocks.push(new Uint8Array(this.buffer.subarray(this.position, position)));
|
||||
this.length += position - this.position;
|
||||
this.position = position;
|
||||
return this._reset();
|
||||
}
|
||||
|
||||
write(buffer) {
|
||||
this.blocks.push(buffer);
|
||||
const length = buffer.length;
|
||||
this.length += length;
|
||||
if (length > 32768) {
|
||||
this.buffer.set(buffer.subarray(length - 32768, length), 0);
|
||||
this.position = 32768;
|
||||
}
|
||||
else {
|
||||
this._reset();
|
||||
this.buffer.set(buffer, this.position);
|
||||
this.position += length;
|
||||
}
|
||||
}
|
||||
|
||||
toBuffer() {
|
||||
const buffer = new Uint8Array(this.length);
|
||||
let offset = 0;
|
||||
for (const block of this.blocks) {
|
||||
buffer.set(block, offset);
|
||||
offset += block.length;
|
||||
}
|
||||
return buffer;
|
||||
}
|
||||
|
||||
_reset() {
|
||||
if (this.position > 32768) {
|
||||
this.buffer.set(this.buffer.subarray(this.position - 32768, this.position), 0);
|
||||
this.position = 32768;
|
||||
}
|
||||
return this.position;
|
||||
}
|
||||
};
|
||||
|
||||
zip.BufferWriter = class {
|
||||
|
||||
constructor(length) {
|
||||
this.buffer = new Uint8Array(length);
|
||||
this.length = length;
|
||||
this.position = 0;
|
||||
}
|
||||
|
||||
|
||||
push(position) {
|
||||
this.position = position;
|
||||
if (this.position > this.length) {
|
||||
throw new zip.Error('Invalid size.');
|
||||
}
|
||||
return this.position;
|
||||
}
|
||||
|
||||
write(buffer) {
|
||||
this.buffer.set(buffer, this.position);
|
||||
this.position += buffer.length;
|
||||
if (this.position > this.length) {
|
||||
throw new zip.Error('Invalid size.');
|
||||
}
|
||||
return this.position;
|
||||
}
|
||||
|
||||
toBuffer() {
|
||||
return this.buffer;
|
||||
}
|
||||
};
|
||||
|
||||
zip.InflaterStream = class {
|
||||
|
||||
constructor(stream, length) {
|
||||
this._stream = stream;
|
||||
this._offset = this._stream.position;
|
||||
this._position = 0;
|
||||
this._length = length;
|
||||
}
|
||||
|
||||
get position() {
|
||||
return this._position;
|
||||
}
|
||||
|
||||
get length() {
|
||||
if (this._length === undefined) {
|
||||
this._inflate();
|
||||
}
|
||||
return this._length;
|
||||
}
|
||||
|
||||
seek(position) {
|
||||
if (this._buffer === undefined) {
|
||||
this._inflate();
|
||||
}
|
||||
this._position = position >= 0 ? position : this._length + position;
|
||||
}
|
||||
|
||||
skip(offset) {
|
||||
if (this._buffer === undefined) {
|
||||
this._inflate();
|
||||
}
|
||||
this._position += offset;
|
||||
}
|
||||
|
||||
peek(length) {
|
||||
const position = this._position;
|
||||
length = length !== undefined ? length : this._length - position;
|
||||
this.skip(length);
|
||||
const end = this._position;
|
||||
this.seek(position);
|
||||
if (position === 0 && length === this._length) {
|
||||
return this._buffer;
|
||||
}
|
||||
return this._buffer.subarray(position, end);
|
||||
}
|
||||
|
||||
read(length) {
|
||||
const position = this._position;
|
||||
length = length !== undefined ? length : this._length - position;
|
||||
this.skip(length);
|
||||
if (position === 0 && length === this._length) {
|
||||
return this._buffer;
|
||||
}
|
||||
return this._buffer.subarray(position, this._position);
|
||||
}
|
||||
|
||||
byte() {
|
||||
const position = this._position;
|
||||
this.skip(1);
|
||||
return this._buffer[position];
|
||||
}
|
||||
|
||||
_inflate() {
|
||||
if (this._buffer === undefined) {
|
||||
const position = this._stream.position;
|
||||
this._stream.seek(this._offset);
|
||||
const buffer = this._stream.peek();
|
||||
this._buffer = new zip.Inflater().inflateRaw(buffer, this._length);
|
||||
this._length = this._buffer.length;
|
||||
this._stream.seek(position);
|
||||
delete this._stream;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
zip.BinaryReader = class {
|
||||
|
||||
constructor(buffer) {
|
||||
this._buffer = buffer;
|
||||
this._length = buffer.length;
|
||||
this._position = 0;
|
||||
this._view = new DataView(buffer.buffer, buffer.byteOffset, buffer.byteLength);
|
||||
}
|
||||
|
||||
get position() {
|
||||
return this._position;
|
||||
}
|
||||
|
||||
get length() {
|
||||
return this._length;
|
||||
}
|
||||
|
||||
create(buffer) {
|
||||
return new zip.BinaryReader(buffer);
|
||||
}
|
||||
|
||||
stream(length) {
|
||||
return this.create(this.read(length));
|
||||
}
|
||||
|
||||
seek(position) {
|
||||
this._position = position >= 0 ? position : this._length + position;
|
||||
}
|
||||
|
||||
skip(offset) {
|
||||
this._position += offset;
|
||||
}
|
||||
|
||||
peek(length) {
|
||||
if (this._position === 0 && length === undefined) {
|
||||
return this._buffer;
|
||||
}
|
||||
const position = this._position;
|
||||
this.skip(length !== undefined ? length : this._length - this._position);
|
||||
const end = this._position;
|
||||
this.seek(position);
|
||||
return this._buffer.subarray(position, end);
|
||||
}
|
||||
|
||||
read(length) {
|
||||
if (this._position === 0 && length === undefined) {
|
||||
this._position = this._length;
|
||||
return this._buffer;
|
||||
}
|
||||
const position = this._position;
|
||||
this.skip(length !== undefined ? length : this._length - this._position);
|
||||
return this._buffer.subarray(position, this._position);
|
||||
}
|
||||
|
||||
byte() {
|
||||
const position = this._position;
|
||||
this.skip(1);
|
||||
return this._buffer[position];
|
||||
}
|
||||
|
||||
uint16() {
|
||||
const position = this._position;
|
||||
this.skip(2);
|
||||
return this._view.getUint16(position, true);
|
||||
}
|
||||
|
||||
uint32() {
|
||||
const position = this._position;
|
||||
this.skip(4);
|
||||
return this._view.getUint32(position, true);
|
||||
}
|
||||
};
|
||||
|
||||
zlib.Archive = class {
|
||||
|
||||
constructor(stream) {
|
||||
const position = stream.position;
|
||||
stream.read(2);
|
||||
const entry = new zlib.Entry(stream);
|
||||
this._entries = new Map([ [ entry.name, entry.stream ] ]);
|
||||
stream.seek(position);
|
||||
}
|
||||
|
||||
get entries() {
|
||||
return this._entries;
|
||||
}
|
||||
};
|
||||
|
||||
zlib.Entry = class {
|
||||
|
||||
constructor(stream) {
|
||||
this._stream = new zip.InflaterStream(stream);
|
||||
}
|
||||
|
||||
get name() {
|
||||
return '';
|
||||
}
|
||||
|
||||
get stream() {
|
||||
return this._stream;
|
||||
}
|
||||
};
|
||||
|
||||
zip.Error = class extends Error {
|
||||
|
||||
constructor(message) {
|
||||
super(message);
|
||||
this.name = 'Zip Error';
|
||||
this.stack = undefined;
|
||||
}
|
||||
};
|
||||
|
||||
if (typeof module !== 'undefined' && typeof module.exports === 'object') {
|
||||
module.exports.Archive = zip.Archive;
|
||||
module.exports.Inflater = zip.Inflater;
|
||||
}
|
||||
Loading…
Reference in New Issue