goscript 0.1.1 → 0.1.2
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-test.go +104 -11
- package/cmd/goscript/cmd-test_test.go +1 -1
- package/cmd/goscript/cmd_compile.go +9 -0
- package/compiler/compile-request.go +31 -0
- package/compiler/compiler.go +1 -1
- package/compiler/compliance_test.go +0 -2
- package/compiler/config.go +2 -0
- package/compiler/gotest/package-result.go +2 -0
- package/compiler/gotest/request.go +85 -20
- package/compiler/gotest/runner.go +733 -96
- package/compiler/gotest/runner_test.go +647 -3
- package/compiler/lowered-program.go +9 -2
- package/compiler/lowering.go +2001 -345
- package/compiler/override-facts.go +77 -27
- package/compiler/override-registry.go +5 -4
- package/compiler/override-registry_test.go +135 -0
- package/compiler/package-graph_test.go +62 -7
- package/compiler/package-test-graph-variant.go +40 -16
- package/compiler/package-test-graph.go +0 -5
- package/compiler/package-test-graph_test.go +61 -3
- package/compiler/runtime-contract.go +40 -0
- package/compiler/semantic-model-types.go +16 -0
- package/compiler/semantic-model.go +336 -91
- package/compiler/semantic-model_test.go +50 -1
- package/compiler/service.go +9 -3
- package/compiler/skeleton_test.go +1921 -298
- package/compiler/tsworkspace/owner-process-unix_test.go +72 -0
- package/compiler/tsworkspace/owner.go +8 -0
- package/compiler/tsworkspace/tool-process-other.go +14 -0
- package/compiler/tsworkspace/tool-process-unix.go +19 -0
- package/compiler/typescript-emitter.go +122 -9
- package/dist/gs/builtin/builtin.d.ts +20 -1
- package/dist/gs/builtin/builtin.js +246 -26
- package/dist/gs/builtin/builtin.js.map +1 -1
- package/dist/gs/builtin/channel.d.ts +24 -10
- package/dist/gs/builtin/channel.js +107 -25
- package/dist/gs/builtin/channel.js.map +1 -1
- package/dist/gs/builtin/defer.d.ts +1 -0
- package/dist/gs/builtin/defer.js +12 -2
- package/dist/gs/builtin/defer.js.map +1 -1
- package/dist/gs/builtin/hostio.d.ts +9 -0
- package/dist/gs/builtin/hostio.js +25 -0
- package/dist/gs/builtin/hostio.js.map +1 -1
- package/dist/gs/builtin/map.js +40 -6
- package/dist/gs/builtin/map.js.map +1 -1
- package/dist/gs/builtin/print.js.map +1 -1
- package/dist/gs/builtin/slice.d.ts +43 -9
- package/dist/gs/builtin/slice.js +437 -234
- package/dist/gs/builtin/slice.js.map +1 -1
- package/dist/gs/builtin/type.d.ts +2 -0
- package/dist/gs/builtin/type.js +47 -7
- package/dist/gs/builtin/type.js.map +1 -1
- package/dist/gs/builtin/varRef.d.ts +2 -0
- package/dist/gs/builtin/varRef.js.map +1 -1
- package/dist/gs/bytes/buffer.gs.js +28 -28
- package/dist/gs/bytes/buffer.gs.js.map +1 -1
- package/dist/gs/bytes/iter.gs.js +13 -13
- package/dist/gs/bytes/iter.gs.js.map +1 -1
- package/dist/gs/compress/zlib/index.d.ts +26 -0
- package/dist/gs/compress/zlib/index.js +168 -0
- package/dist/gs/compress/zlib/index.js.map +1 -0
- package/dist/gs/context/context.d.ts +1 -1
- package/dist/gs/context/context.js +8 -3
- package/dist/gs/context/context.js.map +1 -1
- package/dist/gs/crypto/ecdh/index.d.ts +52 -0
- package/dist/gs/crypto/ecdh/index.js +226 -0
- package/dist/gs/crypto/ecdh/index.js.map +1 -0
- package/dist/gs/crypto/ed25519/index.d.ts +34 -0
- package/dist/gs/crypto/ed25519/index.js +160 -0
- package/dist/gs/crypto/ed25519/index.js.map +1 -0
- package/dist/gs/crypto/internal/constanttime/index.d.ts +4 -0
- package/dist/gs/crypto/internal/constanttime/index.js +18 -0
- package/dist/gs/crypto/internal/constanttime/index.js.map +1 -0
- package/dist/gs/crypto/rand/index.d.ts +2 -0
- package/dist/gs/crypto/rand/index.js +85 -0
- package/dist/gs/crypto/rand/index.js.map +1 -1
- package/dist/gs/crypto/sha256/index.d.ts +8 -0
- package/dist/gs/crypto/sha256/index.js +118 -0
- package/dist/gs/crypto/sha256/index.js.map +1 -0
- package/dist/gs/crypto/sha512/index.d.ts +14 -0
- package/dist/gs/crypto/sha512/index.js +129 -0
- package/dist/gs/crypto/sha512/index.js.map +1 -0
- package/dist/gs/encoding/json/index.d.ts +3 -0
- package/dist/gs/encoding/json/index.js +15 -0
- package/dist/gs/encoding/json/index.js.map +1 -1
- package/dist/gs/errors/errors.js +29 -6
- package/dist/gs/errors/errors.js.map +1 -1
- package/dist/gs/fmt/fmt.js.map +1 -1
- package/dist/gs/github.com/aperturerobotics/protobuf-go-lite/index.d.ts +7 -7
- package/dist/gs/github.com/aperturerobotics/protobuf-go-lite/index.js +52 -18
- package/dist/gs/github.com/aperturerobotics/protobuf-go-lite/index.js.map +1 -1
- package/dist/gs/github.com/aperturerobotics/protobuf-go-lite/json/index.js +56 -20
- package/dist/gs/github.com/aperturerobotics/protobuf-go-lite/json/index.js.map +1 -1
- package/dist/gs/github.com/aperturerobotics/starpc/srpc/index.d.ts +57 -3
- package/dist/gs/github.com/aperturerobotics/starpc/srpc/index.js +366 -1
- package/dist/gs/github.com/aperturerobotics/starpc/srpc/index.js.map +1 -1
- package/dist/gs/github.com/aperturerobotics/util/conc/index.d.ts +20 -0
- package/dist/gs/github.com/aperturerobotics/util/conc/index.js +134 -0
- package/dist/gs/github.com/aperturerobotics/util/conc/index.js.map +1 -0
- package/dist/gs/github.com/aperturerobotics/wasivm/wazero/kernel/runtime/browser/browser.js.map +1 -1
- package/dist/gs/github.com/hack-pad/safejs/internal/catch/index.d.ts +3 -0
- package/dist/gs/github.com/hack-pad/safejs/internal/catch/index.js +50 -0
- package/dist/gs/github.com/hack-pad/safejs/internal/catch/index.js.map +1 -0
- package/dist/gs/github.com/klauspost/compress/internal/le/index.js +3 -2
- package/dist/gs/github.com/klauspost/compress/internal/le/index.js.map +1 -1
- package/dist/gs/github.com/mr-tron/base58/base58/index.d.ts +27 -0
- package/dist/gs/github.com/mr-tron/base58/base58/index.js +172 -0
- package/dist/gs/github.com/mr-tron/base58/base58/index.js.map +1 -0
- package/dist/gs/github.com/zeebo/blake3/internal/consts/index.d.ts +21 -0
- package/dist/gs/github.com/zeebo/blake3/internal/consts/index.js +22 -0
- package/dist/gs/github.com/zeebo/blake3/internal/consts/index.js.map +1 -0
- package/dist/gs/go/token/index.js +11 -4
- package/dist/gs/go/token/index.js.map +1 -1
- package/dist/gs/hash/fnv/index.d.ts +57 -0
- package/dist/gs/hash/fnv/index.js +299 -0
- package/dist/gs/hash/fnv/index.js.map +1 -0
- package/dist/gs/hash/index.d.ts +17 -0
- package/dist/gs/hash/index.js +94 -0
- package/dist/gs/hash/index.js.map +1 -0
- package/dist/gs/io/fs/readlink.js +2 -6
- package/dist/gs/io/fs/readlink.js.map +1 -1
- package/dist/gs/io/fs/walk.js.map +1 -1
- package/dist/gs/io/io.js.map +1 -1
- package/dist/gs/iter/iter.d.ts +3 -2
- package/dist/gs/iter/iter.js.map +1 -1
- package/dist/gs/maps/iter.d.ts +5 -5
- package/dist/gs/maps/iter.js +48 -21
- package/dist/gs/maps/iter.js.map +1 -1
- package/dist/gs/maps/maps.d.ts +6 -6
- package/dist/gs/math/bits/index.js +14 -24
- package/dist/gs/math/bits/index.js.map +1 -1
- package/dist/gs/mime/index.js +3 -1
- package/dist/gs/mime/index.js.map +1 -1
- package/dist/gs/net/http/httptest/index.d.ts +20 -1
- package/dist/gs/net/http/httptest/index.js +83 -3
- package/dist/gs/net/http/httptest/index.js.map +1 -1
- package/dist/gs/net/http/index.d.ts +110 -6
- package/dist/gs/net/http/index.js +262 -16
- package/dist/gs/net/http/index.js.map +1 -1
- package/dist/gs/net/http/pprof/index.d.ts +8 -0
- package/dist/gs/net/http/pprof/index.js +59 -0
- package/dist/gs/net/http/pprof/index.js.map +1 -0
- package/dist/gs/os/error.gs.js +9 -7
- package/dist/gs/os/error.gs.js.map +1 -1
- package/dist/gs/os/types_js.gs.js +95 -15
- package/dist/gs/os/types_js.gs.js.map +1 -1
- package/dist/gs/path/filepath/match.js.map +1 -1
- package/dist/gs/path/filepath/path.d.ts +5 -3
- package/dist/gs/path/filepath/path.js +65 -10
- package/dist/gs/path/filepath/path.js.map +1 -1
- package/dist/gs/reflect/index.d.ts +3 -2
- package/dist/gs/reflect/index.js +2 -1
- package/dist/gs/reflect/index.js.map +1 -1
- package/dist/gs/reflect/iter.js +2 -2
- package/dist/gs/reflect/iter.js.map +1 -1
- package/dist/gs/reflect/map.js +26 -0
- package/dist/gs/reflect/map.js.map +1 -1
- package/dist/gs/reflect/type.d.ts +24 -5
- package/dist/gs/reflect/type.js +390 -38
- package/dist/gs/reflect/type.js.map +1 -1
- package/dist/gs/reflect/types.d.ts +1 -0
- package/dist/gs/reflect/types.js +3 -1
- package/dist/gs/reflect/types.js.map +1 -1
- package/dist/gs/reflect/value.d.ts +4 -1
- package/dist/gs/reflect/value.js +39 -1
- package/dist/gs/reflect/value.js.map +1 -1
- package/dist/gs/reflect/visiblefields.js +1 -1
- package/dist/gs/reflect/visiblefields.js.map +1 -1
- package/dist/gs/runtime/debug/index.d.ts +39 -0
- package/dist/gs/runtime/debug/index.js +58 -0
- package/dist/gs/runtime/debug/index.js.map +1 -1
- package/dist/gs/runtime/pprof/index.d.ts +20 -0
- package/dist/gs/runtime/pprof/index.js +85 -0
- package/dist/gs/runtime/pprof/index.js.map +1 -0
- package/dist/gs/runtime/trace/index.d.ts +19 -0
- package/dist/gs/runtime/trace/index.js +64 -0
- package/dist/gs/runtime/trace/index.js.map +1 -0
- package/dist/gs/slices/slices.d.ts +24 -9
- package/dist/gs/slices/slices.js +229 -24
- package/dist/gs/slices/slices.js.map +1 -1
- package/dist/gs/sort/slice.gs.d.ts +5 -3
- package/dist/gs/sort/slice.gs.js +55 -17
- package/dist/gs/sort/slice.gs.js.map +1 -1
- package/dist/gs/strings/builder.js +26 -17
- package/dist/gs/strings/builder.js.map +1 -1
- package/dist/gs/strings/iter.js +140 -75
- package/dist/gs/strings/iter.js.map +1 -1
- package/dist/gs/strings/replace.js +2 -2
- package/dist/gs/strings/replace.js.map +1 -1
- package/dist/gs/strings/strings.js +52 -6
- package/dist/gs/strings/strings.js.map +1 -1
- package/dist/gs/sync/sync.d.ts +6 -3
- package/dist/gs/sync/sync.js +39 -11
- package/dist/gs/sync/sync.js.map +1 -1
- package/dist/gs/syscall/errors.d.ts +116 -112
- package/dist/gs/syscall/errors.js +38 -1
- package/dist/gs/syscall/errors.js.map +1 -1
- package/dist/gs/syscall/fs.d.ts +2 -8
- package/dist/gs/syscall/fs.js.map +1 -1
- package/dist/gs/syscall/js/index.js +20 -12
- package/dist/gs/syscall/js/index.js.map +1 -1
- package/dist/gs/syscall/types.d.ts +4 -1
- package/dist/gs/syscall/types.js.map +1 -1
- package/dist/gs/testing/testing.d.ts +4 -3
- package/dist/gs/testing/testing.js +21 -4
- package/dist/gs/testing/testing.js.map +1 -1
- package/dist/gs/time/time.js +22 -0
- package/dist/gs/time/time.js.map +1 -1
- package/dist/gs/unicode/unicode.js.map +1 -1
- package/dist/gs/unique/index.js +7 -2
- package/dist/gs/unique/index.js.map +1 -1
- package/go.mod +8 -8
- package/go.sum +14 -23
- package/gs/builtin/builtin.ts +364 -37
- package/gs/builtin/channel.ts +161 -29
- package/gs/builtin/defer.ts +13 -2
- package/gs/builtin/hostio.test.ts +1 -0
- package/gs/builtin/hostio.ts +38 -0
- package/gs/builtin/map.ts +46 -6
- package/gs/builtin/print.ts +12 -3
- package/gs/builtin/runtime-contract.test.ts +257 -10
- package/gs/builtin/slice.test.ts +70 -0
- package/gs/builtin/slice.ts +566 -255
- package/gs/builtin/type.ts +53 -9
- package/gs/builtin/varRef.ts +2 -0
- package/gs/bytes/buffer.gs.ts +28 -28
- package/gs/bytes/iter.gs.ts +13 -14
- package/gs/compress/zlib/index.test.ts +28 -0
- package/gs/compress/zlib/index.ts +200 -0
- package/gs/compress/zlib/meta.json +3 -0
- package/gs/context/context.test.ts +31 -1
- package/gs/context/context.ts +9 -4
- package/gs/crypto/ecdh/index.test.ts +43 -0
- package/gs/crypto/ecdh/index.ts +274 -0
- package/gs/crypto/ed25519/index.test.ts +41 -0
- package/gs/crypto/ed25519/index.ts +238 -0
- package/gs/crypto/ed25519/meta.json +13 -0
- package/gs/crypto/internal/constanttime/index.test.ts +25 -0
- package/gs/crypto/internal/constanttime/index.ts +22 -0
- package/gs/crypto/rand/index.test.ts +89 -1
- package/gs/crypto/rand/index.ts +103 -1
- package/gs/crypto/rand/meta.json +4 -1
- package/gs/crypto/sha256/index.test.ts +78 -0
- package/gs/crypto/sha256/index.ts +150 -0
- package/gs/crypto/sha256/meta.json +9 -0
- package/gs/crypto/sha512/index.test.ts +31 -0
- package/gs/crypto/sha512/index.ts +161 -0
- package/gs/crypto/sha512/meta.json +11 -0
- package/gs/encoding/json/index.test.ts +25 -3
- package/gs/encoding/json/index.ts +21 -3
- package/gs/errors/errors.test.ts +4 -1
- package/gs/errors/errors.ts +32 -8
- package/gs/fmt/fmt.test.ts +3 -1
- package/gs/fmt/fmt.ts +1 -5
- package/gs/github.com/aperturerobotics/protobuf-go-lite/index.test.ts +62 -7
- package/gs/github.com/aperturerobotics/protobuf-go-lite/index.ts +78 -36
- package/gs/github.com/aperturerobotics/protobuf-go-lite/json/index.test.ts +32 -11
- package/gs/github.com/aperturerobotics/protobuf-go-lite/json/index.ts +122 -43
- package/gs/github.com/aperturerobotics/starpc/srpc/index.test.ts +31 -0
- package/gs/github.com/aperturerobotics/starpc/srpc/index.ts +518 -4
- package/gs/github.com/aperturerobotics/starpc/srpc/meta.json +6 -0
- package/gs/github.com/aperturerobotics/util/conc/index.test.ts +30 -0
- package/gs/github.com/aperturerobotics/util/conc/index.ts +172 -0
- package/gs/github.com/aperturerobotics/util/conc/meta.json +9 -0
- package/gs/github.com/aperturerobotics/wasivm/wazero/kernel/runtime/browser/browser.ts +1 -4
- package/gs/github.com/hack-pad/safejs/internal/catch/index.test.ts +35 -0
- package/gs/github.com/hack-pad/safejs/internal/catch/index.ts +65 -0
- package/gs/github.com/hack-pad/safejs/internal/catch/meta.json +9 -0
- package/gs/github.com/klauspost/compress/internal/le/index.test.ts +2 -1
- package/gs/github.com/klauspost/compress/internal/le/index.ts +6 -5
- package/gs/github.com/mr-tron/base58/base58/index.test.ts +70 -0
- package/gs/github.com/mr-tron/base58/base58/index.ts +231 -0
- package/gs/github.com/mr-tron/base58/base58/meta.json +3 -0
- package/gs/github.com/zeebo/blake3/internal/consts/index.test.ts +46 -0
- package/gs/github.com/zeebo/blake3/internal/consts/index.ts +26 -0
- package/gs/go/token/index.ts +17 -4
- package/gs/hash/fnv/index.test.ts +67 -0
- package/gs/hash/fnv/index.ts +351 -0
- package/gs/hash/fnv/meta.json +3 -0
- package/gs/hash/index.test.ts +37 -0
- package/gs/hash/index.ts +118 -0
- package/gs/hash/meta.json +5 -0
- package/gs/internal/byteorder/index.test.ts +6 -6
- package/gs/io/fs/readlink.ts +40 -48
- package/gs/io/fs/walk.ts +10 -2
- package/gs/io/io.ts +4 -1
- package/gs/iter/iter.ts +8 -2
- package/gs/maps/iter.ts +69 -26
- package/gs/maps/maps.test.ts +23 -0
- package/gs/maps/maps.ts +6 -6
- package/gs/math/bits/index.test.ts +20 -0
- package/gs/math/bits/index.ts +15 -28
- package/gs/mime/index.ts +8 -2
- package/gs/net/http/httptest/index.test.ts +53 -0
- package/gs/net/http/httptest/index.ts +98 -3
- package/gs/net/http/index.test.ts +129 -1
- package/gs/net/http/index.ts +370 -19
- package/gs/net/http/meta.json +6 -0
- package/gs/net/http/pprof/index.test.ts +47 -0
- package/gs/net/http/pprof/index.ts +65 -0
- package/gs/os/error.gs.ts +9 -10
- package/gs/os/error.test.ts +41 -0
- package/gs/os/file_unix_js.test.ts +55 -0
- package/gs/os/tempfile.gs.test.ts +37 -10
- package/gs/os/types_js.gs.ts +94 -15
- package/gs/path/filepath/match.ts +4 -1
- package/gs/path/filepath/meta.json +6 -0
- package/gs/path/filepath/path.test.ts +57 -2
- package/gs/path/filepath/path.ts +91 -12
- package/gs/reflect/field.test.ts +63 -0
- package/gs/reflect/index.ts +4 -1
- package/gs/reflect/iter.ts +2 -2
- package/gs/reflect/map.test.ts +24 -2
- package/gs/reflect/map.ts +35 -0
- package/gs/reflect/type.ts +543 -60
- package/gs/reflect/typefor.test.ts +100 -0
- package/gs/reflect/types.ts +3 -1
- package/gs/reflect/value.ts +50 -1
- package/gs/reflect/visiblefields.ts +1 -1
- package/gs/runtime/debug/index.test.ts +22 -1
- package/gs/runtime/debug/index.ts +88 -0
- package/gs/runtime/pprof/index.test.ts +36 -0
- package/gs/runtime/pprof/index.ts +104 -0
- package/gs/runtime/pprof/meta.json +6 -0
- package/gs/runtime/trace/index.test.ts +45 -0
- package/gs/runtime/trace/index.ts +97 -0
- package/gs/runtime/trace/meta.json +7 -0
- package/gs/slices/meta.json +2 -1
- package/gs/slices/slices.test.ts +86 -0
- package/gs/slices/slices.ts +284 -37
- package/gs/sort/slice.gs.ts +73 -23
- package/gs/sort/slice.test.ts +40 -0
- package/gs/strings/builder.test.ts +8 -0
- package/gs/strings/builder.ts +29 -17
- package/gs/strings/iter.test.ts +5 -7
- package/gs/strings/iter.ts +146 -71
- package/gs/strings/replace.test.ts +1 -4
- package/gs/strings/replace.ts +6 -6
- package/gs/strings/strings.test.ts +4 -0
- package/gs/strings/strings.ts +54 -6
- package/gs/sync/sync.test.ts +57 -1
- package/gs/sync/sync.ts +45 -13
- package/gs/syscall/errors.ts +158 -115
- package/gs/syscall/fs.ts +8 -8
- package/gs/syscall/js/index.ts +49 -22
- package/gs/syscall/net.test.ts +26 -0
- package/gs/syscall/types.ts +7 -2
- package/gs/testing/testing.test.ts +56 -0
- package/gs/testing/testing.ts +27 -10
- package/gs/time/meta.json +2 -2
- package/gs/time/time.test.ts +4 -0
- package/gs/time/time.ts +33 -2
- package/gs/unicode/unicode.test.ts +14 -3
- package/gs/unicode/unicode.ts +1 -5
- package/gs/unique/index.ts +9 -2
- package/package.json +3 -3
package/gs/builtin/slice.ts
CHANGED
|
@@ -1,4 +1,60 @@
|
|
|
1
|
-
import { varRef, type VarRef } from './varRef.js'
|
|
1
|
+
import { isVarRef, varRef, type VarRef } from './varRef.js'
|
|
2
|
+
|
|
3
|
+
export class GoBinaryString extends String {
|
|
4
|
+
readonly bytes: Uint8Array
|
|
5
|
+
|
|
6
|
+
constructor(bytes: Uint8Array) {
|
|
7
|
+
super(bytesToBinaryString(bytes))
|
|
8
|
+
this.bytes = bytes.slice()
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
toString(): string {
|
|
12
|
+
return bytesToBinaryString(this.bytes)
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
valueOf(): string {
|
|
16
|
+
return this.toString()
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
[Symbol.toPrimitive](): string {
|
|
20
|
+
return this.toString()
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
type GoStringValue = string | GoBinaryString
|
|
25
|
+
type GoStringBytes = GoStringValue | Slice<number> | Uint8Array
|
|
26
|
+
|
|
27
|
+
function isGoStringValue(value: unknown): value is GoStringValue {
|
|
28
|
+
return typeof value === 'string' || value instanceof GoBinaryString
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
function goStringBytes(str: GoStringValue): Uint8Array {
|
|
32
|
+
if (str instanceof GoBinaryString) {
|
|
33
|
+
return str.bytes.slice()
|
|
34
|
+
}
|
|
35
|
+
return new TextEncoder().encode(str)
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
function goStringComparableBytes(value: GoStringBytes): Uint8Array {
|
|
39
|
+
if (isGoStringValue(value)) {
|
|
40
|
+
return goStringBytes(value)
|
|
41
|
+
}
|
|
42
|
+
if (value instanceof Uint8Array) {
|
|
43
|
+
return value
|
|
44
|
+
}
|
|
45
|
+
if (value === null || value === undefined) {
|
|
46
|
+
return new Uint8Array(0)
|
|
47
|
+
}
|
|
48
|
+
return Uint8Array.from(asArray(value))
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
function goStringFromBytes(bytes: Uint8Array): string {
|
|
52
|
+
try {
|
|
53
|
+
return new TextDecoder('utf-8', { fatal: true }).decode(bytes)
|
|
54
|
+
} catch {
|
|
55
|
+
return new GoBinaryString(bytes) as unknown as string
|
|
56
|
+
}
|
|
57
|
+
}
|
|
2
58
|
|
|
3
59
|
/**
|
|
4
60
|
* GoSliceObject contains metadata for complex slice views
|
|
@@ -8,6 +64,7 @@ interface GoSliceObject<T> {
|
|
|
8
64
|
offset: number // Offset into the backing array
|
|
9
65
|
length: number // Length of the slice
|
|
10
66
|
capacity: number // Capacity of the slice
|
|
67
|
+
target?: T[] // Materialized proxy target for JS array operations
|
|
11
68
|
}
|
|
12
69
|
|
|
13
70
|
const addressStride = 0x100000000
|
|
@@ -21,6 +78,25 @@ export type SliceProxy<T> = T[] & {
|
|
|
21
78
|
__meta__: GoSliceObject<T>
|
|
22
79
|
}
|
|
23
80
|
|
|
81
|
+
type ByteSlice = Uint8Array & {
|
|
82
|
+
__meta__?: GoSliceObject<number>
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
function sliceIndexProperty(prop: string | symbol): number {
|
|
86
|
+
if (typeof prop !== 'string' || prop.length === 0) {
|
|
87
|
+
return -1
|
|
88
|
+
}
|
|
89
|
+
let index = 0
|
|
90
|
+
for (let i = 0; i < prop.length; i++) {
|
|
91
|
+
const digit = prop.charCodeAt(i) - 48
|
|
92
|
+
if (digit < 0 || digit > 9) {
|
|
93
|
+
return -1
|
|
94
|
+
}
|
|
95
|
+
index = index * 10 + digit
|
|
96
|
+
}
|
|
97
|
+
return index
|
|
98
|
+
}
|
|
99
|
+
|
|
24
100
|
/**
|
|
25
101
|
* Slice<T> is a union type that is either a plain array or a proxy
|
|
26
102
|
* null represents the nil state.
|
|
@@ -38,39 +114,41 @@ export type Slice<T> =
|
|
|
38
114
|
* and route it through the backing array.
|
|
39
115
|
*/
|
|
40
116
|
function wrapSliceProxy<T>(proxy: SliceProxy<T>): SliceProxy<T> {
|
|
117
|
+
const meta = proxy.__meta__
|
|
118
|
+
meta.target = proxy
|
|
41
119
|
const handler = {
|
|
42
120
|
get(target: any, prop: string | symbol): any {
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
if (index
|
|
46
|
-
return
|
|
121
|
+
const index = sliceIndexProperty(prop)
|
|
122
|
+
if (index >= 0) {
|
|
123
|
+
if (index < meta.length) {
|
|
124
|
+
return meta.backing[meta.offset + index]
|
|
47
125
|
}
|
|
48
126
|
throw new Error(
|
|
49
|
-
`Slice index out of range: ${index} >= ${
|
|
127
|
+
`Slice index out of range: ${index} >= ${meta.length}`,
|
|
50
128
|
)
|
|
51
129
|
}
|
|
52
130
|
|
|
53
131
|
if (prop === 'length') {
|
|
54
|
-
return
|
|
132
|
+
return meta.length
|
|
55
133
|
}
|
|
56
134
|
|
|
57
135
|
if (prop === '__meta__') {
|
|
58
|
-
return
|
|
136
|
+
return meta
|
|
59
137
|
}
|
|
60
138
|
|
|
61
139
|
return Reflect.get(target, prop)
|
|
62
140
|
},
|
|
63
141
|
|
|
64
142
|
set(target: any, prop: string | symbol, value: any): boolean {
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
if (index
|
|
68
|
-
|
|
143
|
+
const index = sliceIndexProperty(prop)
|
|
144
|
+
if (index >= 0) {
|
|
145
|
+
if (index < meta.length) {
|
|
146
|
+
meta.backing[meta.offset + index] = value
|
|
69
147
|
target[index] = value // Also update the proxy target for consistency
|
|
70
148
|
return true
|
|
71
149
|
}
|
|
72
150
|
throw new Error(
|
|
73
|
-
`Slice index out of range: ${index} >= ${
|
|
151
|
+
`Slice index out of range: ${index} >= ${meta.length}`,
|
|
74
152
|
)
|
|
75
153
|
}
|
|
76
154
|
|
|
@@ -85,6 +163,24 @@ function wrapSliceProxy<T>(proxy: SliceProxy<T>): SliceProxy<T> {
|
|
|
85
163
|
return new Proxy(proxy, handler) as SliceProxy<T>
|
|
86
164
|
}
|
|
87
165
|
|
|
166
|
+
function sliceProxyFromBacking<T>(
|
|
167
|
+
backing: T[],
|
|
168
|
+
offset: number,
|
|
169
|
+
length: number,
|
|
170
|
+
capacity: number,
|
|
171
|
+
target?: T[],
|
|
172
|
+
): SliceProxy<T> {
|
|
173
|
+
const proxyTargetArray = (target ?? new Array<T>(length)) as SliceProxy<T>
|
|
174
|
+
proxyTargetArray.length = length
|
|
175
|
+
if (target === undefined) {
|
|
176
|
+
for (let i = 0; i < length; i++) {
|
|
177
|
+
proxyTargetArray[i] = backing[offset + i]
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
proxyTargetArray.__meta__ = { backing, offset, length, capacity }
|
|
181
|
+
return wrapSliceProxy(proxyTargetArray)
|
|
182
|
+
}
|
|
183
|
+
|
|
88
184
|
// asArray converts a slice to a JavaScript array.
|
|
89
185
|
export function asArray<T>(slice: Slice<T>): T[] {
|
|
90
186
|
if (slice === null || slice === undefined) {
|
|
@@ -121,7 +217,9 @@ export function sliceToArray<T>(
|
|
|
121
217
|
)
|
|
122
218
|
}
|
|
123
219
|
if (typeHint === 'byte') {
|
|
124
|
-
return new Uint8Array(
|
|
220
|
+
return new Uint8Array(
|
|
221
|
+
asArray(slice as Slice<T>).slice(0, length) as number[],
|
|
222
|
+
)
|
|
125
223
|
}
|
|
126
224
|
return asArray(slice as Slice<T>).slice(0, length)
|
|
127
225
|
}
|
|
@@ -140,7 +238,9 @@ export function sliceToArrayPointer<T>(
|
|
|
140
238
|
if (slice instanceof Uint8Array) {
|
|
141
239
|
return varRef(goSlice(slice, 0, length) as unknown as Uint8Array)
|
|
142
240
|
}
|
|
143
|
-
return varRef(
|
|
241
|
+
return varRef(
|
|
242
|
+
goSlice(slice as Slice<T>, 0, length) as unknown as Uint8Array,
|
|
243
|
+
)
|
|
144
244
|
}
|
|
145
245
|
if (slice instanceof Uint8Array) {
|
|
146
246
|
return varRef(goSlice(slice, 0, length) as unknown as T[])
|
|
@@ -168,6 +268,28 @@ function normalizeSliceIndex(value: number | undefined): number | undefined {
|
|
|
168
268
|
return Number(value)
|
|
169
269
|
}
|
|
170
270
|
|
|
271
|
+
function byteSliceMeta(slice: Uint8Array): GoSliceObject<number> | undefined {
|
|
272
|
+
return (slice as ByteSlice).__meta__
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
function byteSliceView(
|
|
276
|
+
backing: Uint8Array,
|
|
277
|
+
offset: number,
|
|
278
|
+
length: number,
|
|
279
|
+
capacity: number,
|
|
280
|
+
): Uint8Array {
|
|
281
|
+
const view = backing.subarray(offset, offset + length) as ByteSlice
|
|
282
|
+
if (capacity !== length) {
|
|
283
|
+
view.__meta__ = {
|
|
284
|
+
backing: backing as unknown as number[],
|
|
285
|
+
offset,
|
|
286
|
+
length,
|
|
287
|
+
capacity,
|
|
288
|
+
}
|
|
289
|
+
}
|
|
290
|
+
return view
|
|
291
|
+
}
|
|
292
|
+
|
|
171
293
|
/**
|
|
172
294
|
* isSliceProxy checks if a slice is a SliceProxy (has __meta__ property)
|
|
173
295
|
* This is an alias for isComplexSlice for better type hinting
|
|
@@ -201,24 +323,7 @@ export const makeSlice = <T>(
|
|
|
201
323
|
return new Uint8Array(length) as Slice<T>
|
|
202
324
|
}
|
|
203
325
|
|
|
204
|
-
|
|
205
|
-
const backingUint8 = new Uint8Array(actualCapacity)
|
|
206
|
-
const backingNumbers = Array.from(backingUint8) as T[] // Convert to number[] for backing
|
|
207
|
-
|
|
208
|
-
const proxyTargetArray = new Array<T>(length)
|
|
209
|
-
for (let i = 0; i < length; i++) {
|
|
210
|
-
proxyTargetArray[i] = 0 as T // Initialize with zeros
|
|
211
|
-
}
|
|
212
|
-
|
|
213
|
-
const proxy = proxyTargetArray as SliceProxy<T>
|
|
214
|
-
proxy.__meta__ = {
|
|
215
|
-
backing: backingNumbers,
|
|
216
|
-
offset: 0,
|
|
217
|
-
length: length,
|
|
218
|
-
capacity: actualCapacity,
|
|
219
|
-
}
|
|
220
|
-
|
|
221
|
-
return wrapSliceProxy(proxy) as Slice<T>
|
|
326
|
+
return byteSliceView(new Uint8Array(actualCapacity), 0, length, actualCapacity) as Slice<T>
|
|
222
327
|
}
|
|
223
328
|
|
|
224
329
|
const actualCapacity = capacity === undefined ? length : capacity
|
|
@@ -245,12 +350,11 @@ export const makeSlice = <T>(
|
|
|
245
350
|
}
|
|
246
351
|
|
|
247
352
|
const backingArr = new Array<T>(actualCapacity)
|
|
248
|
-
//
|
|
249
|
-
|
|
353
|
+
// Go zero-initializes the whole backing array. Elements beyond len become
|
|
354
|
+
// observable when a slice is resliced up to cap.
|
|
355
|
+
for (let i = 0; i < actualCapacity; i++) {
|
|
250
356
|
backingArr[i] = zeroValue()
|
|
251
357
|
}
|
|
252
|
-
// The rest of backingArr (from length to actualCapacity-1) remains uninitialized (undefined),
|
|
253
|
-
// representing available capacity.
|
|
254
358
|
|
|
255
359
|
// OPTIMIZATION: If length equals capacity, return backing array directly
|
|
256
360
|
if (length === actualCapacity) {
|
|
@@ -275,9 +379,9 @@ export const makeSlice = <T>(
|
|
|
275
379
|
// Create a proper Proxy with the handler for SliceProxy behavior
|
|
276
380
|
const handler = {
|
|
277
381
|
get(target: any, prop: string | symbol): any {
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
if (index
|
|
382
|
+
const index = sliceIndexProperty(prop)
|
|
383
|
+
if (index >= 0) {
|
|
384
|
+
if (index < target.__meta__.length) {
|
|
281
385
|
return target.__meta__.backing[target.__meta__.offset + index]
|
|
282
386
|
}
|
|
283
387
|
throw new Error(
|
|
@@ -297,9 +401,9 @@ export const makeSlice = <T>(
|
|
|
297
401
|
},
|
|
298
402
|
|
|
299
403
|
set(target: any, prop: string | symbol, value: any): boolean {
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
if (index
|
|
404
|
+
const index = sliceIndexProperty(prop)
|
|
405
|
+
if (index >= 0) {
|
|
406
|
+
if (index < target.__meta__.length) {
|
|
303
407
|
target.__meta__.backing[target.__meta__.offset + index] = value
|
|
304
408
|
target[index] = value // Also update the proxy target for consistency
|
|
305
409
|
return true
|
|
@@ -349,15 +453,16 @@ export function goSlice<T>( // T can be number for Uint8Array case
|
|
|
349
453
|
high?: number,
|
|
350
454
|
max?: number,
|
|
351
455
|
): Slice<T> {
|
|
456
|
+
s = collectionValue(s) as Slice<T> | Uint8Array
|
|
352
457
|
low = normalizeSliceIndex(low)
|
|
353
458
|
high = normalizeSliceIndex(high)
|
|
354
459
|
max = normalizeSliceIndex(max)
|
|
355
460
|
|
|
356
461
|
const handler = {
|
|
357
462
|
get(target: any, prop: string | symbol): any {
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
if (index
|
|
463
|
+
const index = sliceIndexProperty(prop)
|
|
464
|
+
if (index >= 0) {
|
|
465
|
+
if (index < target.__meta__.length) {
|
|
361
466
|
return target.__meta__.backing[target.__meta__.offset + index]
|
|
362
467
|
}
|
|
363
468
|
throw new Error(
|
|
@@ -392,9 +497,9 @@ export function goSlice<T>( // T can be number for Uint8Array case
|
|
|
392
497
|
},
|
|
393
498
|
|
|
394
499
|
set(target: any, prop: string | symbol, value: any): boolean {
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
if (index
|
|
500
|
+
const index = sliceIndexProperty(prop)
|
|
501
|
+
if (index >= 0) {
|
|
502
|
+
if (index < target.__meta__.length) {
|
|
398
503
|
target.__meta__.backing[target.__meta__.offset + index] = value
|
|
399
504
|
target[index] = value
|
|
400
505
|
return true
|
|
@@ -422,55 +527,51 @@ export function goSlice<T>( // T can be number for Uint8Array case
|
|
|
422
527
|
}
|
|
423
528
|
|
|
424
529
|
if (s instanceof Uint8Array) {
|
|
530
|
+
const meta = byteSliceMeta(s)
|
|
531
|
+
const metaBacking = meta?.backing as unknown
|
|
532
|
+
const backing =
|
|
533
|
+
metaBacking instanceof Uint8Array ? metaBacking : s
|
|
534
|
+
const baseOffset = meta?.offset ?? 0
|
|
535
|
+
const baseCapacity = meta?.capacity ?? s.length
|
|
425
536
|
const actualLow = low ?? 0
|
|
426
537
|
const actualHigh = high ?? s.length
|
|
427
538
|
|
|
428
|
-
if (
|
|
539
|
+
if (
|
|
540
|
+
actualLow < 0 ||
|
|
541
|
+
actualHigh < actualLow ||
|
|
542
|
+
actualLow > baseCapacity ||
|
|
543
|
+
actualHigh > baseCapacity
|
|
544
|
+
) {
|
|
429
545
|
throw new Error(
|
|
430
|
-
`Invalid slice indices: low ${actualLow}, high ${actualHigh} for Uint8Array
|
|
546
|
+
`Invalid slice indices: low ${actualLow}, high ${actualHigh} for Uint8Array with capacity ${baseCapacity}`,
|
|
431
547
|
)
|
|
432
548
|
}
|
|
433
549
|
|
|
434
550
|
const newLength = actualHigh - actualLow
|
|
435
551
|
|
|
436
552
|
if (max !== undefined) {
|
|
437
|
-
if (max < actualHigh || max >
|
|
553
|
+
if (max < actualHigh || max > baseCapacity) {
|
|
438
554
|
// max is relative to the original s.length (capacity)
|
|
439
555
|
throw new Error(
|
|
440
|
-
`Invalid max index: ${max}. Constraints: low ${actualLow} <= high ${actualHigh} <= max <=
|
|
556
|
+
`Invalid max index: ${max}. Constraints: low ${actualLow} <= high ${actualHigh} <= max <= capacity ${baseCapacity}`,
|
|
441
557
|
)
|
|
442
558
|
}
|
|
443
559
|
|
|
444
560
|
const newCap = max - actualLow // Capacity of the new slice view
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
length: newLength,
|
|
452
|
-
capacity: newCap,
|
|
453
|
-
}
|
|
454
|
-
return new Proxy(proxyTarget, handler) as unknown as Slice<T>
|
|
455
|
-
} else {
|
|
456
|
-
// newCap === newLength, standard Uint8Array is fine.
|
|
457
|
-
return s.subarray(actualLow, actualHigh) as Slice<T> // T is number
|
|
458
|
-
}
|
|
561
|
+
return byteSliceView(
|
|
562
|
+
backing,
|
|
563
|
+
baseOffset + actualLow,
|
|
564
|
+
newLength,
|
|
565
|
+
newCap,
|
|
566
|
+
) as Slice<T>
|
|
459
567
|
}
|
|
460
568
|
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
capacity: s.length - actualLow,
|
|
468
|
-
}
|
|
469
|
-
return new Proxy(proxyTarget, handler) as unknown as Slice<T>
|
|
470
|
-
}
|
|
471
|
-
|
|
472
|
-
// max is not defined and length equals capacity, return the Uint8Array view directly.
|
|
473
|
-
return s.subarray(actualLow, actualHigh) as Slice<T> // T is number
|
|
569
|
+
return byteSliceView(
|
|
570
|
+
backing,
|
|
571
|
+
baseOffset + actualLow,
|
|
572
|
+
newLength,
|
|
573
|
+
baseCapacity - actualLow,
|
|
574
|
+
) as Slice<T>
|
|
474
575
|
}
|
|
475
576
|
|
|
476
577
|
// Handle nil slices - in Go, slicing a nil slice with valid bounds returns nil
|
|
@@ -561,7 +662,7 @@ export function goSlice<T>( // T can be number for Uint8Array case
|
|
|
561
662
|
const newOffset = oldOffset + low
|
|
562
663
|
|
|
563
664
|
// OPTIMIZATION: If the result would have offset=0 and length=capacity, return backing directly
|
|
564
|
-
if (newOffset === 0 && newLength === newCap) {
|
|
665
|
+
if (newOffset === 0 && newLength === newCap && backing.length === newLength) {
|
|
565
666
|
return backing as Slice<T>
|
|
566
667
|
}
|
|
567
668
|
|
|
@@ -615,9 +716,9 @@ export const arrayToSlice = <T>(
|
|
|
615
716
|
|
|
616
717
|
const handler = {
|
|
617
718
|
get(target: any, prop: string | symbol): any {
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
if (index
|
|
719
|
+
const index = sliceIndexProperty(prop)
|
|
720
|
+
if (index >= 0) {
|
|
721
|
+
if (index < target.__meta__.length) {
|
|
621
722
|
return target.__meta__.backing[target.__meta__.offset + index]
|
|
622
723
|
}
|
|
623
724
|
throw new Error(
|
|
@@ -652,9 +753,9 @@ export const arrayToSlice = <T>(
|
|
|
652
753
|
},
|
|
653
754
|
|
|
654
755
|
set(target: any, prop: string | symbol, value: any): boolean {
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
if (index
|
|
756
|
+
const index = sliceIndexProperty(prop)
|
|
757
|
+
if (index >= 0) {
|
|
758
|
+
if (index < target.__meta__.length) {
|
|
658
759
|
target.__meta__.backing[target.__meta__.offset + index] = value
|
|
659
760
|
return true
|
|
660
761
|
}
|
|
@@ -699,7 +800,7 @@ export const arrayToSlice = <T>(
|
|
|
699
800
|
*/
|
|
700
801
|
export const len = <T = unknown, V = unknown>(
|
|
701
802
|
obj:
|
|
702
|
-
|
|
|
803
|
+
| GoStringValue
|
|
703
804
|
| Array<T>
|
|
704
805
|
| Slice<T>
|
|
705
806
|
| Map<T, V>
|
|
@@ -709,32 +810,41 @@ export const len = <T = unknown, V = unknown>(
|
|
|
709
810
|
| null
|
|
710
811
|
| undefined,
|
|
711
812
|
): number => {
|
|
813
|
+
obj = collectionValue(obj) as typeof obj
|
|
712
814
|
if (obj === null || obj === undefined) {
|
|
713
815
|
return 0
|
|
714
816
|
}
|
|
715
817
|
|
|
716
818
|
if (typeof obj === 'string') {
|
|
717
|
-
return stringLen(obj)
|
|
819
|
+
return stringLen(obj)
|
|
718
820
|
}
|
|
719
821
|
|
|
720
|
-
if (obj instanceof
|
|
721
|
-
return obj.
|
|
822
|
+
if (obj instanceof Uint8Array) {
|
|
823
|
+
return obj.length
|
|
722
824
|
}
|
|
723
825
|
|
|
724
|
-
if (obj
|
|
826
|
+
if (Array.isArray(obj)) {
|
|
827
|
+
const meta = (obj as unknown as SliceProxy<T>).__meta__
|
|
828
|
+
if (meta !== undefined) {
|
|
829
|
+
return meta.length
|
|
830
|
+
}
|
|
725
831
|
return obj.length
|
|
726
832
|
}
|
|
727
833
|
|
|
728
|
-
if (
|
|
729
|
-
return
|
|
834
|
+
if (obj instanceof Map || obj instanceof Set) {
|
|
835
|
+
return obj.size
|
|
836
|
+
}
|
|
837
|
+
|
|
838
|
+
if (obj instanceof GoBinaryString) {
|
|
839
|
+
return stringLen(obj)
|
|
730
840
|
}
|
|
731
841
|
|
|
732
842
|
if (isComplexSlice(obj as any)) {
|
|
733
|
-
return (obj as SliceProxy<T>).__meta__.length
|
|
843
|
+
return (obj as unknown as SliceProxy<T>).__meta__.length
|
|
734
844
|
}
|
|
735
845
|
|
|
736
|
-
if (
|
|
737
|
-
return obj.
|
|
846
|
+
if (typeof (obj as any).len === 'function') {
|
|
847
|
+
return (obj as { len(): number }).len()
|
|
738
848
|
}
|
|
739
849
|
|
|
740
850
|
throw new Error('cannot determine len of this type')
|
|
@@ -745,23 +855,30 @@ export const len = <T = unknown, V = unknown>(
|
|
|
745
855
|
* @param obj The slice.
|
|
746
856
|
* @returns The capacity of the slice.
|
|
747
857
|
*/
|
|
748
|
-
export const cap = <T>(
|
|
858
|
+
export const cap = <T>(
|
|
859
|
+
obj: Slice<T> | Uint8Array | { cap(): number } | null | undefined,
|
|
860
|
+
): number => {
|
|
861
|
+
obj = collectionValue(obj) as typeof obj
|
|
749
862
|
if (obj === null || obj === undefined) {
|
|
750
863
|
return 0
|
|
751
864
|
}
|
|
752
865
|
|
|
753
|
-
if (obj
|
|
754
|
-
return obj
|
|
866
|
+
if (isComplexSlice(obj as any)) {
|
|
867
|
+
return (obj as SliceProxy<T>).__meta__.capacity
|
|
755
868
|
}
|
|
756
869
|
|
|
757
|
-
if (
|
|
758
|
-
return obj.
|
|
870
|
+
if (obj instanceof Uint8Array) {
|
|
871
|
+
return obj.length // Uint8Array capacity is its length
|
|
759
872
|
}
|
|
760
873
|
|
|
761
874
|
if (Array.isArray(obj)) {
|
|
762
875
|
return obj.length
|
|
763
876
|
}
|
|
764
877
|
|
|
878
|
+
if (typeof (obj as any).cap === 'function') {
|
|
879
|
+
return (obj as { cap(): number }).cap()
|
|
880
|
+
}
|
|
881
|
+
|
|
765
882
|
return 0
|
|
766
883
|
}
|
|
767
884
|
|
|
@@ -776,6 +893,7 @@ export const cap = <T>(obj: Slice<T> | Uint8Array): number => {
|
|
|
776
893
|
export function append(slice: Uint8Array, ...elements: any[]): Uint8Array
|
|
777
894
|
// Overload for null slice with number elements - returns number slice (Bytes compatible)
|
|
778
895
|
export function append(slice: null, ...elements: number[]): Slice<number>
|
|
896
|
+
export function append<T>(slice: null, ...elements: T[]): Slice<T>
|
|
779
897
|
export function append<T>(slice: Slice<T>, ...elements: any[]): Slice<T>
|
|
780
898
|
export function append<T>(
|
|
781
899
|
slice: Slice<T> | Uint8Array | null,
|
|
@@ -788,51 +906,7 @@ export function append<T>(
|
|
|
788
906
|
|
|
789
907
|
// If producing Uint8Array, all elements must be numbers and potentially flattened from other Uint8Arrays/number slices.
|
|
790
908
|
if (produceUint8Array) {
|
|
791
|
-
|
|
792
|
-
// Add bytes from the original slice if it exists and is numeric.
|
|
793
|
-
if (inputIsUint8Array) {
|
|
794
|
-
appendBytes(combinedBytes, slice as Uint8Array)
|
|
795
|
-
} else if (slice !== null && slice !== undefined) {
|
|
796
|
-
// Original was Slice<number> or number[]
|
|
797
|
-
const sliceLen = len(slice)
|
|
798
|
-
for (let i = 0; i < sliceLen; i++) {
|
|
799
|
-
const val = (slice as any)[i]
|
|
800
|
-
if (typeof val !== 'number') {
|
|
801
|
-
throw new Error(
|
|
802
|
-
'Cannot produce Uint8Array: original slice contains non-number elements.',
|
|
803
|
-
)
|
|
804
|
-
}
|
|
805
|
-
combinedBytes.push(val)
|
|
806
|
-
}
|
|
807
|
-
}
|
|
808
|
-
// Add bytes from the varargs elements.
|
|
809
|
-
// For Uint8Array, elements are always flattened if they are slices/Uint8Arrays.
|
|
810
|
-
for (const item of elements) {
|
|
811
|
-
if (item instanceof Uint8Array) {
|
|
812
|
-
appendBytes(combinedBytes, item)
|
|
813
|
-
} else if (isComplexSlice(item) || Array.isArray(item)) {
|
|
814
|
-
const itemLen = len(item as Slice<any>)
|
|
815
|
-
for (let i = 0; i < itemLen; i++) {
|
|
816
|
-
const val = (item as any)[i]
|
|
817
|
-
if (typeof val !== 'number') {
|
|
818
|
-
throw new Error(
|
|
819
|
-
'Cannot produce Uint8Array: appended elements contain non-numbers.',
|
|
820
|
-
)
|
|
821
|
-
}
|
|
822
|
-
combinedBytes.push(val)
|
|
823
|
-
}
|
|
824
|
-
} else {
|
|
825
|
-
if (typeof item !== 'number') {
|
|
826
|
-
throw new Error(
|
|
827
|
-
'Cannot produce Uint8Array: appended elements contain non-numbers.',
|
|
828
|
-
)
|
|
829
|
-
}
|
|
830
|
-
combinedBytes.push(item)
|
|
831
|
-
}
|
|
832
|
-
}
|
|
833
|
-
const newArr = new Uint8Array(combinedBytes.length)
|
|
834
|
-
newArr.set(combinedBytes)
|
|
835
|
-
return newArr as any
|
|
909
|
+
return appendByteSlice(slice as Uint8Array, elements) as any
|
|
836
910
|
}
|
|
837
911
|
|
|
838
912
|
// Handle generic Slice<T> (non-Uint8Array result).
|
|
@@ -844,28 +918,30 @@ export function append<T>(
|
|
|
844
918
|
return slice as any
|
|
845
919
|
}
|
|
846
920
|
|
|
847
|
-
let originalElements: T[]
|
|
921
|
+
let originalElements: T[] | undefined
|
|
922
|
+
let oldLength = 0
|
|
848
923
|
let oldCapacity: number
|
|
849
924
|
let isOriginalComplex = false
|
|
850
925
|
let originalBacking: T[] | undefined = undefined
|
|
926
|
+
let originalTarget: T[] | undefined = undefined
|
|
851
927
|
let originalOffset = 0
|
|
852
928
|
|
|
853
929
|
if (slice === null || slice === undefined) {
|
|
854
930
|
oldCapacity = 0
|
|
855
931
|
} else if (isComplexSlice(slice)) {
|
|
856
932
|
const meta = slice.__meta__
|
|
857
|
-
|
|
858
|
-
originalElements.push(meta.backing[meta.offset + i])
|
|
933
|
+
oldLength = meta.length
|
|
859
934
|
oldCapacity = meta.capacity
|
|
860
935
|
isOriginalComplex = true
|
|
861
936
|
originalBacking = meta.backing
|
|
937
|
+
originalTarget = meta.target
|
|
862
938
|
originalOffset = meta.offset
|
|
863
939
|
} else {
|
|
864
940
|
// Simple T[] array
|
|
865
941
|
originalElements = (slice as T[]).slice()
|
|
866
|
-
|
|
942
|
+
oldLength = originalElements.length
|
|
943
|
+
oldCapacity = oldLength
|
|
867
944
|
}
|
|
868
|
-
const oldLength = originalElements.length
|
|
869
945
|
const newLength = oldLength + numAdded
|
|
870
946
|
|
|
871
947
|
// Case 1: Modify in-place if original was SliceProxy and has enough capacity.
|
|
@@ -873,16 +949,19 @@ export function append<T>(
|
|
|
873
949
|
for (let i = 0; i < numAdded; i++) {
|
|
874
950
|
originalBacking[originalOffset + oldLength + i] = elements[i] as T
|
|
875
951
|
}
|
|
876
|
-
const
|
|
877
|
-
|
|
878
|
-
|
|
879
|
-
|
|
880
|
-
|
|
881
|
-
offset: originalOffset,
|
|
882
|
-
length: newLength,
|
|
883
|
-
capacity: oldCapacity,
|
|
952
|
+
const target = originalTarget
|
|
953
|
+
if (target !== undefined) {
|
|
954
|
+
for (let i = 0; i < numAdded; i++) {
|
|
955
|
+
target[oldLength + i] = elements[i] as T
|
|
956
|
+
}
|
|
884
957
|
}
|
|
885
|
-
return
|
|
958
|
+
return sliceProxyFromBacking(
|
|
959
|
+
originalBacking,
|
|
960
|
+
originalOffset,
|
|
961
|
+
newLength,
|
|
962
|
+
oldCapacity,
|
|
963
|
+
target,
|
|
964
|
+
) as any
|
|
886
965
|
}
|
|
887
966
|
|
|
888
967
|
// Case 2: Reallocation is needed.
|
|
@@ -899,27 +978,86 @@ export function append<T>(
|
|
|
899
978
|
}
|
|
900
979
|
|
|
901
980
|
const newBacking = new Array<T>(newCapacity)
|
|
902
|
-
|
|
903
|
-
|
|
981
|
+
if (isOriginalComplex && originalBacking) {
|
|
982
|
+
for (let i = 0; i < oldLength; i++) {
|
|
983
|
+
newBacking[i] = originalBacking[originalOffset + i]
|
|
984
|
+
}
|
|
985
|
+
} else if (originalElements !== undefined) {
|
|
986
|
+
for (let i = 0; i < oldLength; i++) {
|
|
987
|
+
newBacking[i] = originalElements[i]
|
|
988
|
+
}
|
|
904
989
|
}
|
|
905
990
|
for (let i = 0; i < numAdded; i++) {
|
|
906
991
|
newBacking[oldLength + i] = elements[i] as T
|
|
907
992
|
}
|
|
908
993
|
|
|
909
|
-
|
|
910
|
-
|
|
911
|
-
|
|
912
|
-
|
|
913
|
-
|
|
914
|
-
|
|
915
|
-
|
|
994
|
+
return sliceProxyFromBacking(newBacking, 0, newLength, newCapacity) as any
|
|
995
|
+
}
|
|
996
|
+
|
|
997
|
+
function appendByteSlice(slice: Uint8Array, elements: any[]): Uint8Array {
|
|
998
|
+
const meta = byteSliceMeta(slice)
|
|
999
|
+
const metaBacking = meta?.backing as unknown
|
|
1000
|
+
const backing =
|
|
1001
|
+
metaBacking instanceof Uint8Array ? metaBacking : slice
|
|
1002
|
+
const offset = meta?.offset ?? 0
|
|
1003
|
+
const oldLength = slice.length
|
|
1004
|
+
const oldCapacity = meta?.capacity ?? oldLength
|
|
1005
|
+
let added = 0
|
|
1006
|
+
for (const item of elements) {
|
|
1007
|
+
added += byteElementLength(item)
|
|
1008
|
+
}
|
|
1009
|
+
const newLength = oldLength + added
|
|
1010
|
+
if (newLength <= oldCapacity) {
|
|
1011
|
+
const view = byteSliceView(backing, offset, newLength, oldCapacity)
|
|
1012
|
+
writeByteElements(view, oldLength, elements)
|
|
1013
|
+
return view
|
|
1014
|
+
}
|
|
1015
|
+
const next = new Uint8Array(newLength)
|
|
1016
|
+
next.set(slice)
|
|
1017
|
+
writeByteElements(next, oldLength, elements)
|
|
1018
|
+
return next
|
|
1019
|
+
}
|
|
1020
|
+
|
|
1021
|
+
function byteElementLength(item: any): number {
|
|
1022
|
+
if (item instanceof Uint8Array) {
|
|
1023
|
+
return item.length
|
|
916
1024
|
}
|
|
917
|
-
|
|
1025
|
+
if (isComplexSlice(item) || Array.isArray(item)) {
|
|
1026
|
+
return len(item as Slice<any>)
|
|
1027
|
+
}
|
|
1028
|
+
if (typeof item !== 'number') {
|
|
1029
|
+
throw new Error('Cannot produce Uint8Array: appended elements contain non-numbers.')
|
|
1030
|
+
}
|
|
1031
|
+
return 1
|
|
918
1032
|
}
|
|
919
1033
|
|
|
920
|
-
function
|
|
921
|
-
|
|
922
|
-
|
|
1034
|
+
function writeByteElements(dst: Uint8Array, offset: number, elements: any[]): void {
|
|
1035
|
+
let cursor = offset
|
|
1036
|
+
for (const item of elements) {
|
|
1037
|
+
if (item instanceof Uint8Array) {
|
|
1038
|
+
dst.set(item, cursor)
|
|
1039
|
+
cursor += item.length
|
|
1040
|
+
continue
|
|
1041
|
+
}
|
|
1042
|
+
if (isComplexSlice(item) || Array.isArray(item)) {
|
|
1043
|
+
const itemLen = len(item as Slice<any>)
|
|
1044
|
+
for (let i = 0; i < itemLen; i++) {
|
|
1045
|
+
const value = (item as any)[i]
|
|
1046
|
+
if (typeof value !== 'number') {
|
|
1047
|
+
throw new Error(
|
|
1048
|
+
'Cannot produce Uint8Array: appended elements contain non-numbers.',
|
|
1049
|
+
)
|
|
1050
|
+
}
|
|
1051
|
+
dst[cursor] = value
|
|
1052
|
+
cursor++
|
|
1053
|
+
}
|
|
1054
|
+
continue
|
|
1055
|
+
}
|
|
1056
|
+
if (typeof item !== 'number') {
|
|
1057
|
+
throw new Error('Cannot produce Uint8Array: appended elements contain non-numbers.')
|
|
1058
|
+
}
|
|
1059
|
+
dst[cursor] = item
|
|
1060
|
+
cursor++
|
|
923
1061
|
}
|
|
924
1062
|
}
|
|
925
1063
|
|
|
@@ -935,14 +1073,14 @@ export function copy<T>(dst: Slice<T>, src: Slice<T>): number
|
|
|
935
1073
|
export function copy<T>(dst: Slice<T>, src: string): number
|
|
936
1074
|
export function copy<T>(
|
|
937
1075
|
dst: Slice<T> | Uint8Array,
|
|
938
|
-
src: Slice<T> | Uint8Array |
|
|
1076
|
+
src: Slice<T> | Uint8Array | GoStringValue,
|
|
939
1077
|
): number {
|
|
940
1078
|
if (dst === null) {
|
|
941
1079
|
return 0
|
|
942
1080
|
}
|
|
943
1081
|
|
|
944
1082
|
// Handle string source first
|
|
945
|
-
if (
|
|
1083
|
+
if (isGoStringValue(src)) {
|
|
946
1084
|
return copyFromString(dst, src)
|
|
947
1085
|
}
|
|
948
1086
|
|
|
@@ -983,9 +1121,13 @@ export function copy<T>(
|
|
|
983
1121
|
/**
|
|
984
1122
|
* Helper: Copy from string to any destination type
|
|
985
1123
|
*/
|
|
986
|
-
function copyFromString<T>(
|
|
1124
|
+
function copyFromString<T>(
|
|
1125
|
+
dst: Slice<T> | Uint8Array,
|
|
1126
|
+
src: GoStringValue,
|
|
1127
|
+
): number {
|
|
987
1128
|
const dstLen = dst instanceof Uint8Array ? dst.length : len(dst)
|
|
988
|
-
const
|
|
1129
|
+
const bytes = goStringBytes(src)
|
|
1130
|
+
const count = Math.min(dstLen, bytes.length)
|
|
989
1131
|
|
|
990
1132
|
if (count === 0) {
|
|
991
1133
|
return 0
|
|
@@ -993,18 +1135,18 @@ function copyFromString<T>(dst: Slice<T> | Uint8Array, src: string): number {
|
|
|
993
1135
|
|
|
994
1136
|
if (dst instanceof Uint8Array) {
|
|
995
1137
|
for (let i = 0; i < count; i++) {
|
|
996
|
-
dst[i] =
|
|
1138
|
+
dst[i] = bytes[i]
|
|
997
1139
|
}
|
|
998
1140
|
} else if (isComplexSlice(dst)) {
|
|
999
1141
|
const dstMeta = dst.__meta__
|
|
1000
1142
|
for (let i = 0; i < count; i++) {
|
|
1001
|
-
const byteVal =
|
|
1143
|
+
const byteVal = bytes[i]
|
|
1002
1144
|
dstMeta.backing[dstMeta.offset + i] = byteVal as unknown as T
|
|
1003
1145
|
;(dst as any)[i] = byteVal
|
|
1004
1146
|
}
|
|
1005
1147
|
} else if (Array.isArray(dst)) {
|
|
1006
1148
|
for (let i = 0; i < count; i++) {
|
|
1007
|
-
dst[i] =
|
|
1149
|
+
dst[i] = bytes[i] as unknown as T
|
|
1008
1150
|
}
|
|
1009
1151
|
}
|
|
1010
1152
|
|
|
@@ -1019,15 +1161,9 @@ function copyToUint8Array(
|
|
|
1019
1161
|
src: Slice<number>,
|
|
1020
1162
|
count: number,
|
|
1021
1163
|
): number {
|
|
1022
|
-
|
|
1023
|
-
|
|
1024
|
-
|
|
1025
|
-
dst[i] = srcMeta.backing[srcMeta.offset + i]
|
|
1026
|
-
}
|
|
1027
|
-
} else if (Array.isArray(src)) {
|
|
1028
|
-
for (let i = 0; i < count; i++) {
|
|
1029
|
-
dst[i] = src[i]
|
|
1030
|
-
}
|
|
1164
|
+
const values = copySliceValues(src, count)
|
|
1165
|
+
for (let i = 0; i < count; i++) {
|
|
1166
|
+
dst[i] = values[i]
|
|
1031
1167
|
}
|
|
1032
1168
|
return count
|
|
1033
1169
|
}
|
|
@@ -1040,15 +1176,16 @@ function copyFromUint8Array<T>(
|
|
|
1040
1176
|
src: Uint8Array,
|
|
1041
1177
|
count: number,
|
|
1042
1178
|
): number {
|
|
1179
|
+
const values = Array.from(src.subarray(0, count))
|
|
1043
1180
|
if (isComplexSlice(dst)) {
|
|
1044
1181
|
const dstMeta = dst.__meta__
|
|
1045
1182
|
for (let i = 0; i < count; i++) {
|
|
1046
|
-
dstMeta.backing[dstMeta.offset + i] =
|
|
1047
|
-
;(dst as any)[i] =
|
|
1183
|
+
dstMeta.backing[dstMeta.offset + i] = values[i] as unknown as T
|
|
1184
|
+
;(dst as any)[i] = values[i]
|
|
1048
1185
|
}
|
|
1049
1186
|
} else if (Array.isArray(dst)) {
|
|
1050
1187
|
for (let i = 0; i < count; i++) {
|
|
1051
|
-
dst[i] =
|
|
1188
|
+
dst[i] = values[i] as unknown as T
|
|
1052
1189
|
}
|
|
1053
1190
|
}
|
|
1054
1191
|
return count
|
|
@@ -1062,37 +1199,36 @@ function copyBetweenSlices<T>(
|
|
|
1062
1199
|
src: Slice<T>,
|
|
1063
1200
|
count: number,
|
|
1064
1201
|
): number {
|
|
1202
|
+
const values = copySliceValues(src, count)
|
|
1065
1203
|
if (isComplexSlice(dst)) {
|
|
1066
1204
|
const dstMeta = dst.__meta__
|
|
1067
|
-
|
|
1068
|
-
|
|
1069
|
-
|
|
1070
|
-
for (let i = 0; i < count; i++) {
|
|
1071
|
-
dstMeta.backing[dstMeta.offset + i] =
|
|
1072
|
-
srcMeta.backing[srcMeta.offset + i]
|
|
1073
|
-
;(dst as any)[i] = srcMeta.backing[srcMeta.offset + i]
|
|
1074
|
-
}
|
|
1075
|
-
} else if (Array.isArray(src)) {
|
|
1076
|
-
for (let i = 0; i < count; i++) {
|
|
1077
|
-
dstMeta.backing[dstMeta.offset + i] = src[i]
|
|
1078
|
-
;(dst as any)[i] = src[i]
|
|
1079
|
-
}
|
|
1205
|
+
for (let i = 0; i < count; i++) {
|
|
1206
|
+
dstMeta.backing[dstMeta.offset + i] = values[i]
|
|
1207
|
+
;(dst as any)[i] = values[i]
|
|
1080
1208
|
}
|
|
1081
1209
|
} else if (Array.isArray(dst)) {
|
|
1082
|
-
|
|
1083
|
-
|
|
1084
|
-
for (let i = 0; i < count; i++) {
|
|
1085
|
-
dst[i] = srcMeta.backing[srcMeta.offset + i]
|
|
1086
|
-
}
|
|
1087
|
-
} else if (Array.isArray(src)) {
|
|
1088
|
-
for (let i = 0; i < count; i++) {
|
|
1089
|
-
dst[i] = src[i]
|
|
1090
|
-
}
|
|
1210
|
+
for (let i = 0; i < count; i++) {
|
|
1211
|
+
dst[i] = values[i]
|
|
1091
1212
|
}
|
|
1092
1213
|
}
|
|
1093
1214
|
return count
|
|
1094
1215
|
}
|
|
1095
1216
|
|
|
1217
|
+
function copySliceValues<T>(src: Slice<T>, count: number): T[] {
|
|
1218
|
+
const values = new Array<T>(count)
|
|
1219
|
+
if (isComplexSlice(src)) {
|
|
1220
|
+
const srcMeta = src.__meta__
|
|
1221
|
+
for (let i = 0; i < count; i++) {
|
|
1222
|
+
values[i] = srcMeta.backing[srcMeta.offset + i]
|
|
1223
|
+
}
|
|
1224
|
+
} else if (Array.isArray(src)) {
|
|
1225
|
+
for (let i = 0; i < count; i++) {
|
|
1226
|
+
values[i] = src[i]
|
|
1227
|
+
}
|
|
1228
|
+
}
|
|
1229
|
+
return values
|
|
1230
|
+
}
|
|
1231
|
+
|
|
1096
1232
|
/**
|
|
1097
1233
|
* Accesses an element at a specific index for various Go-like types (string, slice, array).
|
|
1098
1234
|
* Mimics Go's indexing behavior: `myCollection[index]`
|
|
@@ -1105,14 +1241,14 @@ function copyBetweenSlices<T>(
|
|
|
1105
1241
|
* @throws Error if index is out of bounds or type is unsupported.
|
|
1106
1242
|
*/
|
|
1107
1243
|
export function index<T>(
|
|
1108
|
-
collection:
|
|
1244
|
+
collection: GoStringValue | Slice<T> | T[],
|
|
1109
1245
|
index: number,
|
|
1110
1246
|
): T | number {
|
|
1111
1247
|
if (collection === null || collection === undefined) {
|
|
1112
1248
|
throw new Error('runtime error: index on nil or undefined collection')
|
|
1113
1249
|
}
|
|
1114
1250
|
|
|
1115
|
-
if (
|
|
1251
|
+
if (isGoStringValue(collection)) {
|
|
1116
1252
|
return indexString(collection, index) // Use the existing indexString for byte access
|
|
1117
1253
|
} else if (collection instanceof Uint8Array) {
|
|
1118
1254
|
if (index < 0 || index >= collection.length) {
|
|
@@ -1164,6 +1300,8 @@ export function indexRef<T>(
|
|
|
1164
1300
|
},
|
|
1165
1301
|
__isVarRef: true,
|
|
1166
1302
|
__goAddress: () => indexAddress(collection, index),
|
|
1303
|
+
__goCollection: collection,
|
|
1304
|
+
__goIndex: index,
|
|
1167
1305
|
}
|
|
1168
1306
|
}
|
|
1169
1307
|
if (isComplexSlice(collection)) {
|
|
@@ -1182,6 +1320,8 @@ export function indexRef<T>(
|
|
|
1182
1320
|
},
|
|
1183
1321
|
__isVarRef: true,
|
|
1184
1322
|
__goAddress: () => indexAddress(collection, index),
|
|
1323
|
+
__goCollection: collection,
|
|
1324
|
+
__goIndex: index,
|
|
1185
1325
|
}
|
|
1186
1326
|
}
|
|
1187
1327
|
if (Array.isArray(collection)) {
|
|
@@ -1199,11 +1339,41 @@ export function indexRef<T>(
|
|
|
1199
1339
|
},
|
|
1200
1340
|
__isVarRef: true,
|
|
1201
1341
|
__goAddress: () => indexAddress(collection, index),
|
|
1342
|
+
__goCollection: collection,
|
|
1343
|
+
__goIndex: index,
|
|
1202
1344
|
}
|
|
1203
1345
|
}
|
|
1204
1346
|
throw new Error('runtime error: index on unsupported type')
|
|
1205
1347
|
}
|
|
1206
1348
|
|
|
1349
|
+
/**
|
|
1350
|
+
* arrayPointerFromIndexRef turns &slice[i] into a pointer to an N-element array
|
|
1351
|
+
* view. This models unsafe conversions such as (*[64]byte)(unsafe.Pointer(&b[0]))
|
|
1352
|
+
* for packages that immediately slice or index the resulting array pointer.
|
|
1353
|
+
*/
|
|
1354
|
+
export function arrayPointerFromIndexRef<T>(
|
|
1355
|
+
ref: VarRef<T>,
|
|
1356
|
+
length: number,
|
|
1357
|
+
): VarRef<Slice<T> | T[] | Uint8Array> {
|
|
1358
|
+
const collection = ref.__goCollection as
|
|
1359
|
+
| Slice<T>
|
|
1360
|
+
| T[]
|
|
1361
|
+
| Uint8Array
|
|
1362
|
+
| undefined
|
|
1363
|
+
if (collection === undefined) {
|
|
1364
|
+
throw new Error(
|
|
1365
|
+
'unsafe array pointer requires an indexed collection reference',
|
|
1366
|
+
)
|
|
1367
|
+
}
|
|
1368
|
+
const index = ref.__goIndex ?? 0
|
|
1369
|
+
return varRef(
|
|
1370
|
+
goSlice(collection as any, index, index + length) as
|
|
1371
|
+
| Slice<T>
|
|
1372
|
+
| T[]
|
|
1373
|
+
| Uint8Array,
|
|
1374
|
+
)
|
|
1375
|
+
}
|
|
1376
|
+
|
|
1207
1377
|
/**
|
|
1208
1378
|
* indexAddress returns a stable synthetic address for an addressable slice or
|
|
1209
1379
|
* array element.
|
|
@@ -1316,10 +1486,10 @@ export const byte = (n: number): number => {
|
|
|
1316
1486
|
* @throws Error if index is out of bounds.
|
|
1317
1487
|
*/
|
|
1318
1488
|
export const indexString = (
|
|
1319
|
-
str:
|
|
1489
|
+
str: GoStringValue | import('./builtin.js').Bytes,
|
|
1320
1490
|
index: number,
|
|
1321
1491
|
): number => {
|
|
1322
|
-
if (
|
|
1492
|
+
if (!isGoStringValue(str)) {
|
|
1323
1493
|
// Bytes - access directly
|
|
1324
1494
|
if (str instanceof Uint8Array) {
|
|
1325
1495
|
if (index < 0 || index >= str.length) {
|
|
@@ -1342,7 +1512,7 @@ export const indexString = (
|
|
|
1342
1512
|
}
|
|
1343
1513
|
return str[index]
|
|
1344
1514
|
}
|
|
1345
|
-
const bytes =
|
|
1515
|
+
const bytes = goStringBytes(str)
|
|
1346
1516
|
if (index < 0 || index >= bytes.length) {
|
|
1347
1517
|
throw new Error(
|
|
1348
1518
|
`runtime error: index out of range [${index}] with length ${bytes.length}`,
|
|
@@ -1357,8 +1527,8 @@ export const indexString = (
|
|
|
1357
1527
|
* @param str The string.
|
|
1358
1528
|
* @returns The number of bytes in the UTF-8 representation of the string.
|
|
1359
1529
|
*/
|
|
1360
|
-
export const stringLen = (str:
|
|
1361
|
-
return
|
|
1530
|
+
export const stringLen = (str: GoStringValue): number => {
|
|
1531
|
+
return goStringBytes(str).length
|
|
1362
1532
|
}
|
|
1363
1533
|
|
|
1364
1534
|
/**
|
|
@@ -1371,11 +1541,11 @@ export const stringLen = (str: string): number => {
|
|
|
1371
1541
|
* @throws Error if the slice would create invalid UTF-8.
|
|
1372
1542
|
*/
|
|
1373
1543
|
export const sliceString = (
|
|
1374
|
-
str:
|
|
1544
|
+
str: GoStringValue,
|
|
1375
1545
|
low?: number,
|
|
1376
1546
|
high?: number,
|
|
1377
1547
|
): string => {
|
|
1378
|
-
const bytes =
|
|
1548
|
+
const bytes = goStringBytes(str)
|
|
1379
1549
|
const actualLow = low === undefined ? 0 : low
|
|
1380
1550
|
const actualHigh = high === undefined ? bytes.length : high
|
|
1381
1551
|
|
|
@@ -1397,21 +1567,7 @@ export const sliceString = (
|
|
|
1397
1567
|
)
|
|
1398
1568
|
}
|
|
1399
1569
|
|
|
1400
|
-
|
|
1401
|
-
|
|
1402
|
-
try {
|
|
1403
|
-
// Attempt to decode with strict UTF-8 validation
|
|
1404
|
-
const result = new TextDecoder('utf-8', { fatal: true }).decode(slicedBytes)
|
|
1405
|
-
return result
|
|
1406
|
-
} catch (e: unknown) {
|
|
1407
|
-
// If we get here, the slice would create invalid UTF-8
|
|
1408
|
-
// This is a fundamental limitation of JavaScript string handling
|
|
1409
|
-
throw new Error(
|
|
1410
|
-
`Cannot slice string at byte indices [${actualLow}:${actualHigh}] because it would create invalid UTF-8. ` +
|
|
1411
|
-
`This is a limitation of JavaScript's string handling.`,
|
|
1412
|
-
{ cause: e },
|
|
1413
|
-
)
|
|
1414
|
-
}
|
|
1570
|
+
return goStringFromBytes(bytes.subarray(actualLow, actualHigh))
|
|
1415
1571
|
}
|
|
1416
1572
|
|
|
1417
1573
|
/**
|
|
@@ -1425,7 +1581,7 @@ export const bytesToString = (
|
|
|
1425
1581
|
if (bytes === null) return ''
|
|
1426
1582
|
// If it's already a string, just return it
|
|
1427
1583
|
if (typeof bytes === 'string') return bytes
|
|
1428
|
-
if (bytes instanceof Uint8Array) return
|
|
1584
|
+
if (bytes instanceof Uint8Array) return goStringFromBytes(bytes)
|
|
1429
1585
|
// Ensure we get a plain number[] for Uint8Array.from
|
|
1430
1586
|
let byteArray: number[]
|
|
1431
1587
|
if (isComplexSlice(bytes)) {
|
|
@@ -1438,15 +1594,105 @@ export const bytesToString = (
|
|
|
1438
1594
|
// For simple T[] slices
|
|
1439
1595
|
byteArray = bytes
|
|
1440
1596
|
}
|
|
1441
|
-
return
|
|
1597
|
+
return goStringFromBytes(Uint8Array.from(byteArray)) as string
|
|
1442
1598
|
}
|
|
1443
1599
|
|
|
1444
|
-
function
|
|
1445
|
-
|
|
1446
|
-
|
|
1447
|
-
|
|
1448
|
-
|
|
1600
|
+
export function stringEqual(
|
|
1601
|
+
left: GoStringBytes,
|
|
1602
|
+
right: GoStringBytes,
|
|
1603
|
+
): boolean {
|
|
1604
|
+
const leftBytes = goStringComparableBytes(left)
|
|
1605
|
+
const rightBytes = goStringComparableBytes(right)
|
|
1606
|
+
if (leftBytes.length !== rightBytes.length) {
|
|
1607
|
+
return false
|
|
1608
|
+
}
|
|
1609
|
+
for (let i = 0; i < leftBytes.length; i++) {
|
|
1610
|
+
if (leftBytes[i] !== rightBytes[i]) {
|
|
1611
|
+
return false
|
|
1612
|
+
}
|
|
1613
|
+
}
|
|
1614
|
+
return true
|
|
1615
|
+
}
|
|
1616
|
+
|
|
1617
|
+
export function stringCompare(
|
|
1618
|
+
left: GoStringBytes,
|
|
1619
|
+
right: GoStringBytes,
|
|
1620
|
+
): number {
|
|
1621
|
+
if (!isGoStringValue(left) && !isGoStringValue(right)) {
|
|
1622
|
+
const leftBytes = byteStringView(left)
|
|
1623
|
+
const rightBytes = byteStringView(right)
|
|
1624
|
+
const leftLen = leftBytes.length
|
|
1625
|
+
const rightLen = rightBytes.length
|
|
1626
|
+
const sharedLen = Math.min(leftLen, rightLen)
|
|
1627
|
+
for (let i = 0; i < sharedLen; i++) {
|
|
1628
|
+
const diff =
|
|
1629
|
+
(leftBytes.backing[leftBytes.offset + i] ?? 0) -
|
|
1630
|
+
(rightBytes.backing[rightBytes.offset + i] ?? 0)
|
|
1631
|
+
if (diff !== 0) {
|
|
1632
|
+
return diff
|
|
1633
|
+
}
|
|
1634
|
+
}
|
|
1635
|
+
return leftLen - rightLen
|
|
1636
|
+
}
|
|
1637
|
+
|
|
1638
|
+
const leftBytes = goStringComparableBytes(left)
|
|
1639
|
+
const rightBytes = goStringComparableBytes(right)
|
|
1640
|
+
const sharedLen = Math.min(leftBytes.length, rightBytes.length)
|
|
1641
|
+
for (let i = 0; i < sharedLen; i++) {
|
|
1642
|
+
const diff = leftBytes[i] - rightBytes[i]
|
|
1643
|
+
if (diff !== 0) {
|
|
1644
|
+
return diff
|
|
1645
|
+
}
|
|
1449
1646
|
}
|
|
1647
|
+
return leftBytes.length - rightBytes.length
|
|
1648
|
+
}
|
|
1649
|
+
|
|
1650
|
+
type ByteStringView = {
|
|
1651
|
+
backing: ArrayLike<number>
|
|
1652
|
+
offset: number
|
|
1653
|
+
length: number
|
|
1654
|
+
}
|
|
1655
|
+
|
|
1656
|
+
function byteStringView(value: GoStringBytes): ByteStringView {
|
|
1657
|
+
value = collectionValue(value) as GoStringBytes
|
|
1658
|
+
if (value === null || value === undefined) {
|
|
1659
|
+
return { backing: [], offset: 0, length: 0 }
|
|
1660
|
+
}
|
|
1661
|
+
if (value instanceof Uint8Array) {
|
|
1662
|
+
return { backing: value, offset: 0, length: value.length }
|
|
1663
|
+
}
|
|
1664
|
+
if (Array.isArray(value)) {
|
|
1665
|
+
const meta = (value as unknown as SliceProxy<number>).__meta__
|
|
1666
|
+
if (meta !== undefined) {
|
|
1667
|
+
return {
|
|
1668
|
+
backing: meta.backing,
|
|
1669
|
+
offset: meta.offset,
|
|
1670
|
+
length: meta.length,
|
|
1671
|
+
}
|
|
1672
|
+
}
|
|
1673
|
+
return { backing: value, offset: 0, length: value.length }
|
|
1674
|
+
}
|
|
1675
|
+
const meta = (value as unknown as SliceProxy<number>).__meta__
|
|
1676
|
+
return {
|
|
1677
|
+
backing: meta.backing,
|
|
1678
|
+
offset: meta.offset,
|
|
1679
|
+
length: meta.length,
|
|
1680
|
+
}
|
|
1681
|
+
}
|
|
1682
|
+
|
|
1683
|
+
function collectionValue(value: unknown): unknown {
|
|
1684
|
+
if (isVarRef(value)) {
|
|
1685
|
+
return collectionValue(value.value)
|
|
1686
|
+
}
|
|
1687
|
+
if (
|
|
1688
|
+
typeof value === 'object' &&
|
|
1689
|
+
value !== null &&
|
|
1690
|
+
typeof (value as { __goType?: unknown }).__goType === 'string' &&
|
|
1691
|
+
'__goValue' in value
|
|
1692
|
+
) {
|
|
1693
|
+
return collectionValue((value as { __goValue: unknown }).__goValue)
|
|
1694
|
+
}
|
|
1695
|
+
return value
|
|
1450
1696
|
}
|
|
1451
1697
|
|
|
1452
1698
|
function bytesToBinaryString(bytes: Uint8Array): string {
|
|
@@ -1464,10 +1710,10 @@ function bytesToBinaryString(bytes: Uint8Array): string {
|
|
|
1464
1710
|
* @returns A Uint8Array representing the UTF-8 bytes of the string.
|
|
1465
1711
|
*/
|
|
1466
1712
|
export function stringToBytes(
|
|
1467
|
-
s:
|
|
1713
|
+
s: GoStringValue | import('./builtin.js').Bytes,
|
|
1468
1714
|
): Uint8Array {
|
|
1469
|
-
if (
|
|
1470
|
-
return
|
|
1715
|
+
if (isGoStringValue(s)) {
|
|
1716
|
+
return goStringBytes(s)
|
|
1471
1717
|
}
|
|
1472
1718
|
// Already bytes - normalize to Uint8Array
|
|
1473
1719
|
if (s instanceof Uint8Array) {
|
|
@@ -1480,6 +1726,71 @@ export function stringToBytes(
|
|
|
1480
1726
|
return new Uint8Array(Array.isArray(s) ? s : [])
|
|
1481
1727
|
}
|
|
1482
1728
|
|
|
1729
|
+
type StringHeaderData = {
|
|
1730
|
+
kind: 'string'
|
|
1731
|
+
value: string
|
|
1732
|
+
}
|
|
1733
|
+
|
|
1734
|
+
export function stringHeaderRef(s: VarRef<string>): VarRef<{
|
|
1735
|
+
Data: StringHeaderData
|
|
1736
|
+
Len: number
|
|
1737
|
+
}> {
|
|
1738
|
+
return varRef({
|
|
1739
|
+
get Data(): StringHeaderData {
|
|
1740
|
+
return { kind: 'string', value: s.value }
|
|
1741
|
+
},
|
|
1742
|
+
set Data(_value: StringHeaderData) {},
|
|
1743
|
+
get Len(): number {
|
|
1744
|
+
return stringToBytes(s.value).length
|
|
1745
|
+
},
|
|
1746
|
+
set Len(_value: number) {},
|
|
1747
|
+
})
|
|
1748
|
+
}
|
|
1749
|
+
|
|
1750
|
+
export function sliceHeaderRef(b: VarRef<Slice<number>>): VarRef<{
|
|
1751
|
+
Data: StringHeaderData | null
|
|
1752
|
+
Len: number
|
|
1753
|
+
Cap: number
|
|
1754
|
+
}> {
|
|
1755
|
+
let data: StringHeaderData | null = null
|
|
1756
|
+
let length = 0
|
|
1757
|
+
let capacity = 0
|
|
1758
|
+
const refresh = () => {
|
|
1759
|
+
if (data === null) {
|
|
1760
|
+
return
|
|
1761
|
+
}
|
|
1762
|
+
const bytes = stringToBytes(data.value)
|
|
1763
|
+
const out = makeSlice<number>(length, Math.max(capacity, length), 'byte')
|
|
1764
|
+
if (out !== null) {
|
|
1765
|
+
copy(out, goSlice(bytes, 0, Math.min(length, bytes.length)))
|
|
1766
|
+
}
|
|
1767
|
+
b.value = out
|
|
1768
|
+
}
|
|
1769
|
+
return varRef({
|
|
1770
|
+
get Data(): StringHeaderData | null {
|
|
1771
|
+
return data
|
|
1772
|
+
},
|
|
1773
|
+
set Data(value: StringHeaderData | null) {
|
|
1774
|
+
data = value
|
|
1775
|
+
refresh()
|
|
1776
|
+
},
|
|
1777
|
+
get Len(): number {
|
|
1778
|
+
return length
|
|
1779
|
+
},
|
|
1780
|
+
set Len(value: number) {
|
|
1781
|
+
length = value
|
|
1782
|
+
refresh()
|
|
1783
|
+
},
|
|
1784
|
+
get Cap(): number {
|
|
1785
|
+
return capacity
|
|
1786
|
+
},
|
|
1787
|
+
set Cap(value: number) {
|
|
1788
|
+
capacity = value
|
|
1789
|
+
refresh()
|
|
1790
|
+
},
|
|
1791
|
+
})
|
|
1792
|
+
}
|
|
1793
|
+
|
|
1483
1794
|
/**
|
|
1484
1795
|
* Handles string() conversion for values that could be either string or []byte.
|
|
1485
1796
|
* Used for generic type parameters with constraint []byte|string.
|
|
@@ -1492,8 +1803,8 @@ export function genericBytesOrStringToString(
|
|
|
1492
1803
|
if (value === null || value === undefined) {
|
|
1493
1804
|
return ''
|
|
1494
1805
|
}
|
|
1495
|
-
if (
|
|
1496
|
-
return value
|
|
1806
|
+
if (isGoStringValue(value)) {
|
|
1807
|
+
return value as string
|
|
1497
1808
|
}
|
|
1498
1809
|
return bytesToString(value)
|
|
1499
1810
|
}
|
|
@@ -1507,10 +1818,10 @@ export function genericBytesOrStringToString(
|
|
|
1507
1818
|
* @returns The byte value at the specified index
|
|
1508
1819
|
*/
|
|
1509
1820
|
export function indexStringOrBytes(
|
|
1510
|
-
value:
|
|
1821
|
+
value: GoStringValue | import('./builtin.js').Bytes,
|
|
1511
1822
|
index: number,
|
|
1512
1823
|
): number {
|
|
1513
|
-
if (
|
|
1824
|
+
if (isGoStringValue(value)) {
|
|
1514
1825
|
return indexString(value, index)
|
|
1515
1826
|
} else if (value instanceof Uint8Array) {
|
|
1516
1827
|
// For Uint8Array, direct access returns the byte value
|
|
@@ -1546,9 +1857,9 @@ export function indexStringOrBytes(
|
|
|
1546
1857
|
* @returns The sliced value of the same type as input
|
|
1547
1858
|
*/
|
|
1548
1859
|
export function sliceStringOrBytes<
|
|
1549
|
-
T extends
|
|
1860
|
+
T extends GoStringValue | import('./builtin.js').Bytes,
|
|
1550
1861
|
>(value: T, low?: number, high?: number, max?: number): T {
|
|
1551
|
-
if (
|
|
1862
|
+
if (isGoStringValue(value)) {
|
|
1552
1863
|
// For strings, use sliceString and ignore max parameter
|
|
1553
1864
|
return sliceString(value, low, high) as T
|
|
1554
1865
|
} else {
|