const START_SIZE = 32 ; const GROWTH_MULT = 2 ; declare function logStr ( str ) ; declare function logF64 ( val ) ; export class BSONEncoder { offsets : Array < i32 > = new Array < i32 > ( ) ; buffer : Uint8Array = new Uint8Array ( START_SIZE ) ; writeIndex : i32 = 4 ; serialize ( ) { this . writeByte ( 0 ) ; this . int32 ( this . writeIndex , 0 ) ; return this . buffer . subarray ( 0 , this . writeIndex ) ; } setString ( name , value ) { this . writeByte ( 0x02 ) ; this . cstring ( name ) ; let startOffset = this . writeIndex ; this . writeIndex += 4 ; this . cstring ( value ) ; this . int32 ( this . writeIndex - startOffset - 4 , startOffset ) ; } setBoolean ( name , value ) { this . writeByte ( 0x08 ) ; this . cstring ( name ) ; this . writeByte ( value ? 1 : 0 ) ; } setNull ( name ) { this . writeByte ( 0x0A ) ; this . cstring ( name ) ; } setInteger ( name , value ) { this . writeByte ( 0x10 ) ; this . cstring ( name ) ; this . int32 ( value ) ; } setUint8Array ( name , value ) { this . writeByte ( 0x05 ) ; this . cstring ( name ) ; this . int32 ( value . length ) ; this . writeByte ( 0 ) ; for ( let i = 0 ; i < value . length ; i ++ ) { this . writeByte ( value [ i ] ) ; } } pushArray ( name ) { this . writeByte ( 0x04 ) ; this . cstring ( name ) ; this . offsets . push ( this . writeIndex ) ; this . writeIndex += 4 ; } popArray ( ) { this . writeByte ( 0 ) ; let startOffset = this . offsets . pop ( ) ; this . int32 ( this . writeIndex - startOffset , startOffset ) ; } pushObject ( name ) { this . writeByte ( 0x03 ) ; this . cstring ( name ) ; this . offsets . push ( this . writeIndex ) ; this . writeIndex += 4 ; } popObject ( ) { this . writeByte ( 0 ) ; let startOffset = this . offsets . pop ( ) ; this . int32 ( this . writeIndex - startOffset , startOffset ) ; } private cstring ( str ) { for ( let i = 0 , len = str . length ; i < len ; i ++ ) { let c = str . charCodeAt ( i ) ; if ( c < 128 ) { this . writeByte ( c ) ; } else if ( c < 2048 ) { this . writeByte ( ( c >>> 6 ) | 192 ) ; this . writeByte ( ( c & 63 ) | 128 ) ; } else { this . writeByte ( ( c >>> 12 ) | 224 ) ; this . writeByte ( ( ( c >>> 6 ) & 63 ) | 128 ) ; this . writeByte ( ( c & 63 ) | 128 ) ; } } this . writeByte ( 0 ) ; } private int32 ( num , offset = - 1 ) { if ( offset == - 1 ) { this . growIfNeeded ( 4 ) ; offset = this . writeIndex ; this . writeIndex += 4 ; } this . buffer [ offset ] = ( num ) & 0xff ; this . buffer [ offset + 1 ] = ( num >>> 8 ) & 0xff ; this . buffer [ offset + 2 ] = ( num >>> 16 ) & 0xff ; this . buffer [ offset + 3 ] = ( num >>> 24 ) & 0xff ; } private writeByte ( b ) { this . growIfNeeded ( 1 ) ; this . buffer [ this . writeIndex ++ ] = b ; } private growIfNeeded ( numBytes ) { if ( this . buffer . length >= this . writeIndex + numBytes ) { return ; } let oldBuffer = this . buffer ; this . buffer = new Uint8Array ( this . buffer . length * GROWTH_MULT ) ; for ( let i = 0 ; i < oldBuffer . length ; i ++ ) { this . buffer [ i ] = oldBuffer [ i ] ; } } }