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
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { describe, expect, it } from 'vitest'
|
|
2
|
+
import * as $ from '@goscript/builtin/index.js'
|
|
3
|
+
|
|
4
|
+
import { Slice, SliceIsSorted, SliceStable } from './slice.gs.js'
|
|
5
|
+
|
|
6
|
+
describe('sort.Slice override', () => {
|
|
7
|
+
it('sorts slices with logarithmic comparator growth', async () => {
|
|
8
|
+
const values = $.arrayToSlice<number>(
|
|
9
|
+
Array.from({ length: 128 }, (_, i) => 128 - i),
|
|
10
|
+
)
|
|
11
|
+
let calls = 0
|
|
12
|
+
|
|
13
|
+
await Slice(values, (i, j) => {
|
|
14
|
+
calls++
|
|
15
|
+
return values![i] < values![j]
|
|
16
|
+
})
|
|
17
|
+
|
|
18
|
+
expect(values).toEqual(Array.from({ length: 128 }, (_, i) => i + 1))
|
|
19
|
+
expect(calls).toBeLessThan(1200)
|
|
20
|
+
})
|
|
21
|
+
|
|
22
|
+
it('keeps equal values stable for SliceStable', async () => {
|
|
23
|
+
const values = $.arrayToSlice([
|
|
24
|
+
{ group: 1, name: 'a' },
|
|
25
|
+
{ group: 0, name: 'b' },
|
|
26
|
+
{ group: 1, name: 'c' },
|
|
27
|
+
{ group: 0, name: 'd' },
|
|
28
|
+
])
|
|
29
|
+
|
|
30
|
+
await SliceStable(values, (i, j) => values![i].group < values![j].group)
|
|
31
|
+
|
|
32
|
+
expect(values?.map((value) => value.name)).toEqual(['b', 'd', 'a', 'c'])
|
|
33
|
+
expect(
|
|
34
|
+
await SliceIsSorted(
|
|
35
|
+
values,
|
|
36
|
+
(i, j) => values![i].group < values![j].group,
|
|
37
|
+
),
|
|
38
|
+
).toBe(true)
|
|
39
|
+
})
|
|
40
|
+
})
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { describe, it, expect } from 'vitest'
|
|
2
2
|
import { Builder } from './builder.js'
|
|
3
|
+
import { varRef } from '../builtin/varRef.js'
|
|
3
4
|
|
|
4
5
|
describe('strings/Builder', () => {
|
|
5
6
|
describe('Builder', () => {
|
|
@@ -89,6 +90,13 @@ describe('strings/Builder', () => {
|
|
|
89
90
|
expect(b.Len()).toBe(11)
|
|
90
91
|
})
|
|
91
92
|
|
|
93
|
+
it('should accept VarRef pointer receivers', () => {
|
|
94
|
+
const b = varRef(new Builder())
|
|
95
|
+
Builder.prototype.WriteString.call(b, 'hello')
|
|
96
|
+
expect(Builder.prototype.Len.call(b)).toBe(5)
|
|
97
|
+
expect(Builder.prototype.String.call(b)).toBe('hello')
|
|
98
|
+
})
|
|
99
|
+
|
|
92
100
|
it('should handle empty writes', () => {
|
|
93
101
|
const b = new Builder()
|
|
94
102
|
const [n, err] = b.WriteString('')
|
package/gs/strings/builder.ts
CHANGED
|
@@ -1,5 +1,11 @@
|
|
|
1
1
|
import * as $ from '@goscript/builtin/index.js'
|
|
2
2
|
|
|
3
|
+
function builderValue(
|
|
4
|
+
builder: Builder | $.VarRef<Builder> | null | undefined,
|
|
5
|
+
): Builder {
|
|
6
|
+
return $.pointerValue<Builder>(builder)
|
|
7
|
+
}
|
|
8
|
+
|
|
3
9
|
export class Builder {
|
|
4
10
|
private _content: string = ''
|
|
5
11
|
private _addr: Builder | null = null
|
|
@@ -16,21 +22,22 @@ export class Builder {
|
|
|
16
22
|
}
|
|
17
23
|
|
|
18
24
|
private copyCheck(): void {
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
25
|
+
const builder = builderValue(this)
|
|
26
|
+
if (builder._addr == null) {
|
|
27
|
+
builder._addr = builder
|
|
28
|
+
} else if (builder._addr !== builder) {
|
|
22
29
|
$.panic('strings: illegal use of non-zero Builder copied by value')
|
|
23
30
|
}
|
|
24
31
|
}
|
|
25
32
|
|
|
26
33
|
// String returns the accumulated string.
|
|
27
34
|
public String(): string {
|
|
28
|
-
return this._content
|
|
35
|
+
return builderValue(this)._content
|
|
29
36
|
}
|
|
30
37
|
|
|
31
38
|
// Len returns the number of accumulated bytes; b.Len() == len(b.String()).
|
|
32
39
|
public Len(): number {
|
|
33
|
-
return this._content.length
|
|
40
|
+
return builderValue(this)._content.length
|
|
34
41
|
}
|
|
35
42
|
|
|
36
43
|
// Cap returns the capacity of the builder's underlying byte slice. It is the
|
|
@@ -38,20 +45,21 @@ export class Builder {
|
|
|
38
45
|
// already written.
|
|
39
46
|
public Cap(): number {
|
|
40
47
|
// For simplicity, return the current length since JavaScript strings are dynamic
|
|
41
|
-
return this._content.length
|
|
48
|
+
return builderValue(this)._content.length
|
|
42
49
|
}
|
|
43
50
|
|
|
44
51
|
// Reset resets the Builder to be empty.
|
|
45
52
|
public Reset(): void {
|
|
46
|
-
|
|
47
|
-
|
|
53
|
+
const builder = builderValue(this)
|
|
54
|
+
builder._addr = null
|
|
55
|
+
builder._content = ''
|
|
48
56
|
}
|
|
49
57
|
|
|
50
58
|
// Grow grows b's capacity, if necessary, to guarantee space for
|
|
51
59
|
// another n bytes. After Grow(n), at least n bytes can be written to b
|
|
52
60
|
// without another allocation. If n is negative, Grow panics.
|
|
53
61
|
public Grow(n: number): void {
|
|
54
|
-
this.copyCheck()
|
|
62
|
+
builderValue(this).copyCheck()
|
|
55
63
|
if (n < 0) {
|
|
56
64
|
$.panic('strings.Builder.Grow: negative count')
|
|
57
65
|
}
|
|
@@ -61,28 +69,31 @@ export class Builder {
|
|
|
61
69
|
// Write appends the contents of p to b's buffer.
|
|
62
70
|
// Write always returns len(p), nil.
|
|
63
71
|
public Write(p: $.Bytes): [number, $.GoError] {
|
|
64
|
-
this.copyCheck()
|
|
72
|
+
builderValue(this).copyCheck()
|
|
73
|
+
const builder = builderValue(this)
|
|
65
74
|
// Convert byte array to string
|
|
66
75
|
const bytes = $.bytesToUint8Array(p)
|
|
67
76
|
const str = new TextDecoder('utf-8').decode(bytes)
|
|
68
|
-
|
|
77
|
+
builder._content += str
|
|
69
78
|
return [$.len(p), null]
|
|
70
79
|
}
|
|
71
80
|
|
|
72
81
|
// WriteByte appends the byte c to b's buffer.
|
|
73
82
|
// The returned error is always nil.
|
|
74
83
|
public WriteByte(c: number): $.GoError {
|
|
75
|
-
this.copyCheck()
|
|
76
|
-
|
|
84
|
+
builderValue(this).copyCheck()
|
|
85
|
+
const builder = builderValue(this)
|
|
86
|
+
builder._content += String.fromCharCode(c)
|
|
77
87
|
return null
|
|
78
88
|
}
|
|
79
89
|
|
|
80
90
|
// WriteRune appends the UTF-8 encoding of Unicode code point r to b's buffer.
|
|
81
91
|
// It returns the length of r and a nil error.
|
|
82
92
|
public WriteRune(r: number): [number, $.GoError] {
|
|
83
|
-
this.copyCheck()
|
|
93
|
+
builderValue(this).copyCheck()
|
|
94
|
+
const builder = builderValue(this)
|
|
84
95
|
const str = String.fromCodePoint(r)
|
|
85
|
-
|
|
96
|
+
builder._content += str
|
|
86
97
|
// Return the byte length of the UTF-8 encoding
|
|
87
98
|
const byteLength = new TextEncoder().encode(str).length
|
|
88
99
|
return [byteLength, null]
|
|
@@ -91,8 +102,9 @@ export class Builder {
|
|
|
91
102
|
// WriteString appends the contents of s to b's buffer.
|
|
92
103
|
// It returns the length of s and a nil error.
|
|
93
104
|
public WriteString(s: string): [number, $.GoError] {
|
|
94
|
-
this.copyCheck()
|
|
95
|
-
|
|
105
|
+
builderValue(this).copyCheck()
|
|
106
|
+
const builder = builderValue(this)
|
|
107
|
+
builder._content += s
|
|
96
108
|
return [s.length, null]
|
|
97
109
|
}
|
|
98
110
|
|
package/gs/strings/iter.test.ts
CHANGED
|
@@ -124,13 +124,11 @@ describe('strings/iter', () => {
|
|
|
124
124
|
it('should handle unicode', () => {
|
|
125
125
|
const parts: string[] = []
|
|
126
126
|
const seq = SplitSeq('世界,你好', ',')
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
})
|
|
133
|
-
}).toThrow('Cannot slice string at byte indices')
|
|
127
|
+
seq((part: string) => {
|
|
128
|
+
parts.push(part)
|
|
129
|
+
return true
|
|
130
|
+
})
|
|
131
|
+
expect(parts).toEqual(['世界', '你好'])
|
|
134
132
|
})
|
|
135
133
|
})
|
|
136
134
|
|
package/gs/strings/iter.ts
CHANGED
|
@@ -23,38 +23,64 @@ const asciiSpace: { [key: number]: boolean } = {
|
|
|
23
23
|
// If s does not end in a newline, the final yielded line will not end in a newline.
|
|
24
24
|
// It returns a single-use iterator.
|
|
25
25
|
export function Lines(s: string): iter.Seq<string> {
|
|
26
|
-
return (
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
26
|
+
return (
|
|
27
|
+
_yield: ((p0: string) => iter.YieldResult) | null,
|
|
28
|
+
): void | globalThis.Promise<void> => {
|
|
29
|
+
const walk = (): void | globalThis.Promise<void> => {
|
|
30
|
+
for (; $.len(s) > 0; ) {
|
|
31
|
+
let line: string
|
|
32
|
+
{
|
|
33
|
+
let i = IndexByte(s, 10)
|
|
34
|
+
if (i >= 0) {
|
|
35
|
+
;[line, s] = [
|
|
36
|
+
$.sliceString(s, undefined, i + 1),
|
|
37
|
+
$.sliceString(s, i + 1, undefined),
|
|
38
|
+
]
|
|
39
|
+
} else {
|
|
40
|
+
;[line, s] = [s, '']
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
const keepGoing = _yield!(line)
|
|
44
|
+
if (keepGoing instanceof Promise) {
|
|
45
|
+
return keepGoing.then((next) => {
|
|
46
|
+
if (next) {
|
|
47
|
+
return walk()
|
|
48
|
+
}
|
|
49
|
+
})
|
|
50
|
+
}
|
|
51
|
+
if (!keepGoing) {
|
|
52
|
+
return
|
|
38
53
|
}
|
|
39
|
-
}
|
|
40
|
-
if (!_yield!(line)) {
|
|
41
|
-
return
|
|
42
54
|
}
|
|
43
55
|
}
|
|
44
|
-
return
|
|
56
|
+
return walk()
|
|
45
57
|
}
|
|
46
58
|
}
|
|
47
59
|
|
|
48
60
|
// explodeSeq returns an iterator over the runes in s.
|
|
49
61
|
export function explodeSeq(s: string): iter.Seq<string> {
|
|
50
|
-
return (
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
62
|
+
return (
|
|
63
|
+
_yield: ((p0: string) => iter.YieldResult) | null,
|
|
64
|
+
): void | globalThis.Promise<void> => {
|
|
65
|
+
const walk = (): void | globalThis.Promise<void> => {
|
|
66
|
+
for (; $.len(s) > 0; ) {
|
|
67
|
+
let [, size] = utf8.DecodeRuneInString(s)
|
|
68
|
+
const keepGoing = _yield!($.sliceString(s, undefined, size))
|
|
69
|
+
if (keepGoing instanceof Promise) {
|
|
70
|
+
return keepGoing.then((next) => {
|
|
71
|
+
if (next) {
|
|
72
|
+
s = $.sliceString(s, size, undefined)
|
|
73
|
+
return walk()
|
|
74
|
+
}
|
|
75
|
+
})
|
|
76
|
+
}
|
|
77
|
+
if (!keepGoing) {
|
|
78
|
+
return
|
|
79
|
+
}
|
|
80
|
+
s = $.sliceString(s, size, undefined)
|
|
55
81
|
}
|
|
56
|
-
s = $.sliceString(s, size, undefined)
|
|
57
82
|
}
|
|
83
|
+
return walk()
|
|
58
84
|
}
|
|
59
85
|
}
|
|
60
86
|
|
|
@@ -68,19 +94,36 @@ export function splitSeq(
|
|
|
68
94
|
if ($.len(sep) == 0) {
|
|
69
95
|
return explodeSeq(s)
|
|
70
96
|
}
|
|
71
|
-
return (
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
97
|
+
return (
|
|
98
|
+
_yield: ((p0: string) => iter.YieldResult) | null,
|
|
99
|
+
): void | globalThis.Promise<void> => {
|
|
100
|
+
const walk = (): void | globalThis.Promise<void> => {
|
|
101
|
+
for (;;) {
|
|
102
|
+
let i = Index(s, sep)
|
|
103
|
+
if (i < 0) {
|
|
104
|
+
const keepGoing = _yield!(s)
|
|
105
|
+
if (keepGoing instanceof Promise) {
|
|
106
|
+
return keepGoing.then(() => {})
|
|
107
|
+
}
|
|
108
|
+
return
|
|
109
|
+
}
|
|
110
|
+
let frag = $.sliceString(s, undefined, i + sepSave)
|
|
111
|
+
const keepGoing = _yield!(frag)
|
|
112
|
+
if (keepGoing instanceof Promise) {
|
|
113
|
+
return keepGoing.then((next) => {
|
|
114
|
+
if (next) {
|
|
115
|
+
s = $.sliceString(s, i + $.len(sep), undefined)
|
|
116
|
+
return walk()
|
|
117
|
+
}
|
|
118
|
+
})
|
|
119
|
+
}
|
|
120
|
+
if (!keepGoing) {
|
|
121
|
+
return
|
|
122
|
+
}
|
|
123
|
+
s = $.sliceString(s, i + $.len(sep), undefined)
|
|
80
124
|
}
|
|
81
|
-
s = $.sliceString(s, i + $.len(sep), undefined)
|
|
82
125
|
}
|
|
83
|
-
|
|
126
|
+
return walk()
|
|
84
127
|
}
|
|
85
128
|
}
|
|
86
129
|
|
|
@@ -105,31 +148,47 @@ export function SplitAfterSeq(s: string, sep: string): iter.Seq<string> {
|
|
|
105
148
|
// The iterator yields the same strings that would be returned by [Fields](s),
|
|
106
149
|
// but without constructing the slice.
|
|
107
150
|
export function FieldsSeq(s: string): iter.Seq<string> {
|
|
108
|
-
return (
|
|
151
|
+
return (
|
|
152
|
+
_yield: ((p0: string) => iter.YieldResult) | null,
|
|
153
|
+
): void | globalThis.Promise<void> => {
|
|
109
154
|
let start = -1
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
if (
|
|
120
|
-
if (
|
|
121
|
-
|
|
155
|
+
const walk = (i: number): void | globalThis.Promise<void> => {
|
|
156
|
+
for (; i < $.len(s); ) {
|
|
157
|
+
let size = 1
|
|
158
|
+
let r = $.indexString(s, i) as number
|
|
159
|
+
let isSpace = asciiSpace[$.indexString(s, i)] === true
|
|
160
|
+
if (r >= utf8.RuneSelf) {
|
|
161
|
+
;[r, size] = utf8.DecodeRuneInString($.sliceString(s, i, undefined))
|
|
162
|
+
isSpace = unicode.IsSpace(r)
|
|
163
|
+
}
|
|
164
|
+
if (isSpace) {
|
|
165
|
+
if (start >= 0) {
|
|
166
|
+
const keepGoing = _yield!($.sliceString(s, start, i))
|
|
167
|
+
start = -1
|
|
168
|
+
if (keepGoing instanceof Promise) {
|
|
169
|
+
return keepGoing.then((next) => {
|
|
170
|
+
if (next) {
|
|
171
|
+
return walk(i + size)
|
|
172
|
+
}
|
|
173
|
+
})
|
|
174
|
+
}
|
|
175
|
+
if (!keepGoing) {
|
|
176
|
+
return
|
|
177
|
+
}
|
|
122
178
|
}
|
|
123
|
-
|
|
179
|
+
} else if (start < 0) {
|
|
180
|
+
start = i
|
|
181
|
+
}
|
|
182
|
+
i += size
|
|
183
|
+
}
|
|
184
|
+
if (start >= 0) {
|
|
185
|
+
const keepGoing = _yield!($.sliceString(s, start, undefined))
|
|
186
|
+
if (keepGoing instanceof Promise) {
|
|
187
|
+
return keepGoing.then(() => {})
|
|
124
188
|
}
|
|
125
|
-
} else if (start < 0) {
|
|
126
|
-
start = i
|
|
127
189
|
}
|
|
128
|
-
i += size
|
|
129
|
-
}
|
|
130
|
-
if (start >= 0) {
|
|
131
|
-
_yield!($.sliceString(s, start, undefined))
|
|
132
190
|
}
|
|
191
|
+
return walk(0)
|
|
133
192
|
}
|
|
134
193
|
}
|
|
135
194
|
|
|
@@ -141,31 +200,47 @@ export function FieldsFuncSeq(
|
|
|
141
200
|
s: string,
|
|
142
201
|
f: ((p0: number) => boolean) | null,
|
|
143
202
|
): iter.Seq<string> {
|
|
144
|
-
return (
|
|
203
|
+
return (
|
|
204
|
+
_yield: ((p0: string) => iter.YieldResult) | null,
|
|
205
|
+
): void | globalThis.Promise<void> => {
|
|
145
206
|
if (f === null) {
|
|
146
207
|
return
|
|
147
208
|
}
|
|
148
209
|
let start = -1
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
if (
|
|
157
|
-
if (
|
|
158
|
-
|
|
210
|
+
const walk = (i: number): void | globalThis.Promise<void> => {
|
|
211
|
+
for (; i < $.len(s); ) {
|
|
212
|
+
let size = 1
|
|
213
|
+
let r = $.indexString(s, i) as number
|
|
214
|
+
if (r >= utf8.RuneSelf) {
|
|
215
|
+
;[r, size] = utf8.DecodeRuneInString($.sliceString(s, i, undefined))
|
|
216
|
+
}
|
|
217
|
+
if (f(r)) {
|
|
218
|
+
if (start >= 0) {
|
|
219
|
+
const keepGoing = _yield!($.sliceString(s, start, i))
|
|
220
|
+
start = -1
|
|
221
|
+
if (keepGoing instanceof Promise) {
|
|
222
|
+
return keepGoing.then((next) => {
|
|
223
|
+
if (next) {
|
|
224
|
+
return walk(i + size)
|
|
225
|
+
}
|
|
226
|
+
})
|
|
227
|
+
}
|
|
228
|
+
if (!keepGoing) {
|
|
229
|
+
return
|
|
230
|
+
}
|
|
159
231
|
}
|
|
160
|
-
|
|
232
|
+
} else if (start < 0) {
|
|
233
|
+
start = i
|
|
234
|
+
}
|
|
235
|
+
i += size
|
|
236
|
+
}
|
|
237
|
+
if (start >= 0) {
|
|
238
|
+
const keepGoing = _yield!($.sliceString(s, start, undefined))
|
|
239
|
+
if (keepGoing instanceof Promise) {
|
|
240
|
+
return keepGoing.then(() => {})
|
|
161
241
|
}
|
|
162
|
-
} else if (start < 0) {
|
|
163
|
-
start = i
|
|
164
242
|
}
|
|
165
|
-
i += size
|
|
166
|
-
}
|
|
167
|
-
if (start >= 0) {
|
|
168
|
-
_yield!($.sliceString(s, start, undefined))
|
|
169
243
|
}
|
|
244
|
+
return walk(0)
|
|
170
245
|
}
|
|
171
246
|
}
|
|
@@ -124,10 +124,7 @@ describe('strings/Replacer', () => {
|
|
|
124
124
|
it('should handle unicode strings', () => {
|
|
125
125
|
const r = NewReplacer('世界', '世界!')
|
|
126
126
|
if (r) {
|
|
127
|
-
|
|
128
|
-
expect(() => r.Replace('Hello 世界')).toThrow(
|
|
129
|
-
'Cannot slice string at byte indices',
|
|
130
|
-
)
|
|
127
|
+
expect(r.Replace('Hello 世界')).toBe('Hello 世界!')
|
|
131
128
|
}
|
|
132
129
|
})
|
|
133
130
|
|
package/gs/strings/replace.ts
CHANGED
|
@@ -396,12 +396,12 @@ class trieNode {
|
|
|
396
396
|
// what is currently t.prefix[0] will lead to prefixNode, and
|
|
397
397
|
// looking up key[0] will lead to keyNode.
|
|
398
398
|
const prefixNode =
|
|
399
|
-
$.len(t!.prefix) == 1
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
399
|
+
$.len(t!.prefix) == 1 ?
|
|
400
|
+
t!.next
|
|
401
|
+
: new trieNode({
|
|
402
|
+
next: t!.next,
|
|
403
|
+
prefix: $.sliceString(t!.prefix, 1, undefined),
|
|
404
|
+
})
|
|
405
405
|
let keyNode = new trieNode()
|
|
406
406
|
t!.table = $.makeSlice<trieNode | null>(r!.tableSize)
|
|
407
407
|
t!.table![r!.mapping![$.indexString(t!.prefix, 0)]] = prefixNode
|
|
@@ -203,6 +203,7 @@ describe('strings', () => {
|
|
|
203
203
|
expect(Index('hello world', 'xyz')).toBe(-1)
|
|
204
204
|
expect(Index('hello', 'hello')).toBe(0)
|
|
205
205
|
expect(Index('', '')).toBe(0)
|
|
206
|
+
expect(Index('世界,你好', ',')).toBe(6)
|
|
206
207
|
})
|
|
207
208
|
})
|
|
208
209
|
|
|
@@ -219,6 +220,7 @@ describe('strings', () => {
|
|
|
219
220
|
expect(IndexByte('hello', 101)).toBe(1) // 'e'
|
|
220
221
|
expect(IndexByte('hello', 120)).toBe(-1) // 'x'
|
|
221
222
|
expect(IndexByte('', 97)).toBe(-1) // 'a'
|
|
223
|
+
expect(IndexByte('世界,你好', 44)).toBe(6)
|
|
222
224
|
})
|
|
223
225
|
})
|
|
224
226
|
|
|
@@ -257,6 +259,7 @@ describe('strings', () => {
|
|
|
257
259
|
expect(LastIndex('hello world hello', 'hello')).toBe(12)
|
|
258
260
|
expect(LastIndex('hello world', 'xyz')).toBe(-1)
|
|
259
261
|
expect(LastIndex('hello', 'hello')).toBe(0)
|
|
262
|
+
expect(LastIndex('世界,你好', '你好')).toBe(7)
|
|
260
263
|
})
|
|
261
264
|
})
|
|
262
265
|
|
|
@@ -273,6 +276,7 @@ describe('strings', () => {
|
|
|
273
276
|
expect(LastIndexByte('hello', 108)).toBe(3) // 'l'
|
|
274
277
|
expect(LastIndexByte('hello', 120)).toBe(-1) // 'x'
|
|
275
278
|
expect(LastIndexByte('', 97)).toBe(-1) // 'a'
|
|
279
|
+
expect(LastIndexByte('世界,你好', 44)).toBe(6)
|
|
276
280
|
})
|
|
277
281
|
})
|
|
278
282
|
|
package/gs/strings/strings.ts
CHANGED
|
@@ -56,18 +56,31 @@ export function ContainsFunc(
|
|
|
56
56
|
|
|
57
57
|
// Index returns the index of the first instance of substr in s, or -1 if substr is not present in s.
|
|
58
58
|
export function Index(s: string, substr: string): number {
|
|
59
|
-
|
|
59
|
+
if (substr === '') {
|
|
60
|
+
return 0
|
|
61
|
+
}
|
|
62
|
+
return indexBytes($.stringToBytes(s), $.stringToBytes(substr))
|
|
60
63
|
}
|
|
61
64
|
|
|
62
65
|
// LastIndex returns the index of the last instance of substr in s, or -1 if substr is not present in s.
|
|
63
66
|
export function LastIndex(s: string, substr: string): number {
|
|
64
|
-
|
|
67
|
+
const haystack = $.stringToBytes(s)
|
|
68
|
+
const needle = $.stringToBytes(substr)
|
|
69
|
+
if (needle.length === 0) {
|
|
70
|
+
return haystack.length
|
|
71
|
+
}
|
|
72
|
+
return lastIndexBytes(haystack, needle)
|
|
65
73
|
}
|
|
66
74
|
|
|
67
75
|
// IndexByte returns the index of the first instance of c in s, or -1 if c is not present in s.
|
|
68
76
|
export function IndexByte(s: string, c: number): number {
|
|
69
|
-
const
|
|
70
|
-
|
|
77
|
+
const bytes = $.stringToBytes(s)
|
|
78
|
+
for (let i = 0; i < bytes.length; i++) {
|
|
79
|
+
if (bytes[i] === (c & 0xff)) {
|
|
80
|
+
return i
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
return -1
|
|
71
84
|
}
|
|
72
85
|
|
|
73
86
|
// IndexRune returns the index of the first instance of the Unicode code point r, or -1 if rune is not present in s.
|
|
@@ -98,8 +111,43 @@ export function LastIndexAny(s: string, chars: string): number {
|
|
|
98
111
|
|
|
99
112
|
// LastIndexByte returns the index of the last instance of c in s, or -1 if c is not present in s.
|
|
100
113
|
export function LastIndexByte(s: string, c: number): number {
|
|
101
|
-
const
|
|
102
|
-
|
|
114
|
+
const bytes = $.stringToBytes(s)
|
|
115
|
+
for (let i = bytes.length - 1; i >= 0; i--) {
|
|
116
|
+
if (bytes[i] === (c & 0xff)) {
|
|
117
|
+
return i
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
return -1
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
function indexBytes(haystack: Uint8Array, needle: Uint8Array): number {
|
|
124
|
+
if (needle.length === 0) {
|
|
125
|
+
return 0
|
|
126
|
+
}
|
|
127
|
+
outer: for (let i = 0; i <= haystack.length - needle.length; i++) {
|
|
128
|
+
for (let j = 0; j < needle.length; j++) {
|
|
129
|
+
if (haystack[i + j] !== needle[j]) {
|
|
130
|
+
continue outer
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
return i
|
|
134
|
+
}
|
|
135
|
+
return -1
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
function lastIndexBytes(haystack: Uint8Array, needle: Uint8Array): number {
|
|
139
|
+
if (needle.length === 0) {
|
|
140
|
+
return haystack.length
|
|
141
|
+
}
|
|
142
|
+
outer: for (let i = haystack.length - needle.length; i >= 0; i--) {
|
|
143
|
+
for (let j = 0; j < needle.length; j++) {
|
|
144
|
+
if (haystack[i + j] !== needle[j]) {
|
|
145
|
+
continue outer
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
return i
|
|
149
|
+
}
|
|
150
|
+
return -1
|
|
103
151
|
}
|
|
104
152
|
|
|
105
153
|
// IndexFunc returns the index into s of the first Unicode code point satisfying f(c), or -1 if none do.
|