@@ -73,10 +73,18 @@ const enum MessageCodes {
7373
7474export type MessageCallback = ( msg : BackendMessage ) => void
7575
76+ interface CombinedBuffer {
77+ combinedBuffer : Buffer
78+ combinedBufferOffset : number
79+ combinedBufferLength : number
80+ combinedBufferFullLength : number
81+ reuseRemainingBuffer : boolean
82+ }
83+
7684export class Parser {
77- private buffer : Buffer = emptyBuffer
78- private bufferLength : number = 0
79- private bufferOffset : number = 0
85+ private remainingBuffer : Buffer = emptyBuffer
86+ private remainingBufferLength : number = 0
87+ private remainingBufferOffset : number = 0
8088 private reader = new BufferReader ( )
8189 private mode : Mode
8290
@@ -88,65 +96,111 @@ export class Parser {
8896 }
8997
9098 public parse ( buffer : Buffer , callback : MessageCallback ) {
91- this . mergeBuffer ( buffer )
92- const bufferFullLength = this . bufferOffset + this . bufferLength
93- let offset = this . bufferOffset
94- while ( offset + HEADER_LENGTH <= bufferFullLength ) {
99+ const {
100+ combinedBuffer,
101+ combinedBufferOffset,
102+ combinedBufferLength,
103+ reuseRemainingBuffer,
104+ combinedBufferFullLength,
105+ } = this . mergeBuffer ( buffer )
106+ let offset = combinedBufferOffset
107+ while ( offset + HEADER_LENGTH <= combinedBufferFullLength ) {
95108 // code is 1 byte long - it identifies the message type
96- const code = this . buffer [ offset ]
109+ const code = combinedBuffer [ offset ]
110+
97111 // length is 1 Uint32BE - it is the length of the message EXCLUDING the code
98- const length = this . buffer . readUInt32BE ( offset + CODE_LENGTH )
112+ const length = combinedBuffer . readUInt32BE ( offset + CODE_LENGTH )
113+
99114 const fullMessageLength = CODE_LENGTH + length
100- if ( fullMessageLength + offset <= bufferFullLength ) {
101- const message = this . handlePacket ( offset + HEADER_LENGTH , code , length , this . buffer )
115+
116+ if ( fullMessageLength + offset <= combinedBufferFullLength ) {
117+ const message = this . handlePacket ( offset + HEADER_LENGTH , code , length , combinedBuffer )
102118 callback ( message )
103119 offset += fullMessageLength
104120 } else {
105121 break
106122 }
107123 }
108- if ( offset === bufferFullLength ) {
109- // No more use for the buffer
110- this . buffer = emptyBuffer
111- this . bufferLength = 0
112- this . bufferOffset = 0
113- } else {
114- // Adjust the cursors of remainingBuffer
115- this . bufferLength = bufferFullLength - offset
116- this . bufferOffset = offset
117- }
124+ this . consumeBuffer ( {
125+ combinedBuffer,
126+ combinedBufferOffset : offset ,
127+ combinedBufferLength,
128+ reuseRemainingBuffer,
129+ combinedBufferFullLength,
130+ } )
118131 }
119132
120- private mergeBuffer ( buffer : Buffer ) : void {
121- if ( this . bufferLength > 0 ) {
122- const newLength = this . bufferLength + buffer . byteLength
123- const newFullLength = newLength + this . bufferOffset
124- if ( newFullLength > this . buffer . byteLength ) {
133+ private mergeBuffer ( buffer : Buffer ) : CombinedBuffer {
134+ let combinedBuffer = buffer
135+ let combinedBufferLength = buffer . byteLength
136+ let combinedBufferOffset = 0
137+ let reuseRemainingBuffer = this . remainingBufferLength > 0
138+ if ( reuseRemainingBuffer ) {
139+ const newLength = this . remainingBufferLength + combinedBufferLength
140+ const newFullLength = newLength + this . remainingBufferOffset
141+ if ( newFullLength > this . remainingBuffer . byteLength ) {
125142 // We can't concat the new buffer with the remaining one
126143 let newBuffer : Buffer
127- if ( newLength <= this . buffer . byteLength && this . bufferOffset >= this . bufferLength ) {
144+ if ( newLength <= this . remainingBuffer . byteLength && this . remainingBufferOffset >= this . remainingBufferLength ) {
128145 // We can move the relevant part to the beginning of the buffer instead of allocating a new buffer
129- newBuffer = this . buffer
146+ newBuffer = this . remainingBuffer
130147 } else {
131148 // Allocate a new larger buffer
132- let newBufferLength = this . buffer . byteLength * 2
149+ let newBufferLength = this . remainingBuffer . byteLength * 2
133150 while ( newLength >= newBufferLength ) {
134151 newBufferLength *= 2
135152 }
136153 newBuffer = Buffer . allocUnsafe ( newBufferLength )
137154 }
138155 // Move the remaining buffer to the new one
139- this . buffer . copy ( newBuffer , 0 , this . bufferOffset , this . bufferOffset + this . bufferLength )
140- this . buffer = newBuffer
141- this . bufferOffset = 0
156+ this . remainingBuffer . copy (
157+ newBuffer ,
158+ 0 ,
159+ this . remainingBufferOffset ,
160+ this . remainingBufferOffset + this . remainingBufferLength
161+ )
162+ this . remainingBuffer = newBuffer
163+ this . remainingBufferOffset = 0
142164 }
143165 // Concat the new buffer with the remaining one
144- buffer . copy ( this . buffer , this . bufferOffset + this . bufferLength )
145- this . bufferLength = newLength
166+ buffer . copy ( this . remainingBuffer , this . remainingBufferOffset + this . remainingBufferLength )
167+ combinedBuffer = this . remainingBuffer
168+ combinedBufferLength = this . remainingBufferLength = newLength
169+ combinedBufferOffset = this . remainingBufferOffset
170+ }
171+ const combinedBufferFullLength = combinedBufferOffset + combinedBufferLength
172+ return {
173+ combinedBuffer,
174+ combinedBufferOffset,
175+ combinedBufferLength,
176+ reuseRemainingBuffer,
177+ combinedBufferFullLength,
178+ }
179+ }
180+
181+ private consumeBuffer ( {
182+ combinedBufferOffset,
183+ combinedBufferFullLength,
184+ reuseRemainingBuffer,
185+ combinedBuffer,
186+ combinedBufferLength,
187+ } : CombinedBuffer ) {
188+ if ( combinedBufferOffset === combinedBufferFullLength ) {
189+ // No more use for the buffer
190+ this . remainingBuffer = emptyBuffer
191+ this . remainingBufferLength = 0
192+ this . remainingBufferOffset = 0
146193 } else {
147- this . buffer = buffer
148- this . bufferOffset = 0
149- this . bufferLength = buffer . byteLength
194+ this . remainingBufferLength = combinedBufferFullLength - combinedBufferOffset
195+ if ( reuseRemainingBuffer ) {
196+ // Adjust the cursors of remainingBuffer
197+ this . remainingBufferOffset = combinedBufferOffset
198+ } else {
199+ // To avoid side effects, copy the remaining part of the new buffer to remainingBuffer with extra space for next buffer
200+ this . remainingBuffer = Buffer . allocUnsafe ( combinedBufferLength * 2 )
201+ combinedBuffer . copy ( this . remainingBuffer , 0 , combinedBufferOffset )
202+ this . remainingBufferOffset = 0
203+ }
150204 }
151205 }
152206
0 commit comments