goscript 0.2.5 → 0.2.7
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/cmd/goscript/cmd-compile.go +7 -0
- package/cmd/goscript/cmd_compile_test.go +83 -0
- package/compiler/compile-request.go +3 -0
- package/compiler/compiler-cache.go +828 -0
- package/compiler/compiler-cache_test.go +705 -0
- package/compiler/config.go +2 -0
- package/compiler/index.test.ts +26 -1
- package/compiler/index.ts +5 -0
- package/compiler/lowered-program.go +31 -20
- package/compiler/lowering.go +349 -93
- package/compiler/lowering_bench_test.go +1 -0
- package/compiler/override-facts.go +309 -8
- package/compiler/override-parity-verifier.go +45 -1
- package/compiler/override-parity-verifier_test.go +100 -0
- package/compiler/override-registry_test.go +1 -0
- package/compiler/package-graph.go +40 -12
- package/compiler/package-graph_test.go +29 -0
- package/compiler/runtime-contract.go +8 -0
- package/compiler/service.go +98 -11
- package/compiler/skeleton_test.go +110 -14
- package/compiler/typescript-emitter.go +120 -23
- package/dist/compiler/index.d.ts +2 -0
- package/dist/compiler/index.js +3 -0
- package/dist/compiler/index.js.map +1 -1
- package/dist/gs/builtin/builtin.d.ts +24 -33
- package/dist/gs/builtin/builtin.js +54 -61
- package/dist/gs/builtin/builtin.js.map +1 -1
- package/dist/gs/builtin/hostio.d.ts +1 -0
- package/dist/gs/builtin/hostio.js +1 -1
- package/dist/gs/builtin/hostio.js.map +1 -1
- package/dist/gs/builtin/index.d.ts +1 -0
- package/dist/gs/builtin/index.js +1 -0
- package/dist/gs/builtin/index.js.map +1 -1
- package/dist/gs/builtin/panic.d.ts +18 -0
- package/dist/gs/builtin/panic.js +98 -0
- package/dist/gs/builtin/panic.js.map +1 -0
- package/dist/gs/builtin/slice.d.ts +10 -0
- package/dist/gs/builtin/slice.js +110 -53
- package/dist/gs/builtin/slice.js.map +1 -1
- package/dist/gs/builtin/type.js +15 -3
- package/dist/gs/builtin/type.js.map +1 -1
- package/dist/gs/builtin/varRef.d.ts +1 -1
- package/dist/gs/builtin/varRef.js +3 -2
- package/dist/gs/builtin/varRef.js.map +1 -1
- package/dist/gs/bytes/bytes.gs.js +51 -38
- package/dist/gs/bytes/bytes.gs.js.map +1 -1
- package/dist/gs/bytes/reader.gs.d.ts +1 -1
- package/dist/gs/bytes/reader.gs.js +6 -7
- package/dist/gs/bytes/reader.gs.js.map +1 -1
- package/dist/gs/cmp/index.d.ts +1 -1
- package/dist/gs/cmp/index.js +43 -10
- package/dist/gs/cmp/index.js.map +1 -1
- package/dist/gs/context/context.d.ts +2 -2
- package/dist/gs/context/context.js +1 -1
- package/dist/gs/context/context.js.map +1 -1
- package/dist/gs/embed/index.js +1 -1
- package/dist/gs/embed/index.js.map +1 -1
- package/dist/gs/encoding/binary/index.js +201 -8
- package/dist/gs/encoding/binary/index.js.map +1 -1
- package/dist/gs/encoding/json/index.d.ts +5 -0
- package/dist/gs/encoding/json/index.js +388 -25
- package/dist/gs/encoding/json/index.js.map +1 -1
- package/dist/gs/errors/errors.js +17 -24
- package/dist/gs/errors/errors.js.map +1 -1
- package/dist/gs/fmt/fmt.js +129 -35
- package/dist/gs/fmt/fmt.js.map +1 -1
- package/dist/gs/golang.org/x/crypto/cryptobyte/index.js +1 -1
- package/dist/gs/golang.org/x/crypto/cryptobyte/index.js.map +1 -1
- package/dist/gs/internal/bytealg/index.js +43 -8
- package/dist/gs/internal/bytealg/index.js.map +1 -1
- package/dist/gs/internal/byteorder/index.d.ts +2 -2
- package/dist/gs/internal/byteorder/index.js +2 -2
- package/dist/gs/internal/byteorder/index.js.map +1 -1
- package/dist/gs/io/fs/format.js +2 -2
- package/dist/gs/io/fs/format.js.map +1 -1
- package/dist/gs/io/fs/fs.d.ts +1 -1
- package/dist/gs/io/fs/fs.js +1 -1
- package/dist/gs/io/fs/fs.js.map +1 -1
- package/dist/gs/io/io.d.ts +21 -21
- package/dist/gs/io/io.js +49 -50
- package/dist/gs/io/io.js.map +1 -1
- package/dist/gs/math/bits/index.js +26 -8
- package/dist/gs/math/bits/index.js.map +1 -1
- package/dist/gs/math/copysign.gs.js +10 -17
- package/dist/gs/math/copysign.gs.js.map +1 -1
- package/dist/gs/math/pow.gs.js +5 -0
- package/dist/gs/math/pow.gs.js.map +1 -1
- package/dist/gs/math/signbit.gs.js +6 -2
- package/dist/gs/math/signbit.gs.js.map +1 -1
- package/dist/gs/mime/index.js +1 -0
- package/dist/gs/mime/index.js.map +1 -1
- package/dist/gs/net/http/index.d.ts +6 -6
- package/dist/gs/net/http/index.js +507 -43
- package/dist/gs/net/http/index.js.map +1 -1
- package/dist/gs/os/stat.gs.d.ts +2 -2
- package/dist/gs/os/types.gs.d.ts +1 -1
- package/dist/gs/os/types.gs.js +1 -1
- package/dist/gs/os/types.gs.js.map +1 -1
- package/dist/gs/os/types_js.gs.d.ts +1 -1
- package/dist/gs/os/types_js.gs.js +7 -7
- package/dist/gs/os/types_js.gs.js.map +1 -1
- package/dist/gs/os/types_unix.gs.d.ts +1 -1
- package/dist/gs/os/types_unix.gs.js +1 -1
- package/dist/gs/os/types_unix.gs.js.map +1 -1
- package/dist/gs/os/zero_copy_posix.gs.d.ts +1 -1
- package/dist/gs/os/zero_copy_posix.gs.js +1 -1
- package/dist/gs/os/zero_copy_posix.gs.js.map +1 -1
- package/dist/gs/path/filepath/match.js +8 -4
- package/dist/gs/path/filepath/match.js.map +1 -1
- package/dist/gs/path/filepath/path.js +216 -42
- package/dist/gs/path/filepath/path.js.map +1 -1
- package/dist/gs/path/match.js +6 -3
- package/dist/gs/path/match.js.map +1 -1
- package/dist/gs/reflect/type.d.ts +5 -4
- package/dist/gs/reflect/type.js +29 -11
- package/dist/gs/reflect/type.js.map +1 -1
- package/dist/gs/slices/slices.js +11 -11
- package/dist/gs/slices/slices.js.map +1 -1
- package/dist/gs/strconv/atof.gs.js +156 -43
- package/dist/gs/strconv/atof.gs.js.map +1 -1
- package/dist/gs/strconv/atoi.gs.d.ts +3 -2
- package/dist/gs/strconv/atoi.gs.js +86 -67
- package/dist/gs/strconv/atoi.gs.js.map +1 -1
- package/dist/gs/strconv/ftoa.gs.js +73 -3
- package/dist/gs/strconv/ftoa.gs.js.map +1 -1
- package/dist/gs/strconv/itoa.gs.d.ts +4 -4
- package/dist/gs/strconv/itoa.gs.js +5 -4
- package/dist/gs/strconv/itoa.gs.js.map +1 -1
- package/dist/gs/strconv/quote.gs.d.ts +1 -1
- package/dist/gs/strconv/quote.gs.js +311 -103
- package/dist/gs/strconv/quote.gs.js.map +1 -1
- package/dist/gs/strings/reader.d.ts +1 -1
- package/dist/gs/strings/reader.js +8 -8
- package/dist/gs/strings/reader.js.map +1 -1
- package/dist/gs/strings/strings.js +87 -61
- package/dist/gs/strings/strings.js.map +1 -1
- package/dist/gs/sync/atomic/doc_64.gs.d.ts +14 -14
- package/dist/gs/sync/atomic/doc_64.gs.js +10 -10
- package/dist/gs/sync/atomic/doc_64.gs.js.map +1 -1
- package/dist/gs/sync/atomic/type.gs.d.ts +22 -22
- package/dist/gs/sync/atomic/type.gs.js +4 -4
- package/dist/gs/sync/atomic/type.gs.js.map +1 -1
- package/dist/gs/sync/sync.js +50 -12
- package/dist/gs/sync/sync.js.map +1 -1
- package/dist/gs/syscall/fs.d.ts +6 -6
- package/dist/gs/syscall/fs.js +1 -1
- package/dist/gs/syscall/fs.js.map +1 -1
- package/dist/gs/time/time.d.ts +18 -18
- package/dist/gs/time/time.js +58 -55
- package/dist/gs/time/time.js.map +1 -1
- package/dist/gs/unicode/tables.d.ts +11 -0
- package/dist/gs/unicode/tables.js +635 -0
- package/dist/gs/unicode/tables.js.map +1 -0
- package/dist/gs/unicode/unicode.d.ts +58 -38
- package/dist/gs/unicode/unicode.js +362 -278
- package/dist/gs/unicode/unicode.js.map +1 -1
- package/go.sum +13 -0
- package/gs/builtin/builtin.ts +83 -93
- package/gs/builtin/hostio.ts +1 -1
- package/gs/builtin/index.ts +1 -0
- package/gs/builtin/panic.test.ts +189 -0
- package/gs/builtin/panic.ts +107 -0
- package/gs/builtin/runtime-contract.test.ts +5 -5
- package/gs/builtin/slice.test.ts +23 -0
- package/gs/builtin/slice.ts +133 -95
- package/gs/builtin/type.ts +16 -3
- package/gs/builtin/varRef.ts +4 -2
- package/gs/builtin/wide-int.test.ts +41 -0
- package/gs/bytes/bytes.gs.ts +54 -41
- package/gs/bytes/bytes.test.ts +18 -1
- package/gs/bytes/reader.gs.ts +7 -8
- package/gs/cmp/index.test.ts +55 -0
- package/gs/cmp/index.ts +45 -9
- package/gs/context/context.ts +3 -3
- package/gs/embed/index.ts +2 -2
- package/gs/encoding/binary/index.test.ts +104 -0
- package/gs/encoding/binary/index.ts +259 -11
- package/gs/encoding/json/index.test.ts +107 -0
- package/gs/encoding/json/index.ts +400 -29
- package/gs/errors/errors.test.ts +44 -1
- package/gs/errors/errors.ts +15 -31
- package/gs/fmt/fmt.test.ts +70 -2
- package/gs/fmt/fmt.ts +128 -34
- package/gs/golang.org/x/crypto/cryptobyte/index.ts +1 -1
- package/gs/internal/bytealg/index.test.ts +26 -1
- package/gs/internal/bytealg/index.ts +44 -8
- package/gs/internal/byteorder/index.ts +6 -4
- package/gs/io/fs/format.ts +2 -2
- package/gs/io/fs/fs.ts +2 -2
- package/gs/io/fs/stat.test.ts +2 -2
- package/gs/io/fs/sub.test.ts +2 -2
- package/gs/io/fs/walk.test.ts +2 -2
- package/gs/io/io.test.ts +47 -5
- package/gs/io/io.ts +73 -73
- package/gs/io/limit.test.ts +103 -0
- package/gs/math/bits/index.test.ts +128 -0
- package/gs/math/bits/index.ts +26 -8
- package/gs/math/copysign.gs.test.ts +3 -1
- package/gs/math/copysign.gs.ts +10 -22
- package/gs/math/pow.gs.test.ts +4 -5
- package/gs/math/pow.gs.ts +5 -0
- package/gs/math/signbit.gs.test.ts +2 -1
- package/gs/math/signbit.gs.ts +6 -3
- package/gs/mime/index.ts +1 -0
- package/gs/net/http/index.test.ts +683 -2
- package/gs/net/http/index.ts +598 -57
- package/gs/net/http/meta.json +3 -0
- package/gs/os/stat.gs.ts +2 -2
- package/gs/os/types.gs.ts +2 -2
- package/gs/os/types_js.gs.ts +9 -9
- package/gs/os/types_unix.gs.ts +2 -2
- package/gs/os/zero_copy_posix.gs.ts +2 -2
- package/gs/path/filepath/match.test.ts +16 -0
- package/gs/path/filepath/match.ts +8 -4
- package/gs/path/filepath/path.test.ts +91 -9
- package/gs/path/filepath/path.ts +223 -49
- package/gs/path/match.test.ts +32 -0
- package/gs/path/match.ts +6 -3
- package/gs/reflect/deepequal.test.ts +1 -1
- package/gs/reflect/field.test.ts +1 -1
- package/gs/reflect/function-types.test.ts +6 -6
- package/gs/reflect/sliceat.test.ts +13 -13
- package/gs/reflect/structof.test.ts +4 -4
- package/gs/reflect/type.ts +34 -14
- package/gs/reflect/typefor.test.ts +5 -5
- package/gs/runtime/pprof/index.test.ts +20 -0
- package/gs/runtime/trace/index.test.ts +3 -0
- package/gs/slices/slices.test.ts +31 -0
- package/gs/slices/slices.ts +11 -11
- package/gs/strconv/append.test.ts +99 -0
- package/gs/strconv/atof.gs.ts +156 -42
- package/gs/strconv/atof.test.ts +45 -0
- package/gs/strconv/atoi.gs.ts +87 -69
- package/gs/strconv/atoi.test.ts +49 -0
- package/gs/strconv/ftoa.gs.ts +85 -10
- package/gs/strconv/ftoa.test.ts +43 -0
- package/gs/strconv/itoa.gs.ts +10 -9
- package/gs/strconv/quote.gs.ts +335 -108
- package/gs/strconv/quote.test.ts +111 -0
- package/gs/strings/reader.test.ts +10 -10
- package/gs/strings/reader.ts +9 -9
- package/gs/strings/strings.test.ts +18 -5
- package/gs/strings/strings.ts +81 -68
- package/gs/sync/atomic/doc_64.gs.ts +24 -24
- package/gs/sync/atomic/doc_64.test.ts +5 -5
- package/gs/sync/atomic/type.gs.ts +28 -28
- package/gs/sync/sync.test.ts +109 -1
- package/gs/sync/sync.ts +46 -12
- package/gs/syscall/fs.ts +8 -8
- package/gs/syscall/net.test.ts +1 -1
- package/gs/time/parse.test.ts +45 -0
- package/gs/time/time.test.ts +46 -23
- package/gs/time/time.ts +69 -66
- package/gs/unicode/gen.go +198 -0
- package/gs/unicode/tables.ts +646 -0
- package/gs/unicode/unicode.test.ts +69 -0
- package/gs/unicode/unicode.ts +396 -312
- package/package.json +2 -2
- package/dist/gs/github.com/aperturerobotics/util/conc/index.d.ts +0 -20
- package/dist/gs/github.com/aperturerobotics/util/conc/index.js +0 -134
- package/dist/gs/github.com/aperturerobotics/util/conc/index.js.map +0 -1
- package/gs/github.com/aperturerobotics/util/conc/index.test.ts +0 -30
- package/gs/github.com/aperturerobotics/util/conc/index.ts +0 -172
- package/gs/github.com/aperturerobotics/util/conc/meta.json +0 -9
package/gs/io/io.ts
CHANGED
|
@@ -59,7 +59,7 @@ export interface Closer {
|
|
|
59
59
|
|
|
60
60
|
// Seeker is the interface that wraps the basic Seek method
|
|
61
61
|
export interface Seeker {
|
|
62
|
-
Seek(offset:
|
|
62
|
+
Seek(offset: bigint, whence: number): [bigint, $.GoError]
|
|
63
63
|
}
|
|
64
64
|
|
|
65
65
|
// Combined interfaces
|
|
@@ -222,12 +222,12 @@ export function Pipe(): [PipeReader, PipeWriter] {
|
|
|
222
222
|
|
|
223
223
|
// ReaderAt is the interface that wraps the basic ReadAt method
|
|
224
224
|
export interface ReaderAt {
|
|
225
|
-
ReadAt(p: $.Bytes, off:
|
|
225
|
+
ReadAt(p: $.Bytes, off: bigint): [number, $.GoError]
|
|
226
226
|
}
|
|
227
227
|
|
|
228
228
|
// WriterAt is the interface that wraps the basic WriteAt method
|
|
229
229
|
export interface WriterAt {
|
|
230
|
-
WriteAt(p: $.Bytes, off:
|
|
230
|
+
WriteAt(p: $.Bytes, off: bigint): [number, $.GoError]
|
|
231
231
|
}
|
|
232
232
|
|
|
233
233
|
// ByteReader is the interface that wraps the ReadByte method
|
|
@@ -262,12 +262,12 @@ export interface StringWriter {
|
|
|
262
262
|
|
|
263
263
|
// WriterTo is the interface that wraps the WriteTo method
|
|
264
264
|
export interface WriterTo {
|
|
265
|
-
WriteTo(w: Writer): [
|
|
265
|
+
WriteTo(w: Writer): [bigint, $.GoError]
|
|
266
266
|
}
|
|
267
267
|
|
|
268
268
|
// ReaderFrom is the interface that wraps the ReadFrom method
|
|
269
269
|
export interface ReaderFrom {
|
|
270
|
-
ReadFrom(r: Reader): [
|
|
270
|
+
ReadFrom(r: Reader): [bigint, $.GoError]
|
|
271
271
|
}
|
|
272
272
|
|
|
273
273
|
// Discard is a Writer on which all Write calls succeed without doing anything
|
|
@@ -297,25 +297,25 @@ export async function WriteString(
|
|
|
297
297
|
// LimitedReader reads from R but limits the amount of data returned to just N bytes
|
|
298
298
|
export class LimitedReader implements Reader {
|
|
299
299
|
public R: Reader | null
|
|
300
|
-
public N:
|
|
300
|
+
public N: bigint
|
|
301
301
|
|
|
302
302
|
constructor(
|
|
303
|
-
r?: Reader | { R?: Reader | null; N?:
|
|
304
|
-
n?:
|
|
303
|
+
r?: Reader | { R?: Reader | null; N?: bigint } | null,
|
|
304
|
+
n?: bigint,
|
|
305
305
|
) {
|
|
306
306
|
if (r != null && typeof (r as { Read?: unknown }).Read !== 'function') {
|
|
307
|
-
const init = r as { R?: Reader | null; N?:
|
|
307
|
+
const init = r as { R?: Reader | null; N?: bigint }
|
|
308
308
|
this.R = init.R ?? null
|
|
309
|
-
this.N = init.N ??
|
|
309
|
+
this.N = init.N ?? 0n
|
|
310
310
|
return
|
|
311
311
|
}
|
|
312
312
|
this.R = (r as Reader | null | undefined) ?? null
|
|
313
|
-
this.N = n ??
|
|
313
|
+
this.N = n ?? 0n
|
|
314
314
|
}
|
|
315
315
|
|
|
316
316
|
Read(p: $.Bytes): [number, $.GoError] {
|
|
317
317
|
return (async (): Promise<[number, $.GoError]> => {
|
|
318
|
-
if (this.N <=
|
|
318
|
+
if (this.N <= 0n) {
|
|
319
319
|
return [0, EOF]
|
|
320
320
|
}
|
|
321
321
|
if (this.R == null) {
|
|
@@ -323,19 +323,19 @@ export class LimitedReader implements Reader {
|
|
|
323
323
|
}
|
|
324
324
|
|
|
325
325
|
let readBuf = p
|
|
326
|
-
if ($.len(p) > this.N) {
|
|
327
|
-
readBuf = $.goSlice(p, 0, this.N)
|
|
326
|
+
if ($.len(p) > Number(this.N)) {
|
|
327
|
+
readBuf = $.goSlice(p, 0, Number(this.N))
|
|
328
328
|
}
|
|
329
329
|
|
|
330
330
|
const [n, err] = await (this.R.Read(readBuf) as any)
|
|
331
|
-
this.N -= n
|
|
331
|
+
this.N -= BigInt(n)
|
|
332
332
|
return [n, err]
|
|
333
333
|
})() as any
|
|
334
334
|
}
|
|
335
335
|
}
|
|
336
336
|
|
|
337
337
|
// LimitReader returns a Reader that reads from r but stops with EOF after n bytes
|
|
338
|
-
export function LimitReader(r: Reader, n:
|
|
338
|
+
export function LimitReader(r: Reader, n: bigint): Reader {
|
|
339
339
|
return new LimitedReader(r, n)
|
|
340
340
|
}
|
|
341
341
|
|
|
@@ -346,11 +346,11 @@ export class SectionReader implements Reader, Seeker, ReaderAt {
|
|
|
346
346
|
private off: number
|
|
347
347
|
private limit: number
|
|
348
348
|
|
|
349
|
-
constructor(r: ReaderAt, off:
|
|
349
|
+
constructor(r: ReaderAt, off: bigint, n: bigint) {
|
|
350
350
|
this.r = r
|
|
351
|
-
this.base = off
|
|
352
|
-
this.off = off
|
|
353
|
-
this.limit = off + n
|
|
351
|
+
this.base = Number(off)
|
|
352
|
+
this.off = Number(off)
|
|
353
|
+
this.limit = Number(off) + Number(n)
|
|
354
354
|
}
|
|
355
355
|
|
|
356
356
|
Read(p: $.Bytes): [number, $.GoError] {
|
|
@@ -363,7 +363,7 @@ export class SectionReader implements Reader, Seeker, ReaderAt {
|
|
|
363
363
|
p = $.goSlice(p, 0, max)
|
|
364
364
|
}
|
|
365
365
|
|
|
366
|
-
const res = this.r.ReadAt(p, this.off) as any
|
|
366
|
+
const res = this.r.ReadAt(p, BigInt(this.off)) as any
|
|
367
367
|
if (res instanceof Promise) {
|
|
368
368
|
return res.then(([n, err]: [number, $.GoError]) => {
|
|
369
369
|
this.off += n
|
|
@@ -376,39 +376,41 @@ export class SectionReader implements Reader, Seeker, ReaderAt {
|
|
|
376
376
|
return [n, err]
|
|
377
377
|
}
|
|
378
378
|
|
|
379
|
-
Seek(offset:
|
|
379
|
+
Seek(offset: bigint, whence: number): [bigint, $.GoError] {
|
|
380
|
+
const offNum = Number(offset)
|
|
380
381
|
let abs: number
|
|
381
382
|
switch (whence) {
|
|
382
383
|
case SeekStart:
|
|
383
|
-
abs = this.base +
|
|
384
|
+
abs = this.base + offNum
|
|
384
385
|
break
|
|
385
386
|
case SeekCurrent:
|
|
386
|
-
abs = this.off +
|
|
387
|
+
abs = this.off + offNum
|
|
387
388
|
break
|
|
388
389
|
case SeekEnd:
|
|
389
|
-
abs = this.limit +
|
|
390
|
+
abs = this.limit + offNum
|
|
390
391
|
break
|
|
391
392
|
default:
|
|
392
|
-
return [
|
|
393
|
+
return [0n, newError('io.SectionReader.Seek: invalid whence')]
|
|
393
394
|
}
|
|
394
395
|
|
|
395
396
|
if (abs < this.base) {
|
|
396
|
-
return [
|
|
397
|
+
return [0n, newError('io.SectionReader.Seek: negative position')]
|
|
397
398
|
}
|
|
398
399
|
|
|
399
400
|
this.off = abs
|
|
400
|
-
return [abs - this.base, null]
|
|
401
|
+
return [BigInt(abs - this.base), null]
|
|
401
402
|
}
|
|
402
403
|
|
|
403
|
-
ReadAt(p: $.Bytes, off:
|
|
404
|
-
|
|
404
|
+
ReadAt(p: $.Bytes, off: bigint): [number, $.GoError] {
|
|
405
|
+
let offNum = Number(off)
|
|
406
|
+
if (offNum < 0 || offNum >= this.limit - this.base) {
|
|
405
407
|
return [0, EOF]
|
|
406
408
|
}
|
|
407
409
|
|
|
408
|
-
|
|
409
|
-
if (
|
|
410
|
-
p = $.goSlice(p, 0, this.limit -
|
|
411
|
-
const res = this.r.ReadAt(p,
|
|
410
|
+
offNum += this.base
|
|
411
|
+
if (offNum + $.len(p) > this.limit) {
|
|
412
|
+
p = $.goSlice(p, 0, this.limit - offNum)
|
|
413
|
+
const res = this.r.ReadAt(p, BigInt(offNum)) as any
|
|
412
414
|
if (res instanceof Promise) {
|
|
413
415
|
return res.then(([n, err]: [number, $.GoError]) => {
|
|
414
416
|
if (err === null) {
|
|
@@ -424,19 +426,19 @@ export class SectionReader implements Reader, Seeker, ReaderAt {
|
|
|
424
426
|
return [n, err]
|
|
425
427
|
}
|
|
426
428
|
|
|
427
|
-
return this.r.ReadAt(p,
|
|
429
|
+
return this.r.ReadAt(p, BigInt(offNum))
|
|
428
430
|
}
|
|
429
431
|
|
|
430
|
-
Size():
|
|
431
|
-
return this.limit - this.base
|
|
432
|
+
Size(): bigint {
|
|
433
|
+
return BigInt(this.limit - this.base)
|
|
432
434
|
}
|
|
433
435
|
}
|
|
434
436
|
|
|
435
437
|
// NewSectionReader returns a SectionReader that reads from r starting at offset off and stops with EOF after n bytes
|
|
436
438
|
export function NewSectionReader(
|
|
437
439
|
r: ReaderAt,
|
|
438
|
-
off:
|
|
439
|
-
n:
|
|
440
|
+
off: bigint,
|
|
441
|
+
n: bigint,
|
|
440
442
|
): SectionReader {
|
|
441
443
|
return new SectionReader(r, off, n)
|
|
442
444
|
}
|
|
@@ -447,49 +449,51 @@ export class OffsetWriter implements Writer, WriterAt {
|
|
|
447
449
|
private base: number
|
|
448
450
|
private off: number
|
|
449
451
|
|
|
450
|
-
constructor(w: WriterAt, off:
|
|
452
|
+
constructor(w: WriterAt, off: bigint) {
|
|
451
453
|
this.w = w
|
|
452
|
-
this.base = off
|
|
454
|
+
this.base = Number(off)
|
|
453
455
|
this.off = 0
|
|
454
456
|
}
|
|
455
457
|
|
|
456
458
|
Write(p: $.Bytes): [number, $.GoError] {
|
|
457
|
-
const [n, err] = this.w.WriteAt(p, this.base + this.off)
|
|
459
|
+
const [n, err] = this.w.WriteAt(p, BigInt(this.base + this.off))
|
|
458
460
|
this.off += n
|
|
459
461
|
return [n, err]
|
|
460
462
|
}
|
|
461
463
|
|
|
462
|
-
WriteAt(p: $.Bytes, off:
|
|
463
|
-
|
|
464
|
+
WriteAt(p: $.Bytes, off: bigint): [number, $.GoError] {
|
|
465
|
+
const offNum = Number(off)
|
|
466
|
+
if (offNum < 0) {
|
|
464
467
|
return [0, newError('io.OffsetWriter.WriteAt: negative offset')]
|
|
465
468
|
}
|
|
466
|
-
return this.w.WriteAt(p, this.base +
|
|
469
|
+
return this.w.WriteAt(p, BigInt(this.base + offNum))
|
|
467
470
|
}
|
|
468
471
|
|
|
469
|
-
Seek(offset:
|
|
472
|
+
Seek(offset: bigint, whence: number): [bigint, $.GoError] {
|
|
473
|
+
const offNum = Number(offset)
|
|
470
474
|
let abs: number
|
|
471
475
|
switch (whence) {
|
|
472
476
|
case SeekStart:
|
|
473
|
-
abs =
|
|
477
|
+
abs = offNum
|
|
474
478
|
break
|
|
475
479
|
case SeekCurrent:
|
|
476
|
-
abs = this.off +
|
|
480
|
+
abs = this.off + offNum
|
|
477
481
|
break
|
|
478
482
|
default:
|
|
479
|
-
return [
|
|
483
|
+
return [0n, newError('io.OffsetWriter.Seek: invalid whence')]
|
|
480
484
|
}
|
|
481
485
|
|
|
482
486
|
if (abs < 0) {
|
|
483
|
-
return [
|
|
487
|
+
return [0n, newError('io.OffsetWriter.Seek: negative position')]
|
|
484
488
|
}
|
|
485
489
|
|
|
486
490
|
this.off = abs
|
|
487
|
-
return [abs, null]
|
|
491
|
+
return [BigInt(abs), null]
|
|
488
492
|
}
|
|
489
493
|
}
|
|
490
494
|
|
|
491
495
|
// NewOffsetWriter returns an OffsetWriter that writes to w starting at offset off
|
|
492
|
-
export function NewOffsetWriter(w: WriterAt, off:
|
|
496
|
+
export function NewOffsetWriter(w: WriterAt, off: bigint): OffsetWriter {
|
|
493
497
|
return new OffsetWriter(w, off)
|
|
494
498
|
}
|
|
495
499
|
|
|
@@ -497,7 +501,7 @@ export function NewOffsetWriter(w: WriterAt, off: number): OffsetWriter {
|
|
|
497
501
|
export async function Copy(
|
|
498
502
|
dst: WriterLike,
|
|
499
503
|
src: ReaderLike,
|
|
500
|
-
): Promise<[
|
|
504
|
+
): Promise<[bigint, $.GoError]> {
|
|
501
505
|
return await CopyBuffer(dst, src, null)
|
|
502
506
|
}
|
|
503
507
|
|
|
@@ -506,11 +510,11 @@ export async function CopyBuffer(
|
|
|
506
510
|
dst: WriterLike,
|
|
507
511
|
src: ReaderLike,
|
|
508
512
|
buf: $.Bytes | null,
|
|
509
|
-
): Promise<[
|
|
513
|
+
): Promise<[bigint, $.GoError]> {
|
|
510
514
|
dst = unwrapWriter(dst)
|
|
511
515
|
src = unwrapReader(src)
|
|
512
516
|
if (dst === null || src === null) {
|
|
513
|
-
return [
|
|
517
|
+
return [0n, newError('io: copy with nil reader or writer')]
|
|
514
518
|
}
|
|
515
519
|
|
|
516
520
|
// If src implements WriterTo, use it
|
|
@@ -527,7 +531,7 @@ export async function CopyBuffer(
|
|
|
527
531
|
buf = $.makeSlice<number>(32 * 1024, undefined, 'byte') // 32KB default buffer
|
|
528
532
|
}
|
|
529
533
|
|
|
530
|
-
let written =
|
|
534
|
+
let written = 0n
|
|
531
535
|
while (true) {
|
|
532
536
|
const [nr, er] = await (src.Read(buf) as any)
|
|
533
537
|
if (nr > 0) {
|
|
@@ -538,7 +542,7 @@ export async function CopyBuffer(
|
|
|
538
542
|
}
|
|
539
543
|
return [written, ew]
|
|
540
544
|
}
|
|
541
|
-
written += nw
|
|
545
|
+
written += BigInt(nw)
|
|
542
546
|
if (ew !== null) {
|
|
543
547
|
return [written, ew]
|
|
544
548
|
}
|
|
@@ -580,8 +584,8 @@ function unwrapWriter(dst: WriterLike): Writer | null {
|
|
|
580
584
|
export async function CopyN(
|
|
581
585
|
dst: Writer,
|
|
582
586
|
src: Reader,
|
|
583
|
-
n:
|
|
584
|
-
): Promise<[
|
|
587
|
+
n: bigint,
|
|
588
|
+
): Promise<[bigint, $.GoError]> {
|
|
585
589
|
const [written, err] = await Copy(dst, LimitReader(src, n))
|
|
586
590
|
if (written === n) {
|
|
587
591
|
return [written, null]
|
|
@@ -636,6 +640,7 @@ export async function ReadAll(r: Reader): Promise<[$.Bytes, $.GoError]> {
|
|
|
636
640
|
const chunks: $.Bytes[] = []
|
|
637
641
|
let totalLength = 0
|
|
638
642
|
const buf = $.makeSlice<number>(512, undefined, 'byte')
|
|
643
|
+
let readErr: $.GoError = null
|
|
639
644
|
|
|
640
645
|
while (true) {
|
|
641
646
|
const [n, err] = await (r.Read(buf) as any)
|
|
@@ -646,30 +651,25 @@ export async function ReadAll(r: Reader): Promise<[$.Bytes, $.GoError]> {
|
|
|
646
651
|
totalLength += n
|
|
647
652
|
}
|
|
648
653
|
if (err !== null) {
|
|
649
|
-
|
|
650
|
-
|
|
654
|
+
// EOF is the normal terminator and is reported as a nil error. Any other
|
|
655
|
+
// error is returned together with the bytes already read, matching Go.
|
|
656
|
+
if (err !== EOF) {
|
|
657
|
+
readErr = err
|
|
651
658
|
}
|
|
652
|
-
|
|
659
|
+
break
|
|
653
660
|
}
|
|
654
661
|
}
|
|
655
662
|
|
|
656
|
-
// Combine all chunks
|
|
663
|
+
// Combine all chunks.
|
|
657
664
|
const result = $.makeSlice<number>(totalLength, undefined, 'byte')
|
|
658
665
|
let offset = 0
|
|
659
666
|
for (const chunk of chunks) {
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
const resultSlice = $.goSlice(result, offset, offset + chunk.length)
|
|
663
|
-
$.copy(resultSlice, chunk)
|
|
664
|
-
} else {
|
|
665
|
-
// Handle Slice<number> chunks
|
|
666
|
-
const resultSlice = $.goSlice(result, offset, offset + $.len(chunk))
|
|
667
|
-
$.copy(resultSlice, chunk)
|
|
668
|
-
}
|
|
667
|
+
const resultSlice = $.goSlice(result, offset, offset + $.len(chunk))
|
|
668
|
+
$.copy(resultSlice, chunk)
|
|
669
669
|
offset += $.len(chunk)
|
|
670
670
|
}
|
|
671
671
|
|
|
672
|
-
return [result,
|
|
672
|
+
return [result, readErr]
|
|
673
673
|
}
|
|
674
674
|
|
|
675
675
|
// NopCloser returns a ReadCloser with a no-op Close method wrapping the provided Reader r
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
import { describe, expect, test } from 'vitest'
|
|
2
|
+
|
|
3
|
+
import * as $ from '@goscript/builtin/index.js'
|
|
4
|
+
|
|
5
|
+
import {
|
|
6
|
+
EOF,
|
|
7
|
+
ErrShortBuffer,
|
|
8
|
+
ErrUnexpectedEOF,
|
|
9
|
+
LimitReader,
|
|
10
|
+
NewOffsetWriter,
|
|
11
|
+
ReadAtLeast,
|
|
12
|
+
} from './index.js'
|
|
13
|
+
|
|
14
|
+
// A Reader that hands out its data and returns the EOF sentinel once drained,
|
|
15
|
+
// matching Go's convention that a Read may return n>0 with a nil error.
|
|
16
|
+
class chunkReader {
|
|
17
|
+
constructor(private data: Uint8Array) {}
|
|
18
|
+
|
|
19
|
+
Read(p: $.Bytes): [number, $.GoError] {
|
|
20
|
+
if (this.data.length === 0) {
|
|
21
|
+
return [0, EOF]
|
|
22
|
+
}
|
|
23
|
+
const n = Math.min($.len(p), this.data.length)
|
|
24
|
+
p!.set(this.data.subarray(0, n), 0)
|
|
25
|
+
this.data = this.data.subarray(n)
|
|
26
|
+
return [n, null]
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
// A WriterAt that records bytes at their absolute offset.
|
|
31
|
+
class bufferWriterAt {
|
|
32
|
+
public buf: number[] = []
|
|
33
|
+
|
|
34
|
+
WriteAt(p: $.Bytes, off: bigint): [number, $.GoError] {
|
|
35
|
+
const base = Number(off)
|
|
36
|
+
const bytes = p ?? new Uint8Array(0)
|
|
37
|
+
for (let i = 0; i < bytes.length; i++) {
|
|
38
|
+
this.buf[base + i] = bytes[i]
|
|
39
|
+
}
|
|
40
|
+
return [$.len(p), null]
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
describe('io coverage (Go semantics)', () => {
|
|
45
|
+
test('LimitReader stops with EOF after n bytes', async () => {
|
|
46
|
+
const lr = LimitReader(new chunkReader($.stringToBytes('hello world')), 5n)
|
|
47
|
+
const buf = new Uint8Array(32)
|
|
48
|
+
const [n, err] = await (lr.Read(buf) as any)
|
|
49
|
+
expect(n).toBe(5)
|
|
50
|
+
expect(err).toBeNull()
|
|
51
|
+
expect($.bytesToString($.goSlice(buf, 0, n))).toBe('hello')
|
|
52
|
+
const [n2, err2] = await (lr.Read(buf) as any)
|
|
53
|
+
expect(n2).toBe(0)
|
|
54
|
+
expect(err2).toBe(EOF)
|
|
55
|
+
})
|
|
56
|
+
|
|
57
|
+
test('NewOffsetWriter writes at the base offset', () => {
|
|
58
|
+
const w = new bufferWriterAt()
|
|
59
|
+
const ow = NewOffsetWriter(w, 3n)
|
|
60
|
+
const [n, err] = ow.Write($.stringToBytes('abc'))
|
|
61
|
+
expect(n).toBe(3)
|
|
62
|
+
expect(err).toBeNull()
|
|
63
|
+
expect(String.fromCharCode(w.buf[3], w.buf[4], w.buf[5])).toBe('abc')
|
|
64
|
+
expect(w.buf[0]).toBeUndefined()
|
|
65
|
+
})
|
|
66
|
+
|
|
67
|
+
test('ReadAtLeast reads until min and reports short reads', async () => {
|
|
68
|
+
const buf4 = new Uint8Array(4)
|
|
69
|
+
const [n, err] = await ReadAtLeast(
|
|
70
|
+
new chunkReader($.stringToBytes('abcdef')),
|
|
71
|
+
buf4,
|
|
72
|
+
4,
|
|
73
|
+
)
|
|
74
|
+
expect(n).toBe(4)
|
|
75
|
+
expect(err).toBeNull()
|
|
76
|
+
expect($.bytesToString(buf4)).toBe('abcd')
|
|
77
|
+
|
|
78
|
+
const buf5 = new Uint8Array(5)
|
|
79
|
+
const [n2, err2] = await ReadAtLeast(
|
|
80
|
+
new chunkReader($.stringToBytes('ab')),
|
|
81
|
+
buf5,
|
|
82
|
+
4,
|
|
83
|
+
)
|
|
84
|
+
expect(n2).toBe(2)
|
|
85
|
+
expect(err2).toBe(ErrUnexpectedEOF)
|
|
86
|
+
|
|
87
|
+
const [n3, err3] = await ReadAtLeast(
|
|
88
|
+
new chunkReader(new Uint8Array(0)),
|
|
89
|
+
new Uint8Array(4),
|
|
90
|
+
4,
|
|
91
|
+
)
|
|
92
|
+
expect(n3).toBe(0)
|
|
93
|
+
expect(err3).toBe(EOF)
|
|
94
|
+
|
|
95
|
+
const [n4, err4] = await ReadAtLeast(
|
|
96
|
+
new chunkReader($.stringToBytes('abcdef')),
|
|
97
|
+
new Uint8Array(3),
|
|
98
|
+
5,
|
|
99
|
+
)
|
|
100
|
+
expect(n4).toBe(0)
|
|
101
|
+
expect(err4).toBe(ErrShortBuffer)
|
|
102
|
+
})
|
|
103
|
+
})
|
|
@@ -1,14 +1,53 @@
|
|
|
1
1
|
import { describe, expect, it } from 'vitest'
|
|
2
2
|
|
|
3
3
|
import {
|
|
4
|
+
Add,
|
|
5
|
+
Add32,
|
|
6
|
+
Add64,
|
|
7
|
+
Div,
|
|
8
|
+
Div32,
|
|
9
|
+
Div64,
|
|
10
|
+
LeadingZeros16,
|
|
11
|
+
LeadingZeros32,
|
|
12
|
+
LeadingZeros64,
|
|
13
|
+
LeadingZeros8,
|
|
14
|
+
Len16,
|
|
15
|
+
Len32,
|
|
16
|
+
Len64,
|
|
17
|
+
Len8,
|
|
18
|
+
Mul,
|
|
19
|
+
Mul32,
|
|
4
20
|
Mul64,
|
|
21
|
+
OnesCount,
|
|
22
|
+
OnesCount16,
|
|
23
|
+
OnesCount32,
|
|
24
|
+
OnesCount64,
|
|
25
|
+
OnesCount8,
|
|
5
26
|
Rem,
|
|
6
27
|
Rem32,
|
|
7
28
|
Rem64,
|
|
29
|
+
Reverse,
|
|
30
|
+
Reverse16,
|
|
31
|
+
Reverse32,
|
|
32
|
+
Reverse64,
|
|
33
|
+
Reverse8,
|
|
34
|
+
ReverseBytes,
|
|
35
|
+
ReverseBytes16,
|
|
36
|
+
ReverseBytes32,
|
|
37
|
+
ReverseBytes64,
|
|
38
|
+
RotateLeft,
|
|
8
39
|
RotateLeft16,
|
|
9
40
|
RotateLeft32,
|
|
10
41
|
RotateLeft64,
|
|
11
42
|
RotateLeft8,
|
|
43
|
+
Sub,
|
|
44
|
+
Sub32,
|
|
45
|
+
Sub64,
|
|
46
|
+
TrailingZeros,
|
|
47
|
+
TrailingZeros16,
|
|
48
|
+
TrailingZeros32,
|
|
49
|
+
TrailingZeros64,
|
|
50
|
+
TrailingZeros8,
|
|
12
51
|
} from './index.js'
|
|
13
52
|
|
|
14
53
|
describe('math/bits override', () => {
|
|
@@ -27,6 +66,20 @@ describe('math/bits override', () => {
|
|
|
27
66
|
])
|
|
28
67
|
})
|
|
29
68
|
|
|
69
|
+
it('counts leading zeros over the 8/16-bit width, not 32', () => {
|
|
70
|
+
// Zero must yield the full width, and Len of zero is 0 (Go len8tab[0]).
|
|
71
|
+
expect(LeadingZeros8(0)).toBe(8)
|
|
72
|
+
expect(LeadingZeros16(0)).toBe(16)
|
|
73
|
+
expect(Len8(0)).toBe(0)
|
|
74
|
+
expect(Len16(0)).toBe(0)
|
|
75
|
+
// Non-zero values keep their width-relative counts.
|
|
76
|
+
expect(LeadingZeros8(1)).toBe(7)
|
|
77
|
+
expect(LeadingZeros8(0xff)).toBe(0)
|
|
78
|
+
expect(Len8(0xff)).toBe(8)
|
|
79
|
+
expect(LeadingZeros16(1)).toBe(15)
|
|
80
|
+
expect(Len16(0x8000)).toBe(16)
|
|
81
|
+
})
|
|
82
|
+
|
|
30
83
|
it('returns remainders from double-word division helpers', () => {
|
|
31
84
|
expect(Rem32(1, 0, 3)).toBe(1)
|
|
32
85
|
expect(Rem(1n, 0n, 3n)).toBe(1n)
|
|
@@ -34,9 +87,84 @@ describe('math/bits override', () => {
|
|
|
34
87
|
})
|
|
35
88
|
|
|
36
89
|
it('rotates right for negative counts', () => {
|
|
90
|
+
expect(RotateLeft(1n, -1)).toBe(0x8000000000000000n)
|
|
37
91
|
expect(RotateLeft8(1, -1)).toBe(0x80)
|
|
38
92
|
expect(RotateLeft16(1, -1)).toBe(0x8000)
|
|
39
93
|
expect(RotateLeft32(1, -1)).toBe(0x80000000)
|
|
40
94
|
expect(RotateLeft64(1n, -1)).toBe(0x8000000000000000n)
|
|
41
95
|
})
|
|
96
|
+
|
|
97
|
+
// Reference values below are produced by Go's math/bits for the same inputs.
|
|
98
|
+
it('Add carries out of the high bit (Go Add/Add32/Add64)', () => {
|
|
99
|
+
expect(Add32(0xffffffff, 2, 0)).toEqual([1, 1])
|
|
100
|
+
expect(Add64(0xffffffffffffffffn, 2n, 0n)).toEqual([1n, 1n])
|
|
101
|
+
// The width-agnostic dispatcher routes to the 64-bit path.
|
|
102
|
+
expect(Add(0xffffffffffffffffn, 2n, 0n)).toEqual([1n, 1n])
|
|
103
|
+
})
|
|
104
|
+
|
|
105
|
+
it('Sub borrows below zero (Go Sub/Sub32/Sub64)', () => {
|
|
106
|
+
expect(Sub32(0, 1, 0)).toEqual([4294967295, 1])
|
|
107
|
+
expect(Sub64(0n, 1n, 0n)).toEqual([18446744073709551615n, 1n])
|
|
108
|
+
expect(Sub(0n, 1n, 0n)).toEqual([18446744073709551615n, 1n])
|
|
109
|
+
})
|
|
110
|
+
|
|
111
|
+
it('Mul returns the full double-word product (Go Mul/Mul32/Mul64)', () => {
|
|
112
|
+
expect(Mul32(0xffffffff, 0xffffffff)).toEqual([4294967294, 1])
|
|
113
|
+
expect(Mul(0xffffffffffffffffn, 0xffffffffffffffffn)).toEqual([
|
|
114
|
+
0xfffffffffffffffen,
|
|
115
|
+
1n,
|
|
116
|
+
])
|
|
117
|
+
})
|
|
118
|
+
|
|
119
|
+
it('Div splits a double-word dividend (Go Div/Div32/Div64)', () => {
|
|
120
|
+
expect(Div32(1, 0, 3)).toEqual([1431655765, 1])
|
|
121
|
+
expect(Div64(1n, 0n, 3n)).toEqual([6148914691236517205n, 1n])
|
|
122
|
+
expect(Div(1n, 0n, 3n)).toEqual([6148914691236517205n, 1n])
|
|
123
|
+
})
|
|
124
|
+
|
|
125
|
+
it('OnesCount counts set bits over each width (Go OnesCount*)', () => {
|
|
126
|
+
expect(OnesCount(0xff)).toBe(8)
|
|
127
|
+
expect(OnesCount8(0xff)).toBe(8)
|
|
128
|
+
expect(OnesCount16(0xf0f0)).toBe(8)
|
|
129
|
+
expect(OnesCount32(0xffffffff)).toBe(32)
|
|
130
|
+
expect(OnesCount64(0xffffffffffffffffn)).toBe(64)
|
|
131
|
+
})
|
|
132
|
+
|
|
133
|
+
it('TrailingZeros counts low zero bits, full width for zero (Go TrailingZeros*)', () => {
|
|
134
|
+
expect(TrailingZeros(8)).toBe(3)
|
|
135
|
+
expect(TrailingZeros8(0x80)).toBe(7)
|
|
136
|
+
expect(TrailingZeros16(0x8000)).toBe(15)
|
|
137
|
+
expect(TrailingZeros32(0x10)).toBe(4)
|
|
138
|
+
expect(TrailingZeros64(0x100000000n)).toBe(32)
|
|
139
|
+
expect(TrailingZeros8(0)).toBe(8)
|
|
140
|
+
expect(TrailingZeros16(0)).toBe(16)
|
|
141
|
+
expect(TrailingZeros32(0)).toBe(32)
|
|
142
|
+
expect(TrailingZeros64(0n)).toBe(64)
|
|
143
|
+
})
|
|
144
|
+
|
|
145
|
+
it('LeadingZeros32/64 and Len32/64 use the right width (Go)', () => {
|
|
146
|
+
expect(LeadingZeros32(1)).toBe(31)
|
|
147
|
+
expect(LeadingZeros32(0)).toBe(32)
|
|
148
|
+
expect(LeadingZeros64(1n)).toBe(63)
|
|
149
|
+
expect(LeadingZeros64(0n)).toBe(64)
|
|
150
|
+
expect(Len32(0x8000)).toBe(16)
|
|
151
|
+
expect(Len32(0)).toBe(0)
|
|
152
|
+
expect(Len64(0x100000000n)).toBe(33)
|
|
153
|
+
expect(Len64(0n)).toBe(0)
|
|
154
|
+
})
|
|
155
|
+
|
|
156
|
+
it('Reverse flips bit order over each width (Go Reverse*)', () => {
|
|
157
|
+
expect(Reverse8(1)).toBe(128)
|
|
158
|
+
expect(Reverse16(1)).toBe(32768)
|
|
159
|
+
expect(Reverse32(1)).toBe(2147483648)
|
|
160
|
+
expect(Reverse64(1n)).toBe(9223372036854775808n)
|
|
161
|
+
expect(Reverse(1n)).toBe(9223372036854775808n)
|
|
162
|
+
})
|
|
163
|
+
|
|
164
|
+
it('ReverseBytes flips byte order over each width (Go ReverseBytes*)', () => {
|
|
165
|
+
expect(ReverseBytes16(0x0102)).toBe(513)
|
|
166
|
+
expect(ReverseBytes32(0x01020304)).toBe(67305985)
|
|
167
|
+
expect(ReverseBytes64(0x0102030405060708n)).toBe(578437695752307201n)
|
|
168
|
+
expect(ReverseBytes(0x0102030405060708n)).toBe(578437695752307201n)
|
|
169
|
+
})
|
|
42
170
|
})
|
package/gs/math/bits/index.ts
CHANGED
|
@@ -31,12 +31,15 @@ export function LeadingZeros(x: Word64): number {
|
|
|
31
31
|
return LeadingZeros64(x)
|
|
32
32
|
}
|
|
33
33
|
|
|
34
|
+
// LeadingZeros8 derives from Len8 so that zero yields the full width (8), as in
|
|
35
|
+
// Go. Math.clz32 counts over 32 bits and returns 32 for zero, which would be
|
|
36
|
+
// wrong for the 8-bit width.
|
|
34
37
|
export function LeadingZeros8(x: number): number {
|
|
35
|
-
return
|
|
38
|
+
return 8 - Len8(x)
|
|
36
39
|
}
|
|
37
40
|
|
|
38
41
|
export function LeadingZeros16(x: number): number {
|
|
39
|
-
return
|
|
42
|
+
return 16 - Len16(x)
|
|
40
43
|
}
|
|
41
44
|
|
|
42
45
|
export function LeadingZeros32(x: number): number {
|
|
@@ -285,12 +288,26 @@ export function Len(x: Word64): number {
|
|
|
285
288
|
return Len64(x)
|
|
286
289
|
}
|
|
287
290
|
|
|
291
|
+
// Len8 is the bit-length primitive (Go uses a len8tab lookup): the minimum
|
|
292
|
+
// number of bits to represent the low 8 bits of x, and 0 for x == 0.
|
|
288
293
|
export function Len8(x: number): number {
|
|
289
|
-
|
|
294
|
+
x &= 0xff
|
|
295
|
+
let n = 0
|
|
296
|
+
while (x > 0) {
|
|
297
|
+
x >>= 1
|
|
298
|
+
n++
|
|
299
|
+
}
|
|
300
|
+
return n
|
|
290
301
|
}
|
|
291
302
|
|
|
292
303
|
export function Len16(x: number): number {
|
|
293
|
-
|
|
304
|
+
x &= 0xffff
|
|
305
|
+
let n = 0
|
|
306
|
+
while (x > 0) {
|
|
307
|
+
x >>= 1
|
|
308
|
+
n++
|
|
309
|
+
}
|
|
310
|
+
return n
|
|
294
311
|
}
|
|
295
312
|
|
|
296
313
|
export function Len32(x: number): number {
|
|
@@ -310,10 +327,11 @@ export function Mul(x: Word64, y: Word64): [Word64, Word64] {
|
|
|
310
327
|
}
|
|
311
328
|
|
|
312
329
|
export function Mul32(x: number, y: number): [number, number] {
|
|
313
|
-
//
|
|
314
|
-
|
|
315
|
-
const
|
|
316
|
-
const
|
|
330
|
+
// The product of two uint32 needs 64 bits, beyond the 53-bit mantissa of a
|
|
331
|
+
// JS number, so multiply exactly via bigint before splitting hi/lo.
|
|
332
|
+
const product = BigInt(x >>> 0) * BigInt(y >>> 0)
|
|
333
|
+
const hi = Number((product >> 32n) & 0xffffffffn)
|
|
334
|
+
const lo = Number(product & 0xffffffffn)
|
|
317
335
|
return [hi, lo]
|
|
318
336
|
}
|
|
319
337
|
|
|
@@ -30,7 +30,9 @@ describe('Copysign', () => {
|
|
|
30
30
|
it('should handle NaN values', () => {
|
|
31
31
|
expect(Number.isNaN(Copysign(Number.NaN, 1))).toBe(true)
|
|
32
32
|
expect(Number.isNaN(Copysign(Number.NaN, -1))).toBe(true)
|
|
33
|
-
expect(Copysign(5, Number.NaN)).toBe(5) // NaN is
|
|
33
|
+
expect(Copysign(5, Number.NaN)).toBe(5) // quiet NaN sign bit is 0
|
|
34
|
+
// A negative NaN sign bit is honored, matching Go.
|
|
35
|
+
expect(Copysign(1, -Number.NaN)).toBe(-1)
|
|
34
36
|
})
|
|
35
37
|
|
|
36
38
|
it('should handle fractional values', () => {
|