slidge-whatsapp 0.3.0b0__cp313-cp313-manylinux_2_36_aarch64.whl → 0.3.4__cp313-cp313-manylinux_2_36_aarch64.whl
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.
Potentially problematic release.
This version of slidge-whatsapp might be problematic. Click here for more details.
- slidge_whatsapp/contact.py +2 -0
- slidge_whatsapp/event.go +72 -22
- slidge_whatsapp/generated/_whatsapp.cpython-313-aarch64-linux-gnu.h +206 -206
- slidge_whatsapp/generated/_whatsapp.cpython-313-aarch64-linux-gnu.so +0 -0
- slidge_whatsapp/generated/build.py +166 -166
- slidge_whatsapp/generated/go.py +1 -1
- slidge_whatsapp/generated/whatsapp.c +1557 -1557
- slidge_whatsapp/generated/whatsapp.go +1227 -1227
- slidge_whatsapp/generated/whatsapp.py +1382 -1382
- slidge_whatsapp/generated/whatsapp_go.h +206 -206
- slidge_whatsapp/go.mod +11 -11
- slidge_whatsapp/go.sum +26 -26
- slidge_whatsapp/session.go +4 -4
- slidge_whatsapp/vendor/github.com/ebitengine/purego/README.md +21 -5
- slidge_whatsapp/vendor/github.com/ebitengine/purego/abi_loong64.h +60 -0
- slidge_whatsapp/vendor/github.com/ebitengine/purego/cgo.go +1 -1
- slidge_whatsapp/vendor/github.com/ebitengine/purego/dlerror.go +1 -1
- slidge_whatsapp/vendor/github.com/ebitengine/purego/dlfcn.go +1 -1
- slidge_whatsapp/vendor/github.com/ebitengine/purego/dlfcn_netbsd.go +15 -0
- slidge_whatsapp/vendor/github.com/ebitengine/purego/dlfcn_nocgo_netbsd.go +9 -0
- slidge_whatsapp/vendor/github.com/ebitengine/purego/dlfcn_stubs.s +1 -1
- slidge_whatsapp/vendor/github.com/ebitengine/purego/func.go +113 -60
- slidge_whatsapp/vendor/github.com/ebitengine/purego/gen.go +6 -0
- slidge_whatsapp/vendor/github.com/ebitengine/purego/go_runtime.go +1 -1
- slidge_whatsapp/vendor/github.com/ebitengine/purego/internal/cgo/dlfcn_cgo_unix.go +2 -2
- slidge_whatsapp/vendor/github.com/ebitengine/purego/internal/cgo/syscall_cgo_unix.go +2 -2
- slidge_whatsapp/vendor/github.com/ebitengine/purego/internal/fakecgo/abi_loong64.h +60 -0
- slidge_whatsapp/vendor/github.com/ebitengine/purego/internal/fakecgo/asm_loong64.s +40 -0
- slidge_whatsapp/vendor/github.com/ebitengine/purego/internal/fakecgo/callbacks.go +1 -1
- slidge_whatsapp/vendor/github.com/ebitengine/purego/internal/fakecgo/doc.go +1 -1
- slidge_whatsapp/vendor/github.com/ebitengine/purego/internal/fakecgo/go_libinit.go +1 -1
- slidge_whatsapp/vendor/github.com/ebitengine/purego/internal/fakecgo/go_linux_loong64.go +92 -0
- slidge_whatsapp/vendor/github.com/ebitengine/purego/internal/fakecgo/go_netbsd.go +106 -0
- slidge_whatsapp/vendor/github.com/ebitengine/purego/internal/fakecgo/go_setenv.go +1 -1
- slidge_whatsapp/vendor/github.com/ebitengine/purego/internal/fakecgo/go_util.go +1 -1
- slidge_whatsapp/vendor/github.com/ebitengine/purego/internal/fakecgo/iscgo.go +1 -1
- slidge_whatsapp/vendor/github.com/ebitengine/purego/internal/fakecgo/libcgo.go +1 -1
- slidge_whatsapp/vendor/github.com/ebitengine/purego/internal/fakecgo/libcgo_darwin.go +4 -0
- slidge_whatsapp/vendor/github.com/ebitengine/purego/internal/fakecgo/libcgo_freebsd.go +4 -0
- slidge_whatsapp/vendor/github.com/ebitengine/purego/internal/fakecgo/libcgo_linux.go +4 -0
- slidge_whatsapp/vendor/github.com/ebitengine/purego/internal/fakecgo/libcgo_netbsd.go +26 -0
- slidge_whatsapp/vendor/github.com/ebitengine/purego/internal/fakecgo/netbsd.go +23 -0
- slidge_whatsapp/vendor/github.com/ebitengine/purego/internal/fakecgo/setenv.go +1 -1
- slidge_whatsapp/vendor/github.com/ebitengine/purego/internal/fakecgo/symbols.go +11 -1
- slidge_whatsapp/vendor/github.com/ebitengine/purego/internal/fakecgo/symbols_darwin.go +1 -0
- slidge_whatsapp/vendor/github.com/ebitengine/purego/internal/fakecgo/symbols_freebsd.go +1 -0
- slidge_whatsapp/vendor/github.com/ebitengine/purego/internal/fakecgo/symbols_linux.go +1 -0
- slidge_whatsapp/vendor/github.com/ebitengine/purego/internal/fakecgo/symbols_netbsd.go +30 -0
- slidge_whatsapp/vendor/github.com/ebitengine/purego/internal/fakecgo/trampolines_loong64.s +71 -0
- slidge_whatsapp/vendor/github.com/ebitengine/purego/internal/fakecgo/trampolines_stubs.s +5 -1
- slidge_whatsapp/vendor/github.com/ebitengine/purego/nocgo.go +1 -1
- slidge_whatsapp/vendor/github.com/ebitengine/purego/struct_amd64.go +8 -4
- slidge_whatsapp/vendor/github.com/ebitengine/purego/struct_arm64.go +16 -6
- slidge_whatsapp/vendor/github.com/ebitengine/purego/struct_loong64.go +190 -0
- slidge_whatsapp/vendor/github.com/ebitengine/purego/struct_other.go +6 -2
- slidge_whatsapp/vendor/github.com/ebitengine/purego/sys_amd64.s +1 -1
- slidge_whatsapp/vendor/github.com/ebitengine/purego/sys_arm64.s +1 -1
- slidge_whatsapp/vendor/github.com/ebitengine/purego/sys_loong64.s +96 -0
- slidge_whatsapp/vendor/github.com/ebitengine/purego/sys_unix_arm64.s +1 -1
- slidge_whatsapp/vendor/github.com/ebitengine/purego/sys_unix_loong64.s +75 -0
- slidge_whatsapp/vendor/github.com/ebitengine/purego/syscall.go +6 -3
- slidge_whatsapp/vendor/github.com/ebitengine/purego/syscall_cgo_linux.go +3 -3
- slidge_whatsapp/vendor/github.com/ebitengine/purego/syscall_sysv.go +13 -10
- slidge_whatsapp/vendor/github.com/ebitengine/purego/syscall_windows.go +1 -1
- slidge_whatsapp/vendor/github.com/ebitengine/purego/zcallback_amd64.s +2002 -2002
- slidge_whatsapp/vendor/github.com/ebitengine/purego/zcallback_arm64.s +4002 -4002
- slidge_whatsapp/vendor/github.com/ebitengine/purego/zcallback_loong64.s +4014 -0
- slidge_whatsapp/vendor/go.mau.fi/libsignal/session/SessionCipher.go +7 -2
- slidge_whatsapp/vendor/go.mau.fi/util/dbutil/log.go +1 -0
- slidge_whatsapp/vendor/go.mau.fi/util/dbutil/module.go +119 -0
- slidge_whatsapp/vendor/go.mau.fi/util/dbutil/upgradetable.go +3 -34
- slidge_whatsapp/vendor/go.mau.fi/util/exbytes/string.go +20 -0
- slidge_whatsapp/vendor/go.mau.fi/util/exbytes/writer.go +78 -0
- slidge_whatsapp/vendor/go.mau.fi/util/exslices/cast.go +42 -0
- slidge_whatsapp/vendor/go.mau.fi/util/exslices/chunk.go +28 -0
- slidge_whatsapp/vendor/go.mau.fi/util/exslices/deduplicate.go +67 -0
- slidge_whatsapp/vendor/go.mau.fi/util/exslices/diff.go +63 -0
- slidge_whatsapp/vendor/go.mau.fi/util/exsync/event.go +15 -1
- slidge_whatsapp/vendor/go.mau.fi/util/exsync/syncmap.go +48 -7
- slidge_whatsapp/vendor/go.mau.fi/util/exsync/syncset.go +13 -0
- slidge_whatsapp/vendor/go.mau.fi/util/jsontime/helpers.go +16 -5
- slidge_whatsapp/vendor/go.mau.fi/util/jsontime/integer.go +27 -12
- slidge_whatsapp/vendor/go.mau.fi/util/random/string.go +47 -7
- slidge_whatsapp/vendor/go.mau.fi/whatsmeow/appstate/decode.go +1 -0
- slidge_whatsapp/vendor/go.mau.fi/whatsmeow/appstate/encode.go +60 -15
- slidge_whatsapp/vendor/go.mau.fi/whatsmeow/appstate/hash.go +1 -0
- slidge_whatsapp/vendor/go.mau.fi/whatsmeow/appstate.go +20 -2
- slidge_whatsapp/vendor/go.mau.fi/whatsmeow/armadillomessage.go +2 -2
- slidge_whatsapp/vendor/go.mau.fi/whatsmeow/call.go +6 -0
- slidge_whatsapp/vendor/go.mau.fi/whatsmeow/errors.go +1 -0
- slidge_whatsapp/vendor/go.mau.fi/whatsmeow/group.go +63 -42
- slidge_whatsapp/vendor/go.mau.fi/whatsmeow/internals.go +31 -15
- slidge_whatsapp/vendor/go.mau.fi/whatsmeow/message.go +77 -26
- slidge_whatsapp/vendor/go.mau.fi/whatsmeow/msgsecret.go +23 -0
- slidge_whatsapp/vendor/go.mau.fi/whatsmeow/notification.go +5 -1
- slidge_whatsapp/vendor/go.mau.fi/whatsmeow/pair.go +22 -23
- slidge_whatsapp/vendor/go.mau.fi/whatsmeow/prekeys.go +21 -0
- slidge_whatsapp/vendor/go.mau.fi/whatsmeow/proto/waAICommon/WAAICommon.pb.go +7747 -0
- slidge_whatsapp/vendor/go.mau.fi/whatsmeow/proto/{waBotMetadata/WABotMetadata.proto → waAICommon/WAAICommon.proto} +269 -9
- slidge_whatsapp/vendor/go.mau.fi/whatsmeow/proto/waDeviceCapabilities/WAProtobufsDeviceCapabilities.pb.go +128 -14
- slidge_whatsapp/vendor/go.mau.fi/whatsmeow/proto/waDeviceCapabilities/WAProtobufsDeviceCapabilities.proto +10 -0
- slidge_whatsapp/vendor/go.mau.fi/whatsmeow/proto/waE2E/WAWebProtobufsE2E.pb.go +8953 -10087
- slidge_whatsapp/vendor/go.mau.fi/whatsmeow/proto/waE2E/WAWebProtobufsE2E.proto +216 -330
- slidge_whatsapp/vendor/go.mau.fi/whatsmeow/proto/waHistorySync/WAWebProtobufsHistorySync.pb.go +11 -2
- slidge_whatsapp/vendor/go.mau.fi/whatsmeow/proto/waHistorySync/WAWebProtobufsHistorySync.proto +1 -0
- slidge_whatsapp/vendor/go.mau.fi/whatsmeow/proto/waStatusAttributions/WAStatusAttributions.pb.go +226 -83
- slidge_whatsapp/vendor/go.mau.fi/whatsmeow/proto/waStatusAttributions/WAStatusAttributions.proto +14 -0
- slidge_whatsapp/vendor/go.mau.fi/whatsmeow/proto/waSyncAction/WASyncAction.pb.go +709 -449
- slidge_whatsapp/vendor/go.mau.fi/whatsmeow/proto/waSyncAction/WASyncAction.proto +24 -0
- slidge_whatsapp/vendor/go.mau.fi/whatsmeow/proto/waWa6/WAWebProtobufsWa6.pb.go +78 -24
- slidge_whatsapp/vendor/go.mau.fi/whatsmeow/proto/waWa6/WAWebProtobufsWa6.proto +6 -0
- slidge_whatsapp/vendor/go.mau.fi/whatsmeow/proto/waWeb/WAWebProtobufsWeb.pb.go +528 -267
- slidge_whatsapp/vendor/go.mau.fi/whatsmeow/proto/waWeb/WAWebProtobufsWeb.proto +24 -0
- slidge_whatsapp/vendor/go.mau.fi/whatsmeow/receipt.go +47 -14
- slidge_whatsapp/vendor/go.mau.fi/whatsmeow/request.go +4 -0
- slidge_whatsapp/vendor/go.mau.fi/whatsmeow/retry.go +6 -13
- slidge_whatsapp/vendor/go.mau.fi/whatsmeow/send.go +130 -62
- slidge_whatsapp/vendor/go.mau.fi/whatsmeow/sendfb.go +33 -32
- slidge_whatsapp/vendor/go.mau.fi/whatsmeow/store/clientpayload.go +1 -1
- slidge_whatsapp/vendor/go.mau.fi/whatsmeow/store/noop.go +16 -0
- slidge_whatsapp/vendor/go.mau.fi/whatsmeow/store/sessioncache.go +125 -0
- slidge_whatsapp/vendor/go.mau.fi/whatsmeow/store/signal.go +8 -0
- slidge_whatsapp/vendor/go.mau.fi/whatsmeow/store/sqlstore/lidmap.go +82 -4
- slidge_whatsapp/vendor/go.mau.fi/whatsmeow/store/sqlstore/store.go +135 -55
- slidge_whatsapp/vendor/go.mau.fi/whatsmeow/store/sqlstore/upgrades/00-latest-schema.sql +8 -7
- slidge_whatsapp/vendor/go.mau.fi/whatsmeow/store/sqlstore/upgrades/11-redacted-phone-contacts.sql +2 -0
- slidge_whatsapp/vendor/go.mau.fi/whatsmeow/store/store.go +24 -2
- slidge_whatsapp/vendor/go.mau.fi/whatsmeow/types/call.go +6 -5
- slidge_whatsapp/vendor/go.mau.fi/whatsmeow/types/jid.go +24 -9
- slidge_whatsapp/vendor/go.mau.fi/whatsmeow/types/message.go +7 -1
- slidge_whatsapp/vendor/go.mau.fi/whatsmeow/types/user.go +3 -0
- slidge_whatsapp/vendor/go.mau.fi/whatsmeow/user.go +43 -3
- slidge_whatsapp/vendor/golang.org/x/crypto/curve25519/curve25519.go +7 -4
- slidge_whatsapp/vendor/golang.org/x/net/http2/config.go +11 -6
- slidge_whatsapp/vendor/golang.org/x/net/http2/config_go125.go +15 -0
- slidge_whatsapp/vendor/golang.org/x/net/http2/config_go126.go +15 -0
- slidge_whatsapp/vendor/golang.org/x/net/http2/frame.go +24 -1
- slidge_whatsapp/vendor/golang.org/x/net/http2/http2.go +0 -1
- slidge_whatsapp/vendor/golang.org/x/net/http2/server.go +35 -26
- slidge_whatsapp/vendor/golang.org/x/net/http2/transport.go +4 -2
- slidge_whatsapp/vendor/golang.org/x/net/http2/writesched.go +2 -0
- slidge_whatsapp/vendor/golang.org/x/net/http2/{writesched_priority.go → writesched_priority_rfc7540.go} +52 -52
- slidge_whatsapp/vendor/golang.org/x/net/http2/writesched_priority_rfc9128.go +209 -0
- slidge_whatsapp/vendor/golang.org/x/net/http2/writesched_roundrobin.go +1 -1
- slidge_whatsapp/vendor/golang.org/x/net/internal/httpcommon/request.go +2 -2
- slidge_whatsapp/vendor/golang.org/x/net/internal/socks/socks.go +1 -1
- slidge_whatsapp/vendor/golang.org/x/sys/unix/affinity_linux.go +9 -0
- slidge_whatsapp/vendor/golang.org/x/sys/unix/fdset.go +1 -3
- slidge_whatsapp/vendor/golang.org/x/sys/unix/ifreq_linux.go +1 -3
- slidge_whatsapp/vendor/golang.org/x/sys/unix/mkall.sh +1 -0
- slidge_whatsapp/vendor/golang.org/x/sys/unix/syscall_linux.go +1 -3
- slidge_whatsapp/vendor/golang.org/x/sys/unix/syscall_netbsd.go +17 -0
- slidge_whatsapp/vendor/golang.org/x/sys/windows/syscall_windows.go +2 -0
- slidge_whatsapp/vendor/golang.org/x/sys/windows/types_windows.go +16 -0
- slidge_whatsapp/vendor/golang.org/x/sys/windows/zsyscall_windows.go +18 -0
- slidge_whatsapp/vendor/golang.org/x/text/unicode/bidi/core.go +2 -9
- slidge_whatsapp/vendor/google.golang.org/protobuf/internal/filedesc/desc.go +35 -17
- slidge_whatsapp/vendor/google.golang.org/protobuf/internal/filedesc/desc_init.go +14 -0
- slidge_whatsapp/vendor/google.golang.org/protobuf/internal/filedesc/desc_lazy.go +20 -0
- slidge_whatsapp/vendor/google.golang.org/protobuf/internal/version/version.go +1 -1
- slidge_whatsapp/vendor/modules.txt +15 -13
- {slidge_whatsapp-0.3.0b0.dist-info → slidge_whatsapp-0.3.4.dist-info}/METADATA +4 -3
- {slidge_whatsapp-0.3.0b0.dist-info → slidge_whatsapp-0.3.4.dist-info}/RECORD +166 -138
- {slidge_whatsapp-0.3.0b0.dist-info → slidge_whatsapp-0.3.4.dist-info}/WHEEL +1 -1
- slidge_whatsapp/vendor/go.mau.fi/whatsmeow/proto/waBotMetadata/WABotMetadata.pb.go +0 -5156
- {slidge_whatsapp-0.3.0b0.dist-info → slidge_whatsapp-0.3.4.dist-info}/entry_points.txt +0 -0
- {slidge_whatsapp-0.3.0b0.dist-info → slidge_whatsapp-0.3.4.dist-info/licenses}/LICENSE +0 -0
|
@@ -2,6 +2,7 @@ package session
|
|
|
2
2
|
|
|
3
3
|
import (
|
|
4
4
|
"context"
|
|
5
|
+
"errors"
|
|
5
6
|
"fmt"
|
|
6
7
|
|
|
7
8
|
"go.mau.fi/libsignal/cipher"
|
|
@@ -253,12 +254,16 @@ func (d *Cipher) DecryptWithRecord(ctx context.Context, sessionRecord *record.Se
|
|
|
253
254
|
|
|
254
255
|
// If we received an error using the current session state, loop
|
|
255
256
|
// through all previous states.
|
|
256
|
-
if err
|
|
257
|
+
if errors.Is(err, signalerror.ErrOldCounter) {
|
|
258
|
+
return nil, nil, err
|
|
259
|
+
} else if err != nil {
|
|
257
260
|
logger.Warning(err)
|
|
258
261
|
for i, state := range previousStates {
|
|
259
262
|
// Try decrypting the message with previous states
|
|
260
263
|
plaintext, messageKeys, err = d.DecryptWithState(ctx, state, ciphertext)
|
|
261
|
-
if err
|
|
264
|
+
if errors.Is(err, signalerror.ErrOldCounter) {
|
|
265
|
+
return nil, nil, err
|
|
266
|
+
} else if err != nil {
|
|
262
267
|
continue
|
|
263
268
|
}
|
|
264
269
|
|
|
@@ -115,6 +115,7 @@ func (z zeroLogger) QueryTiming(ctx context.Context, method, query string, args
|
|
|
115
115
|
if duration >= 1*time.Second {
|
|
116
116
|
evt := log.Warn().
|
|
117
117
|
Float64("duration_seconds", duration.Seconds()).
|
|
118
|
+
AnErr("result_error", err).
|
|
118
119
|
Str("method", method).
|
|
119
120
|
Str("query", query)
|
|
120
121
|
if z.Caller {
|
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
// Package dbutil provides a simple framework for in-process database
|
|
2
|
+
// migrations. You provide the SQL files and they are run to upgrade
|
|
3
|
+
// the database. A versions table is automatically created in the
|
|
4
|
+
// database to track which migrations have been applied. There is
|
|
5
|
+
// support for multiple migration pathways, for example v0->v2 versus
|
|
6
|
+
// v0->v1->v2, and the shorter one is prioritized if both are
|
|
7
|
+
// provided.
|
|
8
|
+
//
|
|
9
|
+
// Example usage from Go:
|
|
10
|
+
//
|
|
11
|
+
// package main
|
|
12
|
+
//
|
|
13
|
+
// import (
|
|
14
|
+
// "context"
|
|
15
|
+
// "database/sql"
|
|
16
|
+
// "embed"
|
|
17
|
+
//
|
|
18
|
+
// "go.mau.fi/util/dbutil"
|
|
19
|
+
// )
|
|
20
|
+
//
|
|
21
|
+
// //go:embed *.sql
|
|
22
|
+
// var upgrades embed.FS
|
|
23
|
+
//
|
|
24
|
+
// func mainE() error {
|
|
25
|
+
// ctx := context.Background()
|
|
26
|
+
// rawDB, err := sql.Open("sqlite3", "./hotdogs.db")
|
|
27
|
+
// if err != nil {
|
|
28
|
+
// return err
|
|
29
|
+
// }
|
|
30
|
+
// db, err := dbutil.NewWithDB(rawDB, "sqlite3")
|
|
31
|
+
// if err != nil {
|
|
32
|
+
// return err
|
|
33
|
+
// }
|
|
34
|
+
// table := dbutil.UpgradeTable{}
|
|
35
|
+
// table.RegisterFS(upgrades)
|
|
36
|
+
// err = db.Upgrade(ctx)
|
|
37
|
+
// if err != nil {
|
|
38
|
+
// return err
|
|
39
|
+
// }
|
|
40
|
+
// // db has been upgraded to latest version
|
|
41
|
+
// return nil
|
|
42
|
+
// }
|
|
43
|
+
//
|
|
44
|
+
// In dbutil, the database is understood to have a monotonic integer
|
|
45
|
+
// sequence of versions starting at v0, v1, v2, etc. By providing
|
|
46
|
+
// migrations you define a directed acyclic graph (DAG) that allows
|
|
47
|
+
// dbutil to find a path from the current recorded database version to
|
|
48
|
+
// the latest version available.
|
|
49
|
+
//
|
|
50
|
+
// Each SQL migration file has a mandatory comment header that
|
|
51
|
+
// identifies which database versions it upgrades between. For example
|
|
52
|
+
// this is a migration that upgrades from v0 to v2:
|
|
53
|
+
//
|
|
54
|
+
// -- v0 -> v2: Do some things
|
|
55
|
+
//
|
|
56
|
+
// You can omit the first version for the common case of upgrading to
|
|
57
|
+
// a version from the previous version. For example this is a
|
|
58
|
+
// migration that upgrades from v1 to v2:
|
|
59
|
+
//
|
|
60
|
+
// -- v2: Do fewer things
|
|
61
|
+
//
|
|
62
|
+
// By providing "v1" and "v2" migrations, a v0 database would be
|
|
63
|
+
// upgraded to v1 and then v2, while by providing an additional "v0 ->
|
|
64
|
+
// v2" migration a v0 database would be upgraded directly to v2 as it
|
|
65
|
+
// is a more direct path. With that migration provided the "v1"
|
|
66
|
+
// migration is no longer needed.
|
|
67
|
+
//
|
|
68
|
+
// By default, when running migrations, if a more recent database
|
|
69
|
+
// version is live than the current code knows about (for example,
|
|
70
|
+
// from running a previous version of the application), dbutil will
|
|
71
|
+
// error out. However, many database migrations are backwards
|
|
72
|
+
// compatible. You can therefore indicate this when writing a
|
|
73
|
+
// migration, and previous versions of the application will accept a
|
|
74
|
+
// database with that migration applied, even if they are unaware of
|
|
75
|
+
// its contents. For example, if the migration from v1 to v2 was
|
|
76
|
+
// backwards compatible, you could provide this migration:
|
|
77
|
+
//
|
|
78
|
+
// -- v2 (compatible with v1+): Do fewer things
|
|
79
|
+
//
|
|
80
|
+
// When applying the migration, the compatibility level (v1) is saved
|
|
81
|
+
// to the versions table in the database, so that older versions of
|
|
82
|
+
// the application which only know about v1 will see that v2 of the
|
|
83
|
+
// database is still OK to use. If the compatibility level is not set,
|
|
84
|
+
// then it defaults to the same as the target version for the
|
|
85
|
+
// migration, which achieves the default behavior described in the
|
|
86
|
+
// previous paragraph.
|
|
87
|
+
//
|
|
88
|
+
// You can provide additional flags immediately following the header
|
|
89
|
+
// line. To disable wrapping the upgrade in a single transaction, put
|
|
90
|
+
// "transaction: off" on the second line.
|
|
91
|
+
//
|
|
92
|
+
// -- v5: Upgrade without transaction
|
|
93
|
+
// -- transaction: off
|
|
94
|
+
// // do dangerous stuff
|
|
95
|
+
//
|
|
96
|
+
// Within migrations, there is special syntax that can be used to
|
|
97
|
+
// filter parts of the SQL to apply only with specific dialects. To
|
|
98
|
+
// limit the next line to one dialect:
|
|
99
|
+
//
|
|
100
|
+
// -- only: postgres
|
|
101
|
+
//
|
|
102
|
+
// To limit the next N lines:
|
|
103
|
+
//
|
|
104
|
+
// -- only: sqlite for next 123 lines
|
|
105
|
+
//
|
|
106
|
+
// To limit a block of code, fenced by another directive:
|
|
107
|
+
//
|
|
108
|
+
// -- only: sqlite until "end only"
|
|
109
|
+
// QUERY;
|
|
110
|
+
// ANOTHER QUERY;
|
|
111
|
+
// -- end only sqlite
|
|
112
|
+
//
|
|
113
|
+
// If the single-line limit is on the second line of the file, the
|
|
114
|
+
// whole file is limited to that dialect.
|
|
115
|
+
//
|
|
116
|
+
// If the filter ends with `(lines commented)`, then ALL lines chosen
|
|
117
|
+
// by the filter will be uncommented. The `--` comment prefix must be
|
|
118
|
+
// at the beginning of the line with no whitespace ahead of it.
|
|
119
|
+
package dbutil
|
|
@@ -60,24 +60,8 @@ func (ut *UpgradeTable) Register(from, to, compat int, message string, txn TxnMo
|
|
|
60
60
|
(*ut)[from] = upg
|
|
61
61
|
}
|
|
62
62
|
|
|
63
|
-
// Syntax is either
|
|
64
|
-
//
|
|
65
|
-
// -- v0 -> v1: Message
|
|
66
|
-
//
|
|
67
|
-
// or
|
|
68
|
-
//
|
|
69
|
-
// -- v1: Message
|
|
70
|
-
//
|
|
71
|
-
// Both syntaxes may also have a compatibility notice before the colon:
|
|
72
|
-
//
|
|
73
|
-
// -- v5 (compatible with v3+): Upgrade with backwards compatibility
|
|
74
63
|
var upgradeHeaderRegex = regexp.MustCompile(`^-- (?:v(\d+) -> )?v(\d+)(?: \(compatible with v(\d+)\+\))?: (.+)$`)
|
|
75
64
|
|
|
76
|
-
// To disable wrapping the upgrade in a single transaction, put `--transaction: off` on the second line.
|
|
77
|
-
//
|
|
78
|
-
// -- v5: Upgrade without transaction
|
|
79
|
-
// -- transaction: off
|
|
80
|
-
// // do dangerous stuff
|
|
81
65
|
var transactionDisableRegex = regexp.MustCompile(`^-- transaction: ([a-z-]*)`)
|
|
82
66
|
|
|
83
67
|
func parseFileHeader(file []byte) (from, to, compat int, message string, txn TxnMode, lines [][]byte, err error) {
|
|
@@ -123,24 +107,6 @@ func parseFileHeader(file []byte) (from, to, compat int, message string, txn Txn
|
|
|
123
107
|
return
|
|
124
108
|
}
|
|
125
109
|
|
|
126
|
-
// To limit the next line to one dialect:
|
|
127
|
-
//
|
|
128
|
-
// -- only: postgres
|
|
129
|
-
//
|
|
130
|
-
// To limit the next N lines:
|
|
131
|
-
//
|
|
132
|
-
// -- only: sqlite for next 123 lines
|
|
133
|
-
//
|
|
134
|
-
// To limit a block of code, fenced by another directive:
|
|
135
|
-
//
|
|
136
|
-
// -- only: sqlite until "end only"
|
|
137
|
-
// QUERY;
|
|
138
|
-
// ANOTHER QUERY;
|
|
139
|
-
// -- end only sqlite
|
|
140
|
-
//
|
|
141
|
-
// If the single-line limit is on the second line of the file, the whole file is limited to that dialect.
|
|
142
|
-
//
|
|
143
|
-
// If the filter ends with `(lines commented)`, then ALL lines chosen by the filter will be uncommented.
|
|
144
110
|
var dialectLineFilter = regexp.MustCompile(`^\s*-- only: (postgres|sqlite)(?: for next (\d+) lines| until "(end) only")?(?: \(lines? (commented)\))?`)
|
|
145
111
|
|
|
146
112
|
// Constants used to make parseDialectFilter clearer
|
|
@@ -207,6 +173,9 @@ func (db *Database) filterSQLUpgrade(lines [][]byte) (string, error) {
|
|
|
207
173
|
}
|
|
208
174
|
if dialect == db.Dialect {
|
|
209
175
|
if uncomment {
|
|
176
|
+
if !bytes.HasPrefix(lines[i], []byte("--")) {
|
|
177
|
+
return "", fmt.Errorf("line %d isn't commented even though the dialect filter claimed it is (-- must be at beginning of line)", i+1)
|
|
178
|
+
}
|
|
210
179
|
output = append(output, bytes.TrimPrefix(lines[i], []byte("--")))
|
|
211
180
|
} else {
|
|
212
181
|
output = append(output, lines[i])
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
// Copyright (c) 2025 Tulir Asokan
|
|
2
|
+
//
|
|
3
|
+
// This Source Code Form is subject to the terms of the Mozilla Public
|
|
4
|
+
// License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
5
|
+
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
|
6
|
+
|
|
7
|
+
package exbytes
|
|
8
|
+
|
|
9
|
+
import (
|
|
10
|
+
"unsafe"
|
|
11
|
+
)
|
|
12
|
+
|
|
13
|
+
// UnsafeString returns a string that points to the same memory as the input byte slice.
|
|
14
|
+
//
|
|
15
|
+
// The input byte slice must not be modified after this function is called.
|
|
16
|
+
//
|
|
17
|
+
// See [go.mau.fi/util/exstrings.UnsafeBytes] for the reverse operation.
|
|
18
|
+
func UnsafeString(b []byte) string {
|
|
19
|
+
return unsafe.String(unsafe.SliceData(b), len(b))
|
|
20
|
+
}
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
// Copyright (c) 2024 Tulir Asokan
|
|
2
|
+
//
|
|
3
|
+
// This Source Code Form is subject to the terms of the Mozilla Public
|
|
4
|
+
// License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
5
|
+
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
|
6
|
+
|
|
7
|
+
package exbytes
|
|
8
|
+
|
|
9
|
+
import (
|
|
10
|
+
"errors"
|
|
11
|
+
"fmt"
|
|
12
|
+
"io"
|
|
13
|
+
)
|
|
14
|
+
|
|
15
|
+
// Writer is a simple byte writer that does not allow extending the buffer.
|
|
16
|
+
//
|
|
17
|
+
// Writes always go after the current len() and will fail if the slice capacity is too low.
|
|
18
|
+
//
|
|
19
|
+
// The correct way to use this is to create a slice with sufficient capacity and zero length:
|
|
20
|
+
//
|
|
21
|
+
// x := make([]byte, 0, 11)
|
|
22
|
+
// w := (*Writer)(&x)
|
|
23
|
+
// w.Write([]byte("hello"))
|
|
24
|
+
// w.WriteByte(' ')
|
|
25
|
+
// w.WriteString("world")
|
|
26
|
+
// fmt.Println(string(x)) // "hello world"
|
|
27
|
+
type Writer []byte
|
|
28
|
+
|
|
29
|
+
var ErrWriterBufferFull = errors.New("exbytes.Writer: buffer full")
|
|
30
|
+
|
|
31
|
+
var (
|
|
32
|
+
_ io.Writer = (*Writer)(nil)
|
|
33
|
+
_ io.StringWriter = (*Writer)(nil)
|
|
34
|
+
_ io.ByteWriter = (*Writer)(nil)
|
|
35
|
+
)
|
|
36
|
+
|
|
37
|
+
func (w *Writer) extendLen(n int) (int, error) {
|
|
38
|
+
ptr := len(*w)
|
|
39
|
+
if ptr+n > cap(*w) {
|
|
40
|
+
return 0, fmt.Errorf("%w (%d + %d > %d)", ErrWriterBufferFull, ptr, n, cap(*w))
|
|
41
|
+
}
|
|
42
|
+
*w = (*w)[:ptr+n]
|
|
43
|
+
return ptr, nil
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
func (w *Writer) Write(b []byte) (n int, err error) {
|
|
47
|
+
ptr, err := w.extendLen(len(b))
|
|
48
|
+
if err != nil {
|
|
49
|
+
return 0, err
|
|
50
|
+
}
|
|
51
|
+
copy((*w)[ptr:], b)
|
|
52
|
+
return len(b), nil
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
func (w *Writer) WriteString(s string) (n int, err error) {
|
|
56
|
+
ptr, err := w.extendLen(len(s))
|
|
57
|
+
if err != nil {
|
|
58
|
+
return 0, err
|
|
59
|
+
}
|
|
60
|
+
copy((*w)[ptr:], s)
|
|
61
|
+
return len(s), nil
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
func (w *Writer) WriteByte(r byte) error {
|
|
65
|
+
ptr, err := w.extendLen(1)
|
|
66
|
+
if err != nil {
|
|
67
|
+
return err
|
|
68
|
+
}
|
|
69
|
+
(*w)[ptr] = r
|
|
70
|
+
return nil
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
func (w *Writer) String() string {
|
|
74
|
+
if w == nil {
|
|
75
|
+
return "<nil>"
|
|
76
|
+
}
|
|
77
|
+
return string(*w)
|
|
78
|
+
}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
// Copyright (c) 2024 Tulir Asokan
|
|
2
|
+
//
|
|
3
|
+
// This Source Code Form is subject to the terms of the Mozilla Public
|
|
4
|
+
// License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
5
|
+
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
|
6
|
+
|
|
7
|
+
package exslices
|
|
8
|
+
|
|
9
|
+
func CastFunc[To, From any](source []From, conv func(From) To) []To {
|
|
10
|
+
result := make([]To, len(source))
|
|
11
|
+
for i, v := range source {
|
|
12
|
+
result[i] = conv(v)
|
|
13
|
+
}
|
|
14
|
+
return result
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
func CastFuncFilter[To, From any](source []From, conv func(From) (To, bool)) []To {
|
|
18
|
+
result := make([]To, 0, len(source))
|
|
19
|
+
for _, v := range source {
|
|
20
|
+
res, ok := conv(v)
|
|
21
|
+
if ok {
|
|
22
|
+
result = append(result, res)
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
return result
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
func CastToString[To, From ~string](source []From) []To {
|
|
29
|
+
result := make([]To, len(source))
|
|
30
|
+
for i, v := range source {
|
|
31
|
+
result[i] = To(v)
|
|
32
|
+
}
|
|
33
|
+
return result
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
func CastToAny[From any](source []From) []any {
|
|
37
|
+
result := make([]any, len(source))
|
|
38
|
+
for i, v := range source {
|
|
39
|
+
result[i] = v
|
|
40
|
+
}
|
|
41
|
+
return result
|
|
42
|
+
}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
// Copyright (c) 2024 Tulir Asokan
|
|
2
|
+
//
|
|
3
|
+
// This Source Code Form is subject to the terms of the Mozilla Public
|
|
4
|
+
// License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
5
|
+
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
|
6
|
+
|
|
7
|
+
package exslices
|
|
8
|
+
|
|
9
|
+
// Chunk splits a slice into chunks of the given size.
|
|
10
|
+
//
|
|
11
|
+
// From https://github.com/golang/go/issues/53987#issuecomment-1224367139
|
|
12
|
+
//
|
|
13
|
+
// TODO remove this after slices.Chunk can be used (it'll probably be added in Go 1.23, so it can be used after 1.22 is EOL)
|
|
14
|
+
func Chunk[T any](slice []T, size int) (chunks [][]T) {
|
|
15
|
+
if size < 1 {
|
|
16
|
+
panic("chunk size cannot be less than 1")
|
|
17
|
+
}
|
|
18
|
+
for i := 0; ; i++ {
|
|
19
|
+
next := i * size
|
|
20
|
+
if len(slice[next:]) > size {
|
|
21
|
+
end := next + size
|
|
22
|
+
chunks = append(chunks, slice[next:end:end])
|
|
23
|
+
} else {
|
|
24
|
+
chunks = append(chunks, slice[i*size:])
|
|
25
|
+
return
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
}
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
// Copyright (c) 2024 Tulir Asokan
|
|
2
|
+
//
|
|
3
|
+
// This Source Code Form is subject to the terms of the Mozilla Public
|
|
4
|
+
// License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
5
|
+
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
|
6
|
+
|
|
7
|
+
package exslices
|
|
8
|
+
|
|
9
|
+
// DeduplicateUnsorted removes duplicates from the given slice without requiring that the input slice is sorted.
|
|
10
|
+
// The order of the output will be the same as the input. The input slice will not be modified.
|
|
11
|
+
//
|
|
12
|
+
// If you don't care about the order of the output, it's recommended to sort the list and then use [slices.Compact].
|
|
13
|
+
func DeduplicateUnsorted[T comparable](s []T) []T {
|
|
14
|
+
return deduplicateUnsortedInto(s, make([]T, 0, len(s)))
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
// DeduplicateUnsortedOverwrite removes duplicates from the given slice without requiring that the input slice is sorted.
|
|
18
|
+
// The input slice will be modified and used as the output slice to avoid extra allocations.
|
|
19
|
+
//
|
|
20
|
+
// If you don't care about the order of the output, it's recommended to sort the list and then use [slices.Compact].
|
|
21
|
+
func DeduplicateUnsortedOverwrite[T comparable](s []T) []T {
|
|
22
|
+
out := deduplicateUnsortedInto(s, s[:0])
|
|
23
|
+
clear(s[len(out):])
|
|
24
|
+
return out
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
func deduplicateUnsortedInto[T comparable](s, result []T) []T {
|
|
28
|
+
seen := make(map[T]struct{}, len(s))
|
|
29
|
+
for _, item := range s {
|
|
30
|
+
if _, ok := seen[item]; !ok {
|
|
31
|
+
seen[item] = struct{}{}
|
|
32
|
+
result = append(result, item)
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
return result
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
// DeduplicateUnsortedFunc removes duplicates from the given slice using the given key function without requiring
|
|
39
|
+
// that the input slice is sorted. The order of the output will be the same as the input.
|
|
40
|
+
//
|
|
41
|
+
// If you don't care about the order of the output, it's recommended to sort the list and then use [slices.CompactFunc].
|
|
42
|
+
func DeduplicateUnsortedFunc[T any, K comparable](s []T, getKey func(T) K) []T {
|
|
43
|
+
return deduplicateUnsortedFuncInto(s, make([]T, 0, len(s)), getKey)
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
// DeduplicateUnsortedOverwriteFunc removes duplicates from the given slice using the given key function
|
|
47
|
+
// without requiring that the input slice is sorted. The order of the output will be the same as the input.
|
|
48
|
+
// The input slice will be modified and used as the output slice to avoid extra allocations.
|
|
49
|
+
//
|
|
50
|
+
// If you don't care about the order of the output, it's recommended to sort the list and then use [slices.CompactFunc].
|
|
51
|
+
func DeduplicateUnsortedOverwriteFunc[T any, K comparable](s []T, getKey func(T) K) []T {
|
|
52
|
+
out := deduplicateUnsortedFuncInto(s, s[:0], getKey)
|
|
53
|
+
clear(s[len(out):])
|
|
54
|
+
return out
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
func deduplicateUnsortedFuncInto[T any, K comparable](s, result []T, getKey func(T) K) []T {
|
|
58
|
+
seen := make(map[K]struct{}, len(s))
|
|
59
|
+
for _, item := range s {
|
|
60
|
+
key := getKey(item)
|
|
61
|
+
if _, ok := seen[key]; !ok {
|
|
62
|
+
seen[key] = struct{}{}
|
|
63
|
+
result = append(result, item)
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
return result
|
|
67
|
+
}
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
// Copyright (c) 2023 Tulir Asokan
|
|
2
|
+
//
|
|
3
|
+
// This Source Code Form is subject to the terms of the Mozilla Public
|
|
4
|
+
// License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
5
|
+
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
|
6
|
+
|
|
7
|
+
package exslices
|
|
8
|
+
|
|
9
|
+
// SortedDiff returns the difference between two already-sorted slices, with the help of the given comparison function.
|
|
10
|
+
// The output will be in the same order as the input, which means it'll be sorted.
|
|
11
|
+
func SortedDiff[T any](a, b []T, compare func(a, b T) int) (uniqueToA, uniqueToB []T) {
|
|
12
|
+
uniqueToA = make([]T, 0, len(a))
|
|
13
|
+
uniqueToB = make([]T, 0, len(b))
|
|
14
|
+
|
|
15
|
+
var i, j int
|
|
16
|
+
for {
|
|
17
|
+
if j >= len(b) {
|
|
18
|
+
uniqueToA = append(uniqueToA, a[i:]...)
|
|
19
|
+
break
|
|
20
|
+
} else if i >= len(a) {
|
|
21
|
+
uniqueToB = append(uniqueToB, b[j:]...)
|
|
22
|
+
break
|
|
23
|
+
}
|
|
24
|
+
c := compare(a[i], b[j])
|
|
25
|
+
if c < 0 {
|
|
26
|
+
uniqueToA = append(uniqueToA, a[i])
|
|
27
|
+
i++
|
|
28
|
+
} else if c > 0 {
|
|
29
|
+
uniqueToB = append(uniqueToB, b[j])
|
|
30
|
+
j++
|
|
31
|
+
} else {
|
|
32
|
+
i++
|
|
33
|
+
j++
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
return
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
// Diff returns the difference between two slices. The slices may contain duplicates and don't need to be sorted.
|
|
40
|
+
// The output will not be sorted, but is guaranteed to not contain any duplicates.
|
|
41
|
+
func Diff[T comparable](a, b []T) (uniqueToA, uniqueToB []T) {
|
|
42
|
+
maxLen := len(a)
|
|
43
|
+
if len(b) > maxLen {
|
|
44
|
+
maxLen = len(b)
|
|
45
|
+
}
|
|
46
|
+
collector := make(map[T]uint8, maxLen)
|
|
47
|
+
for _, item := range a {
|
|
48
|
+
collector[item] |= 0b01
|
|
49
|
+
}
|
|
50
|
+
for _, item := range b {
|
|
51
|
+
collector[item] |= 0b10
|
|
52
|
+
}
|
|
53
|
+
uniqueToA = make([]T, 0, maxLen)
|
|
54
|
+
uniqueToB = make([]T, 0, maxLen)
|
|
55
|
+
for item, mask := range collector {
|
|
56
|
+
if mask == 0b01 {
|
|
57
|
+
uniqueToA = append(uniqueToA, item)
|
|
58
|
+
} else if mask == 0b10 {
|
|
59
|
+
uniqueToB = append(uniqueToB, item)
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
return
|
|
63
|
+
}
|
|
@@ -8,6 +8,7 @@ package exsync
|
|
|
8
8
|
|
|
9
9
|
import (
|
|
10
10
|
"context"
|
|
11
|
+
"fmt"
|
|
11
12
|
"sync"
|
|
12
13
|
"time"
|
|
13
14
|
)
|
|
@@ -50,7 +51,7 @@ func (e *Event) Wait(ctx context.Context) error {
|
|
|
50
51
|
}
|
|
51
52
|
}
|
|
52
53
|
|
|
53
|
-
// WaitTimeout waits for
|
|
54
|
+
// WaitTimeout waits for the event to happen within the given timeout.
|
|
54
55
|
// If the timeout expires first, the return value is false, otherwise it's true.
|
|
55
56
|
func (e *Event) WaitTimeout(timeout time.Duration) bool {
|
|
56
57
|
select {
|
|
@@ -61,6 +62,19 @@ func (e *Event) WaitTimeout(timeout time.Duration) bool {
|
|
|
61
62
|
}
|
|
62
63
|
}
|
|
63
64
|
|
|
65
|
+
// WaitTimeoutCtx waits for the event to happen, the timeout to expire, or the given context to be done.
|
|
66
|
+
// If the context or timeout is done first, an error is returned, otherwise the return value is nil.
|
|
67
|
+
func (e *Event) WaitTimeoutCtx(ctx context.Context, timeout time.Duration) error {
|
|
68
|
+
select {
|
|
69
|
+
case <-e.GetChan():
|
|
70
|
+
return nil
|
|
71
|
+
case <-ctx.Done():
|
|
72
|
+
return ctx.Err()
|
|
73
|
+
case <-time.After(timeout):
|
|
74
|
+
return fmt.Errorf("exsync.Event: wait timeout")
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
|
|
64
78
|
// IsSet returns true if the event has been set.
|
|
65
79
|
func (e *Event) IsSet() bool {
|
|
66
80
|
e.l.RLock()
|
|
@@ -6,7 +6,11 @@
|
|
|
6
6
|
|
|
7
7
|
package exsync
|
|
8
8
|
|
|
9
|
-
import
|
|
9
|
+
import (
|
|
10
|
+
"iter"
|
|
11
|
+
"maps"
|
|
12
|
+
"sync"
|
|
13
|
+
)
|
|
10
14
|
|
|
11
15
|
// Map is a simple map with a built-in mutex.
|
|
12
16
|
type Map[Key comparable, Value any] struct {
|
|
@@ -15,8 +19,13 @@ type Map[Key comparable, Value any] struct {
|
|
|
15
19
|
}
|
|
16
20
|
|
|
17
21
|
func NewMap[Key comparable, Value any]() *Map[Key, Value] {
|
|
22
|
+
return NewMapWithData(make(map[Key]Value))
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
// NewMapWithData constructs a Map with the given map as data. Accessing the map directly after passing it here is not safe.
|
|
26
|
+
func NewMapWithData[Key comparable, Value any](data map[Key]Value) *Map[Key, Value] {
|
|
18
27
|
return &Map[Key, Value]{
|
|
19
|
-
data:
|
|
28
|
+
data: data,
|
|
20
29
|
}
|
|
21
30
|
}
|
|
22
31
|
|
|
@@ -77,18 +86,50 @@ func (sm *Map[Key, Value]) GetOrSet(key Key, value Value) (actual Value, wasGet
|
|
|
77
86
|
return
|
|
78
87
|
}
|
|
79
88
|
|
|
89
|
+
// Clear removes all items from the map.
|
|
90
|
+
func (sm *Map[Key, Value]) Clear() {
|
|
91
|
+
sm.lock.Lock()
|
|
92
|
+
clear(sm.data)
|
|
93
|
+
sm.lock.Unlock()
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
// Len returns the number of items in the map.
|
|
97
|
+
func (sm *Map[Key, Value]) Len() int {
|
|
98
|
+
sm.lock.RLock()
|
|
99
|
+
l := len(sm.data)
|
|
100
|
+
sm.lock.RUnlock()
|
|
101
|
+
return l
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
// CopyFrom copies all key/value pairs from the given map into this map, overriding any existing keys.
|
|
105
|
+
// Keys present in this map but not in the given map are not removed.
|
|
106
|
+
func (sm *Map[Key, Value]) CopyFrom(other map[Key]Value) {
|
|
107
|
+
sm.lock.Lock()
|
|
108
|
+
maps.Copy(sm.data, other)
|
|
109
|
+
sm.lock.Unlock()
|
|
110
|
+
}
|
|
111
|
+
|
|
80
112
|
// Clone returns a copy of the map.
|
|
81
113
|
func (sm *Map[Key, Value]) Clone() *Map[Key, Value] {
|
|
82
|
-
return
|
|
114
|
+
return NewMapWithData(sm.CopyData())
|
|
83
115
|
}
|
|
84
116
|
|
|
85
117
|
// CopyData returns a copy of the data in the map as a normal (non-atomic) map.
|
|
86
118
|
func (sm *Map[Key, Value]) CopyData() map[Key]Value {
|
|
87
119
|
sm.lock.RLock()
|
|
88
|
-
copied :=
|
|
89
|
-
for key, value := range sm.data {
|
|
90
|
-
copied[key] = value
|
|
91
|
-
}
|
|
120
|
+
copied := maps.Clone(sm.data)
|
|
92
121
|
sm.lock.RUnlock()
|
|
93
122
|
return copied
|
|
94
123
|
}
|
|
124
|
+
|
|
125
|
+
func (sm *Map[Key, Value]) Iter() iter.Seq2[Key, Value] {
|
|
126
|
+
return func(yield func(Key, Value) bool) {
|
|
127
|
+
sm.lock.RLock()
|
|
128
|
+
defer sm.lock.RUnlock()
|
|
129
|
+
for k, v := range sm.data {
|
|
130
|
+
if !yield(k, v) {
|
|
131
|
+
return
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
}
|
|
@@ -7,6 +7,7 @@
|
|
|
7
7
|
package exsync
|
|
8
8
|
|
|
9
9
|
import (
|
|
10
|
+
"iter"
|
|
10
11
|
"sync"
|
|
11
12
|
)
|
|
12
13
|
|
|
@@ -134,3 +135,15 @@ func (s *Set[T]) AsList() []T {
|
|
|
134
135
|
s.l.RUnlock()
|
|
135
136
|
return list
|
|
136
137
|
}
|
|
138
|
+
|
|
139
|
+
func (s *Set[T]) Iter() iter.Seq[T] {
|
|
140
|
+
return func(yield func(T) bool) {
|
|
141
|
+
s.l.RLock()
|
|
142
|
+
defer s.l.RUnlock()
|
|
143
|
+
for item := range s.m {
|
|
144
|
+
if !yield(item) {
|
|
145
|
+
return
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
}
|