goscript 0.2.3 → 0.2.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +8 -8
- package/cmd/go_js_wasm_exec/main.go +1 -1
- package/cmd/go_js_wasm_exec/main_test.go +1 -1
- package/cmd/goscript/cmd-compile.go +9 -1
- package/cmd/goscript/cmd-test.go +1 -1
- package/cmd/goscript/cmd_compile_test.go +44 -0
- package/cmd/goscript/deps.go +1 -1
- package/cmd/goscript-wasm/main.go +2 -2
- package/compiler/compile-request.go +19 -0
- package/compiler/compile_bench_test.go +121 -0
- package/compiler/compliance_test.go +17 -1
- package/compiler/config.go +2 -0
- package/compiler/gotest/result.go +1 -1
- package/compiler/gotest/runner.go +2 -2
- package/compiler/gotest/runner_test.go +4 -7
- package/compiler/index.test.ts +28 -0
- package/compiler/index.ts +32 -16
- package/compiler/lowering.go +1236 -143
- package/compiler/lowering_bench_test.go +4 -0
- package/compiler/override-facts.go +1 -1
- package/compiler/override-registry_test.go +125 -0
- package/compiler/package-graph.go +92 -0
- package/compiler/package-graph_test.go +113 -0
- package/compiler/runtime-contract.go +1 -1
- package/compiler/semantic-model.go +32 -0
- package/compiler/skeleton_test.go +284 -11
- package/compiler/wasm/compile.go +1 -1
- package/compiler/wasm/compile_test.go +1 -1
- package/dist/compiler/index.d.ts +4 -0
- package/dist/compiler/index.js +26 -15
- package/dist/compiler/index.js.map +1 -1
- package/dist/gs/compress/gzip/index.d.ts +41 -0
- package/dist/gs/compress/gzip/index.js +235 -0
- package/dist/gs/compress/gzip/index.js.map +1 -0
- package/dist/gs/database/sql/driver/index.d.ts +165 -0
- package/dist/gs/database/sql/driver/index.js +432 -0
- package/dist/gs/database/sql/driver/index.js.map +1 -0
- package/dist/gs/encoding/binary/index.d.ts +71 -0
- package/dist/gs/encoding/binary/index.js +778 -0
- package/dist/gs/encoding/binary/index.js.map +1 -0
- package/dist/gs/fmt/fmt.js +156 -57
- package/dist/gs/fmt/fmt.js.map +1 -1
- package/dist/gs/github.com/klauspost/cpuid/v2/index.d.ts +11 -0
- package/dist/gs/github.com/klauspost/cpuid/v2/index.js +28 -0
- package/dist/gs/github.com/klauspost/cpuid/v2/index.js.map +1 -0
- package/dist/gs/github.com/pkg/errors/errors.d.ts +0 -2
- package/dist/gs/github.com/pkg/errors/errors.js.map +1 -1
- package/dist/gs/github.com/pkg/errors/index.d.ts +2 -1
- package/dist/gs/github.com/pkg/errors/index.js +1 -1
- package/dist/gs/github.com/pkg/errors/index.js.map +1 -1
- package/dist/gs/github.com/pkg/errors/stack.d.ts +8 -19
- package/dist/gs/github.com/pkg/errors/stack.js +26 -61
- package/dist/gs/github.com/pkg/errors/stack.js.map +1 -1
- package/dist/gs/golang.org/x/crypto/cryptobyte/asn1/index.d.ts +19 -0
- package/dist/gs/golang.org/x/crypto/cryptobyte/asn1/index.js +25 -0
- package/dist/gs/golang.org/x/crypto/cryptobyte/asn1/index.js.map +1 -0
- package/dist/gs/golang.org/x/crypto/cryptobyte/index.d.ts +104 -0
- package/dist/gs/golang.org/x/crypto/cryptobyte/index.js +1107 -0
- package/dist/gs/golang.org/x/crypto/cryptobyte/index.js.map +1 -0
- package/dist/gs/golang.org/x/crypto/internal/alias/index.d.ts +3 -0
- package/dist/gs/golang.org/x/crypto/internal/alias/index.js +39 -0
- package/dist/gs/golang.org/x/crypto/internal/alias/index.js.map +1 -0
- package/dist/gs/io/fs/glob.js +1 -1
- package/dist/gs/io/fs/glob.js.map +1 -1
- package/dist/gs/io/fs/readlink.d.ts +1 -1
- package/dist/gs/io/fs/readlink.js +2 -2
- package/dist/gs/io/fs/readlink.js.map +1 -1
- package/dist/gs/io/fs/stat.d.ts +4 -2
- package/dist/gs/io/fs/stat.js +12 -73
- package/dist/gs/io/fs/stat.js.map +1 -1
- package/dist/gs/io/fs/sub.d.ts +2 -2
- package/dist/gs/io/fs/sub.js +7 -7
- package/dist/gs/io/fs/sub.js.map +1 -1
- package/dist/gs/io/fs/walk.js +1 -1
- package/dist/gs/io/fs/walk.js.map +1 -1
- package/dist/gs/net/http/index.d.ts +18 -14
- package/dist/gs/net/http/index.js +44 -23
- package/dist/gs/net/http/index.js.map +1 -1
- package/dist/gs/net/http/pprof/index.d.ts +5 -5
- package/dist/gs/net/http/pprof/index.js +21 -21
- package/dist/gs/net/http/pprof/index.js.map +1 -1
- package/dist/gs/runtime/runtime.d.ts +6 -1
- package/dist/gs/runtime/runtime.js +15 -8
- package/dist/gs/runtime/runtime.js.map +1 -1
- package/dist/gs/runtime/trace/index.d.ts +8 -5
- package/dist/gs/runtime/trace/index.js +324 -23
- package/dist/gs/runtime/trace/index.js.map +1 -1
- package/dist/gs/slices/slices.d.ts +2 -1
- package/dist/gs/slices/slices.js +9 -3
- package/dist/gs/slices/slices.js.map +1 -1
- package/dist/gs/sort/search.gs.d.ts +3 -1
- package/dist/gs/sort/search.gs.js +18 -53
- package/dist/gs/sort/search.gs.js.map +1 -1
- package/dist/gs/sync/sync.d.ts +1 -1
- package/dist/gs/sync/sync.js +3 -0
- package/dist/gs/sync/sync.js.map +1 -1
- package/dist/gs/time/time.d.ts +22 -29
- package/dist/gs/time/time.js +111 -32
- package/dist/gs/time/time.js.map +1 -1
- package/dist/gs/unsafe/unsafe.d.ts +3 -2
- package/dist/gs/unsafe/unsafe.js.map +1 -1
- package/go.mod +7 -5
- package/go.sum +12 -26
- package/gs/builtin/runtime-contract.test.ts +25 -0
- package/gs/compress/gzip/index.test.ts +86 -0
- package/gs/compress/gzip/index.ts +297 -0
- package/gs/compress/gzip/meta.json +6 -0
- package/gs/compress/gzip/parity.json +45 -0
- package/gs/database/sql/driver/index.test.ts +88 -0
- package/gs/database/sql/driver/index.ts +675 -0
- package/gs/database/sql/driver/meta.json +3 -0
- package/gs/database/sql/driver/parity.json +144 -0
- package/gs/embed/index.test.ts +1 -1
- package/gs/encoding/binary/index.test.ts +239 -0
- package/gs/encoding/binary/index.ts +999 -0
- package/gs/encoding/binary/meta.json +9 -0
- package/gs/encoding/binary/parity.json +72 -0
- package/gs/fmt/fmt.test.ts +28 -0
- package/gs/fmt/fmt.ts +198 -61
- package/gs/fmt/meta.json +2 -1
- package/gs/github.com/klauspost/cpuid/v2/index.ts +38 -0
- package/gs/github.com/klauspost/cpuid/v2/meta.json +3 -0
- package/gs/github.com/pkg/errors/errors.ts +1 -2
- package/gs/github.com/pkg/errors/index.ts +2 -1
- package/gs/github.com/pkg/errors/stack.ts +34 -62
- package/gs/golang.org/x/crypto/cryptobyte/asn1/index.test.ts +19 -0
- package/gs/golang.org/x/crypto/cryptobyte/asn1/index.ts +29 -0
- package/gs/golang.org/x/crypto/cryptobyte/index.test.ts +255 -0
- package/gs/golang.org/x/crypto/cryptobyte/index.ts +1441 -0
- package/gs/golang.org/x/crypto/cryptobyte/meta.json +3 -0
- package/gs/golang.org/x/crypto/internal/alias/index.test.ts +40 -0
- package/gs/golang.org/x/crypto/internal/alias/index.ts +40 -0
- package/gs/io/fs/glob.ts +1 -1
- package/gs/io/fs/meta.json +3 -0
- package/gs/io/fs/readlink.test.ts +2 -2
- package/gs/io/fs/readlink.ts +5 -2
- package/gs/io/fs/stat.test.ts +79 -0
- package/gs/io/fs/stat.ts +24 -10
- package/gs/io/fs/sub.test.ts +93 -0
- package/gs/io/fs/sub.ts +9 -9
- package/gs/io/fs/walk.ts +1 -1
- package/gs/net/http/index.test.ts +207 -2
- package/gs/net/http/index.ts +68 -37
- package/gs/net/http/meta.json +3 -1
- package/gs/net/http/pprof/index.test.ts +4 -4
- package/gs/net/http/pprof/index.ts +30 -27
- package/gs/runtime/runtime.test.ts +16 -0
- package/gs/runtime/runtime.ts +17 -9
- package/gs/runtime/trace/index.test.ts +113 -14
- package/gs/runtime/trace/index.ts +384 -34
- package/gs/runtime/trace/meta.json +1 -0
- package/gs/slices/slices.test.ts +24 -1
- package/gs/slices/slices.ts +14 -4
- package/gs/sort/meta.json +1 -0
- package/gs/sort/search.gs.ts +20 -5
- package/gs/sync/sync.ts +4 -1
- package/gs/time/time.test.ts +79 -2
- package/gs/time/time.ts +133 -33
- package/gs/unsafe/unsafe.ts +4 -2
- package/package.json +2 -2
|
@@ -0,0 +1,1441 @@
|
|
|
1
|
+
import * as $ from '@goscript/builtin/index.js'
|
|
2
|
+
import * as asn1 from '@goscript/golang.org/x/crypto/cryptobyte/asn1/index.js'
|
|
3
|
+
import * as time from '@goscript/time/index.js'
|
|
4
|
+
|
|
5
|
+
export type String = $.Bytes
|
|
6
|
+
|
|
7
|
+
export type BuilderContinuation = ((child: Builder | null) => void) | null
|
|
8
|
+
|
|
9
|
+
export type MarshalingValue = {
|
|
10
|
+
Marshal(builder: Builder | $.VarRef<Builder> | null): $.GoError
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
const maxUint64 = (1n << 64n) - 1n
|
|
14
|
+
const maxInt64 = (1n << 63n) - 1n
|
|
15
|
+
const minInt64 = -(1n << 63n)
|
|
16
|
+
|
|
17
|
+
function byte(value: number | bigint): number {
|
|
18
|
+
if (typeof value === 'bigint') {
|
|
19
|
+
return Number(BigInt.asUintN(8, value))
|
|
20
|
+
}
|
|
21
|
+
return Number(value) & 0xff
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
function bytesArray(bytes: $.Bytes | string | null | undefined): number[] {
|
|
25
|
+
if (bytes == null) {
|
|
26
|
+
return []
|
|
27
|
+
}
|
|
28
|
+
if (typeof bytes === 'string') {
|
|
29
|
+
return Array.from(bytes, (ch) => ch.charCodeAt(0) & 0xff)
|
|
30
|
+
}
|
|
31
|
+
return Array.from($.bytesToUint8Array(bytes))
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
function bytesFromArray(bytes: number[]): $.Bytes {
|
|
35
|
+
return new Uint8Array(bytes.map(byte))
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
function bytesFromString(value: string): $.Bytes {
|
|
39
|
+
return new Uint8Array(Array.from(value, (ch) => ch.charCodeAt(0) & 0xff))
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
function bytesToAscii(bytes: $.Bytes): string {
|
|
43
|
+
return globalThis.String.fromCharCode(...bytesArray(bytes))
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
function stringValue(s: $.VarRef<String> | null): String {
|
|
47
|
+
if (s == null) {
|
|
48
|
+
throw new Error(
|
|
49
|
+
'runtime error: invalid memory address or nil pointer dereference',
|
|
50
|
+
)
|
|
51
|
+
}
|
|
52
|
+
return s.value
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
function read(s: $.VarRef<String> | null, n: number): $.Bytes | null {
|
|
56
|
+
const data = stringValue(s)
|
|
57
|
+
if ($.len(data) < n) {
|
|
58
|
+
return null
|
|
59
|
+
}
|
|
60
|
+
const out = $.goSlice(data, 0, n)
|
|
61
|
+
s!.value = $.goSlice(data, n)
|
|
62
|
+
return out
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
function readUint(bytes: $.Bytes): number {
|
|
66
|
+
let out = 0
|
|
67
|
+
for (const b of bytesArray(bytes)) {
|
|
68
|
+
out = out * 256 + b
|
|
69
|
+
}
|
|
70
|
+
return out
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
function readUint64Value(bytes: $.Bytes): number {
|
|
74
|
+
let out = 0n
|
|
75
|
+
for (const b of bytesArray(bytes)) {
|
|
76
|
+
out = (out << 8n) | BigInt(b)
|
|
77
|
+
}
|
|
78
|
+
return $.uint(out, 64)
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
function writeRef<T>(out: $.VarRef<T> | null, value: T): void {
|
|
82
|
+
if (out == null) {
|
|
83
|
+
throw new Error(
|
|
84
|
+
'runtime error: invalid memory address or nil pointer dereference',
|
|
85
|
+
)
|
|
86
|
+
}
|
|
87
|
+
out.value = value
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
export function String_Skip(s: $.VarRef<String> | null, n: number): boolean {
|
|
91
|
+
return read(s, n) !== null
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
export function String_ReadUint8(
|
|
95
|
+
s: $.VarRef<String> | null,
|
|
96
|
+
out: $.VarRef<number> | null,
|
|
97
|
+
): boolean {
|
|
98
|
+
const v = read(s, 1)
|
|
99
|
+
if (v == null) {
|
|
100
|
+
return false
|
|
101
|
+
}
|
|
102
|
+
writeRef(out, bytesArray(v)[0])
|
|
103
|
+
return true
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
export function String_ReadUint16(
|
|
107
|
+
s: $.VarRef<String> | null,
|
|
108
|
+
out: $.VarRef<number> | null,
|
|
109
|
+
): boolean {
|
|
110
|
+
const v = read(s, 2)
|
|
111
|
+
if (v == null) {
|
|
112
|
+
return false
|
|
113
|
+
}
|
|
114
|
+
writeRef(out, readUint(v))
|
|
115
|
+
return true
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
export function String_ReadUint24(
|
|
119
|
+
s: $.VarRef<String> | null,
|
|
120
|
+
out: $.VarRef<number> | null,
|
|
121
|
+
): boolean {
|
|
122
|
+
const v = read(s, 3)
|
|
123
|
+
if (v == null) {
|
|
124
|
+
return false
|
|
125
|
+
}
|
|
126
|
+
writeRef(out, readUint(v))
|
|
127
|
+
return true
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
export function String_ReadUint32(
|
|
131
|
+
s: $.VarRef<String> | null,
|
|
132
|
+
out: $.VarRef<number> | null,
|
|
133
|
+
): boolean {
|
|
134
|
+
const v = read(s, 4)
|
|
135
|
+
if (v == null) {
|
|
136
|
+
return false
|
|
137
|
+
}
|
|
138
|
+
writeRef(out, $.uint(readUint(v), 32))
|
|
139
|
+
return true
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
export function String_ReadUint48(
|
|
143
|
+
s: $.VarRef<String> | null,
|
|
144
|
+
out: $.VarRef<number> | null,
|
|
145
|
+
): boolean {
|
|
146
|
+
const v = read(s, 6)
|
|
147
|
+
if (v == null) {
|
|
148
|
+
return false
|
|
149
|
+
}
|
|
150
|
+
writeRef(out, readUint(v))
|
|
151
|
+
return true
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
export function String_ReadUint64(
|
|
155
|
+
s: $.VarRef<String> | null,
|
|
156
|
+
out: $.VarRef<number> | null,
|
|
157
|
+
): boolean {
|
|
158
|
+
const v = read(s, 8)
|
|
159
|
+
if (v == null) {
|
|
160
|
+
return false
|
|
161
|
+
}
|
|
162
|
+
writeRef(out, readUint64Value(v))
|
|
163
|
+
return true
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
function readLengthPrefixed(
|
|
167
|
+
s: $.VarRef<String> | null,
|
|
168
|
+
lenLen: number,
|
|
169
|
+
out: $.VarRef<String> | null,
|
|
170
|
+
): boolean {
|
|
171
|
+
const data = stringValue(s)
|
|
172
|
+
if ($.len(data) < lenLen) {
|
|
173
|
+
return false
|
|
174
|
+
}
|
|
175
|
+
const length = readUint($.goSlice(data, 0, lenLen))
|
|
176
|
+
if ($.len(data) < lenLen + length) {
|
|
177
|
+
return false
|
|
178
|
+
}
|
|
179
|
+
writeRef(out, $.goSlice(data, lenLen, lenLen + length))
|
|
180
|
+
s!.value = $.goSlice(data, lenLen + length)
|
|
181
|
+
return true
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
export function String_ReadUint8LengthPrefixed(
|
|
185
|
+
s: $.VarRef<String> | null,
|
|
186
|
+
out: $.VarRef<String> | null,
|
|
187
|
+
): boolean {
|
|
188
|
+
return readLengthPrefixed(s, 1, out)
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
export function String_ReadUint16LengthPrefixed(
|
|
192
|
+
s: $.VarRef<String> | null,
|
|
193
|
+
out: $.VarRef<String> | null,
|
|
194
|
+
): boolean {
|
|
195
|
+
return readLengthPrefixed(s, 2, out)
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
export function String_ReadUint24LengthPrefixed(
|
|
199
|
+
s: $.VarRef<String> | null,
|
|
200
|
+
out: $.VarRef<String> | null,
|
|
201
|
+
): boolean {
|
|
202
|
+
return readLengthPrefixed(s, 3, out)
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
export function String_ReadBytes(
|
|
206
|
+
s: $.VarRef<String> | null,
|
|
207
|
+
out: $.VarRef<$.Bytes> | null,
|
|
208
|
+
n: number,
|
|
209
|
+
): boolean {
|
|
210
|
+
const v = read(s, n)
|
|
211
|
+
if (v == null) {
|
|
212
|
+
return false
|
|
213
|
+
}
|
|
214
|
+
writeRef(out, v)
|
|
215
|
+
return true
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
export function String_CopyBytes(
|
|
219
|
+
s: $.VarRef<String> | null,
|
|
220
|
+
out: $.Bytes,
|
|
221
|
+
): boolean {
|
|
222
|
+
if ($.len(out) > $.len(stringValue(s))) {
|
|
223
|
+
return false
|
|
224
|
+
}
|
|
225
|
+
const v = read(s, $.len(out))
|
|
226
|
+
if (v == null) {
|
|
227
|
+
return false
|
|
228
|
+
}
|
|
229
|
+
$.copy(out, v)
|
|
230
|
+
return true
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
export function String_Empty(s: String): boolean {
|
|
234
|
+
return $.len(s) === 0
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
export class BuildError {
|
|
238
|
+
public Err: $.GoError
|
|
239
|
+
|
|
240
|
+
constructor(init?: Partial<{ Err: $.GoError }>) {
|
|
241
|
+
this.Err = init?.Err ?? null
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
public Error(): string {
|
|
245
|
+
return this.Err == null ? '' : this.Err.Error()
|
|
246
|
+
}
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
export class Builder {
|
|
250
|
+
private err: $.GoError
|
|
251
|
+
private result: number[]
|
|
252
|
+
private fixedSize: boolean
|
|
253
|
+
private capacityLimit: number
|
|
254
|
+
private child: Builder | null
|
|
255
|
+
private offset: number
|
|
256
|
+
private pendingLenLen: number
|
|
257
|
+
private pendingIsASN1: boolean
|
|
258
|
+
|
|
259
|
+
constructor(
|
|
260
|
+
init?: Partial<{
|
|
261
|
+
err: $.GoError
|
|
262
|
+
result: $.Bytes
|
|
263
|
+
resultArray: number[]
|
|
264
|
+
fixedSize: boolean
|
|
265
|
+
capacityLimit: number
|
|
266
|
+
}>,
|
|
267
|
+
) {
|
|
268
|
+
this.err = init?.err ?? null
|
|
269
|
+
this.result = init?.resultArray ?? bytesArray(init?.result)
|
|
270
|
+
this.fixedSize = init?.fixedSize ?? false
|
|
271
|
+
this.capacityLimit =
|
|
272
|
+
init?.capacityLimit ?? (init?.result == null ? this.result.length : $.cap(init.result))
|
|
273
|
+
this.child = null
|
|
274
|
+
this.offset = 0
|
|
275
|
+
this.pendingLenLen = 0
|
|
276
|
+
this.pendingIsASN1 = false
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
public SetError(err: $.GoError): void {
|
|
280
|
+
if (this.err == null) {
|
|
281
|
+
this.err = err
|
|
282
|
+
}
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
public Bytes(): [$.Bytes, $.GoError] {
|
|
286
|
+
this.flushChild()
|
|
287
|
+
if (this.err != null) {
|
|
288
|
+
return [null as unknown as $.Bytes, this.err]
|
|
289
|
+
}
|
|
290
|
+
if (this.fixedSize && this.result.length !== this.capacityLimit) {
|
|
291
|
+
return [null as unknown as $.Bytes, $.newError('cryptobyte: Builder is not full')]
|
|
292
|
+
}
|
|
293
|
+
return [bytesFromArray(this.result), null]
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
public BytesOrPanic(): $.Bytes {
|
|
297
|
+
const [bytes, err] = this.Bytes()
|
|
298
|
+
if (err != null) {
|
|
299
|
+
$.panic(new BuildError({ Err: err }))
|
|
300
|
+
}
|
|
301
|
+
return bytes
|
|
302
|
+
}
|
|
303
|
+
|
|
304
|
+
public AddUint8(v: number): void {
|
|
305
|
+
this.add(byte(v))
|
|
306
|
+
}
|
|
307
|
+
|
|
308
|
+
public AddUint16(v: number): void {
|
|
309
|
+
this.add(byte(v >> 8), byte(v))
|
|
310
|
+
}
|
|
311
|
+
|
|
312
|
+
public AddUint24(v: number): void {
|
|
313
|
+
this.add(byte(v >> 16), byte(v >> 8), byte(v))
|
|
314
|
+
}
|
|
315
|
+
|
|
316
|
+
public AddUint32(v: number): void {
|
|
317
|
+
this.add(byte(v / 0x1000000), byte(v >> 16), byte(v >> 8), byte(v))
|
|
318
|
+
}
|
|
319
|
+
|
|
320
|
+
public AddUint48(v: number): void {
|
|
321
|
+
this.add(
|
|
322
|
+
byte(Math.floor(v / 0x10000000000)),
|
|
323
|
+
byte(Math.floor(v / 0x100000000)),
|
|
324
|
+
byte(v >> 24),
|
|
325
|
+
byte(v >> 16),
|
|
326
|
+
byte(v >> 8),
|
|
327
|
+
byte(v),
|
|
328
|
+
)
|
|
329
|
+
}
|
|
330
|
+
|
|
331
|
+
public AddUint64(v: number): void {
|
|
332
|
+
let value = toUint64BigInt(v)
|
|
333
|
+
const out = new Array<number>(8)
|
|
334
|
+
for (let i = 7; i >= 0; i--) {
|
|
335
|
+
out[i] = byte(value)
|
|
336
|
+
value >>= 8n
|
|
337
|
+
}
|
|
338
|
+
this.add(...out)
|
|
339
|
+
}
|
|
340
|
+
|
|
341
|
+
public AddBytes(v: $.Bytes): void {
|
|
342
|
+
this.add(...bytesArray(v))
|
|
343
|
+
}
|
|
344
|
+
|
|
345
|
+
public AddUint8LengthPrefixed(f: BuilderContinuation): void {
|
|
346
|
+
this.addLengthPrefixed(1, false, f)
|
|
347
|
+
}
|
|
348
|
+
|
|
349
|
+
public AddUint16LengthPrefixed(f: BuilderContinuation): void {
|
|
350
|
+
this.addLengthPrefixed(2, false, f)
|
|
351
|
+
}
|
|
352
|
+
|
|
353
|
+
public AddUint24LengthPrefixed(f: BuilderContinuation): void {
|
|
354
|
+
this.addLengthPrefixed(3, false, f)
|
|
355
|
+
}
|
|
356
|
+
|
|
357
|
+
public AddUint32LengthPrefixed(f: BuilderContinuation): void {
|
|
358
|
+
this.addLengthPrefixed(4, false, f)
|
|
359
|
+
}
|
|
360
|
+
|
|
361
|
+
public AddValue(v: MarshalingValue | null): void {
|
|
362
|
+
if (v == null) {
|
|
363
|
+
this.SetError($.newError('cryptobyte: nil MarshalingValue'))
|
|
364
|
+
return
|
|
365
|
+
}
|
|
366
|
+
this.SetError(v.Marshal(this))
|
|
367
|
+
}
|
|
368
|
+
|
|
369
|
+
public Unwrite(n: number): void {
|
|
370
|
+
this.flushChild()
|
|
371
|
+
if (this.err != null) {
|
|
372
|
+
return
|
|
373
|
+
}
|
|
374
|
+
if (n < 0 || n > this.result.length) {
|
|
375
|
+
this.SetError($.newError('cryptobyte: invalid Unwrite'))
|
|
376
|
+
return
|
|
377
|
+
}
|
|
378
|
+
this.result.length -= n
|
|
379
|
+
}
|
|
380
|
+
|
|
381
|
+
public AddASN1Int64(v: number): void {
|
|
382
|
+
this.AddASN1Int64WithTag(v, asn1.INTEGER)
|
|
383
|
+
}
|
|
384
|
+
|
|
385
|
+
public AddASN1Int64WithTag(v: number, tag: asn1.Tag): void {
|
|
386
|
+
this.addASN1Signed(BigInt(Math.trunc(v)), tag)
|
|
387
|
+
}
|
|
388
|
+
|
|
389
|
+
public AddASN1Enum(v: number): void {
|
|
390
|
+
this.addASN1Signed(BigInt(Math.trunc(v)), asn1.ENUM)
|
|
391
|
+
}
|
|
392
|
+
|
|
393
|
+
public AddASN1Uint64(v: number): void {
|
|
394
|
+
this.AddASN1(asn1.INTEGER, (child) => {
|
|
395
|
+
child!.add(...encodeASN1Unsigned(toUint64BigInt(v)))
|
|
396
|
+
})
|
|
397
|
+
}
|
|
398
|
+
|
|
399
|
+
public AddASN1BigInt(n: unknown): void {
|
|
400
|
+
const value = bigIntValue(n)
|
|
401
|
+
this.AddASN1(asn1.INTEGER, (child) => {
|
|
402
|
+
child!.add(...encodeASN1Signed(value))
|
|
403
|
+
})
|
|
404
|
+
}
|
|
405
|
+
|
|
406
|
+
public AddASN1OctetString(bytes: $.Bytes): void {
|
|
407
|
+
this.AddASN1(asn1.OCTET_STRING, (child) => {
|
|
408
|
+
child!.AddBytes(bytes)
|
|
409
|
+
})
|
|
410
|
+
}
|
|
411
|
+
|
|
412
|
+
public AddASN1GeneralizedTime(t: time.Time | $.VarRef<time.Time> | null): void {
|
|
413
|
+
const value = $.pointerValue(t)
|
|
414
|
+
this.AddASN1(asn1.GeneralizedTime, (child) => {
|
|
415
|
+
child!.AddBytes(bytesFromString(value.Format('20060102150405Z0700')))
|
|
416
|
+
})
|
|
417
|
+
}
|
|
418
|
+
|
|
419
|
+
public AddASN1UTCTime(t: time.Time | $.VarRef<time.Time> | null): void {
|
|
420
|
+
const value = $.pointerValue(t)
|
|
421
|
+
this.AddASN1(asn1.UTCTime, (child) => {
|
|
422
|
+
child!.AddBytes(bytesFromString(value.Format('060102150405Z0700')))
|
|
423
|
+
})
|
|
424
|
+
}
|
|
425
|
+
|
|
426
|
+
public AddASN1BitString(bitString: unknown): void {
|
|
427
|
+
const value = pointerValueOrBox(bitString) as {
|
|
428
|
+
Bytes?: $.Bytes
|
|
429
|
+
BitLength?: number
|
|
430
|
+
} | null
|
|
431
|
+
if (value == null) {
|
|
432
|
+
this.SetError($.newError('cryptobyte: nil BitString'))
|
|
433
|
+
return
|
|
434
|
+
}
|
|
435
|
+
const bytes = value.Bytes ?? null
|
|
436
|
+
const bitLength = Math.trunc(value.BitLength ?? 0)
|
|
437
|
+
const paddingBits = (8 - (bitLength % 8)) % 8
|
|
438
|
+
if (
|
|
439
|
+
(bytes == null && bitLength !== 0) ||
|
|
440
|
+
$.len(bytes) * 8 - paddingBits !== bitLength
|
|
441
|
+
) {
|
|
442
|
+
this.SetError($.newError('cryptobyte: invalid BitString'))
|
|
443
|
+
return
|
|
444
|
+
}
|
|
445
|
+
this.AddASN1(asn1.BIT_STRING, (child) => {
|
|
446
|
+
child!.AddUint8(paddingBits)
|
|
447
|
+
child!.AddBytes(bytes ?? new Uint8Array(0))
|
|
448
|
+
})
|
|
449
|
+
}
|
|
450
|
+
|
|
451
|
+
public AddASN1ObjectIdentifier(oid: $.Slice<number> | null): void {
|
|
452
|
+
if (oid == null || $.len(oid) < 2) {
|
|
453
|
+
this.SetError($.newError('cryptobyte: invalid OID'))
|
|
454
|
+
return
|
|
455
|
+
}
|
|
456
|
+
const first = Number((oid as any)[0])
|
|
457
|
+
const second = Number((oid as any)[1])
|
|
458
|
+
if (first > 2 || second >= 40 && first < 2) {
|
|
459
|
+
this.SetError($.newError('cryptobyte: invalid OID'))
|
|
460
|
+
return
|
|
461
|
+
}
|
|
462
|
+
this.AddASN1(asn1.OBJECT_IDENTIFIER, (child) => {
|
|
463
|
+
child!.addBase128Int(first * 40 + second)
|
|
464
|
+
for (let i = 2; i < $.len(oid); i++) {
|
|
465
|
+
child!.addBase128Int(Number((oid as any)[i]))
|
|
466
|
+
}
|
|
467
|
+
})
|
|
468
|
+
}
|
|
469
|
+
|
|
470
|
+
public AddASN1Boolean(v: boolean): void {
|
|
471
|
+
this.AddASN1(asn1.BOOLEAN, (child) => {
|
|
472
|
+
child!.AddUint8(v ? 0xff : 0)
|
|
473
|
+
})
|
|
474
|
+
}
|
|
475
|
+
|
|
476
|
+
public AddASN1NULL(): void {
|
|
477
|
+
this.add(asn1.NULL, 0)
|
|
478
|
+
}
|
|
479
|
+
|
|
480
|
+
public MarshalASN1(_v: unknown): void {
|
|
481
|
+
this.SetError(
|
|
482
|
+
$.newError('cryptobyte: MarshalASN1 is not supported in the js build'),
|
|
483
|
+
)
|
|
484
|
+
}
|
|
485
|
+
|
|
486
|
+
public AddASN1(tag: asn1.Tag, f: BuilderContinuation): void {
|
|
487
|
+
this.add(byte(tag))
|
|
488
|
+
this.addLengthPrefixed(1, true, f)
|
|
489
|
+
}
|
|
490
|
+
|
|
491
|
+
private addASN1Signed(v: bigint, tag: asn1.Tag): void {
|
|
492
|
+
this.AddASN1(tag, (child) => {
|
|
493
|
+
child!.add(...encodeASN1Signed(v))
|
|
494
|
+
})
|
|
495
|
+
}
|
|
496
|
+
|
|
497
|
+
private addBase128Int(v: number): void {
|
|
498
|
+
if (v < 0) {
|
|
499
|
+
this.SetError($.newError('cryptobyte: negative OID component'))
|
|
500
|
+
return
|
|
501
|
+
}
|
|
502
|
+
const out = [byte(v)]
|
|
503
|
+
v = Math.floor(v / 128)
|
|
504
|
+
while (v > 0) {
|
|
505
|
+
out.unshift(byte(v) | 0x80)
|
|
506
|
+
v = Math.floor(v / 128)
|
|
507
|
+
}
|
|
508
|
+
this.add(...out)
|
|
509
|
+
}
|
|
510
|
+
|
|
511
|
+
private addLengthPrefixed(
|
|
512
|
+
lenLen: number,
|
|
513
|
+
isASN1: boolean,
|
|
514
|
+
f: BuilderContinuation,
|
|
515
|
+
): void {
|
|
516
|
+
this.flushChild()
|
|
517
|
+
if (this.err != null) {
|
|
518
|
+
return
|
|
519
|
+
}
|
|
520
|
+
this.offset = this.result.length
|
|
521
|
+
this.pendingLenLen = lenLen
|
|
522
|
+
this.pendingIsASN1 = isASN1
|
|
523
|
+
this.add(...new Array<number>(lenLen).fill(0))
|
|
524
|
+
const child = new Builder({
|
|
525
|
+
err: this.err,
|
|
526
|
+
resultArray: this.result,
|
|
527
|
+
fixedSize: this.fixedSize,
|
|
528
|
+
capacityLimit: this.capacityLimit,
|
|
529
|
+
})
|
|
530
|
+
this.child = child
|
|
531
|
+
try {
|
|
532
|
+
f?.(child)
|
|
533
|
+
} catch (err) {
|
|
534
|
+
const value = $.panicValue(err)
|
|
535
|
+
if (value instanceof BuildError) {
|
|
536
|
+
this.SetError(value.Err)
|
|
537
|
+
} else {
|
|
538
|
+
throw err
|
|
539
|
+
}
|
|
540
|
+
}
|
|
541
|
+
if (this.child === child) {
|
|
542
|
+
this.flushChild()
|
|
543
|
+
}
|
|
544
|
+
}
|
|
545
|
+
|
|
546
|
+
private flushChild(): void {
|
|
547
|
+
if (this.child == null) {
|
|
548
|
+
return
|
|
549
|
+
}
|
|
550
|
+
if (this.err == null && this.child.err != null) {
|
|
551
|
+
this.err = this.child.err
|
|
552
|
+
}
|
|
553
|
+
const offset = this.offset
|
|
554
|
+
const lenLen = this.pendingLenLen
|
|
555
|
+
const childStart = offset + lenLen
|
|
556
|
+
const length = this.result.length - childStart
|
|
557
|
+
if (this.err == null) {
|
|
558
|
+
if (this.pendingIsASN1) {
|
|
559
|
+
this.flushASN1Length(offset, length)
|
|
560
|
+
} else {
|
|
561
|
+
const max = 1n << BigInt(lenLen * 8)
|
|
562
|
+
if (BigInt(length) >= max) {
|
|
563
|
+
this.SetError($.newError('cryptobyte: length prefix overflow'))
|
|
564
|
+
} else {
|
|
565
|
+
for (let i = lenLen - 1, value = length; i >= 0; i--) {
|
|
566
|
+
this.result[offset + i] = byte(value)
|
|
567
|
+
value = Math.floor(value / 256)
|
|
568
|
+
}
|
|
569
|
+
}
|
|
570
|
+
}
|
|
571
|
+
}
|
|
572
|
+
this.child = null
|
|
573
|
+
}
|
|
574
|
+
|
|
575
|
+
private flushASN1Length(offset: number, length: number): void {
|
|
576
|
+
if (length <= 127) {
|
|
577
|
+
this.result[offset] = length
|
|
578
|
+
return
|
|
579
|
+
}
|
|
580
|
+
const encoded = encodeASN1Length(length)
|
|
581
|
+
const extra = encoded.length - 1
|
|
582
|
+
this.result.push(...new Array<number>(extra).fill(0))
|
|
583
|
+
for (let i = this.result.length - extra - 1; i > offset; i--) {
|
|
584
|
+
this.result[i + extra] = this.result[i]
|
|
585
|
+
}
|
|
586
|
+
for (let i = 0; i < encoded.length; i++) {
|
|
587
|
+
this.result[offset + i] = encoded[i]
|
|
588
|
+
}
|
|
589
|
+
}
|
|
590
|
+
|
|
591
|
+
private add(...bytes: number[]): void {
|
|
592
|
+
this.flushChild()
|
|
593
|
+
if (this.err != null) {
|
|
594
|
+
return
|
|
595
|
+
}
|
|
596
|
+
if (this.fixedSize && this.result.length + bytes.length > this.capacityLimit) {
|
|
597
|
+
this.SetError($.newError('cryptobyte: Builder is exceeding its fixed-size buffer'))
|
|
598
|
+
return
|
|
599
|
+
}
|
|
600
|
+
this.result.push(...bytes.map(byte))
|
|
601
|
+
}
|
|
602
|
+
}
|
|
603
|
+
|
|
604
|
+
export function NewBuilder(buffer?: $.Bytes | null): Builder {
|
|
605
|
+
return new Builder({ result: buffer ?? new Uint8Array(0), fixedSize: false })
|
|
606
|
+
}
|
|
607
|
+
|
|
608
|
+
export function NewFixedBuilder(buffer: $.Bytes): Builder {
|
|
609
|
+
return new Builder({
|
|
610
|
+
result: new Uint8Array(0),
|
|
611
|
+
fixedSize: true,
|
|
612
|
+
capacityLimit: $.cap(buffer),
|
|
613
|
+
})
|
|
614
|
+
}
|
|
615
|
+
|
|
616
|
+
function encodeASN1Length(length: number): number[] {
|
|
617
|
+
if (length <= 127) {
|
|
618
|
+
return [length]
|
|
619
|
+
}
|
|
620
|
+
const out: number[] = []
|
|
621
|
+
let value = length
|
|
622
|
+
while (value > 0) {
|
|
623
|
+
out.unshift(byte(value))
|
|
624
|
+
value = Math.floor(value / 256)
|
|
625
|
+
}
|
|
626
|
+
return [0x80 | out.length, ...out]
|
|
627
|
+
}
|
|
628
|
+
|
|
629
|
+
function encodeASN1Unsigned(value: bigint): number[] {
|
|
630
|
+
if (value < 0n || value > maxUint64) {
|
|
631
|
+
return []
|
|
632
|
+
}
|
|
633
|
+
const out = unsignedBytes(value)
|
|
634
|
+
if (out.length === 0) {
|
|
635
|
+
return [0]
|
|
636
|
+
}
|
|
637
|
+
if ((out[0] & 0x80) !== 0) {
|
|
638
|
+
out.unshift(0)
|
|
639
|
+
}
|
|
640
|
+
return out
|
|
641
|
+
}
|
|
642
|
+
|
|
643
|
+
function encodeASN1Signed(value: bigint): number[] {
|
|
644
|
+
if (value >= 0n) {
|
|
645
|
+
const out = unsignedBytes(value)
|
|
646
|
+
if (out.length === 0) {
|
|
647
|
+
return [0]
|
|
648
|
+
}
|
|
649
|
+
if ((out[0] & 0x80) !== 0) {
|
|
650
|
+
out.unshift(0)
|
|
651
|
+
}
|
|
652
|
+
return out
|
|
653
|
+
}
|
|
654
|
+
let byteLen = 1
|
|
655
|
+
while (value < -(1n << BigInt(byteLen * 8 - 1))) {
|
|
656
|
+
byteLen++
|
|
657
|
+
}
|
|
658
|
+
const mod = 1n << BigInt(byteLen * 8)
|
|
659
|
+
return fixedUnsignedBytes(mod + value, byteLen)
|
|
660
|
+
}
|
|
661
|
+
|
|
662
|
+
function unsignedBytes(value: bigint): number[] {
|
|
663
|
+
if (value === 0n) {
|
|
664
|
+
return []
|
|
665
|
+
}
|
|
666
|
+
const out: number[] = []
|
|
667
|
+
while (value > 0n) {
|
|
668
|
+
out.unshift(byte(value))
|
|
669
|
+
value >>= 8n
|
|
670
|
+
}
|
|
671
|
+
return out
|
|
672
|
+
}
|
|
673
|
+
|
|
674
|
+
function fixedUnsignedBytes(value: bigint, byteLen: number): number[] {
|
|
675
|
+
const out = new Array<number>(byteLen)
|
|
676
|
+
for (let i = byteLen - 1; i >= 0; i--) {
|
|
677
|
+
out[i] = byte(value)
|
|
678
|
+
value >>= 8n
|
|
679
|
+
}
|
|
680
|
+
return out
|
|
681
|
+
}
|
|
682
|
+
|
|
683
|
+
function toUint64BigInt(value: number | bigint): bigint {
|
|
684
|
+
if (typeof value === 'bigint') {
|
|
685
|
+
return BigInt.asUintN(64, value)
|
|
686
|
+
}
|
|
687
|
+
if (Number.isSafeInteger(value) && value >= 0) {
|
|
688
|
+
return BigInt(value)
|
|
689
|
+
}
|
|
690
|
+
return BigInt.asUintN(64, BigInt(Math.trunc(value)))
|
|
691
|
+
}
|
|
692
|
+
|
|
693
|
+
function signedBigInt(bytes: $.Bytes): bigint {
|
|
694
|
+
const arr = bytesArray(bytes)
|
|
695
|
+
let value = 0n
|
|
696
|
+
for (const b of arr) {
|
|
697
|
+
value = (value << 8n) | BigInt(b)
|
|
698
|
+
}
|
|
699
|
+
if (arr.length > 0 && (arr[0] & 0x80) !== 0) {
|
|
700
|
+
value -= 1n << BigInt(arr.length * 8)
|
|
701
|
+
}
|
|
702
|
+
return value
|
|
703
|
+
}
|
|
704
|
+
|
|
705
|
+
function unsignedBigInt(bytes: $.Bytes): bigint {
|
|
706
|
+
let value = 0n
|
|
707
|
+
for (const b of bytesArray(bytes)) {
|
|
708
|
+
value = (value << 8n) | BigInt(b)
|
|
709
|
+
}
|
|
710
|
+
return value
|
|
711
|
+
}
|
|
712
|
+
|
|
713
|
+
function checkASN1Integer(bytes: $.Bytes): boolean {
|
|
714
|
+
const arr = bytesArray(bytes)
|
|
715
|
+
if (arr.length === 0) {
|
|
716
|
+
return false
|
|
717
|
+
}
|
|
718
|
+
if (arr.length === 1) {
|
|
719
|
+
return true
|
|
720
|
+
}
|
|
721
|
+
if (arr[0] === 0 && (arr[1] & 0x80) === 0) {
|
|
722
|
+
return false
|
|
723
|
+
}
|
|
724
|
+
if (arr[0] === 0xff && (arr[1] & 0x80) === 0x80) {
|
|
725
|
+
return false
|
|
726
|
+
}
|
|
727
|
+
return true
|
|
728
|
+
}
|
|
729
|
+
|
|
730
|
+
type WriteTarget = {
|
|
731
|
+
typeName: string
|
|
732
|
+
ref: $.VarRef<unknown> | null
|
|
733
|
+
value: unknown
|
|
734
|
+
}
|
|
735
|
+
|
|
736
|
+
function boxedTypeName(value: unknown): string {
|
|
737
|
+
if (value !== null && typeof value === 'object' && '__goType' in value) {
|
|
738
|
+
return globalThis.String((value as { __goType?: unknown }).__goType ?? '')
|
|
739
|
+
}
|
|
740
|
+
return ''
|
|
741
|
+
}
|
|
742
|
+
|
|
743
|
+
function boxedValue(value: unknown): unknown {
|
|
744
|
+
if (value !== null && typeof value === 'object' && '__goValue' in value) {
|
|
745
|
+
return (value as { __goValue: unknown }).__goValue
|
|
746
|
+
}
|
|
747
|
+
return value
|
|
748
|
+
}
|
|
749
|
+
|
|
750
|
+
function writeTarget(out: unknown): WriteTarget {
|
|
751
|
+
const typeName = boxedTypeName(out)
|
|
752
|
+
const value = boxedValue(out)
|
|
753
|
+
if ($.isVarRef(value)) {
|
|
754
|
+
return { typeName, ref: value as $.VarRef<unknown>, value: value.value }
|
|
755
|
+
}
|
|
756
|
+
if ($.isVarRef(out)) {
|
|
757
|
+
return { typeName, ref: out as $.VarRef<unknown>, value: out.value }
|
|
758
|
+
}
|
|
759
|
+
return { typeName, ref: null, value }
|
|
760
|
+
}
|
|
761
|
+
|
|
762
|
+
function pointerValueOrBox(value: unknown): unknown {
|
|
763
|
+
const raw = boxedValue(value)
|
|
764
|
+
if ($.isVarRef(raw)) {
|
|
765
|
+
return raw.value
|
|
766
|
+
}
|
|
767
|
+
return raw
|
|
768
|
+
}
|
|
769
|
+
|
|
770
|
+
function isBigIntType(target: WriteTarget): boolean {
|
|
771
|
+
const typeName = target.typeName.replace(/^\*/, '')
|
|
772
|
+
const value = pointerValueOrBox(target.value)
|
|
773
|
+
return (
|
|
774
|
+
typeName === 'big.Int' ||
|
|
775
|
+
typeName === 'math/big.Int' ||
|
|
776
|
+
(value !== null &&
|
|
777
|
+
typeof value === 'object' &&
|
|
778
|
+
typeof (value as { SetBytes?: unknown }).SetBytes === 'function' &&
|
|
779
|
+
typeof (value as { Sign?: unknown }).Sign === 'function')
|
|
780
|
+
)
|
|
781
|
+
}
|
|
782
|
+
|
|
783
|
+
function integerKind(typeName: string): string {
|
|
784
|
+
return typeName.replace(/^\*/, '')
|
|
785
|
+
}
|
|
786
|
+
|
|
787
|
+
function writeInteger(target: WriteTarget, value: bigint): void {
|
|
788
|
+
const kind = integerKind(target.typeName)
|
|
789
|
+
if (isBigIntType(target)) {
|
|
790
|
+
setBigIntObject(pointerValueOrBox(target.value), value)
|
|
791
|
+
return
|
|
792
|
+
}
|
|
793
|
+
if (target.ref == null) {
|
|
794
|
+
$.panic('out does not point to an integer type')
|
|
795
|
+
}
|
|
796
|
+
switch (kind) {
|
|
797
|
+
case '':
|
|
798
|
+
case 'int':
|
|
799
|
+
case 'int64':
|
|
800
|
+
if (value < minInt64 || value > maxInt64) {
|
|
801
|
+
throw $.newError('cryptobyte: integer overflow')
|
|
802
|
+
}
|
|
803
|
+
target.ref!.value = $.int(value, 64)
|
|
804
|
+
return
|
|
805
|
+
case 'int8':
|
|
806
|
+
if (value < -128n || value > 127n) {
|
|
807
|
+
throw $.newError('cryptobyte: integer overflow')
|
|
808
|
+
}
|
|
809
|
+
target.ref!.value = $.int(value, 8)
|
|
810
|
+
return
|
|
811
|
+
case 'int16':
|
|
812
|
+
if (value < -32768n || value > 32767n) {
|
|
813
|
+
throw $.newError('cryptobyte: integer overflow')
|
|
814
|
+
}
|
|
815
|
+
target.ref!.value = $.int(value, 16)
|
|
816
|
+
return
|
|
817
|
+
case 'int32':
|
|
818
|
+
if (value < -2147483648n || value > 2147483647n) {
|
|
819
|
+
throw $.newError('cryptobyte: integer overflow')
|
|
820
|
+
}
|
|
821
|
+
target.ref!.value = $.int(value, 32)
|
|
822
|
+
return
|
|
823
|
+
case 'uint':
|
|
824
|
+
case 'uint64':
|
|
825
|
+
case 'uintptr':
|
|
826
|
+
if (value < 0n || value > maxUint64) {
|
|
827
|
+
throw $.newError('cryptobyte: integer overflow')
|
|
828
|
+
}
|
|
829
|
+
target.ref!.value = $.uint(value, 64)
|
|
830
|
+
return
|
|
831
|
+
case 'uint8':
|
|
832
|
+
case 'byte':
|
|
833
|
+
if (value < 0n || value > 255n) {
|
|
834
|
+
throw $.newError('cryptobyte: integer overflow')
|
|
835
|
+
}
|
|
836
|
+
target.ref!.value = $.uint(value, 8)
|
|
837
|
+
return
|
|
838
|
+
case 'uint16':
|
|
839
|
+
if (value < 0n || value > 65535n) {
|
|
840
|
+
throw $.newError('cryptobyte: integer overflow')
|
|
841
|
+
}
|
|
842
|
+
target.ref!.value = $.uint(value, 16)
|
|
843
|
+
return
|
|
844
|
+
case 'uint32':
|
|
845
|
+
if (value < 0n || value > 4294967295n) {
|
|
846
|
+
throw $.newError('cryptobyte: integer overflow')
|
|
847
|
+
}
|
|
848
|
+
target.ref!.value = $.uint(value, 32)
|
|
849
|
+
return
|
|
850
|
+
default:
|
|
851
|
+
throw $.newError(
|
|
852
|
+
'cryptobyte: ReadASN1Integer of a named integer type is not supported in the js build',
|
|
853
|
+
)
|
|
854
|
+
}
|
|
855
|
+
}
|
|
856
|
+
|
|
857
|
+
function integerDefaultValue(defaultValue: unknown): bigint {
|
|
858
|
+
const raw = boxedValue(defaultValue)
|
|
859
|
+
if (typeof raw === 'bigint') {
|
|
860
|
+
return raw
|
|
861
|
+
}
|
|
862
|
+
if (typeof raw === 'number' && Number.isFinite(raw)) {
|
|
863
|
+
return BigInt(Math.trunc(raw))
|
|
864
|
+
}
|
|
865
|
+
if (raw !== null && typeof raw === 'object') {
|
|
866
|
+
return bigIntValue(raw)
|
|
867
|
+
}
|
|
868
|
+
throw $.newError(
|
|
869
|
+
'cryptobyte: ReadOptionalASN1Integer default of a named integer type is not supported in the js build',
|
|
870
|
+
)
|
|
871
|
+
}
|
|
872
|
+
|
|
873
|
+
function setBigIntObject(target: unknown, value: bigint): void {
|
|
874
|
+
if (target == null || typeof target !== 'object') {
|
|
875
|
+
$.panic('out does not point to an integer type')
|
|
876
|
+
}
|
|
877
|
+
const big = target as {
|
|
878
|
+
SetBytes?: (bytes: $.Bytes) => unknown
|
|
879
|
+
SetInt64?: (value: number) => unknown
|
|
880
|
+
Neg?: (value: unknown) => unknown
|
|
881
|
+
value?: bigint
|
|
882
|
+
}
|
|
883
|
+
if ('value' in big) {
|
|
884
|
+
big.value = value
|
|
885
|
+
return
|
|
886
|
+
}
|
|
887
|
+
const magnitude = bytesFromArray(unsignedBytes(value < 0n ? -value : value))
|
|
888
|
+
if (typeof big.SetBytes === 'function') {
|
|
889
|
+
big.SetBytes(magnitude)
|
|
890
|
+
if (value < 0n) {
|
|
891
|
+
if (typeof big.Neg !== 'function') {
|
|
892
|
+
throw $.newError(
|
|
893
|
+
'cryptobyte: big.Int negative assignment is not supported in the js build',
|
|
894
|
+
)
|
|
895
|
+
}
|
|
896
|
+
big.Neg(big)
|
|
897
|
+
}
|
|
898
|
+
return
|
|
899
|
+
}
|
|
900
|
+
if (typeof big.SetInt64 === 'function') {
|
|
901
|
+
big.SetInt64(Number(value))
|
|
902
|
+
return
|
|
903
|
+
}
|
|
904
|
+
throw $.newError('cryptobyte: unsupported big.Int representation')
|
|
905
|
+
}
|
|
906
|
+
|
|
907
|
+
function bigIntValue(value: unknown): bigint {
|
|
908
|
+
const raw = pointerValueOrBox(value)
|
|
909
|
+
if (typeof raw === 'bigint') {
|
|
910
|
+
return raw
|
|
911
|
+
}
|
|
912
|
+
if (typeof raw === 'number') {
|
|
913
|
+
return BigInt(Math.trunc(raw))
|
|
914
|
+
}
|
|
915
|
+
if (raw !== null && typeof raw === 'object') {
|
|
916
|
+
const big = raw as {
|
|
917
|
+
value?: bigint | number
|
|
918
|
+
Sign?: () => number
|
|
919
|
+
Bytes?: () => $.Bytes
|
|
920
|
+
String?: () => string
|
|
921
|
+
}
|
|
922
|
+
if (typeof big.value === 'bigint') {
|
|
923
|
+
return big.value
|
|
924
|
+
}
|
|
925
|
+
if (typeof big.value === 'number') {
|
|
926
|
+
return BigInt(Math.trunc(big.value))
|
|
927
|
+
}
|
|
928
|
+
if (typeof big.Sign === 'function' && typeof big.Bytes === 'function') {
|
|
929
|
+
const sign = big.Sign()
|
|
930
|
+
const mag = unsignedBigInt(big.Bytes())
|
|
931
|
+
return sign < 0 ? -mag : mag
|
|
932
|
+
}
|
|
933
|
+
if (typeof big.String === 'function') {
|
|
934
|
+
return BigInt(big.String())
|
|
935
|
+
}
|
|
936
|
+
}
|
|
937
|
+
throw $.newError('cryptobyte: unsupported big.Int representation')
|
|
938
|
+
}
|
|
939
|
+
|
|
940
|
+
function readASN1Bytes(
|
|
941
|
+
s: $.VarRef<String> | null,
|
|
942
|
+
tag: asn1.Tag,
|
|
943
|
+
): $.Bytes | null {
|
|
944
|
+
const bytes = $.varRef<String>(new Uint8Array(0))
|
|
945
|
+
if (!String_ReadASN1(s, bytes, tag)) {
|
|
946
|
+
return null
|
|
947
|
+
}
|
|
948
|
+
return bytes.value
|
|
949
|
+
}
|
|
950
|
+
|
|
951
|
+
function readASN1SignedInteger(
|
|
952
|
+
s: $.VarRef<String> | null,
|
|
953
|
+
tag: asn1.Tag,
|
|
954
|
+
): bigint | null {
|
|
955
|
+
const bytes = readASN1Bytes(s, tag)
|
|
956
|
+
if (bytes == null || !checkASN1Integer(bytes)) {
|
|
957
|
+
return null
|
|
958
|
+
}
|
|
959
|
+
return signedBigInt(bytes)
|
|
960
|
+
}
|
|
961
|
+
|
|
962
|
+
export function String_ReadASN1Boolean(
|
|
963
|
+
s: $.VarRef<String> | null,
|
|
964
|
+
out: $.VarRef<boolean> | null,
|
|
965
|
+
): boolean {
|
|
966
|
+
const bytes = readASN1Bytes(s, asn1.BOOLEAN)
|
|
967
|
+
const arr = bytesArray(bytes)
|
|
968
|
+
if (bytes == null || arr.length !== 1 || (arr[0] !== 0 && arr[0] !== 0xff)) {
|
|
969
|
+
return false
|
|
970
|
+
}
|
|
971
|
+
writeRef(out, arr[0] === 0xff)
|
|
972
|
+
return true
|
|
973
|
+
}
|
|
974
|
+
|
|
975
|
+
export function String_ReadASN1Integer(
|
|
976
|
+
s: $.VarRef<String> | null,
|
|
977
|
+
out: unknown,
|
|
978
|
+
): boolean {
|
|
979
|
+
const target = writeTarget(out)
|
|
980
|
+
const bytes = readASN1Bytes(s, asn1.INTEGER)
|
|
981
|
+
if (bytes == null || !checkASN1Integer(bytes)) {
|
|
982
|
+
return false
|
|
983
|
+
}
|
|
984
|
+
const value = signedBigInt(bytes)
|
|
985
|
+
writeInteger(target, value)
|
|
986
|
+
return true
|
|
987
|
+
}
|
|
988
|
+
|
|
989
|
+
export function String_ReadASN1Int64WithTag(
|
|
990
|
+
s: $.VarRef<String> | null,
|
|
991
|
+
out: $.VarRef<number> | null,
|
|
992
|
+
tag: asn1.Tag,
|
|
993
|
+
): boolean {
|
|
994
|
+
const value = readASN1SignedInteger(s, tag)
|
|
995
|
+
if (value == null || value < minInt64 || value > maxInt64) {
|
|
996
|
+
return false
|
|
997
|
+
}
|
|
998
|
+
writeRef(out, $.int(value, 64))
|
|
999
|
+
return true
|
|
1000
|
+
}
|
|
1001
|
+
|
|
1002
|
+
export function String_ReadASN1Enum(
|
|
1003
|
+
s: $.VarRef<String> | null,
|
|
1004
|
+
out: $.VarRef<number> | null,
|
|
1005
|
+
): boolean {
|
|
1006
|
+
const value = readASN1SignedInteger(s, asn1.ENUM)
|
|
1007
|
+
if (value == null || value < minInt64 || value > maxInt64) {
|
|
1008
|
+
return false
|
|
1009
|
+
}
|
|
1010
|
+
writeRef(out, $.int(value, 64))
|
|
1011
|
+
return true
|
|
1012
|
+
}
|
|
1013
|
+
|
|
1014
|
+
export function String_ReadASN1ObjectIdentifier(
|
|
1015
|
+
s: $.VarRef<String> | null,
|
|
1016
|
+
out: $.VarRef<$.Slice<number> | null> | null,
|
|
1017
|
+
): boolean {
|
|
1018
|
+
const bytes = readASN1Bytes(s, asn1.OBJECT_IDENTIFIER)
|
|
1019
|
+
const arr = bytesArray(bytes)
|
|
1020
|
+
if (bytes == null || arr.length === 0) {
|
|
1021
|
+
return false
|
|
1022
|
+
}
|
|
1023
|
+
const oid: number[] = []
|
|
1024
|
+
let offset = 0
|
|
1025
|
+
const firstRead = readBase128Int(arr, offset)
|
|
1026
|
+
if (firstRead == null) {
|
|
1027
|
+
return false
|
|
1028
|
+
}
|
|
1029
|
+
offset = firstRead.next
|
|
1030
|
+
if (firstRead.value < 80) {
|
|
1031
|
+
oid.push(Math.floor(firstRead.value / 40), firstRead.value % 40)
|
|
1032
|
+
} else {
|
|
1033
|
+
oid.push(2, firstRead.value - 80)
|
|
1034
|
+
}
|
|
1035
|
+
while (offset < arr.length) {
|
|
1036
|
+
const part = readBase128Int(arr, offset)
|
|
1037
|
+
if (part == null) {
|
|
1038
|
+
return false
|
|
1039
|
+
}
|
|
1040
|
+
offset = part.next
|
|
1041
|
+
oid.push(part.value)
|
|
1042
|
+
}
|
|
1043
|
+
writeRef(out, $.arrayToSlice(oid))
|
|
1044
|
+
return true
|
|
1045
|
+
}
|
|
1046
|
+
|
|
1047
|
+
export function String_ReadASN1GeneralizedTime(
|
|
1048
|
+
s: $.VarRef<String> | null,
|
|
1049
|
+
out: $.VarRef<time.Time> | null,
|
|
1050
|
+
): boolean {
|
|
1051
|
+
const bytes = readASN1Bytes(s, asn1.GeneralizedTime)
|
|
1052
|
+
if (bytes == null) {
|
|
1053
|
+
return false
|
|
1054
|
+
}
|
|
1055
|
+
const parsed = parseGeneralizedTime(bytesToAscii(bytes))
|
|
1056
|
+
if (parsed == null) {
|
|
1057
|
+
return false
|
|
1058
|
+
}
|
|
1059
|
+
writeRef(out, parsed)
|
|
1060
|
+
return true
|
|
1061
|
+
}
|
|
1062
|
+
|
|
1063
|
+
export function String_ReadASN1UTCTime(
|
|
1064
|
+
s: $.VarRef<String> | null,
|
|
1065
|
+
out: $.VarRef<time.Time> | null,
|
|
1066
|
+
): boolean {
|
|
1067
|
+
const bytes = readASN1Bytes(s, asn1.UTCTime)
|
|
1068
|
+
if (bytes == null) {
|
|
1069
|
+
return false
|
|
1070
|
+
}
|
|
1071
|
+
const parsed = parseUTCTime(bytesToAscii(bytes))
|
|
1072
|
+
if (parsed == null) {
|
|
1073
|
+
return false
|
|
1074
|
+
}
|
|
1075
|
+
writeRef(out, parsed)
|
|
1076
|
+
return true
|
|
1077
|
+
}
|
|
1078
|
+
|
|
1079
|
+
export function String_ReadASN1BitString(
|
|
1080
|
+
s: $.VarRef<String> | null,
|
|
1081
|
+
out: unknown,
|
|
1082
|
+
): boolean {
|
|
1083
|
+
const bytes = readASN1Bytes(s, asn1.BIT_STRING)
|
|
1084
|
+
const parsed = parseBitString(bytes)
|
|
1085
|
+
if (parsed == null) {
|
|
1086
|
+
return false
|
|
1087
|
+
}
|
|
1088
|
+
const target = pointerValueOrBox(out) as {
|
|
1089
|
+
Bytes?: $.Bytes
|
|
1090
|
+
BitLength?: number
|
|
1091
|
+
} | null
|
|
1092
|
+
if (target == null) {
|
|
1093
|
+
throw new Error(
|
|
1094
|
+
'runtime error: invalid memory address or nil pointer dereference',
|
|
1095
|
+
)
|
|
1096
|
+
}
|
|
1097
|
+
target.Bytes = parsed.bytes
|
|
1098
|
+
target.BitLength = parsed.bitLength
|
|
1099
|
+
return true
|
|
1100
|
+
}
|
|
1101
|
+
|
|
1102
|
+
export function String_ReadASN1BitStringAsBytes(
|
|
1103
|
+
s: $.VarRef<String> | null,
|
|
1104
|
+
out: $.VarRef<$.Bytes> | null,
|
|
1105
|
+
paddingBits: $.VarRef<number> | null,
|
|
1106
|
+
): boolean {
|
|
1107
|
+
const bytes = readASN1Bytes(s, asn1.BIT_STRING)
|
|
1108
|
+
const parsed = parseBitString(bytes)
|
|
1109
|
+
if (parsed == null) {
|
|
1110
|
+
return false
|
|
1111
|
+
}
|
|
1112
|
+
writeRef(out, parsed.bytes)
|
|
1113
|
+
writeRef(paddingBits, parsed.paddingBits)
|
|
1114
|
+
return true
|
|
1115
|
+
}
|
|
1116
|
+
|
|
1117
|
+
export function String_ReadASN1Bytes(
|
|
1118
|
+
s: $.VarRef<String> | null,
|
|
1119
|
+
out: $.VarRef<$.Bytes> | null,
|
|
1120
|
+
tag: asn1.Tag,
|
|
1121
|
+
): boolean {
|
|
1122
|
+
return String_ReadASN1(s, out as $.VarRef<String> | null, tag)
|
|
1123
|
+
}
|
|
1124
|
+
|
|
1125
|
+
export function String_ReadASN1(
|
|
1126
|
+
s: $.VarRef<String> | null,
|
|
1127
|
+
out: $.VarRef<String> | null,
|
|
1128
|
+
tag: asn1.Tag,
|
|
1129
|
+
): boolean {
|
|
1130
|
+
return readASN1(s, out, null, tag, true)
|
|
1131
|
+
}
|
|
1132
|
+
|
|
1133
|
+
export function String_ReadASN1Element(
|
|
1134
|
+
s: $.VarRef<String> | null,
|
|
1135
|
+
out: $.VarRef<String> | null,
|
|
1136
|
+
tag: asn1.Tag,
|
|
1137
|
+
): boolean {
|
|
1138
|
+
return readASN1(s, out, null, tag, false)
|
|
1139
|
+
}
|
|
1140
|
+
|
|
1141
|
+
export function String_ReadAnyASN1(
|
|
1142
|
+
s: $.VarRef<String> | null,
|
|
1143
|
+
out: $.VarRef<String> | null,
|
|
1144
|
+
outTag: $.VarRef<asn1.Tag> | null,
|
|
1145
|
+
): boolean {
|
|
1146
|
+
return readASN1(s, out, outTag, null, true)
|
|
1147
|
+
}
|
|
1148
|
+
|
|
1149
|
+
export function String_ReadAnyASN1Element(
|
|
1150
|
+
s: $.VarRef<String> | null,
|
|
1151
|
+
out: $.VarRef<String> | null,
|
|
1152
|
+
outTag: $.VarRef<asn1.Tag> | null,
|
|
1153
|
+
): boolean {
|
|
1154
|
+
return readASN1(s, out, outTag, null, false)
|
|
1155
|
+
}
|
|
1156
|
+
|
|
1157
|
+
export function String_PeekASN1Tag(s: String, tag: asn1.Tag): boolean {
|
|
1158
|
+
const parsed = parseASN1(s)
|
|
1159
|
+
return parsed !== null && parsed.tag === tag
|
|
1160
|
+
}
|
|
1161
|
+
|
|
1162
|
+
export function String_SkipASN1(
|
|
1163
|
+
s: $.VarRef<String> | null,
|
|
1164
|
+
tag: asn1.Tag,
|
|
1165
|
+
): boolean {
|
|
1166
|
+
const out = $.varRef<String>(new Uint8Array(0))
|
|
1167
|
+
return String_ReadASN1Element(s, out, tag)
|
|
1168
|
+
}
|
|
1169
|
+
|
|
1170
|
+
export function String_ReadOptionalASN1(
|
|
1171
|
+
s: $.VarRef<String> | null,
|
|
1172
|
+
out: $.VarRef<String> | null,
|
|
1173
|
+
tag: asn1.Tag,
|
|
1174
|
+
defaultValue: String,
|
|
1175
|
+
): boolean {
|
|
1176
|
+
if (!String_PeekASN1Tag(stringValue(s), tag)) {
|
|
1177
|
+
writeRef(out, defaultValue)
|
|
1178
|
+
return true
|
|
1179
|
+
}
|
|
1180
|
+
return String_ReadASN1(s, out, tag)
|
|
1181
|
+
}
|
|
1182
|
+
|
|
1183
|
+
export function String_SkipOptionalASN1(
|
|
1184
|
+
s: $.VarRef<String> | null,
|
|
1185
|
+
tag: asn1.Tag,
|
|
1186
|
+
): boolean {
|
|
1187
|
+
if (!String_PeekASN1Tag(stringValue(s), tag)) {
|
|
1188
|
+
return true
|
|
1189
|
+
}
|
|
1190
|
+
return String_SkipASN1(s, tag)
|
|
1191
|
+
}
|
|
1192
|
+
|
|
1193
|
+
export function String_ReadOptionalASN1Integer(
|
|
1194
|
+
s: $.VarRef<String> | null,
|
|
1195
|
+
out: unknown,
|
|
1196
|
+
tag: asn1.Tag,
|
|
1197
|
+
defaultValue: unknown,
|
|
1198
|
+
): boolean {
|
|
1199
|
+
if (!String_PeekASN1Tag(stringValue(s), tag)) {
|
|
1200
|
+
writeInteger(writeTarget(out), integerDefaultValue(defaultValue))
|
|
1201
|
+
return true
|
|
1202
|
+
}
|
|
1203
|
+
return String_ReadASN1Integer(s, out)
|
|
1204
|
+
}
|
|
1205
|
+
|
|
1206
|
+
export function String_ReadOptionalASN1OctetString(
|
|
1207
|
+
s: $.VarRef<String> | null,
|
|
1208
|
+
out: $.VarRef<$.Bytes> | null,
|
|
1209
|
+
tag: asn1.Tag,
|
|
1210
|
+
defaultValue: $.Bytes,
|
|
1211
|
+
): boolean {
|
|
1212
|
+
if (!String_PeekASN1Tag(stringValue(s), tag)) {
|
|
1213
|
+
writeRef(out, defaultValue)
|
|
1214
|
+
return true
|
|
1215
|
+
}
|
|
1216
|
+
return String_ReadASN1Bytes(s, out, tag)
|
|
1217
|
+
}
|
|
1218
|
+
|
|
1219
|
+
export function String_ReadOptionalASN1Boolean(
|
|
1220
|
+
s: $.VarRef<String> | null,
|
|
1221
|
+
out: $.VarRef<boolean> | null,
|
|
1222
|
+
tag: asn1.Tag,
|
|
1223
|
+
defaultValue: boolean,
|
|
1224
|
+
): boolean {
|
|
1225
|
+
if (!String_PeekASN1Tag(stringValue(s), tag)) {
|
|
1226
|
+
writeRef(out, defaultValue)
|
|
1227
|
+
return true
|
|
1228
|
+
}
|
|
1229
|
+
return String_ReadASN1Boolean(s, out)
|
|
1230
|
+
}
|
|
1231
|
+
|
|
1232
|
+
type ParsedASN1 = {
|
|
1233
|
+
tag: asn1.Tag
|
|
1234
|
+
headerLen: number
|
|
1235
|
+
length: number
|
|
1236
|
+
totalLen: number
|
|
1237
|
+
}
|
|
1238
|
+
|
|
1239
|
+
function parseASN1(data: $.Bytes): ParsedASN1 | null {
|
|
1240
|
+
const arr = bytesArray(data)
|
|
1241
|
+
if (arr.length < 2 || (arr[0] & 0x1f) === 0x1f) {
|
|
1242
|
+
return null
|
|
1243
|
+
}
|
|
1244
|
+
const tag = arr[0]
|
|
1245
|
+
let headerLen = 2
|
|
1246
|
+
let length = arr[1]
|
|
1247
|
+
if ((length & 0x80) !== 0) {
|
|
1248
|
+
const lenLen = length & 0x7f
|
|
1249
|
+
if (lenLen === 0 || lenLen > 4 || arr.length < 2 + lenLen) {
|
|
1250
|
+
return null
|
|
1251
|
+
}
|
|
1252
|
+
if (arr[2] === 0) {
|
|
1253
|
+
return null
|
|
1254
|
+
}
|
|
1255
|
+
length = 0
|
|
1256
|
+
for (let i = 0; i < lenLen; i++) {
|
|
1257
|
+
length = length * 256 + arr[2 + i]
|
|
1258
|
+
}
|
|
1259
|
+
if (length < 128) {
|
|
1260
|
+
return null
|
|
1261
|
+
}
|
|
1262
|
+
headerLen += lenLen
|
|
1263
|
+
}
|
|
1264
|
+
const totalLen = headerLen + length
|
|
1265
|
+
if (arr.length < totalLen) {
|
|
1266
|
+
return null
|
|
1267
|
+
}
|
|
1268
|
+
return { tag, headerLen, length, totalLen }
|
|
1269
|
+
}
|
|
1270
|
+
|
|
1271
|
+
function readASN1(
|
|
1272
|
+
s: $.VarRef<String> | null,
|
|
1273
|
+
out: $.VarRef<String> | null,
|
|
1274
|
+
outTag: $.VarRef<asn1.Tag> | null,
|
|
1275
|
+
expectedTag: asn1.Tag | null,
|
|
1276
|
+
skipHeader: boolean,
|
|
1277
|
+
): boolean {
|
|
1278
|
+
const data = stringValue(s)
|
|
1279
|
+
const parsed = parseASN1(data)
|
|
1280
|
+
if (parsed == null || (expectedTag !== null && parsed.tag !== expectedTag)) {
|
|
1281
|
+
return false
|
|
1282
|
+
}
|
|
1283
|
+
if (outTag != null) {
|
|
1284
|
+
outTag.value = parsed.tag
|
|
1285
|
+
}
|
|
1286
|
+
if (out != null) {
|
|
1287
|
+
out.value = skipHeader
|
|
1288
|
+
? $.goSlice(data, parsed.headerLen, parsed.totalLen)
|
|
1289
|
+
: $.goSlice(data, 0, parsed.totalLen)
|
|
1290
|
+
}
|
|
1291
|
+
s!.value = $.goSlice(data, parsed.totalLen)
|
|
1292
|
+
return true
|
|
1293
|
+
}
|
|
1294
|
+
|
|
1295
|
+
function parseBitString(bytes: $.Bytes | null): {
|
|
1296
|
+
bytes: $.Bytes
|
|
1297
|
+
paddingBits: number
|
|
1298
|
+
bitLength: number
|
|
1299
|
+
} | null {
|
|
1300
|
+
const arr = bytesArray(bytes)
|
|
1301
|
+
if (bytes == null || arr.length === 0) {
|
|
1302
|
+
return null
|
|
1303
|
+
}
|
|
1304
|
+
const paddingBits = arr[0]
|
|
1305
|
+
if (paddingBits > 7 || (arr.length === 1 && paddingBits !== 0)) {
|
|
1306
|
+
return null
|
|
1307
|
+
}
|
|
1308
|
+
if (
|
|
1309
|
+
arr.length > 1 &&
|
|
1310
|
+
paddingBits > 0 &&
|
|
1311
|
+
(arr[arr.length - 1] & ((1 << paddingBits) - 1)) !== 0
|
|
1312
|
+
) {
|
|
1313
|
+
return null
|
|
1314
|
+
}
|
|
1315
|
+
const content = bytesFromArray(arr.slice(1))
|
|
1316
|
+
return {
|
|
1317
|
+
bytes: content,
|
|
1318
|
+
paddingBits,
|
|
1319
|
+
bitLength: $.len(content) * 8 - paddingBits,
|
|
1320
|
+
}
|
|
1321
|
+
}
|
|
1322
|
+
|
|
1323
|
+
function readBase128Int(
|
|
1324
|
+
bytes: number[],
|
|
1325
|
+
offset: number,
|
|
1326
|
+
): { value: number; next: number } | null {
|
|
1327
|
+
let ret = 0
|
|
1328
|
+
for (let i = offset; i < bytes.length; i++) {
|
|
1329
|
+
const b = bytes[i]
|
|
1330
|
+
if (ret === 0 && b === 0x80) {
|
|
1331
|
+
return null
|
|
1332
|
+
}
|
|
1333
|
+
ret = ret * 128 + (b & 0x7f)
|
|
1334
|
+
if (ret > Number.MAX_SAFE_INTEGER) {
|
|
1335
|
+
return null
|
|
1336
|
+
}
|
|
1337
|
+
if ((b & 0x80) === 0) {
|
|
1338
|
+
return { value: ret, next: i + 1 }
|
|
1339
|
+
}
|
|
1340
|
+
}
|
|
1341
|
+
return null
|
|
1342
|
+
}
|
|
1343
|
+
|
|
1344
|
+
function parseFixedDigits(value: string, offset: number, width: number): number | null {
|
|
1345
|
+
const text = value.slice(offset, offset + width)
|
|
1346
|
+
if (!new RegExp(`^[0-9]{${width}}$`).test(text)) {
|
|
1347
|
+
return null
|
|
1348
|
+
}
|
|
1349
|
+
return Number(text)
|
|
1350
|
+
}
|
|
1351
|
+
|
|
1352
|
+
function parseZone(value: string, offset: number): { offsetMinutes: number } | null {
|
|
1353
|
+
if (value[offset] === 'Z' && offset + 1 === value.length) {
|
|
1354
|
+
return { offsetMinutes: 0 }
|
|
1355
|
+
}
|
|
1356
|
+
const sign = value[offset]
|
|
1357
|
+
if ((sign !== '+' && sign !== '-') || offset + 5 !== value.length) {
|
|
1358
|
+
return null
|
|
1359
|
+
}
|
|
1360
|
+
const hour = parseFixedDigits(value, offset + 1, 2)
|
|
1361
|
+
const minute = parseFixedDigits(value, offset + 3, 2)
|
|
1362
|
+
if (hour == null || minute == null || hour > 23 || minute > 59) {
|
|
1363
|
+
return null
|
|
1364
|
+
}
|
|
1365
|
+
const offsetMinutes = hour * 60 + minute
|
|
1366
|
+
return { offsetMinutes: sign === '+' ? offsetMinutes : -offsetMinutes }
|
|
1367
|
+
}
|
|
1368
|
+
|
|
1369
|
+
function makeTime(
|
|
1370
|
+
year: number,
|
|
1371
|
+
month: number,
|
|
1372
|
+
day: number,
|
|
1373
|
+
hour: number,
|
|
1374
|
+
minute: number,
|
|
1375
|
+
second: number,
|
|
1376
|
+
offsetMinutes: number,
|
|
1377
|
+
): time.Time {
|
|
1378
|
+
const millis =
|
|
1379
|
+
globalThis.Date.UTC(year, month - 1, day, hour, minute, second) -
|
|
1380
|
+
offsetMinutes * 60 * 1000
|
|
1381
|
+
return time.Unix(Math.floor(millis / 1000), 0)
|
|
1382
|
+
}
|
|
1383
|
+
|
|
1384
|
+
function parseGeneralizedTime(value: string): time.Time | null {
|
|
1385
|
+
if (value.length < 15) {
|
|
1386
|
+
return null
|
|
1387
|
+
}
|
|
1388
|
+
const year = parseFixedDigits(value, 0, 4)
|
|
1389
|
+
const month = parseFixedDigits(value, 4, 2)
|
|
1390
|
+
const day = parseFixedDigits(value, 6, 2)
|
|
1391
|
+
const hour = parseFixedDigits(value, 8, 2)
|
|
1392
|
+
const minute = parseFixedDigits(value, 10, 2)
|
|
1393
|
+
const second = parseFixedDigits(value, 12, 2)
|
|
1394
|
+
const zone = parseZone(value, 14)
|
|
1395
|
+
if (
|
|
1396
|
+
year == null ||
|
|
1397
|
+
month == null ||
|
|
1398
|
+
day == null ||
|
|
1399
|
+
hour == null ||
|
|
1400
|
+
minute == null ||
|
|
1401
|
+
second == null ||
|
|
1402
|
+
zone == null
|
|
1403
|
+
) {
|
|
1404
|
+
return null
|
|
1405
|
+
}
|
|
1406
|
+
return makeTime(year, month, day, hour, minute, second, zone.offsetMinutes)
|
|
1407
|
+
}
|
|
1408
|
+
|
|
1409
|
+
function parseUTCTime(value: string): time.Time | null {
|
|
1410
|
+
if (value.length !== 11 && value.length !== 13 && value.length !== 15 && value.length !== 17) {
|
|
1411
|
+
return null
|
|
1412
|
+
}
|
|
1413
|
+
const yearPart = parseFixedDigits(value, 0, 2)
|
|
1414
|
+
const month = parseFixedDigits(value, 2, 2)
|
|
1415
|
+
const day = parseFixedDigits(value, 4, 2)
|
|
1416
|
+
const hour = parseFixedDigits(value, 6, 2)
|
|
1417
|
+
const minute = parseFixedDigits(value, 8, 2)
|
|
1418
|
+
let second = 0
|
|
1419
|
+
let zoneOffset = 10
|
|
1420
|
+
if (value.length === 13 || value.length === 17) {
|
|
1421
|
+
const parsedSecond = parseFixedDigits(value, 10, 2)
|
|
1422
|
+
if (parsedSecond == null) {
|
|
1423
|
+
return null
|
|
1424
|
+
}
|
|
1425
|
+
second = parsedSecond
|
|
1426
|
+
zoneOffset = 12
|
|
1427
|
+
}
|
|
1428
|
+
const zone = parseZone(value, zoneOffset)
|
|
1429
|
+
if (
|
|
1430
|
+
yearPart == null ||
|
|
1431
|
+
month == null ||
|
|
1432
|
+
day == null ||
|
|
1433
|
+
hour == null ||
|
|
1434
|
+
minute == null ||
|
|
1435
|
+
zone == null
|
|
1436
|
+
) {
|
|
1437
|
+
return null
|
|
1438
|
+
}
|
|
1439
|
+
const year = yearPart >= 50 ? 1900 + yearPart : 2000 + yearPart
|
|
1440
|
+
return makeTime(year, month, day, hour, minute, second, zone.offsetMinutes)
|
|
1441
|
+
}
|