diff --git a/src/lzma/bit-tree-decoder.ts b/src/lzma/bit-tree-decoder.ts new file mode 100644 index 0000000..2319586 --- /dev/null +++ b/src/lzma/bit-tree-decoder.ts @@ -0,0 +1,42 @@ +import { RangeDecoder } from './range-decoder'; +import { LZMA } from './lzma'; + +/** + * LZMA Decoder + * @author Nidin Vinayakan + */ +export class BitTreeDecoder { + public probs: Uint16Array + private numBits: u32 + + constructor(numBits:u32) { + this.numBits = numBits + this.probs = new Uint16Array(1 << this.numBits) + } + + @inline + public init(): void { + LZMA.INIT_PROBS(this.probs) + } + + @inline + public decode(rc: RangeDecoder): u32 { + var m: u32 = 1 + for (var i: u32 = 0; i < this.numBits; i++) m = (m << 1) + rc.decodeBit(this.probs, m) + return m - (1 << this.numBits) + } + + @inline + public reverseDecode(rc: RangeDecoder): i32 { + return LZMA.BitTreeReverseDecode(this.probs, this.numBits, rc) + } + + @inline + static constructArray(numBits: i32, len: i32): Array { + var vec: BitTreeDecoder[] = new Array(len) + for (var i: i32 = 0; i < len; i++) { + vec.__unchecked_set(i, new BitTreeDecoder(numBits)) + } + return vec + } +} \ No newline at end of file diff --git a/src/lzma/len-decoder.ts b/src/lzma/len-decoder.ts new file mode 100644 index 0000000..dd99178 --- /dev/null +++ b/src/lzma/len-decoder.ts @@ -0,0 +1,42 @@ +import { BitTreeDecoder } from './bit-tree-decoder' +import { LZMA } from './lzma' +import { RangeDecoder } from './range-decoder' + +/** + * LZMA Decoder + * @author Nidin Vinayakan + */ + +export class LenDecoder { + private choice: Uint16Array + private lowCoder: Array + private midCoder: Array + private highCoder: BitTreeDecoder + + constructor() { + this.lowCoder = BitTreeDecoder.constructArray(3, 1 << LZMA.kNumPosBitsMax) + this.midCoder = BitTreeDecoder.constructArray(3, 1 << LZMA.kNumPosBitsMax) + this.highCoder = new BitTreeDecoder(8) + } + + public init(): void { + this.choice = new Uint16Array(2) + this.choice.__unchecked_set(0, LZMA.PROB_INIT_VAL) + this.choice.__unchecked_set(1, LZMA.PROB_INIT_VAL) + this.highCoder.init() + for (var i: i32 = 0; i < 1 << LZMA.kNumPosBitsMax; i++) { + this.lowCoder[i].init() + this.midCoder[i].init() + } + } + + public decode(rc: RangeDecoder, posState: i32): i32 { + if (rc.decodeBit(this.choice, 0) == 0) { + return this.lowCoder[posState].decode(rc) + } + if (rc.decodeBit(this.choice, 1) == 0) { + return 8 + this.midCoder[posState].decode(rc) + } + return 16 + this.highCoder.decode(rc) + } +} \ No newline at end of file diff --git a/src/lzma/lzma-decoder.ts b/src/lzma/lzma-decoder.ts new file mode 100644 index 0000000..5bdd53f --- /dev/null +++ b/src/lzma/lzma-decoder.ts @@ -0,0 +1,312 @@ +import { RangeDecoder } from './range-decoder'; +import { OutWindow } from './out-window'; +import { BitTreeDecoder } from './bit-tree-decoder'; +import { LenDecoder } from './len-decoder'; +import { LZMA } from './lzma'; + +/** + * LZMA Decoder + * @author Nidin Vinayakan + */ +export class LzmaDecoder { + //Public + public markerIsMandatory: boolean + public rangeDec: RangeDecoder //RangeDecoder + public outWindow: OutWindow //OutWindow + public lc: i32 + public pb: i32 + public lp: u8 + public dictSize: u32 + public dictSizeInProperties: u32 + + //Private + private litProbs: Uint16Array + + private posSlotDecoder: Array + private alignDecoder: BitTreeDecoder + private posDecoders: Uint16Array + + private isMatch: Uint16Array + private isRep: Uint16Array + private isRepG0: Uint16Array + private isRepG1: Uint16Array + private isRepG2: Uint16Array + private isRep0Long: Uint16Array + + private lenDecoder: LenDecoder + private repLenDecoder: LenDecoder + + constructor() { + this.posSlotDecoder = BitTreeDecoder.constructArray(6, LZMA.kNumLenToPosStates) //6 + this.alignDecoder = new BitTreeDecoder(LZMA.kNumAlignBits) + this.posDecoders = new Uint16Array(1 + LZMA.kNumFullDistances - LZMA.kEndPosModelIndex) + + this.isMatch = new Uint16Array(LZMA.kNumStates << LZMA.kNumPosBitsMax) + this.isRep = new Uint16Array(LZMA.kNumStates) + this.isRepG0 = new Uint16Array(LZMA.kNumStates) + this.isRepG1 = new Uint16Array(LZMA.kNumStates) + this.isRepG2 = new Uint16Array(LZMA.kNumStates) + this.isRep0Long = new Uint16Array(LZMA.kNumStates << LZMA.kNumPosBitsMax) + + this.lenDecoder = new LenDecoder() + this.repLenDecoder = new LenDecoder() + this.rangeDec = new RangeDecoder() + this.outWindow = new OutWindow() + } + + public init(): void { + this.initLiterals() + this.initDist() + + LZMA.INIT_PROBS(this.isMatch) + LZMA.INIT_PROBS(this.isRep) + LZMA.INIT_PROBS(this.isRepG0) + LZMA.INIT_PROBS(this.isRepG1) + LZMA.INIT_PROBS(this.isRepG2) + LZMA.INIT_PROBS(this.isRep0Long) + + this.lenDecoder.init() + this.repLenDecoder.init() + } + + public create(): void { + this.outWindow.create(this.dictSize) + this.createLiterals() + } + + @inline + private createLiterals(): void { + this.litProbs = new Uint16Array(0x300 << (this.lc + this.lp)) + } + + @inline + private initLiterals(): void { + var num: i32 = 0x300 << (this.lc + this.lp) + for (var i: i32 = 0; i < num; i++) { + this.litProbs.__unchecked_set(i, LZMA.PROB_INIT_VAL) + } + } + + @inline + private decodeLiteral(state:u16, rep0:u32): void { + var prevByte:u32 = 0 + if (!this.outWindow.isEmpty()) prevByte = this.outWindow.getByte(1) + + var symbol:u16 = 1 + var litState:u32 = + ((this.outWindow.totalPos & ((1 << this.lp) - 1)) << this.lc) + + (prevByte >>> (8 - this.lc)) + var probsOffset: i32 = (0x300 * litState) | 0 + + if (state >= 7) { + let matchByte = this.outWindow.getByte(rep0 + 1) + do { + let matchBit = (matchByte >>> 7) & 1 + matchByte <<= 1 + let bit = this.rangeDec.decodeBit( + this.litProbs, + probsOffset + ((1 + matchBit) << 8) + symbol, + ) + symbol = (symbol << 1) | bit + if (matchBit != bit) break + } while (symbol < 0x100) + } + while (symbol < 0x100) { + symbol = + (symbol << 1) | + this.rangeDec.decodeBit(this.litProbs, probsOffset + symbol) + } + this.outWindow.putByte((symbol - 0x100)) + } + + private decodeDistance(len: i32): u32 { + var lenState: u32 = len + if (lenState > LZMA.kNumLenToPosStates - 1) lenState = LZMA.kNumLenToPosStates - 1 + + var posSlot:u32 = this.posSlotDecoder[lenState].decode(this.rangeDec) + if (posSlot < 4) return posSlot + + var numDirectBits:u32 = (posSlot >>> 1) - 1 + var dist:u32 = (2 | (posSlot & 1)) << numDirectBits + if (posSlot < LZMA.kEndPosModelIndex) { + dist += LZMA.BitTreeReverseDecode( + this.posDecoders, + numDirectBits, + this.rangeDec, + dist - posSlot, + ) + } else { + dist += + this.rangeDec.decodeDirectBits(numDirectBits - LZMA.kNumAlignBits) << LZMA.kNumAlignBits + dist += this.alignDecoder.reverseDecode(this.rangeDec) + } + return dist + } + + @inline + private initDist(): void { + for (var i:u32 = 0; i < LZMA.kNumLenToPosStates; i++) { + this.posSlotDecoder[i].init() + } + this.alignDecoder.init() + LZMA.INIT_PROBS(this.posDecoders) + } + + @inline + public decodeProperties(properties: Uint8Array): void { + var prop = new Uint8Array(4) + var p0 = properties.__unchecked_get(0) + prop.__unchecked_set(0, p0) + if (p0 >= 9 * 5 * 5) { + throw 1 + // throw 'Incorrect LZMA properties' + } + var p1 = p0 % 9 + prop.__unchecked_set(1, p1) + p0 /= 9 + prop.__unchecked_set(0, p0) + var p2 = p0 / 5 + var p3 = p0 % 5 + + prop.__unchecked_set(2, p2) + prop.__unchecked_set(3, p3) + + this.lc = p1 + this.pb = p2 + this.lp = p3 + + this.dictSizeInProperties = 0 + for (var i: u32 = 0; i < 4; i++) { + this.dictSizeInProperties |= properties.__unchecked_get(i + 1) << (8 * i) + } + this.dictSize = this.dictSizeInProperties + + if (this.dictSize < LZMA.LZMA_DIC_MIN) { + this.dictSize = LZMA.LZMA_DIC_MIN + } + } + + @inline + private updateState_Literal(state: u8): u8 { + if (state < 4) return 0 + else if (state < 10) return state - 3 + else return state - 6 + } + + @inline + private updateState_ShortRep(state: u8): u8 { + return state < 7 ? 9 : 11 + } + + @inline + private updateState_Rep(state: u8): u8 { + return state < 7 ? 8 : 11 + } + + @inline + private updateState_Match(state: u8): u8 { + return state < 7 ? 7 : 10 + } + + public decode(unpackSizeDefined: boolean, unpackSize: i32): i32 { + this.init() + this.rangeDec.init() + + if (unpackSizeDefined) { + this.outWindow.outStream = new Uint8Array(unpackSize) + } else { + this.outWindow.outStream = new Uint8Array(4) + } + + var rep0:u32 = 0, + rep1:u32 = 0, + rep2:u32 = 0, + rep3:u32 = 0 + var state:u8 = 0 + + for (;;) { + if (unpackSizeDefined && unpackSize == 0 && !this.markerIsMandatory) { + if (this.rangeDec.isFinishedOK()) { + return LZMA.LZMA_RES_FINISHED_WITHOUT_MARKER + } + } + + var posState = this.outWindow.totalPos & ((1 << this.pb) - 1) + + if (this.rangeDec.decodeBit(this.isMatch, (state << LZMA.kNumPosBitsMax) + posState) == 0) { + if (unpackSizeDefined && unpackSize == 0) { + return LZMA.LZMA_RES_ERROR + } + this.decodeLiteral(state, rep0) + state = this.updateState_Literal(state) + unpackSize-- + continue + } + + var len: i32 + + if (this.rangeDec.decodeBit(this.isRep, state) != 0) { + if (unpackSizeDefined && unpackSize == 0) { + return LZMA.LZMA_RES_ERROR + } + if (this.outWindow.isEmpty()) { + return LZMA.LZMA_RES_ERROR + } + if (this.rangeDec.decodeBit(this.isRepG0, state) == 0) { + if (this.rangeDec.decodeBit(this.isRep0Long, (state << LZMA.kNumPosBitsMax) + posState) == 0) { + state = this.updateState_ShortRep(state) + this.outWindow.putByte(this.outWindow.getByte(rep0 + 1)) + unpackSize-- + continue + } + } else { + var dist: i32 + if (this.rangeDec.decodeBit(this.isRepG1, state) == 0) { + dist = rep1 + } else { + if (this.rangeDec.decodeBit(this.isRepG2, state) == 0) { + dist = rep2 + } else { + dist = rep3 + rep3 = rep2 + } + rep2 = rep1 + } + rep1 = rep0 + rep0 = dist + } + len = this.repLenDecoder.decode(this.rangeDec, posState) + state = this.updateState_Rep(state) + } else { + rep3 = rep2 + rep2 = rep1 + rep1 = rep0 + len = this.lenDecoder.decode(this.rangeDec, posState) + state = this.updateState_Match(state) + rep0 = this.decodeDistance(len) + if (rep0 == 0xffffffff) { + return this.rangeDec.isFinishedOK() ? LZMA.LZMA_RES_FINISHED_WITH_MARKER : LZMA.LZMA_RES_ERROR + } + + if (unpackSizeDefined && unpackSize == 0) { + return LZMA.LZMA_RES_ERROR + } + if (rep0 >= this.dictSize || !this.outWindow.checkDistance(rep0)) { + return LZMA.LZMA_RES_ERROR + } + } + len += LZMA.kMatchMinLen + var isError: boolean = false + if (unpackSizeDefined && unpackSize < len) { + len = unpackSize + isError = true + } + this.outWindow.copyMatch(rep0 + 1, len) + unpackSize -= len + if (isError) { + return LZMA.LZMA_RES_ERROR + } + } + return LZMA.LZMA_RES_ERROR + } +} \ No newline at end of file diff --git a/src/lzma/lzma-helper.ts b/src/lzma/lzma-helper.ts new file mode 100644 index 0000000..9ad3e81 --- /dev/null +++ b/src/lzma/lzma-helper.ts @@ -0,0 +1,43 @@ +import { LZMA } from './lzma' + +export class LZMAHelper { + static decoder: LZMA = new LZMA() + static decoderAsync: Worker = new Worker('LZMAWorker.min.js') + static callback: Function + static ENCODE: number = 1 + static DECODE: number = 2 + + static init(): void { + var command = 0 + LZMAHelper.decoderAsync.onmessage = function(e) { + if (command == 0) { + command = e.data + } else if (command == LZMAHelper.ENCODE) { + command = 0 //encode not implemented + } else if (command == LZMAHelper.DECODE) { + command = 0 + LZMAHelper.callback(e.data) + LZMAHelper.callback = null + } + } + } + + static encode(data: ArrayBuffer): ArrayBuffer { + return null + } + static decode(data: ArrayBuffer): ArrayBuffer { + return LZMAHelper.decoder.decode(new Uint8Array(data)).buffer + } + static encodeAsync(data: ArrayBuffer, _callback: Function): void {} + static decodeAsync(data: ArrayBuffer, _callback: Function): void { + if (LZMAHelper.callback == null) { + LZMAHelper.callback = _callback + LZMAHelper.decoderAsync.postMessage(LZMAHelper.DECODE) + LZMAHelper.decoderAsync.postMessage(data, [data]) + } else { + console.log('Warning! Another LZMA decoding is running...') + } + } +} + +LZMAHelper.init() \ No newline at end of file diff --git a/src/lzma/lzma-worker.ts b/src/lzma/lzma-worker.ts new file mode 100644 index 0000000..358bc37 --- /dev/null +++ b/src/lzma/lzma-worker.ts @@ -0,0 +1,36 @@ +import { LZMA } from './lzma' + +export class LZMAWorker { + static ENCODE: number = 1 + static DECODE: number = 2 + private decoder: LZMA + private command: Object = null + private time: number + + constructor() { + var _this = this + this.decoder = new LZMA() + + addEventListener( + 'message', + (e: any) => { + if (_this.command == null) { + _this.command = e.data + } else if (_this.command['job'] == 1) { + _this.command = null + } else if (_this.command['job'] == 2) { + _this.decode(e.data) + } + }, + false + ) + } + private decode(data): void { + this.time = Date.now() + var result = this.decoder.decode(new Uint8Array(data)) + this.command['time'] = Date.now() - this.time + ;(postMessage)(this.command) + ;(postMessage)(result.buffer, [result.buffer]) + } +} +new LZMAWorker() diff --git a/src/lzma/lzma.ts b/src/lzma/lzma.ts new file mode 100644 index 0000000..ff88863 --- /dev/null +++ b/src/lzma/lzma.ts @@ -0,0 +1,135 @@ +import { LzmaDecoder } from './lzma-decoder' +import { RangeDecoder } from './range-decoder' +;('use strict') +/** + * LZMA Decoder + * @author Nidin Vinayakan + */ + +export class DecodeResult { + constructor( + public success: u32, + public errorCode: u32, + public unpackSize: i32, + public data: Uint8Array + ) {} +} + +export class LZMA { + static readonly LZMA_DIC_MIN: u32 = 1 << 12 + static readonly LZMA_RES_ERROR: u32 = 0x1 + static readonly LZMA_RES_FINISHED_WITH_MARKER: u32 = 0x2 + static readonly LZMA_RES_FINISHED_WITHOUT_MARKER: u32 = 0x3 + static readonly kNumBitModelTotalBits: u16 = 11 + static readonly kNumMoveBits: u8 = 5 + static readonly PROB_INIT_VAL: u16 = (1 << LZMA.kNumBitModelTotalBits) / 2 //1024 + static readonly kNumPosBitsMax: u8 = 4 + + static readonly kNumStates: u32 = 12 + static readonly kNumLenToPosStates: u32 = 4 + static readonly kNumAlignBits: u32 = 4 + static readonly kStartPosModelIndex: u32 = 4 + static readonly kEndPosModelIndex: u32 = 14 + static readonly kNumFullDistances: u32 = 1 << (LZMA.kEndPosModelIndex >>> 1) + static readonly kMatchMinLen: u32 = 2 + + public decoder: LzmaDecoder + public data: Uint8Array + + @inline + static INIT_PROBS(p: Uint16Array): void { + p.fill(LZMA.PROB_INIT_VAL) + } + + static BitTreeReverseDecode( + probs: Uint16Array, + numBits: i32, + rc: RangeDecoder, + offset: i32 = 0 + ): i32 { + var m: u32 = 1 + var symbol: u32 = 0 + for (var i: i32 = 0; i < numBits; i++) { + var bit: u32 = rc.decodeBit(probs, offset + m) + m <<= 1 + m += bit + symbol |= bit << i + } + return symbol + } + + constructor() { + this.decoder = new LzmaDecoder() + } + + public unpackSize(data: Uint8Array): u32 { + var header: Uint8Array = new Uint8Array(13) + var i: i32 + for (i = 0; i < 13; i++) { + header[i] = data[i] + } + + var unpackSize: u32 = 0 + var unpackSizeDefined: boolean = false + for (i = 0; i < 8; i++) { + var b: u32 = header[5 + i] + if (b != 0xff) { + unpackSizeDefined = true + } + unpackSize |= b << (8 * i) + } + return unpackSize + } + + public decode(data: Uint8Array): DecodeResult { + this.data = data + var header: Uint8Array = new Uint8Array(13) + var i: i32 + for (i = 0; i < 13; i++) { + header[i] = data[i] + } + this.decoder.decodeProperties(header) + var unpackSize: u32 = 0 + var unpackSizeDefined: boolean = false + for (i = 0; i < 8; i++) { + var b: u32 = header[5 + i] + if (b != 0xff) { + unpackSizeDefined = true + } + unpackSize |= b << (8 * i) + } + + this.decoder.markerIsMandatory = !unpackSizeDefined + this.decoder.rangeDec.inStream = data + this.decoder.create() + // we support the streams that have uncompressed size and marker. + var res: i32 = this.decoder.decode(unpackSizeDefined, unpackSize) + + if (res == LZMA.LZMA_RES_ERROR) { + return new DecodeResult(false, LZMA.LZMA_RES_ERROR, null, null) + //throw 'LZMA decoding error' + } else if (res == LZMA.LZMA_RES_FINISHED_WITHOUT_MARKER) { + //console.log("Finished without end marker"); + } else if (res == LZMA.LZMA_RES_FINISHED_WITH_MARKER) { + if (unpackSizeDefined) { + if (this.decoder.outWindow.out_pos != unpackSize) { + return new DecodeResult(false, LZMA.LZMA_RES_ERROR, null, null) + //throw 'Finished with end marker before than specified size' + } + } + } else { + return new DecodeResult(false, LZMA.LZMA_RES_ERROR, null, null) + //throw 'Internal Error' + } + + if (this.decoder.rangeDec.corrupted) { + // console.log('Warning: LZMA stream is corrupted') + } + return new DecodeResult( + true, + null, + this.decoder.outWindow.out_pos, + this.decoder.outWindow.outStream + ) + } +} diff --git a/src/lzma/out-window.ts b/src/lzma/out-window.ts new file mode 100644 index 0000000..cd8c673 --- /dev/null +++ b/src/lzma/out-window.ts @@ -0,0 +1,92 @@ +import { HEADER_SIZE } from "~lib/internal/arraybuffer"; +/** + * LZMA Decoder + * @author Nidin Vinayakan + */ +export class OutWindow { + public totalPos: i32 + public outStream: Uint8Array + + private buf: Uint8Array + private pos: i32 + public out_pos: i32 + private size: i32 + private isFull: boolean + + constructor() { + this.out_pos = 0 + } + + public create( + dictSize: i32, + ): void { + this.buf = new Uint8Array(dictSize) + this.pos = 0 + this.size = dictSize + this.isFull = false + this.totalPos = 0 + } + + @inline + public putByte(b: u8): void { + this.totalPos++ + this.buf.__unchecked_set(this.pos++, b) + if (this.pos == this.size) { + this.pos = 0 + this.isFull = true + } + if (this.outStream.length === this.out_pos) { + this.grow() + } + this.outStream.__unchecked_set(this.out_pos++, b) + } + + @inline + private grow(): void { + let tmp = this.outStream + this.outStream = new Uint8Array(tmp.length * 2) + + memory.copy( + changetype(this.outStream.buffer) + this.outStream.byteOffset + HEADER_SIZE, + changetype(tmp.buffer) + tmp.byteOffset + HEADER_SIZE, + tmp.length + ); + + let tmp_ptr = tmp; + let AB_ptr = load(tmp_ptr, 0); + __memory_free(AB_ptr); + __memory_free(tmp_ptr) + } + + public trim(): Uint8Array { + var out = this.outStream.subarray(0, this.out_pos) + return out + } + + @inline + public getByte( + dist: i32, + ): u8 { + return this.buf.__unchecked_get(dist <= this.pos ? this.pos - dist : this.size - dist + this.pos) + } + + @inline + public copyMatch( + dist: i32, + len:i32, + ): void { + for (; len > 0; len--) { + this.putByte(this.getByte(dist)) + } + } + + @inline + public checkDistance(dist: i32): boolean { + return dist <= this.pos || this.isFull + } + + @inline + public isEmpty(): boolean { + return this.pos == 0 && !this.isFull + } +} \ No newline at end of file diff --git a/src/lzma/range-decoder.ts b/src/lzma/range-decoder.ts new file mode 100644 index 0000000..a7bba24 --- /dev/null +++ b/src/lzma/range-decoder.ts @@ -0,0 +1,96 @@ +import { LZMA } from "./lzma"; + +/** + * LZMA Decoder + * @author Nidin Vinayakan + */ +export class RangeDecoder { + static kTopValue: u32 = 1 << 24 + + public inStream: Uint8Array + public corrupted: boolean + + public in_pos: i32 + private range: u32 = 0 + private code: u32 = 0 + + constructor() { + this.in_pos = 13 + } + + @inline + public isFinishedOK(): boolean { + return this.code == 0 + } + + @inline + public init(): void { + this.corrupted = false + + if (this.inStream[this.in_pos++] != 0) { + this.corrupted = true + } + + this.range = 0xffffffff + this.code = 0 + + for (var i: i32 = 0; i < 4; i++) { + this.code = (this.code << 8) | this.inStream[this.in_pos++] + } + + if (this.code == this.range) { + this.corrupted = true + } + } + + @inline + public normalize():void { + if (this.range < RangeDecoder.kTopValue) { + this.range <<= 8 + this.code = (this.code << 8) | this.inStream[this.in_pos++] + } + } + + @inline + public decodeDirectBits(numBits: i32): i32 { + var res:u32 = 0 + do { + this.range >>>= 1 + this.code -= this.range + let t:u32 = 0 - (this.code >>> 31) + this.code += this.range & t + + if (this.code == this.range) { + this.corrupted = true + } + + this.normalize() + res <<= 1 + res += t + 1 + } while (--numBits) + return res + } + + @inline + decodeBit(prob: Uint16Array, index: i32):u16 { + var v:u16 = prob.__unchecked_get(index); + var bound:u32 = (this.range >> LZMA.kNumBitModelTotalBits) * v; + var symbol:u16 = 0; + if (this.code < bound) + { + v += ((1 << LZMA.kNumBitModelTotalBits) - v) >> LZMA.kNumMoveBits; + this.range = bound; + symbol = 0; + } + else + { + v -= v >> LZMA.kNumMoveBits; + this.code -= bound; + this.range -= bound; + symbol = 1; + } + prob.__unchecked_set(index, v) + this.normalize(); + return symbol; + } +} \ No newline at end of file diff --git a/src/mappings/metadata.ts b/src/mappings/metadata.ts index bac801f..f15e15a 100644 --- a/src/mappings/metadata.ts +++ b/src/mappings/metadata.ts @@ -1,7 +1,16 @@ -import { BigInt, ethereum } from '@graphprotocol/graph-ts' +import { + json, + BigInt, + ethereum, + log, + Bytes, + JSONValue, + JSONValueKind +} from '@graphprotocol/graph-ts' import { MetadataUpdated, MetadataCreated } from '../@types/Metadata/Metadata' import { Datatoken, MetadataUpdate } from '../@types/schema' +import { LZMA } from '../lzma/lzma' export function handleMetadataEvent( event: ethereum.Event, @@ -36,8 +45,26 @@ export function handleMetadataUpdated(event: MetadataUpdated): void { false ) } +export function jsonToString(val: JSONValue | null): string { + if (val != null && val.kind === JSONValueKind.STRING) { + return val.toString() + } + return '' +} export function handleMetadataCreated(event: MetadataCreated): void { + const lzma = new LZMA() + const data = lzma.decode(event.params.data) + + const obj = json.fromBytes(data.data as Bytes).toObject() + const did = obj.get('id') + const name = obj.get('service.attributes.main.name') + log.info('!!!!!!!!!!!!!!!!!!!!! DECOMPRESSED DATA {} {} {}', [ + name.toString(), + did.toString(), + (data.data as Bytes).toString() + ]) + handleMetadataEvent( event, event.params.dataToken.toHexString(),