@@ -5,20 +5,20 @@ class Bufferfish {
55 inner ;
66 position ;
77 reading ;
8- capacity ;
8+ maxCapacity ;
99 textDecoder ;
1010 textEncoder ;
1111 constructor ( bf = new ArrayBuffer ( 0 ) ) {
1212 this . inner = new Uint8Array ( bf ) ;
1313 this . position = 0 ;
1414 this . reading = false ;
15- this . capacity = 1024 ;
15+ this . maxCapacity = 1024 ;
1616 this . textDecoder = undefined ;
1717 this . textEncoder = undefined ;
1818 }
1919 write ( bf ) {
20- if ( this . capacity > 0 && ( bf . length > this . capacity || this . inner . length + bf . length > this . capacity ) ) {
21- return new Error ( `Bufferfish capacity exceeded (${ this . capacity } bytes)` ) ;
20+ if ( this . maxCapacity > 0 && ( bf . length > this . maxCapacity || this . inner . length + bf . length > this . maxCapacity ) ) {
21+ return new Error ( `Bufferfish capacity exceeded (${ this . maxCapacity } bytes)` ) ;
2222 }
2323 this . reading = false ;
2424 const tmp = new Uint8Array ( this . inner . length + bf . length ) ;
@@ -29,60 +29,46 @@ class Bufferfish {
2929 this . position += bytesWritten ;
3030 return bytesWritten ;
3131 }
32- view = ( ) => {
33- return this . inner . slice ( ) ;
32+ bytes = ( ) => {
33+ return this . inner . subarray ( ) ;
3434 } ;
35- startReading ( ) {
35+ startReading = ( ) => {
3636 if ( this . reading ) {
3737 return ;
3838 }
3939 this . position = 0 ;
4040 this . reading = true ;
41- }
42- setMaxCapacity ( capacity ) {
43- this . capacity = capacity ;
44- }
41+ } ;
42+ setMaxCapacity = ( capacity ) => {
43+ this . maxCapacity = capacity ;
44+ } ;
45+ isEmpty = ( ) => {
46+ return this . inner . length === 0 ;
47+ } ;
48+ length = ( ) => {
49+ return this . inner . length ;
50+ } ;
51+ reset = ( ) => {
52+ this . inner = new Uint8Array ( 0 ) ;
53+ this . position = 0 ;
54+ this . reading = false ;
55+ } ;
4556 peek = ( ) => {
4657 this . startReading ( ) ;
4758 const value = this . inner . slice ( this . position , this . position + 1 ) [ 0 ] ;
4859 if ( this . position >= this . inner . length || value === undefined ) {
49- return new Error ( `peek of 1 byte exceeds the max capacity of ${ this . capacity } bytes on this Bufferfish` ) ;
60+ return new Error ( `peek of 1 byte exceeds the max capacity of ${ this . maxCapacity } bytes on this Bufferfish` ) ;
5061 }
5162 return value ;
5263 } ;
5364 peekN = ( n ) => {
5465 this . startReading ( ) ;
5566 const value = this . inner . slice ( this . position , this . position + n ) ;
5667 if ( this . position + n > this . inner . length ) {
57- return new Error ( `peek of ${ n } bytes exceeds the max capacity of ${ this . capacity } bytes on this Bufferfish` ) ;
68+ return new Error ( `peek of ${ n } bytes exceeds the max capacity of ${ this . maxCapacity } bytes on this Bufferfish` ) ;
5869 }
5970 return value ;
6071 } ;
61- push = ( arr ) => {
62- if ( arr instanceof Bufferfish ) {
63- const err = this . write ( arr . view ( ) ) ;
64- if ( err instanceof Error ) {
65- return err ;
66- }
67- } else if ( arr instanceof Uint8Array ) {
68- const err = this . write ( arr ) ;
69- if ( err instanceof Error ) {
70- return err ;
71- }
72- } else if ( arr instanceof ArrayBuffer ) {
73- const err = this . write ( new Uint8Array ( arr ) ) ;
74- if ( err instanceof Error ) {
75- return err ;
76- }
77- } else if ( arr instanceof Array ) {
78- const err = this . write ( new Uint8Array ( arr ) ) ;
79- if ( err instanceof Error ) {
80- return err ;
81- }
82- } else {
83- return new Error ( "invalid type" ) ;
84- }
85- } ;
8672 writeUint8 = ( value ) => {
8773 if ( value > 255 || value < 0 ) {
8874 return new Error ( `value ${ value } must be between 0 and 255` ) ;
@@ -119,6 +105,31 @@ class Bufferfish {
119105 return err ;
120106 }
121107 } ;
108+ writeUint64 = ( value ) => {
109+ if ( value > BigInt ( "18446744073709551615" ) || value < BigInt ( 0 ) ) {
110+ return new Error ( `value ${ value } must be between 0 and 18446744073709551615` ) ;
111+ }
112+ const slice = new Uint8Array ( 8 ) ;
113+ const view = new DataView ( slice . buffer ) ;
114+ view . setBigUint64 ( 0 , value ) ;
115+ const err = this . write ( slice ) ;
116+ if ( err instanceof Error ) {
117+ return err ;
118+ }
119+ } ;
120+ writeUint128 = ( value ) => {
121+ if ( value > BigInt ( "340282366920938463463374607431768211455" ) || value < BigInt ( 0 ) ) {
122+ return new Error ( `value ${ value } must be between 0 and 340282366920938463463374607431768211455` ) ;
123+ }
124+ const slice = new Uint8Array ( 16 ) ;
125+ const view = new DataView ( slice . buffer ) ;
126+ view . setBigUint64 ( 0 , value >> 64n ) ;
127+ view . setBigUint64 ( 8 , value & BigInt ( "0xffffffffffffffff" ) ) ;
128+ const err = this . write ( slice ) ;
129+ if ( err instanceof Error ) {
130+ return err ;
131+ }
132+ } ;
122133 writeInt8 = ( value ) => {
123134 if ( value > 127 || value < - 128 ) {
124135 return new Error ( `value ${ value } must be between -128 and 127` ) ;
@@ -155,6 +166,35 @@ class Bufferfish {
155166 return err ;
156167 }
157168 } ;
169+ writeInt64 = ( value ) => {
170+ if ( value > BigInt ( "9223372036854775807" ) || value < BigInt ( "-9223372036854775808" ) ) {
171+ return new Error ( `value ${ value } must be between -9223372036854775808 and 9223372036854775807` ) ;
172+ }
173+ const slice = new Uint8Array ( 8 ) ;
174+ const view = new DataView ( slice . buffer ) ;
175+ view . setBigInt64 ( 0 , value ) ;
176+ const err = this . write ( slice ) ;
177+ if ( err instanceof Error ) {
178+ return err ;
179+ }
180+ } ;
181+ writeInt128 = ( value ) => {
182+ if ( value > BigInt ( "170141183460469231731687303715884105727" ) || value < BigInt ( "-170141183460469231731687303715884105728" ) ) {
183+ return new Error ( `value ${ value } must be between -170141183460469231731687303715884105728 and 170141183460469231731687303715884105727` ) ;
184+ }
185+ const slice = new Uint8Array ( 16 ) ;
186+ const view = new DataView ( slice . buffer ) ;
187+ let unsignedValue = value ;
188+ if ( value < 0n ) {
189+ unsignedValue = ( 1n << 128n ) + value ;
190+ }
191+ view . setBigUint64 ( 0 , unsignedValue >> 64n ) ;
192+ view . setBigUint64 ( 8 , unsignedValue & BigInt ( "0xffffffffffffffff" ) ) ;
193+ const err = this . write ( slice ) ;
194+ if ( err instanceof Error ) {
195+ return err ;
196+ }
197+ } ;
158198 writeBool = ( value ) => {
159199 const err = this . writeUint8 ( value ? 1 : 0 ) ;
160200 if ( err instanceof Error ) {
@@ -197,68 +237,125 @@ class Bufferfish {
197237 return err ;
198238 }
199239 } ;
200- readUint8 ( ) {
240+ writeArray = ( values , writeFn ) => {
241+ if ( values . length > 65535 ) {
242+ return new Error ( `array length ${ values . length } exceeds maximum size of 65535` ) ;
243+ }
244+ const err = this . writeUint16 ( values . length ) ;
245+ if ( err instanceof Error ) {
246+ return err ;
247+ }
248+ for ( const value of values ) {
249+ const err2 = writeFn ( value ) ;
250+ if ( err2 instanceof Error ) {
251+ return err2 ;
252+ }
253+ }
254+ } ;
255+ readUint8 = ( ) => {
201256 this . startReading ( ) ;
202257 if ( this . position + 1 > this . inner . length ) {
203258 return new Error ( OVERFLOW_ERR ) ;
204259 }
205260 const value = new DataView ( this . inner . buffer , this . position , 1 ) . getUint8 ( 0 ) ;
206261 this . position += 1 ;
207262 return value ;
208- }
209- readUint16 ( ) {
263+ } ;
264+ readUint16 = ( ) => {
210265 this . startReading ( ) ;
211266 if ( this . position + 2 > this . inner . length ) {
212267 return new Error ( OVERFLOW_ERR ) ;
213268 }
214269 const value = new DataView ( this . inner . buffer , this . position , 2 ) . getUint16 ( 0 ) ;
215270 this . position += 2 ;
216271 return value ;
217- }
218- readUint32 ( ) {
272+ } ;
273+ readUint32 = ( ) => {
219274 this . startReading ( ) ;
220275 if ( this . position + 4 > this . inner . length ) {
221276 return new Error ( OVERFLOW_ERR ) ;
222277 }
223278 const value = new DataView ( this . inner . buffer , this . position , 4 ) . getUint32 ( 0 ) ;
224279 this . position += 4 ;
225280 return value ;
226- }
227- readInt8 ( ) {
281+ } ;
282+ readUint64 = ( ) => {
283+ this . startReading ( ) ;
284+ if ( this . position + 8 > this . inner . length ) {
285+ return new Error ( OVERFLOW_ERR ) ;
286+ }
287+ const value = new DataView ( this . inner . buffer , this . position , 8 ) . getBigUint64 ( 0 ) ;
288+ this . position += 8 ;
289+ return value ;
290+ } ;
291+ readUint128 = ( ) => {
292+ this . startReading ( ) ;
293+ if ( this . position + 16 > this . inner . length ) {
294+ return new Error ( OVERFLOW_ERR ) ;
295+ }
296+ const high = new DataView ( this . inner . buffer , this . position , 8 ) . getBigUint64 ( 0 ) ;
297+ const low = new DataView ( this . inner . buffer , this . position + 8 , 8 ) . getBigUint64 ( 0 ) ;
298+ this . position += 16 ;
299+ return high << 64n | low ;
300+ } ;
301+ readInt8 = ( ) => {
228302 this . startReading ( ) ;
229303 if ( this . position + 1 > this . inner . length ) {
230304 return new Error ( OVERFLOW_ERR ) ;
231305 }
232306 const value = new DataView ( this . inner . buffer , this . position , 1 ) . getInt8 ( 0 ) ;
233307 this . position += 1 ;
234308 return value ;
235- }
236- readInt16 ( ) {
309+ } ;
310+ readInt16 = ( ) => {
237311 this . startReading ( ) ;
238312 if ( this . position + 2 > this . inner . length ) {
239313 return new Error ( OVERFLOW_ERR ) ;
240314 }
241315 const value = new DataView ( this . inner . buffer , this . position , 2 ) . getInt16 ( 0 ) ;
242316 this . position += 2 ;
243317 return value ;
244- }
245- readInt32 ( ) {
318+ } ;
319+ readInt32 = ( ) => {
246320 this . startReading ( ) ;
247321 if ( this . position + 4 > this . inner . length ) {
248322 return new Error ( OVERFLOW_ERR ) ;
249323 }
250324 const value = new DataView ( this . inner . buffer , this . position , 4 ) . getInt32 ( 0 ) ;
251325 this . position += 4 ;
252326 return value ;
253- }
254- readBool ( ) {
327+ } ;
328+ readInt64 = ( ) => {
329+ this . startReading ( ) ;
330+ if ( this . position + 8 > this . inner . length ) {
331+ return new Error ( OVERFLOW_ERR ) ;
332+ }
333+ const value = new DataView ( this . inner . buffer , this . position , 8 ) . getBigInt64 ( 0 ) ;
334+ this . position += 8 ;
335+ return value ;
336+ } ;
337+ readInt128 = ( ) => {
338+ this . startReading ( ) ;
339+ if ( this . position + 16 > this . inner . length ) {
340+ return new Error ( OVERFLOW_ERR ) ;
341+ }
342+ const high = new DataView ( this . inner . buffer , this . position , 8 ) . getBigUint64 ( 0 ) ;
343+ const low = new DataView ( this . inner . buffer , this . position + 8 , 8 ) . getBigUint64 ( 0 ) ;
344+ this . position += 16 ;
345+ let value = high << 64n | low ;
346+ if ( value >> 127n === 1n ) {
347+ value = value - ( 1n << 128n ) ;
348+ }
349+ return value ;
350+ } ;
351+ readBool = ( ) => {
255352 const valueOrError = this . readUint8 ( ) ;
256353 if ( valueOrError instanceof Error ) {
257354 return valueOrError ;
258355 }
259356 return valueOrError === 1 ;
260- }
261- readPackedBools ( count = 8 ) {
357+ } ;
358+ readPackedBools = ( count = 8 ) => {
262359 if ( count > 8 ) {
263360 return new Error ( "cannot read more than 8 bools from a single byte" ) ;
264361 }
@@ -272,8 +369,8 @@ class Bufferfish {
272369 bools . push ( ( packedValue & 1 << 7 - i ) !== 0 ) ;
273370 }
274371 return bools ;
275- }
276- readString ( ) {
372+ } ;
373+ readString = ( ) => {
277374 const lengthOrError = this . readUint16 ( ) ;
278375 if ( lengthOrError instanceof Error ) {
279376 return lengthOrError ;
@@ -287,23 +384,27 @@ class Bufferfish {
287384 const value = this . textDecoder . decode ( this . inner . subarray ( this . position , this . position + length ) ) ;
288385 this . position += length ;
289386 return value ;
290- }
291- readArray ( readFn ) {
387+ } ;
388+ readArray = ( readFn ) => {
292389 const lengthOrError = this . readUint16 ( ) ;
293390 if ( lengthOrError instanceof Error ) {
294391 return lengthOrError ;
295392 }
296393 const length = lengthOrError ;
297- const values = [ ] ;
298- for ( let i = 0 ; i < length ; i ++ ) {
299- const valueOrError = readFn ( ) ;
300- if ( valueOrError instanceof Error ) {
301- return valueOrError ;
394+ const values = new Array ( length ) ;
395+ try {
396+ for ( let i = 0 ; i < length ; i ++ ) {
397+ const valueOrError = readFn ( ) ;
398+ if ( valueOrError instanceof Error ) {
399+ return valueOrError ;
400+ }
401+ values [ i ] = valueOrError ;
302402 }
303- values . push ( valueOrError ) ;
403+ return values ;
404+ } catch ( error ) {
405+ return error instanceof Error ? error : new Error ( String ( error ) ) ;
304406 }
305- return values ;
306- }
407+ } ;
307408}
308409export {
309410 Bufferfish
0 commit comments