import { DecodedData } from "../interfaces/DecodedData" ; export const enum BIT_LENGTH { INT_8 = 1 , INT_16 = 2 , INT_32 = 4 , INT_64 = 8 , INT_128 = 16 } export class Bytes { static putUint < T extends number > ( b , v , bitLength ) { b [ 0 ] = u8 ( v ) ; for ( let i = 1 ; i < u8 ( bitLength ) ; i ++ ) { b [ i ] = u8 ( v >> ( i * 8 ) ) ; } } static toUint < T extends number > ( b , bitLength , index = 0 ) { const buf = new Array < u8 > ( bitLength ) ; Bytes . copy < u8 > ( b , buf , 0 , index ) ; let result = < T > buf [ 0 ] ; for ( let i = 1 ; i < bitLength ; i ++ ) { result |= ( buf [ i ] as T ) << ( 8 * u8 ( i ) ) ; } return result ; } static appendUint < T extends number > ( b , v , bitLength ) { b . push ( u8 ( v ) ) ; for ( let i = 1 ; i < u8 ( bitLength ) ; i ++ ) { b . push ( u8 ( v >> ( i * 8 ) ) ) ; } } description static copy < T > ( src , dst , dstStart = 0 , srcStart = 0 ) { for ( let i = 0 ; i < dst . length ; i ++ ) { if ( src . length - srcStart <= i ) { break ; } dst [ dstStart + i ] = src [ srcStart + i ] ; } } description static copyToTyped ( src , dst , dstStart = 0 , srcStart = 0 ) { for ( let i = 0 ; i < dst . length ; i ++ ) { if ( src . length - srcStart <= i ) { break ; } dst [ dstStart + i ] = src [ srcStart + i ] ; } } static decodeCompactInt ( input , index = 0 ) { assert ( input . length - index != 0 , "Invalid input: Byte array should not be empty" ) ; const mode = input [ index ] & 3 ; if ( i32 ( mode ) <= BIT_LENGTH . INT_16 ) { return Bytes . decodeSmallInt ( input , mode , index ) ; } const topSixBits = input [ index ] >> 2 ; const byteLen = u8 ( topSixBits ) + 4 ; const buf = new Array < u8 > ( byteLen ) ; Bytes . copy < u8 > ( input , buf , 0 , index ) ; if ( i32 ( byteLen ) == BIT_LENGTH . INT_32 ) { return new DecodedData < u64 > ( u64 ( Bytes . toUint < u32 > ( buf , BIT_LENGTH . INT_32 ) ) , BIT_LENGTH . INT_32 ) ; } if ( i32 ( byteLen ) > BIT_LENGTH . INT_32 && i32 ( byteLen ) < BIT_LENGTH . INT_64 ) { const tmp = new Array < u8 > ( 8 ) ; Bytes . copy < u8 > ( buf , tmp ) ; return new DecodedData < u64 > ( Bytes . toUint < i64 > ( tmp , BIT_LENGTH . INT_64 ) , BIT_LENGTH . INT_64 ) ; } throw new Error ( "CompactInt: Invalid encoding of compact int provided" ) ; } static decodeSmallInt ( input , mode , index = 0 ) { assert ( mode == 0 || mode == 1 || mode == 2 , "Small Int: mode is invalid" ) ; if ( mode == 0 ) { return new DecodedData < u64 > ( u64 ( Bytes . decodeByte ( input [ index ] ) ) , BIT_LENGTH . INT_8 ) ; } else if ( mode == 1 ) { assert ( i32 ( input . length - index ) >= BIT_LENGTH . INT_16 , "Invalid input: expected 2 bytes array" ) ; return new DecodedData < u64 > ( u64 ( Bytes . decode2Bytes ( [ input [ index ] , input [ index + 1 ] ] ) ) , BIT_LENGTH . INT_16 ) ; } else { assert ( i32 ( input . length - index ) >= BIT_LENGTH . INT_32 , "Invalid input: expected 4 bytes array" ) ; return new DecodedData < u64 > ( u64 ( Bytes . decode4Bytes ( [ input [ index ] , input [ index + 1 ] , input [ index + 2 ] , input [ index + 3 ] , ] ) ) , BIT_LENGTH . INT_32 ) ; } } static decodeByte ( byte ) { return i64 ( byte >> 2 ) ; } static decode2Bytes ( bytes ) { return i64 ( Bytes . toUint < u16 > ( bytes , BIT_LENGTH . INT_16 ) >> 2 ) ; } static decode4Bytes ( bytes ) { return i64 ( Bytes . toUint < u32 > ( bytes , BIT_LENGTH . INT_32 ) >> 2 ) ; } param bytes static trimEmptyBytes ( bytes ) { for ( let i = bytes . length - 1 ; i > 0 ; i -- ) { if ( bytes [ i ] === 0 ) { bytes . pop ( ) ; } else { break ; } } } param bytes param targetLength static appendZeroBytes ( bytes , targetLength ) { assert ( targetLength >= bytes . length , "invalid padding provided" ) ; const numberOfZeros = targetLength - bytes . length ; for ( let i = 0 ; i < numberOfZeros ; i ++ ) { bytes . push ( 0 ) ; } } }