@@ -5,7 +5,16 @@ import classNames from 'classnames';
5
5
import './App.scss' ;
6
6
import { ObjectInspector } from 'react-inspector' ;
7
7
import { Frame } from 'rsocket-types' ;
8
- import { deserializeFrame , deserializeFrameWithLength , FLAGS , FRAME_TYPES , printFrame , Utf8Encoders } from "rsocket-core" ;
8
+ import {
9
+ BufferEncoders ,
10
+ deserializeFrame ,
11
+ deserializeFrameWithLength ,
12
+ FLAGS ,
13
+ FRAME_TYPES ,
14
+ printFrame ,
15
+ Utf8Encoders
16
+ } from "rsocket-core" ;
17
+ import { Encoders } from "rsocket-core/RSocketEncoding" ;
9
18
10
19
function getRSocketType ( type ) {
11
20
for ( const [ name , code ] of Object . entries ( FRAME_TYPES ) ) {
@@ -59,8 +68,8 @@ function base64ToArrayBuffer(base64: string) {
59
68
return bytes ;
60
69
}
61
70
62
- const FrameEntry = ( { frame, selected, onClick} : { frame : WsFrame , selected : boolean , onClick : MouseEventHandler } ) => {
63
- const rsocketFrame = tryDecodeFrame ( frame . payload )
71
+ const FrameEntry = ( { frame, selected, onClick} : { frame : WsFrame , selected : boolean , onClick : MouseEventHandler } ) => {
72
+ const rsocketFrame = tryDeserializeFrame ( frame . payload )
64
73
const frameName = rsocketFrame
65
74
? < span className = "name" > { shortFrame ( rsocketFrame ) } </ span >
66
75
: < span className = "name" > { frame . text != null ? "Text Frame" : "Binary Frame" } </ span >
@@ -120,10 +129,14 @@ class RSocketFrame extends React.Component<RSocketFrameProps, any> {
120
129
jsonMeta = undefined ;
121
130
}
122
131
const dataField = jsonData
123
- ? < div > < hr /> Data< br /> < ObjectInspector data = { jsonData } /> </ div >
132
+ ? < div >
133
+ < hr />
134
+ Data< br /> < ObjectInspector data = { jsonData } /> </ div >
124
135
: < div />
125
136
const jsonField = jsonMeta
126
- ? < div > < hr /> Metadata< br /> < ObjectInspector data = { jsonMeta } /> </ div >
137
+ ? < div >
138
+ < hr />
139
+ Metadata< br /> < ObjectInspector data = { jsonMeta } /> </ div >
127
140
: < div />
128
141
return (
129
142
< div >
@@ -180,19 +193,47 @@ const TextViewer = ({data}) => (
180
193
</ div >
181
194
) ;
182
195
183
- function tryDecodeFrame ( data : string ) : Frame | undefined {
196
+ // Could
197
+ let cachedEncoders : Encoders < any > = Utf8Encoders
198
+ let cachedLengthPrefixedFrames : boolean = false ;
199
+
200
+ function tryDeserializeFrameWith ( data : string , buffer : Buffer , lengthPrefixedFrames , encoders : Encoders < any > ) {
184
201
try {
185
- let lengthPrefixedFrames = false ;
186
- const buffer = base64ToArrayBuffer ( data ) ;
187
202
return lengthPrefixedFrames
188
- ? deserializeFrameWithLength ( buffer , Utf8Encoders )
189
- : deserializeFrame ( buffer , Utf8Encoders ) ;
203
+ ? deserializeFrameWithLength ( buffer , encoders )
204
+ : deserializeFrame ( buffer , encoders ) ;
190
205
} catch ( e ) {
191
206
// console.error("failed to decode frame", e)
192
207
return undefined ;
193
208
}
194
209
}
195
210
211
+ function tryDeserializeFrame ( data : string ) : Frame | undefined {
212
+ const buffer = base64ToArrayBuffer ( data )
213
+ let frame : Frame | undefined ;
214
+ // fast path
215
+ frame = tryDeserializeFrameWith ( data , buffer , cachedLengthPrefixedFrames , cachedEncoders ) ;
216
+ if ( frame ) {
217
+ return frame ;
218
+ }
219
+ // slow path
220
+ let attempts : [ Encoders < any > , boolean ] [ ] = [
221
+ [ Utf8Encoders , false ] ,
222
+ [ Utf8Encoders , true ] ,
223
+ [ BufferEncoders , false ] ,
224
+ [ BufferEncoders , true ] ,
225
+ ] ;
226
+ for ( let [ encoders , lengthPrefixedFrames ] of attempts ) {
227
+ frame = tryDeserializeFrameWith ( data , buffer , lengthPrefixedFrames , encoders ) ;
228
+ if ( frame ) {
229
+ cachedEncoders = encoders ;
230
+ cachedLengthPrefixedFrames = lengthPrefixedFrames ;
231
+ return frame ;
232
+ }
233
+ }
234
+ return undefined ;
235
+ }
236
+
196
237
const RSocketViewer = ( { frame, data} ) => {
197
238
try {
198
239
return (
@@ -219,10 +260,12 @@ class FrameView extends React.Component<{ wsFrame: WsFrame }, { panel?: string }
219
260
220
261
render ( ) {
221
262
const { wsFrame} = this . props ;
222
- const rsocketFrame = tryDecodeFrame ( wsFrame . payload )
263
+ const rsocketFrame = tryDeserializeFrame ( wsFrame . payload )
223
264
const panel = rsocketFrame
224
265
? < RSocketViewer frame = { rsocketFrame } data = { wsFrame . payload } />
225
- : < TextViewer data = { wsFrame . text } /> ;
266
+ : wsFrame . text
267
+ ? < TextViewer data = { wsFrame . text } />
268
+ : < TextViewer data = { wsFrame . binary } /> ;
226
269
return (
227
270
< div className = "FrameView" >
228
271
{ panel }
0 commit comments