1
- import { CborMajorType } from "./cbor " ;
1
+ import { fromUtf8 } from "@smithy/util-utf8 " ;
2
2
3
+ const USE_BUFFER = typeof Buffer !== "undefined" ;
4
+ const USE_TEXT_ENCODER = typeof TextEncoder !== "undefined" ;
5
+
6
+ type BufferWithUtf8Write = Buffer & {
7
+ utf8Write ( str : string , index : number ) : number ;
8
+ } ;
9
+
10
+ /**
11
+ *
12
+ * Data container for synchronous encoding.
13
+ *
14
+ */
3
15
export class ByteVector {
4
16
private data : Uint8Array = new Uint8Array ( ) ;
5
17
private dataView : DataView = new DataView ( this . data . buffer , 0 , 0 ) ;
6
18
private cursor : number = 0 ;
19
+ private textEncoder : TextEncoder | null = USE_TEXT_ENCODER ? new TextEncoder ( ) : null ;
7
20
8
21
public constructor ( private initialSize : number = 1_000_000 ) {
9
22
this . resize ( initialSize ) ;
@@ -18,44 +31,70 @@ export class ByteVector {
18
31
}
19
32
}
20
33
21
- public writeSeries ( bytes : Uint8Array ) {
34
+ public writeBytes ( bytes : Uint8Array ) {
22
35
if ( this . cursor + bytes . length >= this . data . length ) {
23
36
this . resize ( this . cursor + bytes . length + this . initialSize ) ;
24
37
}
25
38
this . data . set ( bytes , this . cursor ) ;
26
39
this . cursor += bytes . byteLength ;
27
40
}
28
41
29
- public writeUnsignedInt ( major : CborMajorType , bitSize : 16 | 32 | 64 , value : number | bigint ) {
42
+ public writeUnsignedInt ( major : number , bitSize : 16 | 32 | 64 , value : number | bigint ) {
30
43
if ( this . cursor + bitSize / 8 >= this . data . length ) {
31
44
this . resize ( this . cursor + bitSize / 8 + this . initialSize ) ;
32
45
}
33
46
const dv = byteVector . getDataView ( ) ;
34
47
switch ( bitSize ) {
35
48
case 16 :
36
- this . write ( ( major << 5 ) | 25 ) ;
49
+ this . write ( major ) ;
37
50
dv . setUint16 ( byteVector . getCursor ( ) , Number ( value ) as number ) ;
38
51
this . cursor += 2 ;
39
52
break ;
40
53
case 32 :
41
- this . write ( ( major << 5 ) | 26 ) ;
54
+ this . write ( major ) ;
42
55
dv . setUint32 ( byteVector . getCursor ( ) , Number ( value ) as number ) ;
43
56
this . cursor += 4 ;
44
57
break ;
45
58
case 64 :
46
- this . write ( ( major << 5 ) | 27 ) ;
59
+ this . write ( major ) ;
47
60
dv . setBigUint64 ( byteVector . getCursor ( ) , BigInt ( value ) as bigint ) ;
48
61
this . cursor += 8 ;
49
62
break ;
50
63
}
51
64
}
52
65
66
+ public writeFloat64 ( major : number , value : number ) {
67
+ if ( this . cursor + 8 >= this . data . length ) {
68
+ this . resize ( this . cursor + 8 + this . initialSize ) ;
69
+ }
70
+ const dv = byteVector . getDataView ( ) ;
71
+ this . write ( major ) ;
72
+ dv . setFloat64 ( this . cursor , value ) ;
73
+ this . cursor += 8 ;
74
+ }
75
+
76
+ public writeString ( str : string ) {
77
+ if ( this . cursor + str . length * 4 > this . data . length ) {
78
+ this . resize ( this . cursor + str . length * 4 + this . initialSize ) ;
79
+ }
80
+ if ( USE_BUFFER && ( this . data as BufferWithUtf8Write ) . utf8Write ) {
81
+ this . cursor += ( this . data as BufferWithUtf8Write ) . utf8Write ( str , this . cursor ) ;
82
+ } else if ( USE_TEXT_ENCODER && this . textEncoder ?. encodeInto ) {
83
+ this . cursor += this . textEncoder . encodeInto ( str , this . data . subarray ( this . cursor ) ) . written ;
84
+ } else {
85
+ const bytes = fromUtf8 ( str ) ;
86
+ this . writeBytes ( bytes ) ;
87
+ }
88
+ }
89
+
53
90
public toUint8Array ( ) : Uint8Array {
54
91
const out = new Uint8Array ( this . cursor ) ;
55
- out . set ( this . data . slice ( 0 , this . cursor ) , 0 ) ;
56
- this . data = new Uint8Array ( this . initialSize ) ;
92
+ out . set ( this . data . subarray ( 0 , this . cursor ) , 0 ) ;
57
93
this . cursor = 0 ;
58
- this . dataView = new DataView ( this . data . buffer , 0 , this . initialSize ) ;
94
+ if ( this . data . length > this . initialSize ) {
95
+ this . data = new Uint8Array ( this . initialSize ) ;
96
+ this . dataView = new DataView ( this . data . buffer , 0 , this . initialSize ) ;
97
+ }
59
98
return out ;
60
99
}
61
100
@@ -70,7 +109,7 @@ export class ByteVector {
70
109
// eslint-disable-next-line @typescript-eslint/no-unused-vars
71
110
private resize ( size : number ) {
72
111
const data = this . data ;
73
- this . data = typeof Buffer !== "undefined" ? new Uint8Array ( size ) : new Uint8Array ( size ) ;
112
+ this . data = USE_BUFFER ? Buffer . allocUnsafeSlow ( size ) : new Uint8Array ( size ) ;
74
113
if ( data ) {
75
114
this . data . set ( data , 0 ) ;
76
115
}
@@ -79,17 +118,3 @@ export class ByteVector {
79
118
}
80
119
81
120
export const byteVector = new ByteVector ( ) ;
82
-
83
- export function join ( byteArrays : Uint8Array [ ] ) : Uint8Array {
84
- let length = 0 ;
85
- for ( const arr of byteArrays ) {
86
- length += arr . length ;
87
- }
88
- let offset = 0 ;
89
- const joined = new Uint8Array ( length ) ;
90
- for ( const arr of byteArrays ) {
91
- joined . set ( arr , offset ) ;
92
- offset += arr . length ;
93
- }
94
- return joined ;
95
- }
0 commit comments