slidge-whatsapp 0.3.0b0__cp311-cp311-manylinux_2_36_aarch64.whl → 0.3.4__cp311-cp311-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.

Files changed (167) hide show
  1. slidge_whatsapp/contact.py +2 -0
  2. slidge_whatsapp/event.go +72 -22
  3. slidge_whatsapp/generated/_whatsapp.cpython-311-aarch64-linux-gnu.h +199 -199
  4. slidge_whatsapp/generated/_whatsapp.cpython-311-aarch64-linux-gnu.so +0 -0
  5. slidge_whatsapp/generated/build.py +156 -156
  6. slidge_whatsapp/generated/go.py +1 -1
  7. slidge_whatsapp/generated/whatsapp.c +1543 -1543
  8. slidge_whatsapp/generated/whatsapp.go +1203 -1203
  9. slidge_whatsapp/generated/whatsapp.py +1377 -1377
  10. slidge_whatsapp/generated/whatsapp_go.h +199 -199
  11. slidge_whatsapp/go.mod +11 -11
  12. slidge_whatsapp/go.sum +26 -26
  13. slidge_whatsapp/session.go +4 -4
  14. slidge_whatsapp/vendor/github.com/ebitengine/purego/README.md +21 -5
  15. slidge_whatsapp/vendor/github.com/ebitengine/purego/abi_loong64.h +60 -0
  16. slidge_whatsapp/vendor/github.com/ebitengine/purego/cgo.go +1 -1
  17. slidge_whatsapp/vendor/github.com/ebitengine/purego/dlerror.go +1 -1
  18. slidge_whatsapp/vendor/github.com/ebitengine/purego/dlfcn.go +1 -1
  19. slidge_whatsapp/vendor/github.com/ebitengine/purego/dlfcn_netbsd.go +15 -0
  20. slidge_whatsapp/vendor/github.com/ebitengine/purego/dlfcn_nocgo_netbsd.go +9 -0
  21. slidge_whatsapp/vendor/github.com/ebitengine/purego/dlfcn_stubs.s +1 -1
  22. slidge_whatsapp/vendor/github.com/ebitengine/purego/func.go +113 -60
  23. slidge_whatsapp/vendor/github.com/ebitengine/purego/gen.go +6 -0
  24. slidge_whatsapp/vendor/github.com/ebitengine/purego/go_runtime.go +1 -1
  25. slidge_whatsapp/vendor/github.com/ebitengine/purego/internal/cgo/dlfcn_cgo_unix.go +2 -2
  26. slidge_whatsapp/vendor/github.com/ebitengine/purego/internal/cgo/syscall_cgo_unix.go +2 -2
  27. slidge_whatsapp/vendor/github.com/ebitengine/purego/internal/fakecgo/abi_loong64.h +60 -0
  28. slidge_whatsapp/vendor/github.com/ebitengine/purego/internal/fakecgo/asm_loong64.s +40 -0
  29. slidge_whatsapp/vendor/github.com/ebitengine/purego/internal/fakecgo/callbacks.go +1 -1
  30. slidge_whatsapp/vendor/github.com/ebitengine/purego/internal/fakecgo/doc.go +1 -1
  31. slidge_whatsapp/vendor/github.com/ebitengine/purego/internal/fakecgo/go_libinit.go +1 -1
  32. slidge_whatsapp/vendor/github.com/ebitengine/purego/internal/fakecgo/go_linux_loong64.go +92 -0
  33. slidge_whatsapp/vendor/github.com/ebitengine/purego/internal/fakecgo/go_netbsd.go +106 -0
  34. slidge_whatsapp/vendor/github.com/ebitengine/purego/internal/fakecgo/go_setenv.go +1 -1
  35. slidge_whatsapp/vendor/github.com/ebitengine/purego/internal/fakecgo/go_util.go +1 -1
  36. slidge_whatsapp/vendor/github.com/ebitengine/purego/internal/fakecgo/iscgo.go +1 -1
  37. slidge_whatsapp/vendor/github.com/ebitengine/purego/internal/fakecgo/libcgo.go +1 -1
  38. slidge_whatsapp/vendor/github.com/ebitengine/purego/internal/fakecgo/libcgo_darwin.go +4 -0
  39. slidge_whatsapp/vendor/github.com/ebitengine/purego/internal/fakecgo/libcgo_freebsd.go +4 -0
  40. slidge_whatsapp/vendor/github.com/ebitengine/purego/internal/fakecgo/libcgo_linux.go +4 -0
  41. slidge_whatsapp/vendor/github.com/ebitengine/purego/internal/fakecgo/libcgo_netbsd.go +26 -0
  42. slidge_whatsapp/vendor/github.com/ebitengine/purego/internal/fakecgo/netbsd.go +23 -0
  43. slidge_whatsapp/vendor/github.com/ebitengine/purego/internal/fakecgo/setenv.go +1 -1
  44. slidge_whatsapp/vendor/github.com/ebitengine/purego/internal/fakecgo/symbols.go +11 -1
  45. slidge_whatsapp/vendor/github.com/ebitengine/purego/internal/fakecgo/symbols_darwin.go +1 -0
  46. slidge_whatsapp/vendor/github.com/ebitengine/purego/internal/fakecgo/symbols_freebsd.go +1 -0
  47. slidge_whatsapp/vendor/github.com/ebitengine/purego/internal/fakecgo/symbols_linux.go +1 -0
  48. slidge_whatsapp/vendor/github.com/ebitengine/purego/internal/fakecgo/symbols_netbsd.go +30 -0
  49. slidge_whatsapp/vendor/github.com/ebitengine/purego/internal/fakecgo/trampolines_loong64.s +71 -0
  50. slidge_whatsapp/vendor/github.com/ebitengine/purego/internal/fakecgo/trampolines_stubs.s +5 -1
  51. slidge_whatsapp/vendor/github.com/ebitengine/purego/nocgo.go +1 -1
  52. slidge_whatsapp/vendor/github.com/ebitengine/purego/struct_amd64.go +8 -4
  53. slidge_whatsapp/vendor/github.com/ebitengine/purego/struct_arm64.go +16 -6
  54. slidge_whatsapp/vendor/github.com/ebitengine/purego/struct_loong64.go +190 -0
  55. slidge_whatsapp/vendor/github.com/ebitengine/purego/struct_other.go +6 -2
  56. slidge_whatsapp/vendor/github.com/ebitengine/purego/sys_amd64.s +1 -1
  57. slidge_whatsapp/vendor/github.com/ebitengine/purego/sys_arm64.s +1 -1
  58. slidge_whatsapp/vendor/github.com/ebitengine/purego/sys_loong64.s +96 -0
  59. slidge_whatsapp/vendor/github.com/ebitengine/purego/sys_unix_arm64.s +1 -1
  60. slidge_whatsapp/vendor/github.com/ebitengine/purego/sys_unix_loong64.s +75 -0
  61. slidge_whatsapp/vendor/github.com/ebitengine/purego/syscall.go +6 -3
  62. slidge_whatsapp/vendor/github.com/ebitengine/purego/syscall_cgo_linux.go +3 -3
  63. slidge_whatsapp/vendor/github.com/ebitengine/purego/syscall_sysv.go +13 -10
  64. slidge_whatsapp/vendor/github.com/ebitengine/purego/syscall_windows.go +1 -1
  65. slidge_whatsapp/vendor/github.com/ebitengine/purego/zcallback_amd64.s +2002 -2002
  66. slidge_whatsapp/vendor/github.com/ebitengine/purego/zcallback_arm64.s +4002 -4002
  67. slidge_whatsapp/vendor/github.com/ebitengine/purego/zcallback_loong64.s +4014 -0
  68. slidge_whatsapp/vendor/go.mau.fi/libsignal/session/SessionCipher.go +7 -2
  69. slidge_whatsapp/vendor/go.mau.fi/util/dbutil/log.go +1 -0
  70. slidge_whatsapp/vendor/go.mau.fi/util/dbutil/module.go +119 -0
  71. slidge_whatsapp/vendor/go.mau.fi/util/dbutil/upgradetable.go +3 -34
  72. slidge_whatsapp/vendor/go.mau.fi/util/exbytes/string.go +20 -0
  73. slidge_whatsapp/vendor/go.mau.fi/util/exbytes/writer.go +78 -0
  74. slidge_whatsapp/vendor/go.mau.fi/util/exslices/cast.go +42 -0
  75. slidge_whatsapp/vendor/go.mau.fi/util/exslices/chunk.go +28 -0
  76. slidge_whatsapp/vendor/go.mau.fi/util/exslices/deduplicate.go +67 -0
  77. slidge_whatsapp/vendor/go.mau.fi/util/exslices/diff.go +63 -0
  78. slidge_whatsapp/vendor/go.mau.fi/util/exsync/event.go +15 -1
  79. slidge_whatsapp/vendor/go.mau.fi/util/exsync/syncmap.go +48 -7
  80. slidge_whatsapp/vendor/go.mau.fi/util/exsync/syncset.go +13 -0
  81. slidge_whatsapp/vendor/go.mau.fi/util/jsontime/helpers.go +16 -5
  82. slidge_whatsapp/vendor/go.mau.fi/util/jsontime/integer.go +27 -12
  83. slidge_whatsapp/vendor/go.mau.fi/util/random/string.go +47 -7
  84. slidge_whatsapp/vendor/go.mau.fi/whatsmeow/appstate/decode.go +1 -0
  85. slidge_whatsapp/vendor/go.mau.fi/whatsmeow/appstate/encode.go +60 -15
  86. slidge_whatsapp/vendor/go.mau.fi/whatsmeow/appstate/hash.go +1 -0
  87. slidge_whatsapp/vendor/go.mau.fi/whatsmeow/appstate.go +20 -2
  88. slidge_whatsapp/vendor/go.mau.fi/whatsmeow/armadillomessage.go +2 -2
  89. slidge_whatsapp/vendor/go.mau.fi/whatsmeow/call.go +6 -0
  90. slidge_whatsapp/vendor/go.mau.fi/whatsmeow/errors.go +1 -0
  91. slidge_whatsapp/vendor/go.mau.fi/whatsmeow/group.go +63 -42
  92. slidge_whatsapp/vendor/go.mau.fi/whatsmeow/internals.go +31 -15
  93. slidge_whatsapp/vendor/go.mau.fi/whatsmeow/message.go +77 -26
  94. slidge_whatsapp/vendor/go.mau.fi/whatsmeow/msgsecret.go +23 -0
  95. slidge_whatsapp/vendor/go.mau.fi/whatsmeow/notification.go +5 -1
  96. slidge_whatsapp/vendor/go.mau.fi/whatsmeow/pair.go +22 -23
  97. slidge_whatsapp/vendor/go.mau.fi/whatsmeow/prekeys.go +21 -0
  98. slidge_whatsapp/vendor/go.mau.fi/whatsmeow/proto/waAICommon/WAAICommon.pb.go +7747 -0
  99. slidge_whatsapp/vendor/go.mau.fi/whatsmeow/proto/{waBotMetadata/WABotMetadata.proto → waAICommon/WAAICommon.proto} +269 -9
  100. slidge_whatsapp/vendor/go.mau.fi/whatsmeow/proto/waDeviceCapabilities/WAProtobufsDeviceCapabilities.pb.go +128 -14
  101. slidge_whatsapp/vendor/go.mau.fi/whatsmeow/proto/waDeviceCapabilities/WAProtobufsDeviceCapabilities.proto +10 -0
  102. slidge_whatsapp/vendor/go.mau.fi/whatsmeow/proto/waE2E/WAWebProtobufsE2E.pb.go +8953 -10087
  103. slidge_whatsapp/vendor/go.mau.fi/whatsmeow/proto/waE2E/WAWebProtobufsE2E.proto +216 -330
  104. slidge_whatsapp/vendor/go.mau.fi/whatsmeow/proto/waHistorySync/WAWebProtobufsHistorySync.pb.go +11 -2
  105. slidge_whatsapp/vendor/go.mau.fi/whatsmeow/proto/waHistorySync/WAWebProtobufsHistorySync.proto +1 -0
  106. slidge_whatsapp/vendor/go.mau.fi/whatsmeow/proto/waStatusAttributions/WAStatusAttributions.pb.go +226 -83
  107. slidge_whatsapp/vendor/go.mau.fi/whatsmeow/proto/waStatusAttributions/WAStatusAttributions.proto +14 -0
  108. slidge_whatsapp/vendor/go.mau.fi/whatsmeow/proto/waSyncAction/WASyncAction.pb.go +709 -449
  109. slidge_whatsapp/vendor/go.mau.fi/whatsmeow/proto/waSyncAction/WASyncAction.proto +24 -0
  110. slidge_whatsapp/vendor/go.mau.fi/whatsmeow/proto/waWa6/WAWebProtobufsWa6.pb.go +78 -24
  111. slidge_whatsapp/vendor/go.mau.fi/whatsmeow/proto/waWa6/WAWebProtobufsWa6.proto +6 -0
  112. slidge_whatsapp/vendor/go.mau.fi/whatsmeow/proto/waWeb/WAWebProtobufsWeb.pb.go +528 -267
  113. slidge_whatsapp/vendor/go.mau.fi/whatsmeow/proto/waWeb/WAWebProtobufsWeb.proto +24 -0
  114. slidge_whatsapp/vendor/go.mau.fi/whatsmeow/receipt.go +47 -14
  115. slidge_whatsapp/vendor/go.mau.fi/whatsmeow/request.go +4 -0
  116. slidge_whatsapp/vendor/go.mau.fi/whatsmeow/retry.go +6 -13
  117. slidge_whatsapp/vendor/go.mau.fi/whatsmeow/send.go +130 -62
  118. slidge_whatsapp/vendor/go.mau.fi/whatsmeow/sendfb.go +33 -32
  119. slidge_whatsapp/vendor/go.mau.fi/whatsmeow/store/clientpayload.go +1 -1
  120. slidge_whatsapp/vendor/go.mau.fi/whatsmeow/store/noop.go +16 -0
  121. slidge_whatsapp/vendor/go.mau.fi/whatsmeow/store/sessioncache.go +125 -0
  122. slidge_whatsapp/vendor/go.mau.fi/whatsmeow/store/signal.go +8 -0
  123. slidge_whatsapp/vendor/go.mau.fi/whatsmeow/store/sqlstore/lidmap.go +82 -4
  124. slidge_whatsapp/vendor/go.mau.fi/whatsmeow/store/sqlstore/store.go +135 -55
  125. slidge_whatsapp/vendor/go.mau.fi/whatsmeow/store/sqlstore/upgrades/00-latest-schema.sql +8 -7
  126. slidge_whatsapp/vendor/go.mau.fi/whatsmeow/store/sqlstore/upgrades/11-redacted-phone-contacts.sql +2 -0
  127. slidge_whatsapp/vendor/go.mau.fi/whatsmeow/store/store.go +24 -2
  128. slidge_whatsapp/vendor/go.mau.fi/whatsmeow/types/call.go +6 -5
  129. slidge_whatsapp/vendor/go.mau.fi/whatsmeow/types/jid.go +24 -9
  130. slidge_whatsapp/vendor/go.mau.fi/whatsmeow/types/message.go +7 -1
  131. slidge_whatsapp/vendor/go.mau.fi/whatsmeow/types/user.go +3 -0
  132. slidge_whatsapp/vendor/go.mau.fi/whatsmeow/user.go +43 -3
  133. slidge_whatsapp/vendor/golang.org/x/crypto/curve25519/curve25519.go +7 -4
  134. slidge_whatsapp/vendor/golang.org/x/net/http2/config.go +11 -6
  135. slidge_whatsapp/vendor/golang.org/x/net/http2/config_go125.go +15 -0
  136. slidge_whatsapp/vendor/golang.org/x/net/http2/config_go126.go +15 -0
  137. slidge_whatsapp/vendor/golang.org/x/net/http2/frame.go +24 -1
  138. slidge_whatsapp/vendor/golang.org/x/net/http2/http2.go +0 -1
  139. slidge_whatsapp/vendor/golang.org/x/net/http2/server.go +35 -26
  140. slidge_whatsapp/vendor/golang.org/x/net/http2/transport.go +4 -2
  141. slidge_whatsapp/vendor/golang.org/x/net/http2/writesched.go +2 -0
  142. slidge_whatsapp/vendor/golang.org/x/net/http2/{writesched_priority.go → writesched_priority_rfc7540.go} +52 -52
  143. slidge_whatsapp/vendor/golang.org/x/net/http2/writesched_priority_rfc9128.go +209 -0
  144. slidge_whatsapp/vendor/golang.org/x/net/http2/writesched_roundrobin.go +1 -1
  145. slidge_whatsapp/vendor/golang.org/x/net/internal/httpcommon/request.go +2 -2
  146. slidge_whatsapp/vendor/golang.org/x/net/internal/socks/socks.go +1 -1
  147. slidge_whatsapp/vendor/golang.org/x/sys/unix/affinity_linux.go +9 -0
  148. slidge_whatsapp/vendor/golang.org/x/sys/unix/fdset.go +1 -3
  149. slidge_whatsapp/vendor/golang.org/x/sys/unix/ifreq_linux.go +1 -3
  150. slidge_whatsapp/vendor/golang.org/x/sys/unix/mkall.sh +1 -0
  151. slidge_whatsapp/vendor/golang.org/x/sys/unix/syscall_linux.go +1 -3
  152. slidge_whatsapp/vendor/golang.org/x/sys/unix/syscall_netbsd.go +17 -0
  153. slidge_whatsapp/vendor/golang.org/x/sys/windows/syscall_windows.go +2 -0
  154. slidge_whatsapp/vendor/golang.org/x/sys/windows/types_windows.go +16 -0
  155. slidge_whatsapp/vendor/golang.org/x/sys/windows/zsyscall_windows.go +18 -0
  156. slidge_whatsapp/vendor/golang.org/x/text/unicode/bidi/core.go +2 -9
  157. slidge_whatsapp/vendor/google.golang.org/protobuf/internal/filedesc/desc.go +35 -17
  158. slidge_whatsapp/vendor/google.golang.org/protobuf/internal/filedesc/desc_init.go +14 -0
  159. slidge_whatsapp/vendor/google.golang.org/protobuf/internal/filedesc/desc_lazy.go +20 -0
  160. slidge_whatsapp/vendor/google.golang.org/protobuf/internal/version/version.go +1 -1
  161. slidge_whatsapp/vendor/modules.txt +15 -13
  162. {slidge_whatsapp-0.3.0b0.dist-info → slidge_whatsapp-0.3.4.dist-info}/METADATA +4 -3
  163. {slidge_whatsapp-0.3.0b0.dist-info → slidge_whatsapp-0.3.4.dist-info}/RECORD +166 -138
  164. {slidge_whatsapp-0.3.0b0.dist-info → slidge_whatsapp-0.3.4.dist-info}/WHEEL +1 -1
  165. slidge_whatsapp/vendor/go.mau.fi/whatsmeow/proto/waBotMetadata/WABotMetadata.pb.go +0 -5156
  166. {slidge_whatsapp-0.3.0b0.dist-info → slidge_whatsapp-0.3.4.dist-info}/entry_points.txt +0 -0
  167. {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 != nil {
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 != nil {
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 either the event to happen within the given timeout.
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 "sync"
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: make(map[Key]Value),
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 &Map[Key, Value]{data: sm.CopyData()}
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 := make(map[Key]Value, len(sm.data))
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
+ }