import { RenderBatch , ArrayRange , RenderTreeDiff , ArrayValues , RenderTreeEdit , EditType , FrameType , RenderTreeFrame , RenderTreeDiffReader , RenderTreeFrameReader , RenderTreeEditReader , ArrayRangeReader , ArrayBuilderSegmentReader , ArrayBuilderSegment } from './RenderBatch' ; import { decodeUtf8 } from './Utf8Decoder' ; const updatedComponentsEntryLength = 4 ; const referenceFramesEntryLength = 20 ; const disposedComponentIdsEntryLength = 4 ; const disposedEventHandlerIdsEntryLength = 8 ; const editsEntryLength = 16 ; const stringTableEntryLength = 4 ; const uint64HighPartShift = Math . pow ( 2 , 32 ) ; const maxSafeNumberHighPart = Math . pow ( 2 , 21 ) - 1 ; export class OutOfProcessRenderBatch implements RenderBatch { constructor ( private batchData ) { const stringReader = new OutOfProcessStringReader ( batchData ) ; this . arrayRangeReader = new OutOfProcessArrayRangeReader ( batchData ) ; this . arrayBuilderSegmentReader = new OutOfProcessArrayBuilderSegmentReader ( batchData ) ; this . diffReader = new OutOfProcessRenderTreeDiffReader ( batchData ) ; this . editReader = new OutOfProcessRenderTreeEditReader ( batchData , stringReader ) ; this . frameReader = new OutOfProcessRenderTreeFrameReader ( batchData , stringReader ) ; } updatedComponents ( ) { return readInt32LE ( this . batchData , this . batchData . length - 20 ) ; } referenceFrames ( ) { return readInt32LE ( this . batchData , this . batchData . length - 16 ) ; } disposedComponentIds ( ) { return readInt32LE ( this . batchData , this . batchData . length - 12 ) ; } disposedEventHandlerIds ( ) { return readInt32LE ( this . batchData , this . batchData . length - 8 ) ; } updatedComponentsEntry ( values , index ) { const tableEntryPos = ( values as any ) + index * updatedComponentsEntryLength ; return readInt32LE ( this . batchData , tableEntryPos ) ; } referenceFramesEntry ( values , index ) { return ( values as any ) + index * referenceFramesEntryLength as any ; } disposedComponentIdsEntry ( values , index ) { const entryPos = ( values as any ) + index * disposedComponentIdsEntryLength ; return readInt32LE ( this . batchData , entryPos ) ; } disposedEventHandlerIdsEntry ( values , index ) { const entryPos = ( values as any ) + index * disposedEventHandlerIdsEntryLength ; return readUint64LE ( this . batchData , entryPos ) ; } diffReader : RenderTreeDiffReader ; editReader : RenderTreeEditReader ; frameReader : RenderTreeFrameReader ; arrayRangeReader : ArrayRangeReader ; arrayBuilderSegmentReader : ArrayBuilderSegmentReader ; } class OutOfProcessRenderTreeDiffReader implements RenderTreeDiffReader { constructor ( private batchDataUint8 ) { } componentId ( diff ) { return readInt32LE ( this . batchDataUint8 , diff as any ) ; } edits ( diff ) { return ( diff as any + 4 ) ; } editsEntry ( values , index ) { return ( values as any ) + index * editsEntryLength ; } } class OutOfProcessRenderTreeEditReader implements RenderTreeEditReader { constructor ( private batchDataUint8 , private stringReader ) { } editType ( edit ) { return readInt32LE ( this . batchDataUint8 , edit as any ) ; } siblingIndex ( edit ) { return readInt32LE ( this . batchDataUint8 , edit as any + 4 ) ; } newTreeIndex ( edit ) { return readInt32LE ( this . batchDataUint8 , edit as any + 8 ) ; } moveToSiblingIndex ( edit ) { return readInt32LE ( this . batchDataUint8 , edit as any + 8 ) ; } removedAttributeName ( edit ) { const stringIndex = readInt32LE ( this . batchDataUint8 , edit as any + 12 ) ; return this . stringReader . readString ( stringIndex ) ; } } class OutOfProcessRenderTreeFrameReader implements RenderTreeFrameReader { constructor ( private batchDataUint8 , private stringReader ) { } frameType ( frame ) { return readInt32LE ( this . batchDataUint8 , frame as any ) ; } subtreeLength ( frame ) { return readInt32LE ( this . batchDataUint8 , frame as any + 4 ) ; } elementReferenceCaptureId ( frame ) { const stringIndex = readInt32LE ( this . batchDataUint8 , frame as any + 4 ) ; return this . stringReader . readString ( stringIndex ) ; } componentId ( frame ) { return readInt32LE ( this . batchDataUint8 , frame as any + 8 ) ; } elementName ( frame ) { const stringIndex = readInt32LE ( this . batchDataUint8 , frame as any + 8 ) ; return this . stringReader . readString ( stringIndex ) ; } textContent ( frame ) { const stringIndex = readInt32LE ( this . batchDataUint8 , frame as any + 4 ) ; return this . stringReader . readString ( stringIndex ) ; } markupContent ( frame ) { const stringIndex = readInt32LE ( this . batchDataUint8 , frame as any + 4 ) ; return this . stringReader . readString ( stringIndex ) ! ; } attributeName ( frame ) { const stringIndex = readInt32LE ( this . batchDataUint8 , frame as any + 4 ) ; return this . stringReader . readString ( stringIndex ) ; } attributeValue ( frame ) { const stringIndex = readInt32LE ( this . batchDataUint8 , frame as any + 8 ) ; return this . stringReader . readString ( stringIndex ) ; } attributeEventHandlerId ( frame ) { return readUint64LE ( this . batchDataUint8 , frame as any + 12 ) ; } } class OutOfProcessStringReader { private stringTableStartIndex : number ; constructor ( private batchDataUint8 ) { this . stringTableStartIndex = readInt32LE ( batchDataUint8 , batchDataUint8 . length - 4 ) ; } readString ( index ) { if ( index === - 1 ) { return null ; } else { const stringTableEntryPos = readInt32LE ( this . batchDataUint8 , this . stringTableStartIndex + index * stringTableEntryLength ) ; const numUtf8Bytes = readLEB128 ( this . batchDataUint8 , stringTableEntryPos ) ; const charsStart = stringTableEntryPos + numLEB128Bytes ( numUtf8Bytes ) ; const utf8Data = new Uint8Array ( this . batchDataUint8 . buffer , this . batchDataUint8 . byteOffset + charsStart , numUtf8Bytes ) ; return decodeUtf8 ( utf8Data ) ; } } } class OutOfProcessArrayRangeReader implements ArrayRangeReader { constructor ( private batchDataUint8 ) { } count < T > ( arrayRange ) { return readInt32LE ( this . batchDataUint8 , arrayRange as any ) ; } values < T > ( arrayRange ) { return arrayRange as any + 4 ; } } class OutOfProcessArrayBuilderSegmentReader implements ArrayBuilderSegmentReader { constructor ( private batchDataUint8 ) { } offset < T > ( arrayBuilderSegment ) { return 0 ; } count < T > ( arrayBuilderSegment ) { return readInt32LE ( this . batchDataUint8 , arrayBuilderSegment as any ) ; } values < T > ( arrayBuilderSegment ) { return arrayBuilderSegment as any + 4 ; } } function readInt32LE ( buffer , position ) { return ( buffer [ position ] ) | ( buffer [ position + 1 ] << 8 ) | ( buffer [ position + 2 ] << 16 ) | ( buffer [ position + 3 ] << 24 ) ; } function readUint32LE ( buffer , position ) { return ( buffer [ position ] ) + ( buffer [ position + 1 ] << 8 ) + ( buffer [ position + 2 ] << 16 ) + ( ( buffer [ position + 3 ] << 24 ) >>> 0 ) ; } function readUint64LE ( buffer , position ) { const highPart = readUint32LE ( buffer , position + 4 ) ; if ( highPart > maxSafeNumberHighPart ) { throw new Error ( `Cannot read uint64 with high order part ${ highPart }, because the result would exceed Number.MAX_SAFE_INTEGER.` ) ; } return ( highPart * uint64HighPartShift ) + readUint32LE ( buffer , position ) ; } function readLEB128 ( buffer , position ) { let result = 0 ; let shift = 0 ; for ( let index = 0 ; index < 4 ; index ++ ) { const byte = buffer [ position + index ] ; result |= ( byte & 127 ) << shift ; if ( byte < 128 ) { break ; } shift += 7 ; } return result ; } function numLEB128Bytes ( value ) { return value < 128 ? 1 : value < 16384 ? 2 : value < 2097152 ? 3 : 4 ; }