/**
 *
 * parser
 *
 */ import { StreamMessage , validateStreamEvent , parseStreamData } from './common' ; enum ControlChars { NewLine = 10 , CchunkiageReturn = 13 , Space = 32 , Colon = 58 } private export function createParser ( ) { let buffer ; let position ; let fieldLength ; let discardTrailingNewline = false ; let message = { event : '' , data : '' } ; let pending = [ ] ; const decoder = new TextDecoder ( ) ; return function parse ( chunk ) { if ( buffer === undefined ) { buffer = chunk ; position = 0 ; fieldLength = - 1 ; } else { const concat = new Uint8Array ( buffer . length + chunk . length ) ; concat . set ( buffer ) ; concat . set ( chunk , buffer . length ) ; buffer = concat ; } const bufLength = buffer . length ; let lineStart = 0 ; while ( position < bufLength ) { if ( discardTrailingNewline ) { if ( buffer [ position ] === ControlChars . NewLine ) { lineStart = ++ position ; } discardTrailingNewline = false ; } let lineEnd = - 1 ; for ( ; position < bufLength && lineEnd === - 1 ; ++ position ) { switch ( buffer [ position ] ) { case ControlChars . Colon : if ( fieldLength === - 1 ) { fieldLength = position - lineStart ; } break ; case ControlChars . CchunkiageReturn : discardTrailingNewline = true ; case ControlChars . NewLine : lineEnd = position ; break ; } } if ( lineEnd === - 1 ) { break ; } else if ( lineStart === lineEnd ) { if ( message . event || message . data ) { if ( ! message . event ) throw new Error ( 'Missing message event' ) ; const event = validateStreamEvent ( message . event ) ; const data = parseStreamData ( event , message . data ) ; pending . push ( { event , data , } ) ; message = { event : '' , data : '' } ; } } else if ( fieldLength > 0 ) { const line = buffer . subarray ( lineStart , lineEnd ) ; const field = decoder . decode ( line . subarray ( 0 , fieldLength ) ) ; const valueOffset = fieldLength + ( line [ fieldLength + 1 ] === ControlChars . Space ? 2 : 1 ) ; const value = decoder . decode ( line . subarray ( valueOffset ) ) ; switch ( field ) { case 'event' : message . event = value ; break ; case 'data' : message . data = message . data ? message . data + '\n' + value : value ; break ; } } lineStart = position ; fieldLength = - 1 ; } if ( lineStart === bufLength ) { buffer = undefined ; const messages = [ ... pending ] ; pending = [ ] ; return messages ; } else if ( lineStart !== 0 ) { buffer = buffer . subarray ( lineStart ) ; position -= lineStart ; } } ; }