diff --git a/go.mod b/go.mod
index 892d0f7..58826c0 100644
--- a/go.mod
+++ b/go.mod
@@ -17,7 +17,7 @@ require (
github.com/etkecc/go-secgen v1.4.0
github.com/etkecc/go-validator/v2 v2.2.6
github.com/fsnotify/fsnotify v1.9.0
- github.com/gabriel-vasile/mimetype v1.4.11
+ github.com/gabriel-vasile/mimetype v1.4.12
github.com/getsentry/sentry-go v0.40.0
github.com/jhillyerd/enmime/v2 v2.2.0
github.com/kvannotten/mailstrip v0.0.0-20200711213611-0002f5c0467e
@@ -26,9 +26,9 @@ require (
github.com/raja/argon2pw v1.0.2-0.20210910183755-a391af63bd39
github.com/rs/zerolog v1.34.0
github.com/swaggo/swag v1.16.3
- golang.org/x/exp v0.0.0-20251125195548-87e1e737ad39
- maunium.net/go/mautrix v0.26.0
- modernc.org/sqlite v1.40.1
+ golang.org/x/exp v0.0.0-20251219203646-944ab1f22d93
+ maunium.net/go/mautrix v0.26.1
+ modernc.org/sqlite v1.41.0
)
require (
@@ -39,7 +39,7 @@ require (
github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578 // indirect
github.com/buger/jsonparser v1.1.1 // indirect
github.com/cention-sany/utf7 v0.0.0-20170124080048-26cad61bd60a // indirect
- github.com/clipperhouse/displaywidth v0.6.1 // indirect
+ github.com/clipperhouse/displaywidth v0.6.2 // indirect
github.com/clipperhouse/stringish v0.1.1 // indirect
github.com/clipperhouse/uax29/v2 v2.3.0 // indirect
github.com/dustin/go-humanize v1.0.1 // indirect
@@ -74,12 +74,12 @@ require (
github.com/tidwall/pretty v1.2.1 // indirect
github.com/tidwall/sjson v1.2.5 // indirect
github.com/yuin/goldmark v1.7.13 // indirect
- go.mau.fi/util v0.9.3 // indirect
+ go.mau.fi/util v0.9.4 // indirect
golang.org/x/crypto v0.46.0 // indirect
golang.org/x/net v0.48.0 // indirect
golang.org/x/sys v0.39.0 // indirect
golang.org/x/text v0.32.0 // indirect
- golang.org/x/tools v0.39.0 // indirect
+ golang.org/x/tools v0.40.0 // indirect
gopkg.in/yaml.v2 v2.4.0 // indirect
modernc.org/libc v1.67.1 // indirect
modernc.org/mathutil v1.7.1 // indirect
diff --git a/go.sum b/go.sum
index 8d68c1c..d288f7d 100644
--- a/go.sum
+++ b/go.sum
@@ -16,8 +16,8 @@ github.com/buger/jsonparser v1.1.1 h1:2PnMjfWD7wBILjqQbt530v576A/cAbQvEW9gGIpYMU
github.com/buger/jsonparser v1.1.1/go.mod h1:6RYKKt7H4d4+iWqouImQ9R2FZql3VbhNgx27UK13J/0=
github.com/cention-sany/utf7 v0.0.0-20170124080048-26cad61bd60a h1:MISbI8sU/PSK/ztvmWKFcI7UGb5/HQT7B+i3a2myKgI=
github.com/cention-sany/utf7 v0.0.0-20170124080048-26cad61bd60a/go.mod h1:2GxOXOlEPAMFPfp014mK1SWq8G8BN8o7/dfYqJrVGn8=
-github.com/clipperhouse/displaywidth v0.6.1 h1:/zMlAezfDzT2xy6acHBzwIfyu2ic0hgkT83UX5EY2gY=
-github.com/clipperhouse/displaywidth v0.6.1/go.mod h1:R+kHuzaYWFkTm7xoMmK1lFydbci4X2CicfbGstSGg0o=
+github.com/clipperhouse/displaywidth v0.6.2 h1:ZDpTkFfpHOKte4RG5O/BOyf3ysnvFswpyYrV7z2uAKo=
+github.com/clipperhouse/displaywidth v0.6.2/go.mod h1:R+kHuzaYWFkTm7xoMmK1lFydbci4X2CicfbGstSGg0o=
github.com/clipperhouse/stringish v0.1.1 h1:+NSqMOr3GR6k1FdRhhnXrLfztGzuG+VuFDfatpWHKCs=
github.com/clipperhouse/stringish v0.1.1/go.mod h1:v/WhFtE1q0ovMta2+m+UbpZ+2/HEXNWYXQgCt4hdOzA=
github.com/clipperhouse/uax29/v2 v2.3.0 h1:SNdx9DVUqMoBuBoW3iLOj4FQv3dN5mDtuqwuhIGpJy4=
@@ -59,8 +59,8 @@ github.com/fatih/color v1.18.0 h1:S8gINlzdQ840/4pfAwic/ZE0djQEH3wM94VfqLTZcOM=
github.com/fatih/color v1.18.0/go.mod h1:4FelSpRwEGDpQ12mAdzqdOukCy4u8WUtOY6lkT/6HfU=
github.com/fsnotify/fsnotify v1.9.0 h1:2Ml+OJNzbYCTzsxtv8vKSFD9PbJjmhYF14k/jKC7S9k=
github.com/fsnotify/fsnotify v1.9.0/go.mod h1:8jBTzvmWwFyi3Pb8djgCCO5IBqzKJ/Jwo8TRcHyHii0=
-github.com/gabriel-vasile/mimetype v1.4.11 h1:AQvxbp830wPhHTqc1u7nzoLT+ZFxGY7emj5DR5DYFik=
-github.com/gabriel-vasile/mimetype v1.4.11/go.mod h1:d+9Oxyo1wTzWdyVUPMmXFvp4F9tea18J8ufA774AB3s=
+github.com/gabriel-vasile/mimetype v1.4.12 h1:e9hWvmLYvtp846tLHam2o++qitpguFiYCKbn0w9jyqw=
+github.com/gabriel-vasile/mimetype v1.4.12/go.mod h1:d+9Oxyo1wTzWdyVUPMmXFvp4F9tea18J8ufA774AB3s=
github.com/getsentry/sentry-go v0.40.0 h1:VTJMN9zbTvqDqPwheRVLcp0qcUcM+8eFivvGocAaSbo=
github.com/getsentry/sentry-go v0.40.0/go.mod h1:eRXCoh3uvmjQLY6qu63BjUZnaBu5L5WhMV1RwYO8W5s=
github.com/go-errors/errors v1.4.2 h1:J6MZopCL4uSllY1OfXM374weqZFFItUbrImctkmUxIA=
@@ -175,16 +175,16 @@ github.com/tidwall/sjson v1.2.5 h1:kLy8mja+1c9jlljvWTlSazM7cKDRfJuR/bOJhcY5NcY=
github.com/tidwall/sjson v1.2.5/go.mod h1:Fvgq9kS/6ociJEDnK0Fk1cpYF4FIW6ZF7LAe+6jwd28=
github.com/yuin/goldmark v1.7.13 h1:GPddIs617DnBLFFVJFgpo1aBfe/4xcvMc3SB5t/D0pA=
github.com/yuin/goldmark v1.7.13/go.mod h1:ip/1k0VRfGynBgxOz0yCqHrbZXhcjxyuS66Brc7iBKg=
-go.mau.fi/util v0.9.3 h1:aqNF8KDIN8bFpFbybSk+mEBil7IHeBwlujfyTnvP0uU=
-go.mau.fi/util v0.9.3/go.mod h1:krWWfBM1jWTb5f8NCa2TLqWMQuM81X7TGQjhMjBeXmQ=
+go.mau.fi/util v0.9.4 h1:gWdUff+K2rCynRPysXalqqQyr2ahkSWaestH6YhSpso=
+go.mau.fi/util v0.9.4/go.mod h1:647nVfwUvuhlZFOnro3aRNPmRd2y3iDha9USb8aKSmM=
go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto=
go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE=
golang.org/x/crypto v0.46.0 h1:cKRW/pmt1pKAfetfu+RCEvjvZkA9RimPbh7bhFjGVBU=
golang.org/x/crypto v0.46.0/go.mod h1:Evb/oLKmMraqjZ2iQTwDwvCtJkczlDuTmdJXoZVzqU0=
-golang.org/x/exp v0.0.0-20251125195548-87e1e737ad39 h1:DHNhtq3sNNzrvduZZIiFyXWOL9IWaDPHqTnLJp+rCBY=
-golang.org/x/exp v0.0.0-20251125195548-87e1e737ad39/go.mod h1:46edojNIoXTNOhySWIWdix628clX9ODXwPsQuG6hsK0=
-golang.org/x/mod v0.30.0 h1:fDEXFVZ/fmCKProc/yAXXUijritrDzahmwwefnjoPFk=
-golang.org/x/mod v0.30.0/go.mod h1:lAsf5O2EvJeSFMiBxXDki7sCgAxEUcZHXoXMKT4GJKc=
+golang.org/x/exp v0.0.0-20251219203646-944ab1f22d93 h1:fQsdNF2N+/YewlRZiricy4P1iimyPKZ/xwniHj8Q2a0=
+golang.org/x/exp v0.0.0-20251219203646-944ab1f22d93/go.mod h1:EPRbTFwzwjXj9NpYyyrvenVh9Y+GFeEvMNh7Xuz7xgU=
+golang.org/x/mod v0.31.0 h1:HaW9xtz0+kOcWKwli0ZXy79Ix+UW/vOfmWI5QVd2tgI=
+golang.org/x/mod v0.31.0/go.mod h1:43JraMp9cGx1Rx3AqioxrbrhNsLl2l/iNAvuBkrezpg=
golang.org/x/net v0.0.0-20180911220305-26e67e76b6c3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20210421230115-4e50805a0758/go.mod h1:72T/g9IO56b78aLF+1Kcs5dz7/ng1VjMUvfKvpfy+jM=
golang.org/x/net v0.48.0 h1:zyQRTTrjc33Lhh0fBgT/H3oZq9WuvRR5gPC70xpDiQU=
@@ -206,8 +206,8 @@ golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
golang.org/x/text v0.32.0 h1:ZD01bjUt1FQ9WJ0ClOL5vxgxOI/sVCNgX1YtKwcY0mU=
golang.org/x/text v0.32.0/go.mod h1:o/rUWzghvpD5TXrTIBuJU77MTaN0ljMWE47kxGJQ7jY=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
-golang.org/x/tools v0.39.0 h1:ik4ho21kwuQln40uelmciQPp9SipgNDdrafrYA4TmQQ=
-golang.org/x/tools v0.39.0/go.mod h1:JnefbkDPyD8UU2kI5fuf8ZX4/yUeh9W877ZeBONxUqQ=
+golang.org/x/tools v0.40.0 h1:yLkxfA+Qnul4cs9QA3KnlFu0lVmd8JJfoq+E41uSutA=
+golang.org/x/tools v0.40.0/go.mod h1:Ik/tzLRlbscWpqqMRjyWYDisX8bG13FrdXp3o4Sr9lc=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
@@ -220,8 +220,8 @@ gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C
gopkg.in/yaml.v3 v3.0.0-20200615113413-eeeca48fe776/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
-maunium.net/go/mautrix v0.26.0 h1:valc2VmZF+oIY4bMq4Cd5H9cEKMRe8eP4FM7iiaYLxI=
-maunium.net/go/mautrix v0.26.0/go.mod h1:NWMv+243NX/gDrLofJ2nNXJPrG8vzoM+WUCWph85S6Q=
+maunium.net/go/mautrix v0.26.1 h1:FWCC1xY5vwJ5ou3duEBjB6w9IIlwfc9el3q3Mju3Dlg=
+maunium.net/go/mautrix v0.26.1/go.mod h1:UySSpb8OqXG1sMJ6dDqyzmfcqr2ayZK+KzwqOTAkAOM=
modernc.org/cc/v4 v4.27.1 h1:9W30zRlYrefrDV2JE2O8VDtJ1yPGownxciz5rrbQZis=
modernc.org/cc/v4 v4.27.1/go.mod h1:uVtb5OGqUKpoLWhqwNQo/8LwvoiEBLvZXIQ/SmO6mL0=
modernc.org/ccgo/v4 v4.30.1 h1:4r4U1J6Fhj98NKfSjnPUN7Ze2c6MnAdL0hWw6+LrJpc=
@@ -244,8 +244,8 @@ modernc.org/opt v0.1.4 h1:2kNGMRiUjrp4LcaPuLY2PzUfqM/w9N23quVwhKt5Qm8=
modernc.org/opt v0.1.4/go.mod h1:03fq9lsNfvkYSfxrfUhZCWPk1lm4cq4N+Bh//bEtgns=
modernc.org/sortutil v1.2.1 h1:+xyoGf15mM3NMlPDnFqrteY07klSFxLElE2PVuWIJ7w=
modernc.org/sortutil v1.2.1/go.mod h1:7ZI3a3REbai7gzCLcotuw9AC4VZVpYMjDzETGsSMqJE=
-modernc.org/sqlite v1.40.1 h1:VfuXcxcUWWKRBuP8+BR9L7VnmusMgBNNnBYGEe9w/iY=
-modernc.org/sqlite v1.40.1/go.mod h1:9fjQZ0mB1LLP0GYrp39oOJXx/I2sxEnZtzCmEQIKvGE=
+modernc.org/sqlite v1.41.0 h1:bJXddp4ZpsqMsNN1vS0jWo4IJTZzb8nWpcgvyCFG9Ck=
+modernc.org/sqlite v1.41.0/go.mod h1:9fjQZ0mB1LLP0GYrp39oOJXx/I2sxEnZtzCmEQIKvGE=
modernc.org/strutil v1.2.1 h1:UneZBkQA+DX2Rp35KcM69cSsNES9ly8mQWD71HKlOA0=
modernc.org/strutil v1.2.1/go.mod h1:EHkiggD70koQxjVdSBM3JKM7k6L0FbGE5eymy9i3B9A=
modernc.org/token v1.1.0 h1:Xl7Ap9dKaEs5kLoOQeQmPWevfnk/DM5qcLcYlA8ys6Y=
diff --git a/internal/bot/sync.go b/internal/bot/sync.go
index bfbbb1e..929aed1 100644
--- a/internal/bot/sync.go
+++ b/internal/bot/sync.go
@@ -91,6 +91,13 @@ func (b *Bot) onReaction(ctx context.Context, evt *event.Event) {
// onBotJoin handles the "bot joined the room" event
func (b *Bot) onBotJoin(ctx context.Context) {
evt := eventFromContext(ctx)
+
+ // do not send introduction/help messages to mailbox rooms where just a profile change occurred
+ cfg, err := b.cfg.GetRoom(ctx, evt.RoomID)
+ if err == nil && cfg.Mailbox() != "" {
+ return
+ }
+
// Workaround for membership=join events which are delivered to us twice,
// as described in this bug report: https://github.com/matrix-org/synapse/issues/9768
_, ok := b.handledMembershipEvents.LoadOrStore(evt.ID, true)
diff --git a/vendor/github.com/clipperhouse/displaywidth/trie.go b/vendor/github.com/clipperhouse/displaywidth/trie.go
index c63ed32..b03f882 100644
--- a/vendor/github.com/clipperhouse/displaywidth/trie.go
+++ b/vendor/github.com/clipperhouse/displaywidth/trie.go
@@ -10,14 +10,10 @@ type property uint8
const (
// Always 0 width, includes combining marks, control characters, non-printable, etc
_Zero_Width property = iota + 1
- // Always 2 wide (East Asian Wide F/W)
- _East_Asian_Wide
+ // Always 2 wide (East Asian Wide F/W, Emoji, Regional Indicator)
+ _Wide
// Width depends on EastAsianWidth option
_East_Asian_Ambiguous
- // Extended_Pictographic + Emoji_Presentation
- _Emoji
- // Regional Indicator symbols (used in flag emoji pairs)
- _Regional_Indicator
)
// lookup returns the trie value for the first UTF-8 encoding in s and
@@ -83,7 +79,7 @@ func lookup[T stringish.Interface](s T) (v uint8, sz int) {
return 0, 1
}
-// stringWidthTrie. Total size: 17792 bytes (17.38 KiB). Checksum: a03a02693a639d4a.
+// stringWidthTrie. Total size: 17664 bytes (17.25 KiB). Checksum: c77d82ff2d69f0d2.
// type stringWidthTrie struct { }
// func newStringWidthTrie(i int) *stringWidthTrie {
@@ -98,9 +94,9 @@ func lookupValue(n uint32, b byte) uint8 {
}
}
-// stringWidthValues: 248 blocks, 15872 entries, 15872 bytes
+// stringWidthValues: 246 blocks, 15744 entries, 15744 bytes
// The third block is the zero block.
-var stringWidthValues = [15872]uint8{
+var stringWidthValues = [15744]uint8{
// Block 0x0, offset 0x0
// Block 0x1, offset 0x40
// Block 0x2, offset 0x80
@@ -579,13 +575,13 @@ var stringWidthValues = [15872]uint8{
0x167f: 0x0003,
// Block 0x5a, offset 0x1680
0x1692: 0x0003,
- 0x169a: 0x0004, 0x169b: 0x0004,
+ 0x169a: 0x0002, 0x169b: 0x0002,
0x16a9: 0x0002,
0x16aa: 0x0002,
// Block 0x5b, offset 0x16c0
- 0x16e9: 0x0004,
- 0x16ea: 0x0004, 0x16eb: 0x0004, 0x16ec: 0x0004,
- 0x16f0: 0x0004, 0x16f3: 0x0004,
+ 0x16e9: 0x0002,
+ 0x16ea: 0x0002, 0x16eb: 0x0002, 0x16ec: 0x0002,
+ 0x16f0: 0x0002, 0x16f3: 0x0002,
// Block 0x5c, offset 0x1700
0x1720: 0x0003, 0x1721: 0x0003, 0x1722: 0x0003, 0x1723: 0x0003,
0x1724: 0x0003, 0x1725: 0x0003, 0x1726: 0x0003, 0x1727: 0x0003, 0x1728: 0x0003, 0x1729: 0x0003,
@@ -644,63 +640,63 @@ var stringWidthValues = [15872]uint8{
0x1862: 0x0003, 0x1863: 0x0003,
0x1864: 0x0003, 0x1865: 0x0003,
0x186f: 0x0003,
- 0x187d: 0x0004, 0x187e: 0x0004,
+ 0x187d: 0x0002, 0x187e: 0x0002,
// Block 0x62, offset 0x1880
0x1885: 0x0003,
0x1886: 0x0003, 0x1889: 0x0003,
0x188e: 0x0003, 0x188f: 0x0003,
- 0x1894: 0x0004, 0x1895: 0x0004,
+ 0x1894: 0x0002, 0x1895: 0x0002,
0x189c: 0x0003,
0x189e: 0x0003,
0x18b0: 0x0002, 0x18b1: 0x0002, 0x18b2: 0x0002, 0x18b3: 0x0002, 0x18b4: 0x0002, 0x18b5: 0x0002,
0x18b6: 0x0002, 0x18b7: 0x0002,
// Block 0x63, offset 0x18c0
0x18c0: 0x0003, 0x18c2: 0x0003,
- 0x18c8: 0x0004, 0x18c9: 0x0004, 0x18ca: 0x0004, 0x18cb: 0x0004,
- 0x18cc: 0x0004, 0x18cd: 0x0004, 0x18ce: 0x0004, 0x18cf: 0x0004, 0x18d0: 0x0004, 0x18d1: 0x0004,
- 0x18d2: 0x0004, 0x18d3: 0x0004,
+ 0x18c8: 0x0002, 0x18c9: 0x0002, 0x18ca: 0x0002, 0x18cb: 0x0002,
+ 0x18cc: 0x0002, 0x18cd: 0x0002, 0x18ce: 0x0002, 0x18cf: 0x0002, 0x18d0: 0x0002, 0x18d1: 0x0002,
+ 0x18d2: 0x0002, 0x18d3: 0x0002,
0x18e0: 0x0003, 0x18e1: 0x0003, 0x18e3: 0x0003,
0x18e4: 0x0003, 0x18e5: 0x0003, 0x18e7: 0x0003, 0x18e8: 0x0003, 0x18e9: 0x0003,
0x18ea: 0x0003, 0x18ec: 0x0003, 0x18ed: 0x0003, 0x18ef: 0x0003,
- 0x18ff: 0x0004,
+ 0x18ff: 0x0002,
// Block 0x64, offset 0x1900
0x190a: 0x0002, 0x190b: 0x0002,
0x190c: 0x0002, 0x190d: 0x0002, 0x190e: 0x0002, 0x190f: 0x0002,
- 0x1913: 0x0004,
- 0x191e: 0x0003, 0x191f: 0x0003, 0x1921: 0x0004,
- 0x192a: 0x0004, 0x192b: 0x0004,
- 0x193d: 0x0004, 0x193e: 0x0004, 0x193f: 0x0003,
+ 0x1913: 0x0002,
+ 0x191e: 0x0003, 0x191f: 0x0003, 0x1921: 0x0002,
+ 0x192a: 0x0002, 0x192b: 0x0002,
+ 0x193d: 0x0002, 0x193e: 0x0002, 0x193f: 0x0003,
// Block 0x65, offset 0x1940
- 0x1944: 0x0004, 0x1945: 0x0004,
+ 0x1944: 0x0002, 0x1945: 0x0002,
0x1946: 0x0003, 0x1947: 0x0003, 0x1948: 0x0003, 0x1949: 0x0003, 0x194a: 0x0003, 0x194b: 0x0003,
- 0x194c: 0x0003, 0x194d: 0x0003, 0x194e: 0x0004, 0x194f: 0x0003, 0x1950: 0x0003, 0x1951: 0x0003,
- 0x1952: 0x0003, 0x1953: 0x0003, 0x1954: 0x0004, 0x1955: 0x0003, 0x1956: 0x0003, 0x1957: 0x0003,
+ 0x194c: 0x0003, 0x194d: 0x0003, 0x194e: 0x0002, 0x194f: 0x0003, 0x1950: 0x0003, 0x1951: 0x0003,
+ 0x1952: 0x0003, 0x1953: 0x0003, 0x1954: 0x0002, 0x1955: 0x0003, 0x1956: 0x0003, 0x1957: 0x0003,
0x1958: 0x0003, 0x1959: 0x0003, 0x195a: 0x0003, 0x195b: 0x0003, 0x195c: 0x0003, 0x195d: 0x0003,
0x195e: 0x0003, 0x195f: 0x0003, 0x1960: 0x0003, 0x1961: 0x0003, 0x1963: 0x0003,
0x1968: 0x0003, 0x1969: 0x0003,
- 0x196a: 0x0004, 0x196b: 0x0003, 0x196c: 0x0003, 0x196d: 0x0003, 0x196e: 0x0003, 0x196f: 0x0003,
- 0x1970: 0x0003, 0x1971: 0x0003, 0x1972: 0x0004, 0x1973: 0x0004, 0x1974: 0x0003, 0x1975: 0x0004,
- 0x1976: 0x0003, 0x1977: 0x0003, 0x1978: 0x0003, 0x1979: 0x0003, 0x197a: 0x0004, 0x197b: 0x0003,
- 0x197c: 0x0003, 0x197d: 0x0004, 0x197e: 0x0003, 0x197f: 0x0003,
+ 0x196a: 0x0002, 0x196b: 0x0003, 0x196c: 0x0003, 0x196d: 0x0003, 0x196e: 0x0003, 0x196f: 0x0003,
+ 0x1970: 0x0003, 0x1971: 0x0003, 0x1972: 0x0002, 0x1973: 0x0002, 0x1974: 0x0003, 0x1975: 0x0002,
+ 0x1976: 0x0003, 0x1977: 0x0003, 0x1978: 0x0003, 0x1979: 0x0003, 0x197a: 0x0002, 0x197b: 0x0003,
+ 0x197c: 0x0003, 0x197d: 0x0002, 0x197e: 0x0003, 0x197f: 0x0003,
// Block 0x66, offset 0x1980
- 0x1985: 0x0004,
- 0x198a: 0x0004, 0x198b: 0x0004,
- 0x19a8: 0x0004,
+ 0x1985: 0x0002,
+ 0x198a: 0x0002, 0x198b: 0x0002,
+ 0x19a8: 0x0002,
0x19bd: 0x0003,
// Block 0x67, offset 0x19c0
- 0x19cc: 0x0004, 0x19ce: 0x0004,
- 0x19d3: 0x0004, 0x19d4: 0x0004, 0x19d5: 0x0004, 0x19d7: 0x0004,
+ 0x19cc: 0x0002, 0x19ce: 0x0002,
+ 0x19d3: 0x0002, 0x19d4: 0x0002, 0x19d5: 0x0002, 0x19d7: 0x0002,
0x19f6: 0x0003, 0x19f7: 0x0003, 0x19f8: 0x0003, 0x19f9: 0x0003, 0x19fa: 0x0003, 0x19fb: 0x0003,
0x19fc: 0x0003, 0x19fd: 0x0003, 0x19fe: 0x0003, 0x19ff: 0x0003,
// Block 0x68, offset 0x1a00
- 0x1a15: 0x0004, 0x1a16: 0x0004, 0x1a17: 0x0004,
- 0x1a30: 0x0004,
- 0x1a3f: 0x0004,
+ 0x1a15: 0x0002, 0x1a16: 0x0002, 0x1a17: 0x0002,
+ 0x1a30: 0x0002,
+ 0x1a3f: 0x0002,
// Block 0x69, offset 0x1a40
- 0x1a5b: 0x0004, 0x1a5c: 0x0004,
+ 0x1a5b: 0x0002, 0x1a5c: 0x0002,
// Block 0x6a, offset 0x1a80
- 0x1a90: 0x0004,
- 0x1a95: 0x0004, 0x1a96: 0x0003, 0x1a97: 0x0003,
+ 0x1a90: 0x0002,
+ 0x1a95: 0x0002, 0x1a96: 0x0003, 0x1a97: 0x0003,
0x1a98: 0x0003, 0x1a99: 0x0003,
// Block 0x6b, offset 0x1ac0
0x1aef: 0x0001,
@@ -1275,9 +1271,9 @@ var stringWidthValues = [15872]uint8{
0x3604: 0x0001, 0x3605: 0x0001,
0x3606: 0x0001, 0x3607: 0x0001, 0x3608: 0x0001, 0x3609: 0x0001, 0x360a: 0x0001,
// Block 0xd9, offset 0x3640
- 0x3644: 0x0004,
+ 0x3644: 0x0002,
// Block 0xda, offset 0x3680
- 0x368f: 0x0004,
+ 0x368f: 0x0002,
// Block 0xdb, offset 0x36c0
0x36c0: 0x0003, 0x36c1: 0x0003, 0x36c2: 0x0003, 0x36c3: 0x0003, 0x36c4: 0x0003, 0x36c5: 0x0003,
0x36c6: 0x0003, 0x36c7: 0x0003, 0x36c8: 0x0003, 0x36c9: 0x0003, 0x36ca: 0x0003,
@@ -1304,252 +1300,228 @@ var stringWidthValues = [15872]uint8{
// Block 0xdd, offset 0x3740
0x3740: 0x0003, 0x3741: 0x0003, 0x3742: 0x0003, 0x3743: 0x0003, 0x3744: 0x0003, 0x3745: 0x0003,
0x3746: 0x0003, 0x3747: 0x0003, 0x3748: 0x0003, 0x3749: 0x0003, 0x374a: 0x0003, 0x374b: 0x0003,
- 0x374c: 0x0003, 0x374d: 0x0003, 0x374e: 0x0004, 0x374f: 0x0003, 0x3750: 0x0003, 0x3751: 0x0004,
- 0x3752: 0x0004, 0x3753: 0x0004, 0x3754: 0x0004, 0x3755: 0x0004, 0x3756: 0x0004, 0x3757: 0x0004,
- 0x3758: 0x0004, 0x3759: 0x0004, 0x375a: 0x0004, 0x375b: 0x0003, 0x375c: 0x0003, 0x375d: 0x0003,
+ 0x374c: 0x0003, 0x374d: 0x0003, 0x374e: 0x0002, 0x374f: 0x0003, 0x3750: 0x0003, 0x3751: 0x0002,
+ 0x3752: 0x0002, 0x3753: 0x0002, 0x3754: 0x0002, 0x3755: 0x0002, 0x3756: 0x0002, 0x3757: 0x0002,
+ 0x3758: 0x0002, 0x3759: 0x0002, 0x375a: 0x0002, 0x375b: 0x0003, 0x375c: 0x0003, 0x375d: 0x0003,
0x375e: 0x0003, 0x375f: 0x0003, 0x3760: 0x0003, 0x3761: 0x0003, 0x3762: 0x0003, 0x3763: 0x0003,
0x3764: 0x0003, 0x3765: 0x0003, 0x3766: 0x0003, 0x3767: 0x0003, 0x3768: 0x0003, 0x3769: 0x0003,
0x376a: 0x0003, 0x376b: 0x0003, 0x376c: 0x0003,
// Block 0xde, offset 0x3780
- 0x37a6: 0x0005, 0x37a7: 0x0005, 0x37a8: 0x0005, 0x37a9: 0x0005,
- 0x37aa: 0x0005, 0x37ab: 0x0005, 0x37ac: 0x0005, 0x37ad: 0x0005, 0x37ae: 0x0005, 0x37af: 0x0005,
- 0x37b0: 0x0005, 0x37b1: 0x0005, 0x37b2: 0x0005, 0x37b3: 0x0005, 0x37b4: 0x0005, 0x37b5: 0x0005,
- 0x37b6: 0x0005, 0x37b7: 0x0005, 0x37b8: 0x0005, 0x37b9: 0x0005, 0x37ba: 0x0005, 0x37bb: 0x0005,
- 0x37bc: 0x0005, 0x37bd: 0x0005, 0x37be: 0x0005, 0x37bf: 0x0005,
+ 0x37a6: 0x0002, 0x37a7: 0x0002, 0x37a8: 0x0002, 0x37a9: 0x0002,
+ 0x37aa: 0x0002, 0x37ab: 0x0002, 0x37ac: 0x0002, 0x37ad: 0x0002, 0x37ae: 0x0002, 0x37af: 0x0002,
+ 0x37b0: 0x0002, 0x37b1: 0x0002, 0x37b2: 0x0002, 0x37b3: 0x0002, 0x37b4: 0x0002, 0x37b5: 0x0002,
+ 0x37b6: 0x0002, 0x37b7: 0x0002, 0x37b8: 0x0002, 0x37b9: 0x0002, 0x37ba: 0x0002, 0x37bb: 0x0002,
+ 0x37bc: 0x0002, 0x37bd: 0x0002, 0x37be: 0x0002, 0x37bf: 0x0002,
// Block 0xdf, offset 0x37c0
- 0x37c0: 0x0002, 0x37c1: 0x0004, 0x37c2: 0x0002,
+ 0x37c0: 0x0002, 0x37c1: 0x0002, 0x37c2: 0x0002,
0x37d0: 0x0002, 0x37d1: 0x0002,
0x37d2: 0x0002, 0x37d3: 0x0002, 0x37d4: 0x0002, 0x37d5: 0x0002, 0x37d6: 0x0002, 0x37d7: 0x0002,
- 0x37d8: 0x0002, 0x37d9: 0x0002, 0x37da: 0x0004, 0x37db: 0x0002, 0x37dc: 0x0002, 0x37dd: 0x0002,
+ 0x37d8: 0x0002, 0x37d9: 0x0002, 0x37da: 0x0002, 0x37db: 0x0002, 0x37dc: 0x0002, 0x37dd: 0x0002,
0x37de: 0x0002, 0x37df: 0x0002, 0x37e0: 0x0002, 0x37e1: 0x0002, 0x37e2: 0x0002, 0x37e3: 0x0002,
0x37e4: 0x0002, 0x37e5: 0x0002, 0x37e6: 0x0002, 0x37e7: 0x0002, 0x37e8: 0x0002, 0x37e9: 0x0002,
- 0x37ea: 0x0002, 0x37eb: 0x0002, 0x37ec: 0x0002, 0x37ed: 0x0002, 0x37ee: 0x0002, 0x37ef: 0x0004,
- 0x37f0: 0x0002, 0x37f1: 0x0002, 0x37f2: 0x0004, 0x37f3: 0x0004, 0x37f4: 0x0004, 0x37f5: 0x0004,
- 0x37f6: 0x0004, 0x37f7: 0x0002, 0x37f8: 0x0004, 0x37f9: 0x0004, 0x37fa: 0x0004, 0x37fb: 0x0002,
+ 0x37ea: 0x0002, 0x37eb: 0x0002, 0x37ec: 0x0002, 0x37ed: 0x0002, 0x37ee: 0x0002, 0x37ef: 0x0002,
+ 0x37f0: 0x0002, 0x37f1: 0x0002, 0x37f2: 0x0002, 0x37f3: 0x0002, 0x37f4: 0x0002, 0x37f5: 0x0002,
+ 0x37f6: 0x0002, 0x37f7: 0x0002, 0x37f8: 0x0002, 0x37f9: 0x0002, 0x37fa: 0x0002, 0x37fb: 0x0002,
// Block 0xe0, offset 0x3800
0x3800: 0x0002, 0x3801: 0x0002, 0x3802: 0x0002, 0x3803: 0x0002, 0x3804: 0x0002, 0x3805: 0x0002,
0x3806: 0x0002, 0x3807: 0x0002, 0x3808: 0x0002,
- 0x3810: 0x0004, 0x3811: 0x0004,
+ 0x3810: 0x0002, 0x3811: 0x0002,
0x3820: 0x0002, 0x3821: 0x0002, 0x3822: 0x0002, 0x3823: 0x0002,
0x3824: 0x0002, 0x3825: 0x0002,
// Block 0xe1, offset 0x3840
- 0x3840: 0x0004, 0x3841: 0x0004, 0x3842: 0x0004, 0x3843: 0x0004, 0x3844: 0x0004, 0x3845: 0x0004,
- 0x3846: 0x0004, 0x3847: 0x0004, 0x3848: 0x0004, 0x3849: 0x0004, 0x384a: 0x0004, 0x384b: 0x0004,
- 0x384c: 0x0004, 0x384d: 0x0004, 0x384e: 0x0004, 0x384f: 0x0004, 0x3850: 0x0004, 0x3851: 0x0004,
- 0x3852: 0x0004, 0x3853: 0x0004, 0x3854: 0x0004, 0x3855: 0x0004, 0x3856: 0x0004, 0x3857: 0x0004,
- 0x3858: 0x0004, 0x3859: 0x0004, 0x385a: 0x0004, 0x385b: 0x0004, 0x385c: 0x0004, 0x385d: 0x0004,
- 0x385e: 0x0004, 0x385f: 0x0004, 0x3860: 0x0004,
- 0x386d: 0x0004, 0x386e: 0x0004, 0x386f: 0x0004,
- 0x3870: 0x0004, 0x3871: 0x0004, 0x3872: 0x0004, 0x3873: 0x0004, 0x3874: 0x0004, 0x3875: 0x0004,
- 0x3877: 0x0004, 0x3878: 0x0004, 0x3879: 0x0004, 0x387a: 0x0004, 0x387b: 0x0004,
- 0x387c: 0x0004, 0x387d: 0x0004, 0x387e: 0x0004, 0x387f: 0x0004,
+ 0x3840: 0x0002, 0x3841: 0x0002, 0x3842: 0x0002, 0x3843: 0x0002, 0x3844: 0x0002, 0x3845: 0x0002,
+ 0x3846: 0x0002, 0x3847: 0x0002, 0x3848: 0x0002, 0x3849: 0x0002, 0x384a: 0x0002, 0x384b: 0x0002,
+ 0x384c: 0x0002, 0x384d: 0x0002, 0x384e: 0x0002, 0x384f: 0x0002, 0x3850: 0x0002, 0x3851: 0x0002,
+ 0x3852: 0x0002, 0x3853: 0x0002, 0x3854: 0x0002, 0x3855: 0x0002, 0x3856: 0x0002, 0x3857: 0x0002,
+ 0x3858: 0x0002, 0x3859: 0x0002, 0x385a: 0x0002, 0x385b: 0x0002, 0x385c: 0x0002, 0x385d: 0x0002,
+ 0x385e: 0x0002, 0x385f: 0x0002, 0x3860: 0x0002,
+ 0x386d: 0x0002, 0x386e: 0x0002, 0x386f: 0x0002,
+ 0x3870: 0x0002, 0x3871: 0x0002, 0x3872: 0x0002, 0x3873: 0x0002, 0x3874: 0x0002, 0x3875: 0x0002,
+ 0x3877: 0x0002, 0x3878: 0x0002, 0x3879: 0x0002, 0x387a: 0x0002, 0x387b: 0x0002,
+ 0x387c: 0x0002, 0x387d: 0x0002, 0x387e: 0x0002, 0x387f: 0x0002,
// Block 0xe2, offset 0x3880
- 0x3880: 0x0004, 0x3881: 0x0004, 0x3882: 0x0004, 0x3883: 0x0004, 0x3884: 0x0004, 0x3885: 0x0004,
- 0x3886: 0x0004, 0x3887: 0x0004, 0x3888: 0x0004, 0x3889: 0x0004, 0x388a: 0x0004, 0x388b: 0x0004,
- 0x388c: 0x0004, 0x388d: 0x0004, 0x388e: 0x0004, 0x388f: 0x0004, 0x3890: 0x0004, 0x3891: 0x0004,
- 0x3892: 0x0004, 0x3893: 0x0004, 0x3894: 0x0004, 0x3895: 0x0004, 0x3896: 0x0004, 0x3897: 0x0004,
- 0x3898: 0x0004, 0x3899: 0x0004, 0x389a: 0x0004, 0x389b: 0x0004, 0x389c: 0x0004, 0x389d: 0x0004,
- 0x389e: 0x0004, 0x389f: 0x0004, 0x38a0: 0x0004, 0x38a1: 0x0004, 0x38a2: 0x0004, 0x38a3: 0x0004,
- 0x38a4: 0x0004, 0x38a5: 0x0004, 0x38a6: 0x0004, 0x38a7: 0x0004, 0x38a8: 0x0004, 0x38a9: 0x0004,
- 0x38aa: 0x0004, 0x38ab: 0x0004, 0x38ac: 0x0004, 0x38ad: 0x0004, 0x38ae: 0x0004, 0x38af: 0x0004,
- 0x38b0: 0x0004, 0x38b1: 0x0004, 0x38b2: 0x0004, 0x38b3: 0x0004, 0x38b4: 0x0004, 0x38b5: 0x0004,
- 0x38b6: 0x0004, 0x38b7: 0x0004, 0x38b8: 0x0004, 0x38b9: 0x0004, 0x38ba: 0x0004, 0x38bb: 0x0004,
- 0x38bc: 0x0004, 0x38be: 0x0004, 0x38bf: 0x0004,
+ 0x3880: 0x0002, 0x3881: 0x0002, 0x3882: 0x0002, 0x3883: 0x0002, 0x3884: 0x0002, 0x3885: 0x0002,
+ 0x3886: 0x0002, 0x3887: 0x0002, 0x3888: 0x0002, 0x3889: 0x0002, 0x388a: 0x0002, 0x388b: 0x0002,
+ 0x388c: 0x0002, 0x388d: 0x0002, 0x388e: 0x0002, 0x388f: 0x0002, 0x3890: 0x0002, 0x3891: 0x0002,
+ 0x3892: 0x0002, 0x3893: 0x0002, 0x3894: 0x0002, 0x3895: 0x0002, 0x3896: 0x0002, 0x3897: 0x0002,
+ 0x3898: 0x0002, 0x3899: 0x0002, 0x389a: 0x0002, 0x389b: 0x0002, 0x389c: 0x0002, 0x389d: 0x0002,
+ 0x389e: 0x0002, 0x389f: 0x0002, 0x38a0: 0x0002, 0x38a1: 0x0002, 0x38a2: 0x0002, 0x38a3: 0x0002,
+ 0x38a4: 0x0002, 0x38a5: 0x0002, 0x38a6: 0x0002, 0x38a7: 0x0002, 0x38a8: 0x0002, 0x38a9: 0x0002,
+ 0x38aa: 0x0002, 0x38ab: 0x0002, 0x38ac: 0x0002, 0x38ad: 0x0002, 0x38ae: 0x0002, 0x38af: 0x0002,
+ 0x38b0: 0x0002, 0x38b1: 0x0002, 0x38b2: 0x0002, 0x38b3: 0x0002, 0x38b4: 0x0002, 0x38b5: 0x0002,
+ 0x38b6: 0x0002, 0x38b7: 0x0002, 0x38b8: 0x0002, 0x38b9: 0x0002, 0x38ba: 0x0002, 0x38bb: 0x0002,
+ 0x38bc: 0x0002, 0x38be: 0x0002, 0x38bf: 0x0002,
// Block 0xe3, offset 0x38c0
- 0x38c0: 0x0004, 0x38c1: 0x0004, 0x38c2: 0x0004, 0x38c3: 0x0004, 0x38c4: 0x0004, 0x38c5: 0x0004,
- 0x38c6: 0x0004, 0x38c7: 0x0004, 0x38c8: 0x0004, 0x38c9: 0x0004, 0x38ca: 0x0004, 0x38cb: 0x0004,
- 0x38cc: 0x0004, 0x38cd: 0x0004, 0x38ce: 0x0004, 0x38cf: 0x0004, 0x38d0: 0x0004, 0x38d1: 0x0004,
- 0x38d2: 0x0004, 0x38d3: 0x0004,
- 0x38e0: 0x0004, 0x38e1: 0x0004, 0x38e2: 0x0004, 0x38e3: 0x0004,
- 0x38e4: 0x0004, 0x38e5: 0x0004, 0x38e6: 0x0004, 0x38e7: 0x0004, 0x38e8: 0x0004, 0x38e9: 0x0004,
- 0x38ea: 0x0004, 0x38eb: 0x0004, 0x38ec: 0x0004, 0x38ed: 0x0004, 0x38ee: 0x0004, 0x38ef: 0x0004,
- 0x38f0: 0x0004, 0x38f1: 0x0004, 0x38f2: 0x0004, 0x38f3: 0x0004, 0x38f4: 0x0004, 0x38f5: 0x0004,
- 0x38f6: 0x0004, 0x38f7: 0x0004, 0x38f8: 0x0004, 0x38f9: 0x0004, 0x38fa: 0x0004, 0x38fb: 0x0004,
- 0x38fc: 0x0004, 0x38fd: 0x0004, 0x38fe: 0x0004, 0x38ff: 0x0004,
+ 0x38c0: 0x0002, 0x38c1: 0x0002, 0x38c2: 0x0002, 0x38c3: 0x0002, 0x38c4: 0x0002, 0x38c5: 0x0002,
+ 0x38c6: 0x0002, 0x38c7: 0x0002, 0x38c8: 0x0002, 0x38c9: 0x0002, 0x38ca: 0x0002, 0x38cb: 0x0002,
+ 0x38cc: 0x0002, 0x38cd: 0x0002, 0x38ce: 0x0002, 0x38cf: 0x0002, 0x38d0: 0x0002, 0x38d1: 0x0002,
+ 0x38d2: 0x0002, 0x38d3: 0x0002,
+ 0x38e0: 0x0002, 0x38e1: 0x0002, 0x38e2: 0x0002, 0x38e3: 0x0002,
+ 0x38e4: 0x0002, 0x38e5: 0x0002, 0x38e6: 0x0002, 0x38e7: 0x0002, 0x38e8: 0x0002, 0x38e9: 0x0002,
+ 0x38ea: 0x0002, 0x38eb: 0x0002, 0x38ec: 0x0002, 0x38ed: 0x0002, 0x38ee: 0x0002, 0x38ef: 0x0002,
+ 0x38f0: 0x0002, 0x38f1: 0x0002, 0x38f2: 0x0002, 0x38f3: 0x0002, 0x38f4: 0x0002, 0x38f5: 0x0002,
+ 0x38f6: 0x0002, 0x38f7: 0x0002, 0x38f8: 0x0002, 0x38f9: 0x0002, 0x38fa: 0x0002, 0x38fb: 0x0002,
+ 0x38fc: 0x0002, 0x38fd: 0x0002, 0x38fe: 0x0002, 0x38ff: 0x0002,
// Block 0xe4, offset 0x3900
- 0x3900: 0x0004, 0x3901: 0x0004, 0x3902: 0x0004, 0x3903: 0x0004, 0x3904: 0x0004, 0x3905: 0x0004,
- 0x3906: 0x0004, 0x3907: 0x0004, 0x3908: 0x0004, 0x3909: 0x0004, 0x390a: 0x0004,
- 0x390f: 0x0004, 0x3910: 0x0004, 0x3911: 0x0004,
- 0x3912: 0x0004, 0x3913: 0x0004,
- 0x3920: 0x0004, 0x3921: 0x0004, 0x3922: 0x0004, 0x3923: 0x0004,
- 0x3924: 0x0004, 0x3925: 0x0004, 0x3926: 0x0004, 0x3927: 0x0004, 0x3928: 0x0004, 0x3929: 0x0004,
- 0x392a: 0x0004, 0x392b: 0x0004, 0x392c: 0x0004, 0x392d: 0x0004, 0x392e: 0x0004, 0x392f: 0x0004,
- 0x3930: 0x0004, 0x3934: 0x0004,
- 0x3938: 0x0004, 0x3939: 0x0004, 0x393a: 0x0004, 0x393b: 0x0002,
+ 0x3900: 0x0002, 0x3901: 0x0002, 0x3902: 0x0002, 0x3903: 0x0002, 0x3904: 0x0002, 0x3905: 0x0002,
+ 0x3906: 0x0002, 0x3907: 0x0002, 0x3908: 0x0002, 0x3909: 0x0002, 0x390a: 0x0002,
+ 0x390f: 0x0002, 0x3910: 0x0002, 0x3911: 0x0002,
+ 0x3912: 0x0002, 0x3913: 0x0002,
+ 0x3920: 0x0002, 0x3921: 0x0002, 0x3922: 0x0002, 0x3923: 0x0002,
+ 0x3924: 0x0002, 0x3925: 0x0002, 0x3926: 0x0002, 0x3927: 0x0002, 0x3928: 0x0002, 0x3929: 0x0002,
+ 0x392a: 0x0002, 0x392b: 0x0002, 0x392c: 0x0002, 0x392d: 0x0002, 0x392e: 0x0002, 0x392f: 0x0002,
+ 0x3930: 0x0002, 0x3934: 0x0002,
+ 0x3938: 0x0002, 0x3939: 0x0002, 0x393a: 0x0002, 0x393b: 0x0002,
0x393c: 0x0002, 0x393d: 0x0002, 0x393e: 0x0002, 0x393f: 0x0002,
// Block 0xe5, offset 0x3940
- 0x3940: 0x0004, 0x3941: 0x0004, 0x3942: 0x0004, 0x3943: 0x0004, 0x3944: 0x0004, 0x3945: 0x0004,
- 0x3946: 0x0004, 0x3947: 0x0004, 0x3948: 0x0004, 0x3949: 0x0004, 0x394a: 0x0004, 0x394b: 0x0004,
- 0x394c: 0x0004, 0x394d: 0x0004, 0x394e: 0x0004, 0x394f: 0x0004, 0x3950: 0x0004, 0x3951: 0x0004,
- 0x3952: 0x0004, 0x3953: 0x0004, 0x3954: 0x0004, 0x3955: 0x0004, 0x3956: 0x0004, 0x3957: 0x0004,
- 0x3958: 0x0004, 0x3959: 0x0004, 0x395a: 0x0004, 0x395b: 0x0004, 0x395c: 0x0004, 0x395d: 0x0004,
- 0x395e: 0x0004, 0x395f: 0x0004, 0x3960: 0x0004, 0x3961: 0x0004, 0x3962: 0x0004, 0x3963: 0x0004,
- 0x3964: 0x0004, 0x3965: 0x0004, 0x3966: 0x0004, 0x3967: 0x0004, 0x3968: 0x0004, 0x3969: 0x0004,
- 0x396a: 0x0004, 0x396b: 0x0004, 0x396c: 0x0004, 0x396d: 0x0004, 0x396e: 0x0004, 0x396f: 0x0004,
- 0x3970: 0x0004, 0x3971: 0x0004, 0x3972: 0x0004, 0x3973: 0x0004, 0x3974: 0x0004, 0x3975: 0x0004,
- 0x3976: 0x0004, 0x3977: 0x0004, 0x3978: 0x0004, 0x3979: 0x0004, 0x397a: 0x0004, 0x397b: 0x0004,
- 0x397c: 0x0004, 0x397d: 0x0004, 0x397e: 0x0004,
+ 0x3940: 0x0002, 0x3941: 0x0002, 0x3942: 0x0002, 0x3943: 0x0002, 0x3944: 0x0002, 0x3945: 0x0002,
+ 0x3946: 0x0002, 0x3947: 0x0002, 0x3948: 0x0002, 0x3949: 0x0002, 0x394a: 0x0002, 0x394b: 0x0002,
+ 0x394c: 0x0002, 0x394d: 0x0002, 0x394e: 0x0002, 0x394f: 0x0002, 0x3950: 0x0002, 0x3951: 0x0002,
+ 0x3952: 0x0002, 0x3953: 0x0002, 0x3954: 0x0002, 0x3955: 0x0002, 0x3956: 0x0002, 0x3957: 0x0002,
+ 0x3958: 0x0002, 0x3959: 0x0002, 0x395a: 0x0002, 0x395b: 0x0002, 0x395c: 0x0002, 0x395d: 0x0002,
+ 0x395e: 0x0002, 0x395f: 0x0002, 0x3960: 0x0002, 0x3961: 0x0002, 0x3962: 0x0002, 0x3963: 0x0002,
+ 0x3964: 0x0002, 0x3965: 0x0002, 0x3966: 0x0002, 0x3967: 0x0002, 0x3968: 0x0002, 0x3969: 0x0002,
+ 0x396a: 0x0002, 0x396b: 0x0002, 0x396c: 0x0002, 0x396d: 0x0002, 0x396e: 0x0002, 0x396f: 0x0002,
+ 0x3970: 0x0002, 0x3971: 0x0002, 0x3972: 0x0002, 0x3973: 0x0002, 0x3974: 0x0002, 0x3975: 0x0002,
+ 0x3976: 0x0002, 0x3977: 0x0002, 0x3978: 0x0002, 0x3979: 0x0002, 0x397a: 0x0002, 0x397b: 0x0002,
+ 0x397c: 0x0002, 0x397d: 0x0002, 0x397e: 0x0002,
// Block 0xe6, offset 0x3980
- 0x3980: 0x0004, 0x3982: 0x0004, 0x3983: 0x0004, 0x3984: 0x0004, 0x3985: 0x0004,
- 0x3986: 0x0004, 0x3987: 0x0004, 0x3988: 0x0004, 0x3989: 0x0004, 0x398a: 0x0004, 0x398b: 0x0004,
- 0x398c: 0x0004, 0x398d: 0x0004, 0x398e: 0x0004, 0x398f: 0x0004, 0x3990: 0x0004, 0x3991: 0x0004,
- 0x3992: 0x0004, 0x3993: 0x0004, 0x3994: 0x0004, 0x3995: 0x0004, 0x3996: 0x0004, 0x3997: 0x0004,
- 0x3998: 0x0004, 0x3999: 0x0004, 0x399a: 0x0004, 0x399b: 0x0004, 0x399c: 0x0004, 0x399d: 0x0004,
- 0x399e: 0x0004, 0x399f: 0x0004, 0x39a0: 0x0004, 0x39a1: 0x0004, 0x39a2: 0x0004, 0x39a3: 0x0004,
- 0x39a4: 0x0004, 0x39a5: 0x0004, 0x39a6: 0x0004, 0x39a7: 0x0004, 0x39a8: 0x0004, 0x39a9: 0x0004,
- 0x39aa: 0x0004, 0x39ab: 0x0004, 0x39ac: 0x0004, 0x39ad: 0x0004, 0x39ae: 0x0004, 0x39af: 0x0004,
- 0x39b0: 0x0004, 0x39b1: 0x0004, 0x39b2: 0x0004, 0x39b3: 0x0004, 0x39b4: 0x0004, 0x39b5: 0x0004,
- 0x39b6: 0x0004, 0x39b7: 0x0004, 0x39b8: 0x0004, 0x39b9: 0x0004, 0x39ba: 0x0004, 0x39bb: 0x0004,
- 0x39bc: 0x0004, 0x39bd: 0x0004, 0x39be: 0x0004, 0x39bf: 0x0004,
+ 0x3980: 0x0002, 0x3982: 0x0002, 0x3983: 0x0002, 0x3984: 0x0002, 0x3985: 0x0002,
+ 0x3986: 0x0002, 0x3987: 0x0002, 0x3988: 0x0002, 0x3989: 0x0002, 0x398a: 0x0002, 0x398b: 0x0002,
+ 0x398c: 0x0002, 0x398d: 0x0002, 0x398e: 0x0002, 0x398f: 0x0002, 0x3990: 0x0002, 0x3991: 0x0002,
+ 0x3992: 0x0002, 0x3993: 0x0002, 0x3994: 0x0002, 0x3995: 0x0002, 0x3996: 0x0002, 0x3997: 0x0002,
+ 0x3998: 0x0002, 0x3999: 0x0002, 0x399a: 0x0002, 0x399b: 0x0002, 0x399c: 0x0002, 0x399d: 0x0002,
+ 0x399e: 0x0002, 0x399f: 0x0002, 0x39a0: 0x0002, 0x39a1: 0x0002, 0x39a2: 0x0002, 0x39a3: 0x0002,
+ 0x39a4: 0x0002, 0x39a5: 0x0002, 0x39a6: 0x0002, 0x39a7: 0x0002, 0x39a8: 0x0002, 0x39a9: 0x0002,
+ 0x39aa: 0x0002, 0x39ab: 0x0002, 0x39ac: 0x0002, 0x39ad: 0x0002, 0x39ae: 0x0002, 0x39af: 0x0002,
+ 0x39b0: 0x0002, 0x39b1: 0x0002, 0x39b2: 0x0002, 0x39b3: 0x0002, 0x39b4: 0x0002, 0x39b5: 0x0002,
+ 0x39b6: 0x0002, 0x39b7: 0x0002, 0x39b8: 0x0002, 0x39b9: 0x0002, 0x39ba: 0x0002, 0x39bb: 0x0002,
+ 0x39bc: 0x0002, 0x39bd: 0x0002, 0x39be: 0x0002, 0x39bf: 0x0002,
// Block 0xe7, offset 0x39c0
- 0x39c0: 0x0004, 0x39c1: 0x0004, 0x39c2: 0x0004, 0x39c3: 0x0004, 0x39c4: 0x0004, 0x39c5: 0x0004,
- 0x39c6: 0x0004, 0x39c7: 0x0004, 0x39c8: 0x0004, 0x39c9: 0x0004, 0x39ca: 0x0004, 0x39cb: 0x0004,
- 0x39cc: 0x0004, 0x39cd: 0x0004, 0x39ce: 0x0004, 0x39cf: 0x0004, 0x39d0: 0x0004, 0x39d1: 0x0004,
- 0x39d2: 0x0004, 0x39d3: 0x0004, 0x39d4: 0x0004, 0x39d5: 0x0004, 0x39d6: 0x0004, 0x39d7: 0x0004,
- 0x39d8: 0x0004, 0x39d9: 0x0004, 0x39da: 0x0004, 0x39db: 0x0004, 0x39dc: 0x0004, 0x39dd: 0x0004,
- 0x39de: 0x0004, 0x39df: 0x0004, 0x39e0: 0x0004, 0x39e1: 0x0004, 0x39e2: 0x0004, 0x39e3: 0x0004,
- 0x39e4: 0x0004, 0x39e5: 0x0004, 0x39e6: 0x0004, 0x39e7: 0x0004, 0x39e8: 0x0004, 0x39e9: 0x0004,
- 0x39ea: 0x0004, 0x39eb: 0x0004, 0x39ec: 0x0004, 0x39ed: 0x0004, 0x39ee: 0x0004, 0x39ef: 0x0004,
- 0x39f0: 0x0004, 0x39f1: 0x0004, 0x39f2: 0x0004, 0x39f3: 0x0004, 0x39f4: 0x0004, 0x39f5: 0x0004,
- 0x39f6: 0x0004, 0x39f7: 0x0004, 0x39f8: 0x0004, 0x39f9: 0x0004, 0x39fa: 0x0004, 0x39fb: 0x0004,
- 0x39fc: 0x0004, 0x39fd: 0x0004, 0x39fe: 0x0004, 0x39ff: 0x0004,
+ 0x39c0: 0x0002, 0x39c1: 0x0002, 0x39c2: 0x0002, 0x39c3: 0x0002, 0x39c4: 0x0002, 0x39c5: 0x0002,
+ 0x39c6: 0x0002, 0x39c7: 0x0002, 0x39c8: 0x0002, 0x39c9: 0x0002, 0x39ca: 0x0002, 0x39cb: 0x0002,
+ 0x39cc: 0x0002, 0x39cd: 0x0002, 0x39ce: 0x0002, 0x39cf: 0x0002, 0x39d0: 0x0002, 0x39d1: 0x0002,
+ 0x39d2: 0x0002, 0x39d3: 0x0002, 0x39d4: 0x0002, 0x39d5: 0x0002, 0x39d6: 0x0002, 0x39d7: 0x0002,
+ 0x39d8: 0x0002, 0x39d9: 0x0002, 0x39da: 0x0002, 0x39db: 0x0002, 0x39dc: 0x0002, 0x39dd: 0x0002,
+ 0x39de: 0x0002, 0x39df: 0x0002, 0x39e0: 0x0002, 0x39e1: 0x0002, 0x39e2: 0x0002, 0x39e3: 0x0002,
+ 0x39e4: 0x0002, 0x39e5: 0x0002, 0x39e6: 0x0002, 0x39e7: 0x0002, 0x39e8: 0x0002, 0x39e9: 0x0002,
+ 0x39ea: 0x0002, 0x39eb: 0x0002, 0x39ec: 0x0002, 0x39ed: 0x0002, 0x39ee: 0x0002, 0x39ef: 0x0002,
+ 0x39f0: 0x0002, 0x39f1: 0x0002, 0x39f2: 0x0002, 0x39f3: 0x0002, 0x39f4: 0x0002, 0x39f5: 0x0002,
+ 0x39f6: 0x0002, 0x39f7: 0x0002, 0x39f8: 0x0002, 0x39f9: 0x0002, 0x39fa: 0x0002, 0x39fb: 0x0002,
+ 0x39fc: 0x0002, 0x39ff: 0x0002,
// Block 0xe8, offset 0x3a00
- 0x3a00: 0x0004, 0x3a01: 0x0004, 0x3a02: 0x0004, 0x3a03: 0x0004, 0x3a04: 0x0004, 0x3a05: 0x0004,
- 0x3a06: 0x0004, 0x3a07: 0x0004, 0x3a08: 0x0004, 0x3a09: 0x0004, 0x3a0a: 0x0004, 0x3a0b: 0x0004,
- 0x3a0c: 0x0004, 0x3a0d: 0x0004, 0x3a0e: 0x0004, 0x3a0f: 0x0004, 0x3a10: 0x0004, 0x3a11: 0x0004,
- 0x3a12: 0x0004, 0x3a13: 0x0004, 0x3a14: 0x0004, 0x3a15: 0x0004, 0x3a16: 0x0004, 0x3a17: 0x0004,
- 0x3a18: 0x0004, 0x3a19: 0x0004, 0x3a1a: 0x0004, 0x3a1b: 0x0004, 0x3a1c: 0x0004, 0x3a1d: 0x0004,
- 0x3a1e: 0x0004, 0x3a1f: 0x0004, 0x3a20: 0x0004, 0x3a21: 0x0004, 0x3a22: 0x0004, 0x3a23: 0x0004,
- 0x3a24: 0x0004, 0x3a25: 0x0004, 0x3a26: 0x0004, 0x3a27: 0x0004, 0x3a28: 0x0004, 0x3a29: 0x0004,
- 0x3a2a: 0x0004, 0x3a2b: 0x0004, 0x3a2c: 0x0004, 0x3a2d: 0x0004, 0x3a2e: 0x0004, 0x3a2f: 0x0004,
- 0x3a30: 0x0004, 0x3a31: 0x0004, 0x3a32: 0x0004, 0x3a33: 0x0004, 0x3a34: 0x0004, 0x3a35: 0x0004,
- 0x3a36: 0x0004, 0x3a37: 0x0004, 0x3a38: 0x0004, 0x3a39: 0x0004, 0x3a3a: 0x0004, 0x3a3b: 0x0004,
- 0x3a3c: 0x0004, 0x3a3f: 0x0004,
+ 0x3a00: 0x0002, 0x3a01: 0x0002, 0x3a02: 0x0002, 0x3a03: 0x0002, 0x3a04: 0x0002, 0x3a05: 0x0002,
+ 0x3a06: 0x0002, 0x3a07: 0x0002, 0x3a08: 0x0002, 0x3a09: 0x0002, 0x3a0a: 0x0002, 0x3a0b: 0x0002,
+ 0x3a0c: 0x0002, 0x3a0d: 0x0002, 0x3a0e: 0x0002, 0x3a0f: 0x0002, 0x3a10: 0x0002, 0x3a11: 0x0002,
+ 0x3a12: 0x0002, 0x3a13: 0x0002, 0x3a14: 0x0002, 0x3a15: 0x0002, 0x3a16: 0x0002, 0x3a17: 0x0002,
+ 0x3a18: 0x0002, 0x3a19: 0x0002, 0x3a1a: 0x0002, 0x3a1b: 0x0002, 0x3a1c: 0x0002, 0x3a1d: 0x0002,
+ 0x3a1e: 0x0002, 0x3a1f: 0x0002, 0x3a20: 0x0002, 0x3a21: 0x0002, 0x3a22: 0x0002, 0x3a23: 0x0002,
+ 0x3a24: 0x0002, 0x3a25: 0x0002, 0x3a26: 0x0002, 0x3a27: 0x0002, 0x3a28: 0x0002, 0x3a29: 0x0002,
+ 0x3a2a: 0x0002, 0x3a2b: 0x0002, 0x3a2c: 0x0002, 0x3a2d: 0x0002, 0x3a2e: 0x0002, 0x3a2f: 0x0002,
+ 0x3a30: 0x0002, 0x3a31: 0x0002, 0x3a32: 0x0002, 0x3a33: 0x0002, 0x3a34: 0x0002, 0x3a35: 0x0002,
+ 0x3a36: 0x0002, 0x3a37: 0x0002, 0x3a38: 0x0002, 0x3a39: 0x0002, 0x3a3a: 0x0002, 0x3a3b: 0x0002,
+ 0x3a3c: 0x0002, 0x3a3d: 0x0002,
// Block 0xe9, offset 0x3a40
- 0x3a40: 0x0004, 0x3a41: 0x0004, 0x3a42: 0x0004, 0x3a43: 0x0004, 0x3a44: 0x0004, 0x3a45: 0x0004,
- 0x3a46: 0x0004, 0x3a47: 0x0004, 0x3a48: 0x0004, 0x3a49: 0x0004, 0x3a4a: 0x0004, 0x3a4b: 0x0004,
- 0x3a4c: 0x0004, 0x3a4d: 0x0004, 0x3a4e: 0x0004, 0x3a4f: 0x0004, 0x3a50: 0x0004, 0x3a51: 0x0004,
- 0x3a52: 0x0004, 0x3a53: 0x0004, 0x3a54: 0x0004, 0x3a55: 0x0004, 0x3a56: 0x0004, 0x3a57: 0x0004,
- 0x3a58: 0x0004, 0x3a59: 0x0004, 0x3a5a: 0x0004, 0x3a5b: 0x0004, 0x3a5c: 0x0004, 0x3a5d: 0x0004,
- 0x3a5e: 0x0004, 0x3a5f: 0x0004, 0x3a60: 0x0004, 0x3a61: 0x0004, 0x3a62: 0x0004, 0x3a63: 0x0004,
- 0x3a64: 0x0004, 0x3a65: 0x0004, 0x3a66: 0x0004, 0x3a67: 0x0004, 0x3a68: 0x0004, 0x3a69: 0x0004,
- 0x3a6a: 0x0004, 0x3a6b: 0x0004, 0x3a6c: 0x0004, 0x3a6d: 0x0004, 0x3a6e: 0x0004, 0x3a6f: 0x0004,
- 0x3a70: 0x0004, 0x3a71: 0x0004, 0x3a72: 0x0004, 0x3a73: 0x0004, 0x3a74: 0x0004, 0x3a75: 0x0004,
- 0x3a76: 0x0004, 0x3a77: 0x0004, 0x3a78: 0x0004, 0x3a79: 0x0004, 0x3a7a: 0x0004, 0x3a7b: 0x0004,
- 0x3a7c: 0x0004, 0x3a7d: 0x0004,
+ 0x3a4b: 0x0002,
+ 0x3a4c: 0x0002, 0x3a4d: 0x0002, 0x3a4e: 0x0002, 0x3a50: 0x0002, 0x3a51: 0x0002,
+ 0x3a52: 0x0002, 0x3a53: 0x0002, 0x3a54: 0x0002, 0x3a55: 0x0002, 0x3a56: 0x0002, 0x3a57: 0x0002,
+ 0x3a58: 0x0002, 0x3a59: 0x0002, 0x3a5a: 0x0002, 0x3a5b: 0x0002, 0x3a5c: 0x0002, 0x3a5d: 0x0002,
+ 0x3a5e: 0x0002, 0x3a5f: 0x0002, 0x3a60: 0x0002, 0x3a61: 0x0002, 0x3a62: 0x0002, 0x3a63: 0x0002,
+ 0x3a64: 0x0002, 0x3a65: 0x0002, 0x3a66: 0x0002, 0x3a67: 0x0002,
+ 0x3a7a: 0x0002,
// Block 0xea, offset 0x3a80
- 0x3a8b: 0x0004,
- 0x3a8c: 0x0004, 0x3a8d: 0x0004, 0x3a8e: 0x0004, 0x3a90: 0x0004, 0x3a91: 0x0004,
- 0x3a92: 0x0004, 0x3a93: 0x0004, 0x3a94: 0x0004, 0x3a95: 0x0004, 0x3a96: 0x0004, 0x3a97: 0x0004,
- 0x3a98: 0x0004, 0x3a99: 0x0004, 0x3a9a: 0x0004, 0x3a9b: 0x0004, 0x3a9c: 0x0004, 0x3a9d: 0x0004,
- 0x3a9e: 0x0004, 0x3a9f: 0x0004, 0x3aa0: 0x0004, 0x3aa1: 0x0004, 0x3aa2: 0x0004, 0x3aa3: 0x0004,
- 0x3aa4: 0x0004, 0x3aa5: 0x0004, 0x3aa6: 0x0004, 0x3aa7: 0x0004,
- 0x3aba: 0x0004,
+ 0x3a95: 0x0002, 0x3a96: 0x0002,
+ 0x3aa4: 0x0002,
// Block 0xeb, offset 0x3ac0
- 0x3ad5: 0x0004, 0x3ad6: 0x0004,
- 0x3ae4: 0x0004,
+ 0x3afb: 0x0002,
+ 0x3afc: 0x0002, 0x3afd: 0x0002, 0x3afe: 0x0002, 0x3aff: 0x0002,
// Block 0xec, offset 0x3b00
- 0x3b3b: 0x0004,
- 0x3b3c: 0x0004, 0x3b3d: 0x0004, 0x3b3e: 0x0004, 0x3b3f: 0x0004,
+ 0x3b00: 0x0002, 0x3b01: 0x0002, 0x3b02: 0x0002, 0x3b03: 0x0002, 0x3b04: 0x0002, 0x3b05: 0x0002,
+ 0x3b06: 0x0002, 0x3b07: 0x0002, 0x3b08: 0x0002, 0x3b09: 0x0002, 0x3b0a: 0x0002, 0x3b0b: 0x0002,
+ 0x3b0c: 0x0002, 0x3b0d: 0x0002, 0x3b0e: 0x0002, 0x3b0f: 0x0002,
// Block 0xed, offset 0x3b40
- 0x3b40: 0x0004, 0x3b41: 0x0004, 0x3b42: 0x0004, 0x3b43: 0x0004, 0x3b44: 0x0004, 0x3b45: 0x0004,
- 0x3b46: 0x0004, 0x3b47: 0x0004, 0x3b48: 0x0004, 0x3b49: 0x0004, 0x3b4a: 0x0004, 0x3b4b: 0x0004,
- 0x3b4c: 0x0004, 0x3b4d: 0x0004, 0x3b4e: 0x0004, 0x3b4f: 0x0004,
+ 0x3b40: 0x0002, 0x3b41: 0x0002, 0x3b42: 0x0002, 0x3b43: 0x0002, 0x3b44: 0x0002, 0x3b45: 0x0002,
+ 0x3b4c: 0x0002, 0x3b50: 0x0002, 0x3b51: 0x0002,
+ 0x3b52: 0x0002, 0x3b55: 0x0002, 0x3b56: 0x0002, 0x3b57: 0x0002,
+ 0x3b5c: 0x0002, 0x3b5d: 0x0002,
+ 0x3b5e: 0x0002, 0x3b5f: 0x0002,
+ 0x3b6b: 0x0002, 0x3b6c: 0x0002,
+ 0x3b74: 0x0002, 0x3b75: 0x0002,
+ 0x3b76: 0x0002, 0x3b77: 0x0002, 0x3b78: 0x0002, 0x3b79: 0x0002, 0x3b7a: 0x0002, 0x3b7b: 0x0002,
+ 0x3b7c: 0x0002,
// Block 0xee, offset 0x3b80
- 0x3b80: 0x0004, 0x3b81: 0x0004, 0x3b82: 0x0004, 0x3b83: 0x0004, 0x3b84: 0x0004, 0x3b85: 0x0004,
- 0x3b8c: 0x0004, 0x3b90: 0x0004, 0x3b91: 0x0004,
- 0x3b92: 0x0004, 0x3b95: 0x0004, 0x3b96: 0x0004, 0x3b97: 0x0004,
- 0x3b9c: 0x0004, 0x3b9d: 0x0004,
- 0x3b9e: 0x0004, 0x3b9f: 0x0004,
- 0x3bab: 0x0004, 0x3bac: 0x0004,
- 0x3bb4: 0x0004, 0x3bb5: 0x0004,
- 0x3bb6: 0x0004, 0x3bb7: 0x0004, 0x3bb8: 0x0004, 0x3bb9: 0x0004, 0x3bba: 0x0004, 0x3bbb: 0x0004,
- 0x3bbc: 0x0004,
+ 0x3ba0: 0x0002, 0x3ba1: 0x0002, 0x3ba2: 0x0002, 0x3ba3: 0x0002,
+ 0x3ba4: 0x0002, 0x3ba5: 0x0002, 0x3ba6: 0x0002, 0x3ba7: 0x0002, 0x3ba8: 0x0002, 0x3ba9: 0x0002,
+ 0x3baa: 0x0002, 0x3bab: 0x0002,
+ 0x3bb0: 0x0002,
// Block 0xef, offset 0x3bc0
- 0x3be0: 0x0004, 0x3be1: 0x0004, 0x3be2: 0x0004, 0x3be3: 0x0004,
- 0x3be4: 0x0004, 0x3be5: 0x0004, 0x3be6: 0x0004, 0x3be7: 0x0004, 0x3be8: 0x0004, 0x3be9: 0x0004,
- 0x3bea: 0x0004, 0x3beb: 0x0004,
- 0x3bf0: 0x0004,
+ 0x3bcc: 0x0002, 0x3bcd: 0x0002, 0x3bce: 0x0002, 0x3bcf: 0x0002, 0x3bd0: 0x0002, 0x3bd1: 0x0002,
+ 0x3bd2: 0x0002, 0x3bd3: 0x0002, 0x3bd4: 0x0002, 0x3bd5: 0x0002, 0x3bd6: 0x0002, 0x3bd7: 0x0002,
+ 0x3bd8: 0x0002, 0x3bd9: 0x0002, 0x3bda: 0x0002, 0x3bdb: 0x0002, 0x3bdc: 0x0002, 0x3bdd: 0x0002,
+ 0x3bde: 0x0002, 0x3bdf: 0x0002, 0x3be0: 0x0002, 0x3be1: 0x0002, 0x3be2: 0x0002, 0x3be3: 0x0002,
+ 0x3be4: 0x0002, 0x3be5: 0x0002, 0x3be6: 0x0002, 0x3be7: 0x0002, 0x3be8: 0x0002, 0x3be9: 0x0002,
+ 0x3bea: 0x0002, 0x3beb: 0x0002, 0x3bec: 0x0002, 0x3bed: 0x0002, 0x3bee: 0x0002, 0x3bef: 0x0002,
+ 0x3bf0: 0x0002, 0x3bf1: 0x0002, 0x3bf2: 0x0002, 0x3bf3: 0x0002, 0x3bf4: 0x0002, 0x3bf5: 0x0002,
+ 0x3bf6: 0x0002, 0x3bf7: 0x0002, 0x3bf8: 0x0002, 0x3bf9: 0x0002, 0x3bfa: 0x0002,
+ 0x3bfc: 0x0002, 0x3bfd: 0x0002, 0x3bfe: 0x0002, 0x3bff: 0x0002,
// Block 0xf0, offset 0x3c00
- 0x3c0c: 0x0004, 0x3c0d: 0x0004, 0x3c0e: 0x0004, 0x3c0f: 0x0004, 0x3c10: 0x0004, 0x3c11: 0x0004,
- 0x3c12: 0x0004, 0x3c13: 0x0004, 0x3c14: 0x0004, 0x3c15: 0x0004, 0x3c16: 0x0004, 0x3c17: 0x0004,
- 0x3c18: 0x0004, 0x3c19: 0x0004, 0x3c1a: 0x0004, 0x3c1b: 0x0004, 0x3c1c: 0x0004, 0x3c1d: 0x0004,
- 0x3c1e: 0x0004, 0x3c1f: 0x0004, 0x3c20: 0x0004, 0x3c21: 0x0004, 0x3c22: 0x0004, 0x3c23: 0x0004,
- 0x3c24: 0x0004, 0x3c25: 0x0004, 0x3c26: 0x0004, 0x3c27: 0x0004, 0x3c28: 0x0004, 0x3c29: 0x0004,
- 0x3c2a: 0x0004, 0x3c2b: 0x0004, 0x3c2c: 0x0004, 0x3c2d: 0x0004, 0x3c2e: 0x0004, 0x3c2f: 0x0004,
- 0x3c30: 0x0004, 0x3c31: 0x0004, 0x3c32: 0x0004, 0x3c33: 0x0004, 0x3c34: 0x0004, 0x3c35: 0x0004,
- 0x3c36: 0x0004, 0x3c37: 0x0004, 0x3c38: 0x0004, 0x3c39: 0x0004, 0x3c3a: 0x0004,
- 0x3c3c: 0x0004, 0x3c3d: 0x0004, 0x3c3e: 0x0004, 0x3c3f: 0x0004,
+ 0x3c00: 0x0002, 0x3c01: 0x0002, 0x3c02: 0x0002, 0x3c03: 0x0002, 0x3c04: 0x0002, 0x3c05: 0x0002,
+ 0x3c07: 0x0002, 0x3c08: 0x0002, 0x3c09: 0x0002, 0x3c0a: 0x0002, 0x3c0b: 0x0002,
+ 0x3c0c: 0x0002, 0x3c0d: 0x0002, 0x3c0e: 0x0002, 0x3c0f: 0x0002, 0x3c10: 0x0002, 0x3c11: 0x0002,
+ 0x3c12: 0x0002, 0x3c13: 0x0002, 0x3c14: 0x0002, 0x3c15: 0x0002, 0x3c16: 0x0002, 0x3c17: 0x0002,
+ 0x3c18: 0x0002, 0x3c19: 0x0002, 0x3c1a: 0x0002, 0x3c1b: 0x0002, 0x3c1c: 0x0002, 0x3c1d: 0x0002,
+ 0x3c1e: 0x0002, 0x3c1f: 0x0002, 0x3c20: 0x0002, 0x3c21: 0x0002, 0x3c22: 0x0002, 0x3c23: 0x0002,
+ 0x3c24: 0x0002, 0x3c25: 0x0002, 0x3c26: 0x0002, 0x3c27: 0x0002, 0x3c28: 0x0002, 0x3c29: 0x0002,
+ 0x3c2a: 0x0002, 0x3c2b: 0x0002, 0x3c2c: 0x0002, 0x3c2d: 0x0002, 0x3c2e: 0x0002, 0x3c2f: 0x0002,
+ 0x3c30: 0x0002, 0x3c31: 0x0002, 0x3c32: 0x0002, 0x3c33: 0x0002, 0x3c34: 0x0002, 0x3c35: 0x0002,
+ 0x3c36: 0x0002, 0x3c37: 0x0002, 0x3c38: 0x0002, 0x3c39: 0x0002, 0x3c3a: 0x0002, 0x3c3b: 0x0002,
+ 0x3c3c: 0x0002, 0x3c3d: 0x0002, 0x3c3e: 0x0002, 0x3c3f: 0x0002,
// Block 0xf1, offset 0x3c40
- 0x3c40: 0x0004, 0x3c41: 0x0004, 0x3c42: 0x0004, 0x3c43: 0x0004, 0x3c44: 0x0004, 0x3c45: 0x0004,
- 0x3c47: 0x0004, 0x3c48: 0x0004, 0x3c49: 0x0004, 0x3c4a: 0x0004, 0x3c4b: 0x0004,
- 0x3c4c: 0x0004, 0x3c4d: 0x0004, 0x3c4e: 0x0004, 0x3c4f: 0x0004, 0x3c50: 0x0004, 0x3c51: 0x0004,
- 0x3c52: 0x0004, 0x3c53: 0x0004, 0x3c54: 0x0004, 0x3c55: 0x0004, 0x3c56: 0x0004, 0x3c57: 0x0004,
- 0x3c58: 0x0004, 0x3c59: 0x0004, 0x3c5a: 0x0004, 0x3c5b: 0x0004, 0x3c5c: 0x0004, 0x3c5d: 0x0004,
- 0x3c5e: 0x0004, 0x3c5f: 0x0004, 0x3c60: 0x0004, 0x3c61: 0x0004, 0x3c62: 0x0004, 0x3c63: 0x0004,
- 0x3c64: 0x0004, 0x3c65: 0x0004, 0x3c66: 0x0004, 0x3c67: 0x0004, 0x3c68: 0x0004, 0x3c69: 0x0004,
- 0x3c6a: 0x0004, 0x3c6b: 0x0004, 0x3c6c: 0x0004, 0x3c6d: 0x0004, 0x3c6e: 0x0004, 0x3c6f: 0x0004,
- 0x3c70: 0x0004, 0x3c71: 0x0004, 0x3c72: 0x0004, 0x3c73: 0x0004, 0x3c74: 0x0004, 0x3c75: 0x0004,
- 0x3c76: 0x0004, 0x3c77: 0x0004, 0x3c78: 0x0004, 0x3c79: 0x0004, 0x3c7a: 0x0004, 0x3c7b: 0x0004,
- 0x3c7c: 0x0004, 0x3c7d: 0x0004, 0x3c7e: 0x0004, 0x3c7f: 0x0004,
+ 0x3c70: 0x0002, 0x3c71: 0x0002, 0x3c72: 0x0002, 0x3c73: 0x0002, 0x3c74: 0x0002, 0x3c75: 0x0002,
+ 0x3c76: 0x0002, 0x3c77: 0x0002, 0x3c78: 0x0002, 0x3c79: 0x0002, 0x3c7a: 0x0002, 0x3c7b: 0x0002,
+ 0x3c7c: 0x0002,
// Block 0xf2, offset 0x3c80
- 0x3cb0: 0x0004, 0x3cb1: 0x0004, 0x3cb2: 0x0004, 0x3cb3: 0x0004, 0x3cb4: 0x0004, 0x3cb5: 0x0004,
- 0x3cb6: 0x0004, 0x3cb7: 0x0004, 0x3cb8: 0x0004, 0x3cb9: 0x0004, 0x3cba: 0x0004, 0x3cbb: 0x0004,
- 0x3cbc: 0x0004,
+ 0x3c80: 0x0002, 0x3c81: 0x0002, 0x3c82: 0x0002, 0x3c83: 0x0002, 0x3c84: 0x0002, 0x3c85: 0x0002,
+ 0x3c86: 0x0002, 0x3c87: 0x0002, 0x3c88: 0x0002, 0x3c89: 0x0002,
+ 0x3c8f: 0x0002, 0x3c90: 0x0002, 0x3c91: 0x0002,
+ 0x3c92: 0x0002, 0x3c93: 0x0002, 0x3c94: 0x0002, 0x3c95: 0x0002, 0x3c96: 0x0002, 0x3c97: 0x0002,
+ 0x3c98: 0x0002, 0x3c99: 0x0002, 0x3c9a: 0x0002, 0x3c9b: 0x0002, 0x3c9c: 0x0002, 0x3c9d: 0x0002,
+ 0x3c9e: 0x0002, 0x3c9f: 0x0002, 0x3ca0: 0x0002, 0x3ca1: 0x0002, 0x3ca2: 0x0002, 0x3ca3: 0x0002,
+ 0x3ca4: 0x0002, 0x3ca5: 0x0002, 0x3ca6: 0x0002, 0x3ca7: 0x0002, 0x3ca8: 0x0002, 0x3ca9: 0x0002,
+ 0x3caa: 0x0002, 0x3cab: 0x0002, 0x3cac: 0x0002, 0x3cad: 0x0002, 0x3cae: 0x0002, 0x3caf: 0x0002,
+ 0x3cb0: 0x0002, 0x3cb1: 0x0002, 0x3cb2: 0x0002, 0x3cb3: 0x0002, 0x3cb4: 0x0002, 0x3cb5: 0x0002,
+ 0x3cb6: 0x0002, 0x3cb7: 0x0002, 0x3cb8: 0x0002, 0x3cb9: 0x0002, 0x3cba: 0x0002, 0x3cbb: 0x0002,
+ 0x3cbc: 0x0002, 0x3cbd: 0x0002, 0x3cbe: 0x0002, 0x3cbf: 0x0002,
// Block 0xf3, offset 0x3cc0
- 0x3cc0: 0x0004, 0x3cc1: 0x0004, 0x3cc2: 0x0004, 0x3cc3: 0x0004, 0x3cc4: 0x0004, 0x3cc5: 0x0004,
- 0x3cc6: 0x0004, 0x3cc7: 0x0004, 0x3cc8: 0x0004, 0x3cc9: 0x0004,
- 0x3ccf: 0x0004, 0x3cd0: 0x0004, 0x3cd1: 0x0004,
- 0x3cd2: 0x0004, 0x3cd3: 0x0004, 0x3cd4: 0x0004, 0x3cd5: 0x0004, 0x3cd6: 0x0004, 0x3cd7: 0x0004,
- 0x3cd8: 0x0004, 0x3cd9: 0x0004, 0x3cda: 0x0004, 0x3cdb: 0x0004, 0x3cdc: 0x0004, 0x3cdd: 0x0004,
- 0x3cde: 0x0004, 0x3cdf: 0x0004, 0x3ce0: 0x0004, 0x3ce1: 0x0004, 0x3ce2: 0x0004, 0x3ce3: 0x0004,
- 0x3ce4: 0x0004, 0x3ce5: 0x0004, 0x3ce6: 0x0004, 0x3ce7: 0x0004, 0x3ce8: 0x0004, 0x3ce9: 0x0004,
- 0x3cea: 0x0004, 0x3ceb: 0x0004, 0x3cec: 0x0004, 0x3ced: 0x0004, 0x3cee: 0x0004, 0x3cef: 0x0004,
- 0x3cf0: 0x0004, 0x3cf1: 0x0004, 0x3cf2: 0x0004, 0x3cf3: 0x0004, 0x3cf4: 0x0004, 0x3cf5: 0x0004,
- 0x3cf6: 0x0004, 0x3cf7: 0x0004, 0x3cf8: 0x0004, 0x3cf9: 0x0004, 0x3cfa: 0x0004, 0x3cfb: 0x0004,
- 0x3cfc: 0x0004, 0x3cfd: 0x0004, 0x3cfe: 0x0004, 0x3cff: 0x0004,
+ 0x3cc0: 0x0002, 0x3cc1: 0x0002, 0x3cc2: 0x0002, 0x3cc3: 0x0002, 0x3cc4: 0x0002, 0x3cc5: 0x0002,
+ 0x3cc6: 0x0002,
+ 0x3cce: 0x0002, 0x3ccf: 0x0002, 0x3cd0: 0x0002, 0x3cd1: 0x0002,
+ 0x3cd2: 0x0002, 0x3cd3: 0x0002, 0x3cd4: 0x0002, 0x3cd5: 0x0002, 0x3cd6: 0x0002, 0x3cd7: 0x0002,
+ 0x3cd8: 0x0002, 0x3cd9: 0x0002, 0x3cda: 0x0002, 0x3cdb: 0x0002, 0x3cdc: 0x0002,
+ 0x3cdf: 0x0002, 0x3ce0: 0x0002, 0x3ce1: 0x0002, 0x3ce2: 0x0002, 0x3ce3: 0x0002,
+ 0x3ce4: 0x0002, 0x3ce5: 0x0002, 0x3ce6: 0x0002, 0x3ce7: 0x0002, 0x3ce8: 0x0002, 0x3ce9: 0x0002,
+ 0x3cf0: 0x0002, 0x3cf1: 0x0002, 0x3cf2: 0x0002, 0x3cf3: 0x0002, 0x3cf4: 0x0002, 0x3cf5: 0x0002,
+ 0x3cf6: 0x0002, 0x3cf7: 0x0002, 0x3cf8: 0x0002,
// Block 0xf4, offset 0x3d00
- 0x3d00: 0x0004, 0x3d01: 0x0004, 0x3d02: 0x0004, 0x3d03: 0x0004, 0x3d04: 0x0004, 0x3d05: 0x0004,
- 0x3d06: 0x0004,
- 0x3d0e: 0x0004, 0x3d0f: 0x0004, 0x3d10: 0x0004, 0x3d11: 0x0004,
- 0x3d12: 0x0004, 0x3d13: 0x0004, 0x3d14: 0x0004, 0x3d15: 0x0004, 0x3d16: 0x0004, 0x3d17: 0x0004,
- 0x3d18: 0x0004, 0x3d19: 0x0004, 0x3d1a: 0x0004, 0x3d1b: 0x0004, 0x3d1c: 0x0004,
- 0x3d1f: 0x0004, 0x3d20: 0x0004, 0x3d21: 0x0004, 0x3d22: 0x0004, 0x3d23: 0x0004,
- 0x3d24: 0x0004, 0x3d25: 0x0004, 0x3d26: 0x0004, 0x3d27: 0x0004, 0x3d28: 0x0004, 0x3d29: 0x0004,
- 0x3d30: 0x0004, 0x3d31: 0x0004, 0x3d32: 0x0004, 0x3d33: 0x0004, 0x3d34: 0x0004, 0x3d35: 0x0004,
- 0x3d36: 0x0004, 0x3d37: 0x0004, 0x3d38: 0x0004,
+ 0x3d01: 0x0001,
+ 0x3d20: 0x0001, 0x3d21: 0x0001, 0x3d22: 0x0001, 0x3d23: 0x0001,
+ 0x3d24: 0x0001, 0x3d25: 0x0001, 0x3d26: 0x0001, 0x3d27: 0x0001, 0x3d28: 0x0001, 0x3d29: 0x0001,
+ 0x3d2a: 0x0001, 0x3d2b: 0x0001, 0x3d2c: 0x0001, 0x3d2d: 0x0001, 0x3d2e: 0x0001, 0x3d2f: 0x0001,
+ 0x3d30: 0x0001, 0x3d31: 0x0001, 0x3d32: 0x0001, 0x3d33: 0x0001, 0x3d34: 0x0001, 0x3d35: 0x0001,
+ 0x3d36: 0x0001, 0x3d37: 0x0001, 0x3d38: 0x0001, 0x3d39: 0x0001, 0x3d3a: 0x0001, 0x3d3b: 0x0001,
+ 0x3d3c: 0x0001, 0x3d3d: 0x0001, 0x3d3e: 0x0001, 0x3d3f: 0x0001,
// Block 0xf5, offset 0x3d40
- 0x3d40: 0x0002, 0x3d41: 0x0002, 0x3d42: 0x0002, 0x3d43: 0x0002, 0x3d44: 0x0002, 0x3d45: 0x0002,
- 0x3d46: 0x0002, 0x3d47: 0x0002, 0x3d48: 0x0002, 0x3d49: 0x0002, 0x3d4a: 0x0002, 0x3d4b: 0x0002,
- 0x3d4c: 0x0002, 0x3d4d: 0x0002, 0x3d4e: 0x0002, 0x3d4f: 0x0002, 0x3d50: 0x0002, 0x3d51: 0x0002,
- 0x3d52: 0x0002, 0x3d53: 0x0002, 0x3d54: 0x0002, 0x3d55: 0x0002, 0x3d56: 0x0002, 0x3d57: 0x0002,
- 0x3d58: 0x0002, 0x3d59: 0x0002, 0x3d5a: 0x0002, 0x3d5b: 0x0002, 0x3d5c: 0x0002, 0x3d5d: 0x0002,
- 0x3d5e: 0x0002, 0x3d5f: 0x0002, 0x3d60: 0x0002, 0x3d61: 0x0002, 0x3d62: 0x0002, 0x3d63: 0x0002,
- 0x3d64: 0x0002, 0x3d65: 0x0002, 0x3d66: 0x0002, 0x3d67: 0x0002, 0x3d68: 0x0002, 0x3d69: 0x0002,
- 0x3d6a: 0x0002, 0x3d6b: 0x0002, 0x3d6c: 0x0002, 0x3d6d: 0x0002, 0x3d6e: 0x0002, 0x3d6f: 0x0002,
- 0x3d70: 0x0002, 0x3d71: 0x0002, 0x3d72: 0x0002, 0x3d73: 0x0002, 0x3d74: 0x0002, 0x3d75: 0x0002,
- 0x3d76: 0x0002, 0x3d77: 0x0002, 0x3d78: 0x0002, 0x3d79: 0x0002, 0x3d7a: 0x0002, 0x3d7b: 0x0002,
- 0x3d7c: 0x0002, 0x3d7d: 0x0002,
- // Block 0xf6, offset 0x3d80
- 0x3d81: 0x0001,
- 0x3da0: 0x0001, 0x3da1: 0x0001, 0x3da2: 0x0001, 0x3da3: 0x0001,
- 0x3da4: 0x0001, 0x3da5: 0x0001, 0x3da6: 0x0001, 0x3da7: 0x0001, 0x3da8: 0x0001, 0x3da9: 0x0001,
- 0x3daa: 0x0001, 0x3dab: 0x0001, 0x3dac: 0x0001, 0x3dad: 0x0001, 0x3dae: 0x0001, 0x3daf: 0x0001,
- 0x3db0: 0x0001, 0x3db1: 0x0001, 0x3db2: 0x0001, 0x3db3: 0x0001, 0x3db4: 0x0001, 0x3db5: 0x0001,
- 0x3db6: 0x0001, 0x3db7: 0x0001, 0x3db8: 0x0001, 0x3db9: 0x0001, 0x3dba: 0x0001, 0x3dbb: 0x0001,
- 0x3dbc: 0x0001, 0x3dbd: 0x0001, 0x3dbe: 0x0001, 0x3dbf: 0x0001,
- // Block 0xf7, offset 0x3dc0
- 0x3dc0: 0x0003, 0x3dc1: 0x0003, 0x3dc2: 0x0003, 0x3dc3: 0x0003, 0x3dc4: 0x0003, 0x3dc5: 0x0003,
- 0x3dc6: 0x0003, 0x3dc7: 0x0003, 0x3dc8: 0x0003, 0x3dc9: 0x0003, 0x3dca: 0x0003, 0x3dcb: 0x0003,
- 0x3dcc: 0x0003, 0x3dcd: 0x0003, 0x3dce: 0x0003, 0x3dcf: 0x0003, 0x3dd0: 0x0003, 0x3dd1: 0x0003,
- 0x3dd2: 0x0003, 0x3dd3: 0x0003, 0x3dd4: 0x0003, 0x3dd5: 0x0003, 0x3dd6: 0x0003, 0x3dd7: 0x0003,
- 0x3dd8: 0x0003, 0x3dd9: 0x0003, 0x3dda: 0x0003, 0x3ddb: 0x0003, 0x3ddc: 0x0003, 0x3ddd: 0x0003,
- 0x3dde: 0x0003, 0x3ddf: 0x0003, 0x3de0: 0x0003, 0x3de1: 0x0003, 0x3de2: 0x0003, 0x3de3: 0x0003,
- 0x3de4: 0x0003, 0x3de5: 0x0003, 0x3de6: 0x0003, 0x3de7: 0x0003, 0x3de8: 0x0003, 0x3de9: 0x0003,
- 0x3dea: 0x0003, 0x3deb: 0x0003, 0x3dec: 0x0003, 0x3ded: 0x0003, 0x3dee: 0x0003, 0x3def: 0x0003,
- 0x3df0: 0x0003, 0x3df1: 0x0003, 0x3df2: 0x0003, 0x3df3: 0x0003, 0x3df4: 0x0003, 0x3df5: 0x0003,
- 0x3df6: 0x0003, 0x3df7: 0x0003, 0x3df8: 0x0003, 0x3df9: 0x0003, 0x3dfa: 0x0003, 0x3dfb: 0x0003,
- 0x3dfc: 0x0003, 0x3dfd: 0x0003,
+ 0x3d40: 0x0003, 0x3d41: 0x0003, 0x3d42: 0x0003, 0x3d43: 0x0003, 0x3d44: 0x0003, 0x3d45: 0x0003,
+ 0x3d46: 0x0003, 0x3d47: 0x0003, 0x3d48: 0x0003, 0x3d49: 0x0003, 0x3d4a: 0x0003, 0x3d4b: 0x0003,
+ 0x3d4c: 0x0003, 0x3d4d: 0x0003, 0x3d4e: 0x0003, 0x3d4f: 0x0003, 0x3d50: 0x0003, 0x3d51: 0x0003,
+ 0x3d52: 0x0003, 0x3d53: 0x0003, 0x3d54: 0x0003, 0x3d55: 0x0003, 0x3d56: 0x0003, 0x3d57: 0x0003,
+ 0x3d58: 0x0003, 0x3d59: 0x0003, 0x3d5a: 0x0003, 0x3d5b: 0x0003, 0x3d5c: 0x0003, 0x3d5d: 0x0003,
+ 0x3d5e: 0x0003, 0x3d5f: 0x0003, 0x3d60: 0x0003, 0x3d61: 0x0003, 0x3d62: 0x0003, 0x3d63: 0x0003,
+ 0x3d64: 0x0003, 0x3d65: 0x0003, 0x3d66: 0x0003, 0x3d67: 0x0003, 0x3d68: 0x0003, 0x3d69: 0x0003,
+ 0x3d6a: 0x0003, 0x3d6b: 0x0003, 0x3d6c: 0x0003, 0x3d6d: 0x0003, 0x3d6e: 0x0003, 0x3d6f: 0x0003,
+ 0x3d70: 0x0003, 0x3d71: 0x0003, 0x3d72: 0x0003, 0x3d73: 0x0003, 0x3d74: 0x0003, 0x3d75: 0x0003,
+ 0x3d76: 0x0003, 0x3d77: 0x0003, 0x3d78: 0x0003, 0x3d79: 0x0003, 0x3d7a: 0x0003, 0x3d7b: 0x0003,
+ 0x3d7c: 0x0003, 0x3d7d: 0x0003,
}
// stringWidthIndex: 30 blocks, 1920 entries, 1920 bytes
@@ -1683,10 +1655,10 @@ var stringWidthIndex = [1920]uint8{
// Block 0x17, offset 0x5c0
0x5c0: 0xd7, 0x5c3: 0xd8, 0x5c4: 0xd9, 0x5c5: 0xda, 0x5c6: 0xdb, 0x5c7: 0xdc,
0x5c8: 0xdd, 0x5c9: 0xde, 0x5cc: 0xdf, 0x5cd: 0xe0, 0x5ce: 0xe1, 0x5cf: 0xe2,
- 0x5d0: 0xe3, 0x5d1: 0xe4, 0x5d2: 0xe5, 0x5d3: 0xe6, 0x5d4: 0xe7, 0x5d5: 0xe8, 0x5d6: 0xe9, 0x5d7: 0xea,
- 0x5d8: 0xe5, 0x5d9: 0xeb, 0x5da: 0xe5, 0x5db: 0xec, 0x5df: 0xed,
- 0x5e4: 0xee, 0x5e5: 0xef, 0x5e6: 0xe5, 0x5e7: 0xe5,
- 0x5e9: 0xf0, 0x5ea: 0xf1, 0x5eb: 0xf2,
+ 0x5d0: 0xe3, 0x5d1: 0xe4, 0x5d2: 0x39, 0x5d3: 0xe5, 0x5d4: 0xe6, 0x5d5: 0xe7, 0x5d6: 0xe8, 0x5d7: 0xe9,
+ 0x5d8: 0x39, 0x5d9: 0xea, 0x5da: 0x39, 0x5db: 0xeb, 0x5df: 0xec,
+ 0x5e4: 0xed, 0x5e5: 0xee, 0x5e6: 0x39, 0x5e7: 0x39,
+ 0x5e9: 0xef, 0x5ea: 0xf0, 0x5eb: 0xf1,
// Block 0x18, offset 0x600
0x600: 0x39, 0x601: 0x39, 0x602: 0x39, 0x603: 0x39, 0x604: 0x39, 0x605: 0x39, 0x606: 0x39, 0x607: 0x39,
0x608: 0x39, 0x609: 0x39, 0x60a: 0x39, 0x60b: 0x39, 0x60c: 0x39, 0x60d: 0x39, 0x60e: 0x39, 0x60f: 0x39,
@@ -1695,7 +1667,7 @@ var stringWidthIndex = [1920]uint8{
0x620: 0x39, 0x621: 0x39, 0x622: 0x39, 0x623: 0x39, 0x624: 0x39, 0x625: 0x39, 0x626: 0x39, 0x627: 0x39,
0x628: 0x39, 0x629: 0x39, 0x62a: 0x39, 0x62b: 0x39, 0x62c: 0x39, 0x62d: 0x39, 0x62e: 0x39, 0x62f: 0x39,
0x630: 0x39, 0x631: 0x39, 0x632: 0x39, 0x633: 0x39, 0x634: 0x39, 0x635: 0x39, 0x636: 0x39, 0x637: 0x39,
- 0x638: 0x39, 0x639: 0x39, 0x63a: 0x39, 0x63b: 0x39, 0x63c: 0x39, 0x63d: 0x39, 0x63e: 0x39, 0x63f: 0xf3,
+ 0x638: 0x39, 0x639: 0x39, 0x63a: 0x39, 0x63b: 0x39, 0x63c: 0x39, 0x63d: 0x39, 0x63e: 0x39, 0x63f: 0xe6,
// Block 0x19, offset 0x640
0x650: 0x0b, 0x651: 0x0c, 0x653: 0x0d, 0x656: 0x0e, 0x657: 0x06,
0x658: 0x0f, 0x65a: 0x10, 0x65b: 0x11, 0x65c: 0x12, 0x65d: 0x13, 0x65e: 0x14, 0x65f: 0x15,
@@ -1704,7 +1676,7 @@ var stringWidthIndex = [1920]uint8{
0x670: 0x06, 0x671: 0x06, 0x672: 0x06, 0x673: 0x06, 0x674: 0x06, 0x675: 0x06, 0x676: 0x06, 0x677: 0x06,
0x678: 0x06, 0x679: 0x06, 0x67a: 0x06, 0x67b: 0x06, 0x67c: 0x06, 0x67d: 0x06, 0x67e: 0x06, 0x67f: 0x16,
// Block 0x1a, offset 0x680
- 0x680: 0xf4, 0x681: 0x08, 0x684: 0x08, 0x685: 0x08, 0x686: 0x08, 0x687: 0x09,
+ 0x680: 0xf2, 0x681: 0x08, 0x684: 0x08, 0x685: 0x08, 0x686: 0x08, 0x687: 0x09,
// Block 0x1b, offset 0x6c0
0x6c0: 0x5b, 0x6c1: 0x5b, 0x6c2: 0x5b, 0x6c3: 0x5b, 0x6c4: 0x5b, 0x6c5: 0x5b, 0x6c6: 0x5b, 0x6c7: 0x5b,
0x6c8: 0x5b, 0x6c9: 0x5b, 0x6ca: 0x5b, 0x6cb: 0x5b, 0x6cc: 0x5b, 0x6cd: 0x5b, 0x6ce: 0x5b, 0x6cf: 0x5b,
@@ -1713,7 +1685,7 @@ var stringWidthIndex = [1920]uint8{
0x6e0: 0x5b, 0x6e1: 0x5b, 0x6e2: 0x5b, 0x6e3: 0x5b, 0x6e4: 0x5b, 0x6e5: 0x5b, 0x6e6: 0x5b, 0x6e7: 0x5b,
0x6e8: 0x5b, 0x6e9: 0x5b, 0x6ea: 0x5b, 0x6eb: 0x5b, 0x6ec: 0x5b, 0x6ed: 0x5b, 0x6ee: 0x5b, 0x6ef: 0x5b,
0x6f0: 0x5b, 0x6f1: 0x5b, 0x6f2: 0x5b, 0x6f3: 0x5b, 0x6f4: 0x5b, 0x6f5: 0x5b, 0x6f6: 0x5b, 0x6f7: 0x5b,
- 0x6f8: 0x5b, 0x6f9: 0x5b, 0x6fa: 0x5b, 0x6fb: 0x5b, 0x6fc: 0x5b, 0x6fd: 0x5b, 0x6fe: 0x5b, 0x6ff: 0xf5,
+ 0x6f8: 0x5b, 0x6f9: 0x5b, 0x6fa: 0x5b, 0x6fb: 0x5b, 0x6fc: 0x5b, 0x6fd: 0x5b, 0x6fe: 0x5b, 0x6ff: 0xf3,
// Block 0x1c, offset 0x700
0x720: 0x18,
0x730: 0x09, 0x731: 0x09, 0x732: 0x09, 0x733: 0x09, 0x734: 0x09, 0x735: 0x09, 0x736: 0x09, 0x737: 0x09,
diff --git a/vendor/github.com/clipperhouse/displaywidth/width.go b/vendor/github.com/clipperhouse/displaywidth/width.go
index 55dd458..a96ab0b 100644
--- a/vendor/github.com/clipperhouse/displaywidth/width.go
+++ b/vendor/github.com/clipperhouse/displaywidth/width.go
@@ -122,28 +122,18 @@ func graphemeWidth[T stringish.Interface](s T, options Options) int {
prop := property(p)
// Variation Selector 16 (VS16) requests emoji presentation
- if sz > 0 && len(s) >= sz+3 {
+ if prop != _Wide && sz > 0 && len(s) >= sz+3 {
vs := s[sz : sz+3]
if isVS16(vs) {
- prop = _Emoji
+ prop = _Wide
}
// VS15 (0x8E) requests text presentation but does not affect width,
// in my reading of Unicode TR51. Falls through to return the base
// character's property.
}
- /*
- Note: we previously had some regional indicator handling here,
- intending to treat single RI's as width 1 and pairs as width 2.
- We think that's what the Unicode #11 indicates?
-
- Then we looked at what actual terminals do, and they seem to treat
- single and paired RI's as width 2, regardless. See terminal-test/.
- Looks like VS Code does the same FWIW.
- */
-
if options.EastAsianWidth && prop == _East_Asian_Ambiguous {
- prop = _East_Asian_Wide
+ prop = _Wide
}
if prop > upperBound {
@@ -167,13 +157,11 @@ func isVS16[T stringish.Interface](s T) bool {
}
// propertyWidths is a jump table of sorts, instead of a switch
-var propertyWidths = [6]int{
+var propertyWidths = [4]int{
_Default: 1,
_Zero_Width: 0,
- _East_Asian_Wide: 2,
+ _Wide: 2,
_East_Asian_Ambiguous: 1,
- _Emoji: 2,
- _Regional_Indicator: 2,
}
const upperBound = property(len(propertyWidths) - 1)
diff --git a/vendor/github.com/gabriel-vasile/mimetype/.golangci.yml b/vendor/github.com/gabriel-vasile/mimetype/.golangci.yml
index f2058cc..5b30cd6 100644
--- a/vendor/github.com/gabriel-vasile/mimetype/.golangci.yml
+++ b/vendor/github.com/gabriel-vasile/mimetype/.golangci.yml
@@ -1,5 +1,41 @@
version: "2"
+
+run:
+ timeout: 5m
+
linters:
exclusions:
presets:
- std-error-handling
+ enable:
+ - gosec # Detects security problems.
+ # Keep all extras disabled for now to focus on the integer overflow problem.
+ # TODO: enable these and other good linters
+ - dogsled # Detects assignments with too many blank identifiers.
+ - errcheck
+ - errchkjson # Detects unsupported types passed to json encoding functions and reports if checks for the returned error can be omitted.
+ - exhaustive # Detects missing options in enum switch statements.
+ - gocyclo
+ - govet
+ - ineffassign
+ - makezero # Finds slice declarations with non-zero initial length.
+ - misspell # Detects commonly misspelled English words in comments.
+ - nakedret # Detects uses of naked returns.
+ - prealloc # Detects slice declarations that could potentially be pre-allocated.
+ - predeclared # Detects code that shadows one of Go's predeclared identifiers.
+ - reassign # Detects reassigning a top-level variable in another package.
+ - staticcheck
+ - thelper # Detects test helpers without t.Helper().
+ - tparallel # Detects inappropriate usage of t.Parallel().
+ - unconvert # Detects unnecessary type conversions.
+ - unused
+ - usestdlibvars # Detects the possibility to use variables/constants from the Go standard library.
+ - usetesting # Reports uses of functions with replacement inside the testing package.
+ settings:
+ govet:
+ disable:
+ - stdversion
+ gosec:
+ excludes:
+ - G404 # Weak random number generator used in tests.
+ - G304 # File inclusion
diff --git a/vendor/github.com/gabriel-vasile/mimetype/README.md b/vendor/github.com/gabriel-vasile/mimetype/README.md
index ea5c89a..9fe71ac 100644
--- a/vendor/github.com/gabriel-vasile/mimetype/README.md
+++ b/vendor/github.com/gabriel-vasile/mimetype/README.md
@@ -70,13 +70,13 @@ If increasing the limit does not help, please
## Tests
In addition to unit tests,
[mimetype_tests](https://github.com/gabriel-vasile/mimetype_tests) compares the
-library with the [Unix file utility](https://en.wikipedia.org/wiki/File_(command))
+library with [libmagic](https://en.wikipedia.org/wiki/File_(command))
for around 50 000 sample files. Check the latest comparison results
[here](https://github.com/gabriel-vasile/mimetype_tests/actions).
## Benchmarks
-Benchmarks for each file format are performed when a PR is open. The results can
-be seen on the [workflows page](https://github.com/gabriel-vasile/mimetype/actions/workflows/benchmark.yml).
+Benchmarks are performed when a PR is open. The results can be seen on the
+[workflows page](https://github.com/gabriel-vasile/mimetype/actions/workflows/benchmark.yml).
Performance improvements are welcome but correctness is prioritized.
## Structure
diff --git a/vendor/github.com/gabriel-vasile/mimetype/internal/json/parser.go b/vendor/github.com/gabriel-vasile/mimetype/internal/json/parser.go
index d11c0a8..fc3c772 100644
--- a/vendor/github.com/gabriel-vasile/mimetype/internal/json/parser.go
+++ b/vendor/github.com/gabriel-vasile/mimetype/internal/json/parser.go
@@ -94,20 +94,6 @@ func eq(path1, path2 [][]byte) bool {
return true
}
-// LooksLikeObjectOrArray reports if first non white space character from raw
-// is either { or [. Parsing raw as JSON is a heavy operation. When receiving some
-// text input we can skip parsing if the input does not even look like JSON.
-func LooksLikeObjectOrArray(raw []byte) bool {
- for i := range raw {
- if isSpace(raw[i]) {
- continue
- }
- return raw[i] == '{' || raw[i] == '['
- }
-
- return false
-}
-
// Parse will take out a parser from the pool depending on queryType and tries
// to parse raw bytes as JSON.
func Parse(queryType string, raw []byte) (parsed, inspected, firstToken int, querySatisfied bool) {
diff --git a/vendor/github.com/gabriel-vasile/mimetype/internal/magic/archive.go b/vendor/github.com/gabriel-vasile/mimetype/internal/magic/archive.go
index 8a0c849..0b4c62f 100644
--- a/vendor/github.com/gabriel-vasile/mimetype/internal/magic/archive.go
+++ b/vendor/github.com/gabriel-vasile/mimetype/internal/magic/archive.go
@@ -106,10 +106,10 @@ func CRX(raw []byte, limit uint32) bool {
if len(raw) < minHeaderLen || !bytes.HasPrefix(raw, []byte("Cr24")) {
return false
}
- pubkeyLen := binary.LittleEndian.Uint32(raw[8:12])
- sigLen := binary.LittleEndian.Uint32(raw[12:16])
+ pubkeyLen := int64(binary.LittleEndian.Uint32(raw[8:12]))
+ sigLen := int64(binary.LittleEndian.Uint32(raw[12:16]))
zipOffset := minHeaderLen + pubkeyLen + sigLen
- if uint32(len(raw)) < zipOffset {
+ if zipOffset < 0 || int64(len(raw)) < zipOffset {
return false
}
return Zip(raw[zipOffset:], limit)
@@ -209,3 +209,13 @@ func tarChksum(b []byte) (unsigned, signed int64) {
}
return unsigned, signed
}
+
+// Zlib matches zlib compressed files.
+func Zlib(raw []byte, _ uint32) bool {
+ // https://www.ietf.org/rfc/rfc6713.txt
+ // This check has one fault: ASCII code can satisfy it; for ex: []byte("x ")
+ zlib := len(raw) > 1 &&
+ raw[0] == 'x' && binary.BigEndian.Uint16(raw)%31 == 0
+ // Check that the file is not a regular text to avoid false positives.
+ return zlib && !Text(raw, 0)
+}
diff --git a/vendor/github.com/gabriel-vasile/mimetype/internal/magic/meteo.go b/vendor/github.com/gabriel-vasile/mimetype/internal/magic/meteo.go
new file mode 100644
index 0000000..da77d0b
--- /dev/null
+++ b/vendor/github.com/gabriel-vasile/mimetype/internal/magic/meteo.go
@@ -0,0 +1,12 @@
+package magic
+
+import "bytes"
+
+// GRIB matches a GRIdded Binary meteorological file.
+// https://www.nco.ncep.noaa.gov/pmb/docs/on388/
+// https://www.nco.ncep.noaa.gov/pmb/docs/grib2/grib2_doc/
+func GRIB(raw []byte, _ uint32) bool {
+ return len(raw) > 7 &&
+ bytes.HasPrefix(raw, []byte("GRIB")) &&
+ (raw[7] == 1 || raw[7] == 2)
+}
diff --git a/vendor/github.com/gabriel-vasile/mimetype/internal/magic/ms_office.go b/vendor/github.com/gabriel-vasile/mimetype/internal/magic/ms_office.go
index bd4a0c3..e689e92 100644
--- a/vendor/github.com/gabriel-vasile/mimetype/internal/magic/ms_office.go
+++ b/vendor/github.com/gabriel-vasile/mimetype/internal/magic/ms_office.go
@@ -192,7 +192,8 @@ func matchOleClsid(in []byte, clsid []byte) bool {
// Expected offset of CLSID for root storage object.
clsidOffset := sectorLength*(1+firstSecID) + 80
- if len(in) <= clsidOffset+16 {
+ // #731 offset is outside in or wrapped around due to integer overflow.
+ if len(in) <= clsidOffset+16 || clsidOffset < 0 {
return false
}
diff --git a/vendor/github.com/gabriel-vasile/mimetype/internal/magic/text.go b/vendor/github.com/gabriel-vasile/mimetype/internal/magic/text.go
index fb84e85..82f6c67 100644
--- a/vendor/github.com/gabriel-vasile/mimetype/internal/magic/text.go
+++ b/vendor/github.com/gabriel-vasile/mimetype/internal/magic/text.go
@@ -283,7 +283,7 @@ func Shell(raw []byte, _ uint32) bool {
// Text matches a plain text file.
//
// TODO: This function does not parse BOM-less UTF16 and UTF32 files. Not really
-// sure it should. Linux file utility also requires a BOM for UTF16 and UTF32.
+// sure it should. libmagic also requires a BOM for UTF16 and UTF32.
func Text(raw []byte, _ uint32) bool {
// First look for BOM.
if cset := charset.FromBOM(raw); cset != "" {
@@ -352,13 +352,20 @@ func GLTF(raw []byte, limit uint32) bool {
return jsonHelper(raw, limit, json.QueryGLTF, json.TokObject)
}
-func jsonHelper(raw []byte, limit uint32, q string, wantTok int) bool {
- if !json.LooksLikeObjectOrArray(raw) {
+func jsonHelper(raw scan.Bytes, limit uint32, q string, wantToks ...int) bool {
+ firstNonWS := raw.FirstNonWS()
+
+ hasTargetTok := false
+ for _, t := range wantToks {
+ hasTargetTok = hasTargetTok || (t&json.TokArray > 0 && firstNonWS == '[')
+ hasTargetTok = hasTargetTok || (t&json.TokObject > 0 && firstNonWS == '{')
+ }
+ if !hasTargetTok {
return false
}
lraw := len(raw)
- parsed, inspected, firstToken, querySatisfied := json.Parse(q, raw)
- if !querySatisfied || firstToken&wantTok == 0 {
+ parsed, inspected, _, querySatisfied := json.Parse(q, raw)
+ if !querySatisfied {
return false
}
@@ -369,7 +376,7 @@ func jsonHelper(raw []byte, limit uint32, q string, wantTok int) bool {
// If a section of the file was provided, check if all of it was inspected.
// In other words, check that if there was a problem parsing, that problem
- // occured at the last byte in the input.
+ // occurred at the last byte in the input.
return inspected == lraw && lraw > 0
}
@@ -536,3 +543,57 @@ func Vtt(raw []byte, limit uint32) bool {
return bytes.Equal(raw, []byte{0xEF, 0xBB, 0xBF, 0x57, 0x45, 0x42, 0x56, 0x54, 0x54}) || // UTF-8 BOM and "WEBVTT"
bytes.Equal(raw, []byte{0x57, 0x45, 0x42, 0x56, 0x54, 0x54}) // "WEBVTT"
}
+
+type rfc822Hint struct {
+ h []byte
+ matchFlags scan.Flags
+}
+
+// The hints come from libmagic, but the implementation is bit different. libmagic
+// only checks if the file starts with the hint, while we additionally look for
+// a secondary hint in the first few lines of input.
+func RFC822(raw []byte, limit uint32) bool {
+ b := scan.Bytes(raw)
+
+ // Keep hints here to avoid instantiating them several times in lineHasRFC822Hint.
+ // The alternative is to make them a package level var, but then they'd go
+ // on the heap.
+ // Some of the hints are IgnoreCase, some not. I selected based on what libmagic
+ // does and based on personal observations from sample files.
+ hints := []rfc822Hint{
+ {[]byte("From: "), 0},
+ {[]byte("To: "), 0},
+ {[]byte("CC: "), scan.IgnoreCase},
+ {[]byte("Date: "), 0},
+ {[]byte("Subject: "), 0},
+ {[]byte("Received: "), 0},
+ {[]byte("Relay-Version: "), 0},
+ {[]byte("#! rnews"), 0},
+ {[]byte("N#! rnews"), 0},
+ {[]byte("Forward to"), 0},
+ {[]byte("Pipe to"), 0},
+ {[]byte("DELIVERED-TO: "), scan.IgnoreCase},
+ {[]byte("RETURN-PATH: "), scan.IgnoreCase},
+ {[]byte("Content-Type: "), 0},
+ {[]byte("Content-Transfer-Encoding: "), 0},
+ }
+ if !lineHasRFC822Hint(b.Line(), hints) {
+ return false
+ }
+ for i := 0; i < 20; i++ {
+ if lineHasRFC822Hint(b.Line(), hints) {
+ return true
+ }
+ }
+
+ return false
+}
+
+func lineHasRFC822Hint(b scan.Bytes, hints []rfc822Hint) bool {
+ for _, h := range hints {
+ if b.Match(h.h, h.matchFlags) > -1 {
+ return true
+ }
+ }
+ return false
+}
diff --git a/vendor/github.com/gabriel-vasile/mimetype/internal/magic/video.go b/vendor/github.com/gabriel-vasile/mimetype/internal/magic/video.go
index 830c5ed..23e30da 100644
--- a/vendor/github.com/gabriel-vasile/mimetype/internal/magic/video.go
+++ b/vendor/github.com/gabriel-vasile/mimetype/internal/magic/video.go
@@ -69,9 +69,9 @@ func isFileTypeNamePresent(in []byte, flType string) bool {
// vintWidth parses the variable-integer width in matroska containers
func vintWidth(v int) int {
- mask, max, num := 128, 8, 1
- for num < max && v&mask == 0 {
- mask = mask >> 1
+ mask, nTimes, num := 128, 8, 1
+ for num < nTimes && v&mask == 0 {
+ mask >>= 1
num++
}
return num
diff --git a/vendor/github.com/gabriel-vasile/mimetype/internal/magic/zip.go b/vendor/github.com/gabriel-vasile/mimetype/internal/magic/zip.go
index 31f4248..f3bfa2a 100644
--- a/vendor/github.com/gabriel-vasile/mimetype/internal/magic/zip.go
+++ b/vendor/github.com/gabriel-vasile/mimetype/internal/magic/zip.go
@@ -85,10 +85,14 @@ func Zip(raw []byte, limit uint32) bool {
// (instead of relying on offsets told by the file.)
func Jar(raw []byte, limit uint32) bool {
return executableJar(raw) ||
+ // First entry must be an empty META-INF directory or the manifest.
+ // There is no specification saying that, but the jar reader and writer
+ // implementations from Java do it that way.
+ // https://github.com/openjdk/jdk/blob/88c4678eed818cbe9380f35352e90883fed27d33/src/java.base/share/classes/java/util/jar/JarInputStream.java#L170-L173
zipHas(raw, zipEntries{{
- name: []byte("META-INF/MANIFEST.MF"),
- }, {
name: []byte("META-INF/"),
+ }, {
+ name: []byte("META-INF/MANIFEST.MF"),
}}, 1)
}
@@ -127,11 +131,14 @@ type zipEntries []struct {
func (z zipEntries) match(file []byte) bool {
for i := range z {
- if z[i].dir && bytes.HasPrefix(file, z[i].name) {
- return true
- }
- if bytes.Equal(file, z[i].name) {
- return true
+ if z[i].dir {
+ if bytes.HasPrefix(file, z[i].name) {
+ return true
+ }
+ } else {
+ if bytes.Equal(file, z[i].name) {
+ return true
+ }
}
}
return false
diff --git a/vendor/github.com/gabriel-vasile/mimetype/internal/scan/bytes.go b/vendor/github.com/gabriel-vasile/mimetype/internal/scan/bytes.go
index b19a949..552b4ea 100644
--- a/vendor/github.com/gabriel-vasile/mimetype/internal/scan/bytes.go
+++ b/vendor/github.com/gabriel-vasile/mimetype/internal/scan/bytes.go
@@ -35,6 +35,19 @@ func (b *Bytes) TrimRWS() {
}
}
+// FirstNonWS returns the first non-whitespace character from b,
+// or 0x00 if no such character is found.
+func (b Bytes) FirstNonWS() byte {
+ for i := range b {
+ if ByteIsWS(b[i]) {
+ continue
+ }
+ return b[i]
+ }
+
+ return 0x00
+}
+
// Peek one byte from b or 0x00 if b is empty.
func (b *Bytes) Peek() byte {
if len(*b) > 0 {
@@ -63,8 +76,8 @@ func (b *Bytes) PopN(n int) []byte {
return nil
}
-// PopUntil will advance b until, but not including, the first occurence of stopAt
-// character. If no occurence is found, then it will advance until the end of b.
+// PopUntil will advance b until, but not including, the first occurrence of stopAt
+// character. If no occurrence is found, then it will advance until the end of b.
// The returned Bytes is a slice of all the bytes that we're advanced over.
func (b *Bytes) PopUntil(stopAt ...byte) Bytes {
if len(*b) == 0 {
@@ -77,7 +90,7 @@ func (b *Bytes) PopUntil(stopAt ...byte) Bytes {
prefix := (*b)[:i]
*b = (*b)[i:]
- return Bytes(prefix)
+ return prefix
}
// ReadSlice is the same as PopUntil, but the returned value includes stopAt as well.
@@ -94,7 +107,7 @@ func (b *Bytes) ReadSlice(stopAt byte) Bytes {
prefix := (*b)[:i]
*b = (*b)[i:]
- return Bytes(prefix)
+ return prefix
}
// Line returns the first line from b and advances b with the length of the
@@ -117,7 +130,7 @@ func (b *Bytes) Line() Bytes {
// If b length is less than readLimit, it means we received an incomplete file
// and proceed with dropping the last line.
func (b *Bytes) DropLastLine(readLimit uint32) {
- if readLimit == 0 || uint32(len(*b)) < readLimit {
+ if readLimit == 0 || uint64(len(*b)) < uint64(readLimit) {
return
}
@@ -151,7 +164,7 @@ const (
FullWord
)
-// Search for occurences of pattern p inside b at any index.
+// Search for occurrences of pattern p inside b at any index.
// It returns the index where p was found in b and how many bytes were needed
// for matching the pattern.
func (b Bytes) Search(p []byte, flags Flags) (i int, l int) {
diff --git a/vendor/github.com/gabriel-vasile/mimetype/mime.go b/vendor/github.com/gabriel-vasile/mimetype/mime.go
index ec2bc5b..3dadf72 100644
--- a/vendor/github.com/gabriel-vasile/mimetype/mime.go
+++ b/vendor/github.com/gabriel-vasile/mimetype/mime.go
@@ -2,6 +2,7 @@ package mimetype
import (
"mime"
+ "slices"
"strings"
"github.com/gabriel-vasile/mimetype/internal/charset"
@@ -58,10 +59,8 @@ func (m *MIME) Is(expectedMIME string) bool {
return true
}
- for _, alias := range m.aliases {
- if alias == expectedMIME {
- return true
- }
+ if slices.Contains(m.aliases, expectedMIME) {
+ return true
}
return false
@@ -180,10 +179,8 @@ func (m *MIME) lookup(mime string) *MIME {
if mime == m.mime {
return m
}
- for _, n := range m.aliases {
- if n == mime {
- return m
- }
+ if slices.Contains(m.aliases, mime) {
+ return m
}
for _, c := range m.children {
diff --git a/vendor/github.com/gabriel-vasile/mimetype/supported_mimes.md b/vendor/github.com/gabriel-vasile/mimetype/supported_mimes.md
index 241a81f..45de7b9 100644
--- a/vendor/github.com/gabriel-vasile/mimetype/supported_mimes.md
+++ b/vendor/github.com/gabriel-vasile/mimetype/supported_mimes.md
@@ -1,4 +1,4 @@
-## 192 Supported MIME types
+## 195 Supported MIME types
This file is automatically generated when running tests. Do not edit manually.
Extension | MIME type
Aliases | Hierarchy
@@ -152,6 +152,8 @@ Extension | MIME type
Aliases | Hierarchy
**.chm** | **application/vnd.ms-htmlhelp** | chm>root
**.wpd** | **application/vnd.wordperfect** | wpd>root
**.dxf** | **image/vnd.dxf** | dxf>root
+**.grb** | **application/grib** | grb>root
+**n/a** | **application/zlib** | zlib>root
**.txt** | **text/plain** | txt>root
**.svg** | **image/svg+xml** | svg>txt>root
**.html** | **text/html** | html>txt>root
@@ -195,3 +197,4 @@ Extension | MIME type
Aliases | Hierarchy
**.pgm** | **image/x-portable-graymap** | pgm>txt>root
**.ppm** | **image/x-portable-pixmap** | ppm>txt>root
**.pam** | **image/x-portable-arbitrarymap** | pam>txt>root
+**.eml** | **message/rfc822** | eml>txt>root
diff --git a/vendor/github.com/gabriel-vasile/mimetype/tree.go b/vendor/github.com/gabriel-vasile/mimetype/tree.go
index 21b70d5..29ef820 100644
--- a/vendor/github.com/gabriel-vasile/mimetype/tree.go
+++ b/vendor/github.com/gabriel-vasile/mimetype/tree.go
@@ -24,7 +24,7 @@ var root = newMIME("application/octet-stream", "",
woff2, otf, ttc, eot, wasm, shx, dbf, dcm, rar, djvu, mobi, lit, bpg, cbor,
sqlite3, dwg, nes, lnk, macho, qcp, icns, hdr, mrc, mdb, accdb, zstd, cab,
rpm, xz, lzip, torrent, cpio, tzif, xcf, pat, gbr, glb, cabIS, jxr, parquet,
- oneNote, chm, wpd, dxf,
+ oneNote, chm, wpd, dxf, grib, zlib,
// Keep text last because it is the slowest check.
text,
)
@@ -82,7 +82,7 @@ var (
alias("application/x-ogg")
oggAudio = newMIME("audio/ogg", ".oga", magic.OggAudio)
oggVideo = newMIME("video/ogg", ".ogv", magic.OggVideo)
- text = newMIME("text/plain", ".txt", magic.Text, svg, html, xml, php, js, lua, perl, python, ruby, json, ndJSON, rtf, srt, tcl, csv, tsv, vCard, iCalendar, warc, vtt, shell, netpbm, netpgm, netppm, netpam)
+ text = newMIME("text/plain", ".txt", magic.Text, svg, html, xml, php, js, lua, perl, python, ruby, json, ndJSON, rtf, srt, tcl, csv, tsv, vCard, iCalendar, warc, vtt, shell, netpbm, netpgm, netppm, netpam, rfc822)
xml = newMIME("text/xml", ".xml", magic.XML, rss, atom, x3d, kml, xliff, collada, gml, gpx, tcx, amf, threemf, xfdf, owl2, xhtml).
alias("application/xml")
xhtml = newMIME("application/xhtml+xml", ".html", magic.XHTML)
@@ -287,4 +287,7 @@ var (
chm = newMIME("application/vnd.ms-htmlhelp", ".chm", magic.CHM)
wpd = newMIME("application/vnd.wordperfect", ".wpd", magic.WPD)
dxf = newMIME("image/vnd.dxf", ".dxf", magic.DXF)
+ rfc822 = newMIME("message/rfc822", ".eml", magic.RFC822)
+ grib = newMIME("application/grib", ".grb", magic.GRIB)
+ zlib = newMIME("application/zlib", "", magic.Zlib)
)
diff --git a/vendor/go.mau.fi/util/dbutil/upgrades.go b/vendor/go.mau.fi/util/dbutil/upgrades.go
index d2aa88f..9536a27 100644
--- a/vendor/go.mau.fi/util/dbutil/upgrades.go
+++ b/vendor/go.mau.fi/util/dbutil/upgrades.go
@@ -33,6 +33,18 @@ var ErrForeignTables = errors.New("the database contains foreign tables")
var ErrNotOwned = errors.New("the database is owned by")
var ErrUnsupportedDialect = errors.New("unsupported database dialect")
+type NotOwnedError struct {
+ Owner string
+}
+
+func (e NotOwnedError) Error() string {
+ return fmt.Sprintf("%v %s", ErrNotOwned, e.Owner)
+}
+
+func (e NotOwnedError) Unwrap() error {
+ return ErrNotOwned
+}
+
func DangerousInternalUpgradeVersionTable(ctx context.Context, db *Database) error {
return db.upgradeVersionTable(ctx)
}
@@ -143,7 +155,7 @@ func (db *Database) checkDatabaseOwner(ctx context.Context) error {
} else if err != nil {
return fmt.Errorf("failed to check database owner: %w", err)
} else if owner != db.Owner {
- return fmt.Errorf("%w %s", ErrNotOwned, owner)
+ return NotOwnedError{owner}
}
return nil
}
diff --git a/vendor/go.mau.fi/util/exsync/syncmap.go b/vendor/go.mau.fi/util/exsync/syncmap.go
index b2013f2..f49a57a 100644
--- a/vendor/go.mau.fi/util/exsync/syncmap.go
+++ b/vendor/go.mau.fi/util/exsync/syncmap.go
@@ -82,6 +82,23 @@ func (sm *Map[Key, Value]) GetDefault(key Key, def Value) Value {
return def
}
+// GetOrSetFactory gets a value in the map if the key already exists,
+// otherwise inserts a new value from the given function and returns it.
+func (sm *Map[Key, Value]) GetOrSetFactory(key Key, def func() Value) Value {
+ val, ok := sm.Get(key)
+ if ok {
+ return val
+ }
+ sm.lock.Lock()
+ defer sm.lock.Unlock()
+ value, ok := sm.data[key]
+ if !ok {
+ value = def()
+ sm.data[key] = value
+ }
+ return value
+}
+
// GetOrSet gets a value in the map if the key already exists, otherwise inserts the given value and returns it.
//
// The boolean return parameter is true if the key already exists, and false if the given value was inserted.
@@ -120,6 +137,21 @@ func (sm *Map[Key, Value]) CopyFrom(other map[Key]Value) {
sm.lock.Unlock()
}
+// SwapData replaces the internal map with the given map, returning the previous map.
+// If the given map is nil, a new empty map is created.
+// The given map must not be modified after passing it to this function.
+func (sm *Map[Key, Value]) SwapData(other map[Key]Value) map[Key]Value {
+ sm.lock.Lock()
+ prev := sm.data
+ if other == nil {
+ sm.data = make(map[Key]Value)
+ } else {
+ sm.data = other
+ }
+ sm.lock.Unlock()
+ return prev
+}
+
// Clone returns a copy of the map.
func (sm *Map[Key, Value]) Clone() *Map[Key, Value] {
return NewMapWithData(sm.CopyData())
diff --git a/vendor/golang.org/x/tools/go/ast/astutil/imports.go b/vendor/golang.org/x/tools/go/ast/astutil/imports.go
index 5bacc0f..adb4711 100644
--- a/vendor/golang.org/x/tools/go/ast/astutil/imports.go
+++ b/vendor/golang.org/x/tools/go/ast/astutil/imports.go
@@ -9,6 +9,7 @@ import (
"fmt"
"go/ast"
"go/token"
+ "reflect"
"slices"
"strconv"
"strings"
@@ -149,7 +150,7 @@ func AddNamedImport(fset *token.FileSet, f *ast.File, name, path string) (added
if newImport.Name != nil {
newImport.Name.NamePos = pos
}
- newImport.Path.ValuePos = pos
+ updateBasicLitPos(newImport.Path, pos)
newImport.EndPos = pos
// Clean up parens. impDecl contains at least one spec.
@@ -184,7 +185,7 @@ func AddNamedImport(fset *token.FileSet, f *ast.File, name, path string) (added
first.Lparen = first.Pos()
// Move the imports of the other import declaration to the first one.
for _, spec := range gen.Specs {
- spec.(*ast.ImportSpec).Path.ValuePos = first.Pos()
+ updateBasicLitPos(spec.(*ast.ImportSpec).Path, first.Pos())
first.Specs = append(first.Specs, spec)
}
f.Decls = slices.Delete(f.Decls, i, i+1)
@@ -470,3 +471,17 @@ func Imports(fset *token.FileSet, f *ast.File) [][]*ast.ImportSpec {
return groups
}
+
+// updateBasicLitPos updates lit.Pos,
+// ensuring that lit.End (if set) is displaced by the same amount.
+// (See https://go.dev/issue/76395.)
+func updateBasicLitPos(lit *ast.BasicLit, pos token.Pos) {
+ len := lit.End() - lit.Pos()
+ lit.ValuePos = pos
+ // TODO(adonovan): after go1.26, simplify to:
+ // lit.ValueEnd = pos + len
+ v := reflect.ValueOf(lit).Elem().FieldByName("ValueEnd")
+ if v.IsValid() && v.Int() != 0 {
+ v.SetInt(int64(pos + len))
+ }
+}
diff --git a/vendor/maunium.net/go/mautrix/.pre-commit-config.yaml b/vendor/maunium.net/go/mautrix/.pre-commit-config.yaml
index 0b9785a..616fccb 100644
--- a/vendor/maunium.net/go/mautrix/.pre-commit-config.yaml
+++ b/vendor/maunium.net/go/mautrix/.pre-commit-config.yaml
@@ -1,6 +1,6 @@
repos:
- repo: https://github.com/pre-commit/pre-commit-hooks
- rev: v5.0.0
+ rev: v6.0.0
hooks:
- id: trailing-whitespace
exclude_types: [markdown]
@@ -9,7 +9,7 @@ repos:
- id: check-added-large-files
- repo: https://github.com/tekwizely/pre-commit-golang
- rev: v1.0.0-rc.1
+ rev: v1.0.0-rc.4
hooks:
- id: go-imports-repo
args:
@@ -18,8 +18,7 @@ repos:
- "-w"
- id: go-vet-repo-mod
- id: go-mod-tidy
- # TODO enable this
- #- id: go-staticcheck-repo-mod
+ - id: go-staticcheck-repo-mod
- repo: https://github.com/beeper/pre-commit-go
rev: v0.4.2
diff --git a/vendor/maunium.net/go/mautrix/CHANGELOG.md b/vendor/maunium.net/go/mautrix/CHANGELOG.md
index b6c0ff7..0fb1a10 100644
--- a/vendor/maunium.net/go/mautrix/CHANGELOG.md
+++ b/vendor/maunium.net/go/mautrix/CHANGELOG.md
@@ -1,3 +1,35 @@
+## v0.26.1 (2025-12-16)
+
+* **Breaking change *(mediaproxy)*** Changed `GetMediaResponseFile` to return
+ the mime type from the callback rather than in the return get media return
+ value. The callback can now also redirect the caller to a different file.
+* *(federation)* Added join/knock/leave functions
+ (thanks to [@nexy7574] in [#422]).
+* *(federation/eventauth)* Fixed various incorrect checks.
+* *(client)* Added backoff for retrying media uploads to external URLs
+ (with MSC3870).
+* *(bridgev2/config)* Added support for overriding config fields using
+ environment variables.
+* *(bridgev2/commands)* Added command to mute chat on remote network.
+* *(bridgev2)* Added interface for network connectors to redirect to a different
+ user ID when handling an invite from Matrix.
+* *(bridgev2)* Added interface for signaling message request status of portals.
+* *(bridgev2)* Changed portal creation to not backfill unless `CanBackfill` flag
+ is set in chat info.
+* *(bridgev2)* Changed Matrix reaction handling to only delete old reaction if
+ bridging the new one is successful.
+* *(bridgev2/mxmain)* Improved error message when trying to run bridge with
+ pre-megabridge database when no database migration exists.
+* *(bridgev2)* Improved reliability of database migration when enabling split
+ portals.
+* *(bridgev2)* Improved detection of orphaned DM rooms when starting new chats.
+* *(bridgev2)* Stopped sending redundant invites when joining ghosts to public
+ portal rooms.
+* *(bridgev2)* Stopped hardcoding room versions in favor of checking
+ server capabilities to determine appropriate `/createRoom` parameters.
+
+[#422]: https://github.com/mautrix/go/pull/422
+
## v0.26.0 (2025-11-16)
* *(client,appservice)* Deprecated `SendMassagedStateEvent` as `SendStateEvent`
@@ -43,7 +75,7 @@
* *(federation)* Fixed validating auth for requests with query params.
* *(federation/eventauth)* Fixed typo causing restricted joins to not work.
-[MSC416]: https://github.com/matrix-org/matrix-spec-proposals/pull/4169
+[MSC4169]: https://github.com/matrix-org/matrix-spec-proposals/pull/4169
[#411]: github.com/mautrix/go/pull/411
[#420]: github.com/mautrix/go/pull/420
[#426]: github.com/mautrix/go/pull/426
diff --git a/vendor/maunium.net/go/mautrix/client.go b/vendor/maunium.net/go/mautrix/client.go
index d07bede..9073758 100644
--- a/vendor/maunium.net/go/mautrix/client.go
+++ b/vendor/maunium.net/go/mautrix/client.go
@@ -614,7 +614,9 @@ func (cli *Client) doRetry(
select {
case <-time.After(backoff):
case <-req.Context().Done():
- return nil, nil, req.Context().Err()
+ if !errors.Is(context.Cause(req.Context()), ErrContextCancelRetry) {
+ return nil, nil, req.Context().Err()
+ }
}
if cli.UpdateRequestOnRetry != nil {
req = cli.UpdateRequestOnRetry(req, cause)
@@ -740,12 +742,15 @@ func (cli *Client) executeCompiledRequest(
cli.RequestStart(req)
startTime := time.Now()
res, err := client.Do(req)
- duration := time.Now().Sub(startTime)
+ duration := time.Since(startTime)
if res != nil && !dontReadResponse {
defer res.Body.Close()
}
if err != nil {
- if retries > 0 && !errors.Is(err, context.Canceled) {
+ // Either error is *not* canceled or the underlying cause of cancelation explicitly asks to retry
+ canRetry := !errors.Is(err, context.Canceled) ||
+ errors.Is(context.Cause(req.Context()), ErrContextCancelRetry)
+ if retries > 0 && canRetry {
return cli.doRetry(
req, err, retries, backoff, responseJSON, handler, dontReadResponse, sizeLimit, client,
)
@@ -857,7 +862,7 @@ func (cli *Client) FullSyncRequest(ctx context.Context, req ReqSync) (resp *Resp
}
start := time.Now()
_, err = cli.MakeFullRequest(ctx, fullReq)
- duration := time.Now().Sub(start)
+ duration := time.Since(start)
timeout := time.Duration(req.Timeout) * time.Millisecond
buffer := 10 * time.Second
if req.Since == "" {
@@ -961,7 +966,7 @@ func (cli *Client) RegisterGuest(ctx context.Context, req *ReqRegister) (*RespRe
// }
// token := res.AccessToken
func (cli *Client) RegisterDummy(ctx context.Context, req *ReqRegister) (*RespRegister, error) {
- res, uia, err := cli.Register(ctx, req)
+ _, uia, err := cli.Register(ctx, req)
if err != nil && uia == nil {
return nil, err
} else if uia == nil {
@@ -970,7 +975,7 @@ func (cli *Client) RegisterDummy(ctx context.Context, req *ReqRegister) (*RespRe
return nil, errors.New("server does not support m.login.dummy")
}
req.Auth = BaseAuthData{Type: AuthTypeDummy, Session: uia.Session}
- res, _, err = cli.Register(ctx, req)
+ res, _, err := cli.Register(ctx, req)
if err != nil {
return nil, err
}
@@ -1746,6 +1751,8 @@ func parseRoomStateArray(req *http.Request, res *http.Response, responseJSON any
return nil, nil
}
+type RoomStateMap = map[event.Type]map[string]*event.Event
+
// State gets all state in a room.
// See https://spec.matrix.org/v1.2/client-server-api/#get_matrixclientv3roomsroomidstate
func (cli *Client) State(ctx context.Context, roomID id.RoomID) (stateMap RoomStateMap, err error) {
@@ -2014,8 +2021,16 @@ func (cli *Client) uploadMediaToURL(ctx context.Context, data ReqUploadMedia) (*
Msg("Error uploading media to external URL, not retrying")
return nil, err
}
- cli.Log.Warn().Str("url", data.UnstableUploadURL).Err(err).
+ backoff := time.Second * time.Duration(cli.DefaultHTTPRetries-retries)
+ cli.Log.Warn().Err(err).
+ Str("url", data.UnstableUploadURL).
+ Int("retry_in_seconds", int(backoff.Seconds())).
Msg("Error uploading media to external URL, retrying")
+ select {
+ case <-time.After(backoff):
+ case <-ctx.Done():
+ return nil, ctx.Err()
+ }
retries--
_, err = readerSeeker.Seek(0, io.SeekStart)
if err != nil {
diff --git a/vendor/maunium.net/go/mautrix/crypto/attachment/attachments.go b/vendor/maunium.net/go/mautrix/crypto/attachment/attachments.go
index 155cca5..727aacb 100644
--- a/vendor/maunium.net/go/mautrix/crypto/attachment/attachments.go
+++ b/vendor/maunium.net/go/mautrix/crypto/attachment/attachments.go
@@ -21,13 +21,24 @@ import (
)
var (
- HashMismatch = errors.New("mismatching SHA-256 digest")
- UnsupportedVersion = errors.New("unsupported Matrix file encryption version")
- UnsupportedAlgorithm = errors.New("unsupported JWK encryption algorithm")
- InvalidKey = errors.New("failed to decode key")
- InvalidInitVector = errors.New("failed to decode initialization vector")
- InvalidHash = errors.New("failed to decode SHA-256 hash")
- ReaderClosed = errors.New("encrypting reader was already closed")
+ ErrHashMismatch = errors.New("mismatching SHA-256 digest")
+ ErrUnsupportedVersion = errors.New("unsupported Matrix file encryption version")
+ ErrUnsupportedAlgorithm = errors.New("unsupported JWK encryption algorithm")
+ ErrInvalidKey = errors.New("failed to decode key")
+ ErrInvalidInitVector = errors.New("failed to decode initialization vector")
+ ErrInvalidHash = errors.New("failed to decode SHA-256 hash")
+ ErrReaderClosed = errors.New("encrypting reader was already closed")
+)
+
+// Deprecated: use variables prefixed with Err
+var (
+ HashMismatch = ErrHashMismatch
+ UnsupportedVersion = ErrUnsupportedVersion
+ UnsupportedAlgorithm = ErrUnsupportedAlgorithm
+ InvalidKey = ErrInvalidKey
+ InvalidInitVector = ErrInvalidInitVector
+ InvalidHash = ErrInvalidHash
+ ReaderClosed = ErrReaderClosed
)
var (
@@ -85,25 +96,25 @@ func (ef *EncryptedFile) decodeKeys(includeHash bool) error {
if ef.decoded != nil {
return nil
} else if len(ef.Key.Key) != keyBase64Length {
- return InvalidKey
+ return ErrInvalidKey
} else if len(ef.InitVector) != ivBase64Length {
- return InvalidInitVector
+ return ErrInvalidInitVector
} else if includeHash && len(ef.Hashes.SHA256) != hashBase64Length {
- return InvalidHash
+ return ErrInvalidHash
}
ef.decoded = &decodedKeys{}
_, err := base64.RawURLEncoding.Decode(ef.decoded.key[:], []byte(ef.Key.Key))
if err != nil {
- return InvalidKey
+ return ErrInvalidKey
}
_, err = base64.RawStdEncoding.Decode(ef.decoded.iv[:], []byte(ef.InitVector))
if err != nil {
- return InvalidInitVector
+ return ErrInvalidInitVector
}
if includeHash {
_, err = base64.RawStdEncoding.Decode(ef.decoded.sha256[:], []byte(ef.Hashes.SHA256))
if err != nil {
- return InvalidHash
+ return ErrInvalidHash
}
}
return nil
@@ -179,7 +190,7 @@ var _ io.ReadSeekCloser = (*encryptingReader)(nil)
func (r *encryptingReader) Seek(offset int64, whence int) (int64, error) {
if r.closed {
- return 0, ReaderClosed
+ return 0, ErrReaderClosed
}
if offset != 0 || whence != io.SeekStart {
return 0, fmt.Errorf("attachments.EncryptStream: only seeking to the beginning is supported")
@@ -200,7 +211,7 @@ func (r *encryptingReader) Seek(offset int64, whence int) (int64, error) {
func (r *encryptingReader) Read(dst []byte) (n int, err error) {
if r.closed {
- return 0, ReaderClosed
+ return 0, ErrReaderClosed
} else if r.isDecrypting && r.file.decoded == nil {
if err = r.file.PrepareForDecryption(); err != nil {
return
@@ -224,7 +235,7 @@ func (r *encryptingReader) Close() (err error) {
}
if r.isDecrypting {
if !hmac.Equal(r.hash.Sum(nil), r.file.decoded.sha256[:]) {
- return HashMismatch
+ return ErrHashMismatch
}
} else {
r.file.Hashes.SHA256 = base64.RawStdEncoding.EncodeToString(r.hash.Sum(nil))
@@ -265,9 +276,9 @@ func (ef *EncryptedFile) Decrypt(ciphertext []byte) ([]byte, error) {
// DecryptInPlace will always call this automatically, so calling this manually is not necessary when using that function.
func (ef *EncryptedFile) PrepareForDecryption() error {
if ef.Version != "v2" {
- return UnsupportedVersion
+ return ErrUnsupportedVersion
} else if ef.Key.Algorithm != "A256CTR" {
- return UnsupportedAlgorithm
+ return ErrUnsupportedAlgorithm
} else if err := ef.decodeKeys(true); err != nil {
return err
}
@@ -281,7 +292,7 @@ func (ef *EncryptedFile) DecryptInPlace(data []byte) error {
}
dataHash := sha256.Sum256(data)
if !hmac.Equal(ef.decoded.sha256[:], dataHash[:]) {
- return HashMismatch
+ return ErrHashMismatch
}
utils.XorA256CTR(data, ef.decoded.key, ef.decoded.iv)
return nil
diff --git a/vendor/maunium.net/go/mautrix/crypto/cross_sign_pubkey.go b/vendor/maunium.net/go/mautrix/crypto/cross_sign_pubkey.go
index f85d1ea..223fc7b 100644
--- a/vendor/maunium.net/go/mautrix/crypto/cross_sign_pubkey.go
+++ b/vendor/maunium.net/go/mautrix/crypto/cross_sign_pubkey.go
@@ -63,8 +63,8 @@ func (mach *OlmMachine) GetCrossSigningPublicKeys(ctx context.Context, userID id
if len(dbKeys) > 0 {
masterKey, ok := dbKeys[id.XSUsageMaster]
if ok {
- selfSigning, _ := dbKeys[id.XSUsageSelfSigning]
- userSigning, _ := dbKeys[id.XSUsageUserSigning]
+ selfSigning := dbKeys[id.XSUsageSelfSigning]
+ userSigning := dbKeys[id.XSUsageUserSigning]
return &CrossSigningPublicKeysCache{
MasterKey: masterKey.Key,
SelfSigningKey: selfSigning.Key,
diff --git a/vendor/maunium.net/go/mautrix/crypto/cross_sign_store.go b/vendor/maunium.net/go/mautrix/crypto/cross_sign_store.go
index d30b7e3..57406b1 100644
--- a/vendor/maunium.net/go/mautrix/crypto/cross_sign_store.go
+++ b/vendor/maunium.net/go/mautrix/crypto/cross_sign_store.go
@@ -26,24 +26,22 @@ func (mach *OlmMachine) storeCrossSigningKeys(ctx context.Context, crossSigningK
log.Error().Err(err).
Msg("Error fetching current cross-signing keys of user")
}
- if currentKeys != nil {
- for curKeyUsage, curKey := range currentKeys {
- log := log.With().Stringer("old_key", curKey.Key).Str("old_key_usage", string(curKeyUsage)).Logger()
- // got a new key with the same usage as an existing key
- for _, newKeyUsage := range userKeys.Usage {
- if newKeyUsage == curKeyUsage {
- if _, ok := userKeys.Keys[id.NewKeyID(id.KeyAlgorithmEd25519, curKey.Key.String())]; !ok {
- // old key is not in the new key map, so we drop signatures made by it
- if count, err := mach.CryptoStore.DropSignaturesByKey(ctx, userID, curKey.Key); err != nil {
- log.Error().Err(err).Msg("Error deleting old signatures made by user")
- } else {
- log.Debug().
- Int64("signature_count", count).
- Msg("Dropped signatures made by old key as it has been replaced")
- }
+ for curKeyUsage, curKey := range currentKeys {
+ log := log.With().Stringer("old_key", curKey.Key).Str("old_key_usage", string(curKeyUsage)).Logger()
+ // got a new key with the same usage as an existing key
+ for _, newKeyUsage := range userKeys.Usage {
+ if newKeyUsage == curKeyUsage {
+ if _, ok := userKeys.Keys[id.NewKeyID(id.KeyAlgorithmEd25519, curKey.Key.String())]; !ok {
+ // old key is not in the new key map, so we drop signatures made by it
+ if count, err := mach.CryptoStore.DropSignaturesByKey(ctx, userID, curKey.Key); err != nil {
+ log.Error().Err(err).Msg("Error deleting old signatures made by user")
+ } else {
+ log.Debug().
+ Int64("signature_count", count).
+ Msg("Dropped signatures made by old key as it has been replaced")
}
- break
}
+ break
}
}
}
diff --git a/vendor/maunium.net/go/mautrix/crypto/cryptohelper/cryptohelper.go b/vendor/maunium.net/go/mautrix/crypto/cryptohelper/cryptohelper.go
index 1939ea7..b62dc12 100644
--- a/vendor/maunium.net/go/mautrix/crypto/cryptohelper/cryptohelper.go
+++ b/vendor/maunium.net/go/mautrix/crypto/cryptohelper/cryptohelper.go
@@ -278,7 +278,7 @@ func (helper *CryptoHelper) verifyDeviceKeysOnServer(ctx context.Context) error
}
}
-var NoSessionFound = crypto.NoSessionFound
+var NoSessionFound = crypto.ErrNoSessionFound
const initialSessionWaitTimeout = 3 * time.Second
const extendedSessionWaitTimeout = 22 * time.Second
@@ -371,6 +371,7 @@ func (helper *CryptoHelper) waitLongerForSession(ctx context.Context, evt *event
content := evt.Content.AsEncrypted()
log.Debug().Int("wait_seconds", int(extendedSessionWaitTimeout.Seconds())).Msg("Couldn't find session, requesting keys and waiting longer...")
+ //lint:ignore SA1019 RequestSession will gracefully request from all devices if DeviceID is blank
go helper.RequestSession(context.TODO(), evt.RoomID, content.SenderKey, content.SessionID, evt.Sender, content.DeviceID)
if !helper.mach.WaitForSession(ctx, evt.RoomID, content.SenderKey, content.SessionID, extendedSessionWaitTimeout) {
@@ -418,7 +419,7 @@ func (helper *CryptoHelper) EncryptWithStateKey(ctx context.Context, roomID id.R
defer helper.lock.RUnlock()
encrypted, err = helper.mach.EncryptMegolmEventWithStateKey(ctx, roomID, evtType, stateKey, content)
if err != nil {
- if !errors.Is(err, crypto.SessionExpired) && err != crypto.NoGroupSession && !errors.Is(err, crypto.SessionNotShared) {
+ if !errors.Is(err, crypto.ErrSessionExpired) && err != crypto.ErrNoGroupSession && !errors.Is(err, crypto.ErrSessionNotShared) {
return
}
helper.log.Debug().
diff --git a/vendor/maunium.net/go/mautrix/crypto/decryptmegolm.go b/vendor/maunium.net/go/mautrix/crypto/decryptmegolm.go
index 4727947..d8b419a 100644
--- a/vendor/maunium.net/go/mautrix/crypto/decryptmegolm.go
+++ b/vendor/maunium.net/go/mautrix/crypto/decryptmegolm.go
@@ -24,13 +24,24 @@ import (
)
var (
- IncorrectEncryptedContentType = errors.New("event content is not instance of *event.EncryptedEventContent")
- NoSessionFound = errors.New("failed to decrypt megolm event: no session with given ID found")
- DuplicateMessageIndex = errors.New("duplicate megolm message index")
- WrongRoom = errors.New("encrypted megolm event is not intended for this room")
- DeviceKeyMismatch = errors.New("device keys in event and verified device info do not match")
- SenderKeyMismatch = errors.New("sender keys in content and megolm session do not match")
- RatchetError = errors.New("failed to ratchet session after use")
+ ErrIncorrectEncryptedContentType = errors.New("event content is not instance of *event.EncryptedEventContent")
+ ErrNoSessionFound = errors.New("failed to decrypt megolm event: no session with given ID found")
+ ErrDuplicateMessageIndex = errors.New("duplicate megolm message index")
+ ErrWrongRoom = errors.New("encrypted megolm event is not intended for this room")
+ ErrDeviceKeyMismatch = errors.New("device keys in event and verified device info do not match")
+ ErrSenderKeyMismatch = errors.New("sender keys in content and megolm session do not match")
+ ErrRatchetError = errors.New("failed to ratchet session after use")
+)
+
+// Deprecated: use variables prefixed with Err
+var (
+ IncorrectEncryptedContentType = ErrIncorrectEncryptedContentType
+ NoSessionFound = ErrNoSessionFound
+ DuplicateMessageIndex = ErrDuplicateMessageIndex
+ WrongRoom = ErrWrongRoom
+ DeviceKeyMismatch = ErrDeviceKeyMismatch
+ SenderKeyMismatch = ErrSenderKeyMismatch
+ RatchetError = ErrRatchetError
)
type megolmEvent struct {
@@ -49,9 +60,9 @@ var (
func (mach *OlmMachine) DecryptMegolmEvent(ctx context.Context, evt *event.Event) (*event.Event, error) {
content, ok := evt.Content.Parsed.(*event.EncryptedEventContent)
if !ok {
- return nil, IncorrectEncryptedContentType
+ return nil, ErrIncorrectEncryptedContentType
} else if content.Algorithm != id.AlgorithmMegolmV1 {
- return nil, UnsupportedAlgorithm
+ return nil, ErrUnsupportedAlgorithm
}
log := mach.machOrContextLog(ctx).With().
Str("action", "decrypt megolm event").
@@ -97,7 +108,7 @@ func (mach *OlmMachine) DecryptMegolmEvent(ctx context.Context, evt *event.Event
Msg("Couldn't resolve trust level of session: sent by unknown device")
trustLevel = id.TrustStateUnknownDevice
} else if device.SigningKey != sess.SigningKey || device.IdentityKey != sess.SenderKey {
- return nil, DeviceKeyMismatch
+ return nil, ErrDeviceKeyMismatch
} else {
trustLevel, err = mach.ResolveTrustContext(ctx, device)
if err != nil {
@@ -147,7 +158,7 @@ func (mach *OlmMachine) DecryptMegolmEvent(ctx context.Context, evt *event.Event
if err != nil {
return nil, fmt.Errorf("failed to parse megolm payload: %w", err)
} else if megolmEvt.RoomID != encryptionRoomID {
- return nil, WrongRoom
+ return nil, ErrWrongRoom
}
if evt.StateKey != nil && megolmEvt.StateKey != nil && mach.AllowEncryptedState {
megolmEvt.Type.Class = event.StateEventType
@@ -201,19 +212,19 @@ func (mach *OlmMachine) checkUndecryptableMessageIndexDuplication(ctx context.Co
messageIndex, decodeErr := ParseMegolmMessageIndex(content.MegolmCiphertext)
if decodeErr != nil {
log.Warn().Err(decodeErr).Msg("Failed to parse message index to check if it's a duplicate for message that failed to decrypt")
- return 0, fmt.Errorf("%w (also failed to parse message index)", olm.UnknownMessageIndex)
+ return 0, fmt.Errorf("%w (also failed to parse message index)", olm.ErrUnknownMessageIndex)
}
firstKnown := sess.Internal.FirstKnownIndex()
log = log.With().Uint("message_index", messageIndex).Uint32("first_known_index", firstKnown).Logger()
if ok, err := mach.CryptoStore.ValidateMessageIndex(ctx, sess.SenderKey, content.SessionID, evt.ID, messageIndex, evt.Timestamp); err != nil {
log.Debug().Err(err).Msg("Failed to check if message index is duplicate")
- return messageIndex, fmt.Errorf("%w (failed to check if index is duplicate; received: %d, earliest known: %d)", olm.UnknownMessageIndex, messageIndex, firstKnown)
+ return messageIndex, fmt.Errorf("%w (failed to check if index is duplicate; received: %d, earliest known: %d)", olm.ErrUnknownMessageIndex, messageIndex, firstKnown)
} else if !ok {
log.Debug().Msg("Failed to decrypt message due to unknown index and found duplicate")
- return messageIndex, fmt.Errorf("%w %d (also failed to decrypt because earliest known index is %d)", DuplicateMessageIndex, messageIndex, firstKnown)
+ return messageIndex, fmt.Errorf("%w %d (also failed to decrypt because earliest known index is %d)", ErrDuplicateMessageIndex, messageIndex, firstKnown)
}
log.Debug().Msg("Failed to decrypt message due to unknown index, but index is not duplicate")
- return messageIndex, fmt.Errorf("%w (not duplicate index; received: %d, earliest known: %d)", olm.UnknownMessageIndex, messageIndex, firstKnown)
+ return messageIndex, fmt.Errorf("%w (not duplicate index; received: %d, earliest known: %d)", olm.ErrUnknownMessageIndex, messageIndex, firstKnown)
}
func (mach *OlmMachine) actuallyDecryptMegolmEvent(ctx context.Context, evt *event.Event, encryptionRoomID id.RoomID, content *event.EncryptedEventContent) (*InboundGroupSession, []byte, uint, error) {
@@ -224,13 +235,13 @@ func (mach *OlmMachine) actuallyDecryptMegolmEvent(ctx context.Context, evt *eve
if err != nil {
return nil, nil, 0, fmt.Errorf("failed to get group session: %w", err)
} else if sess == nil {
- return nil, nil, 0, fmt.Errorf("%w (ID %s)", NoSessionFound, content.SessionID)
+ return nil, nil, 0, fmt.Errorf("%w (ID %s)", ErrNoSessionFound, content.SessionID)
} else if content.SenderKey != "" && content.SenderKey != sess.SenderKey {
- return sess, nil, 0, SenderKeyMismatch
+ return sess, nil, 0, ErrSenderKeyMismatch
}
plaintext, messageIndex, err := sess.Internal.Decrypt(content.MegolmCiphertext)
if err != nil {
- if errors.Is(err, olm.UnknownMessageIndex) && mach.RatchetKeysOnDecrypt {
+ if errors.Is(err, olm.ErrUnknownMessageIndex) && mach.RatchetKeysOnDecrypt {
messageIndex, err = mach.checkUndecryptableMessageIndexDuplication(ctx, sess, evt, content)
return sess, nil, messageIndex, fmt.Errorf("failed to decrypt megolm event: %w", err)
}
@@ -238,7 +249,7 @@ func (mach *OlmMachine) actuallyDecryptMegolmEvent(ctx context.Context, evt *eve
} else if ok, err := mach.CryptoStore.ValidateMessageIndex(ctx, sess.SenderKey, content.SessionID, evt.ID, messageIndex, evt.Timestamp); err != nil {
return sess, nil, messageIndex, fmt.Errorf("failed to check if message index is duplicate: %w", err)
} else if !ok {
- return sess, nil, messageIndex, fmt.Errorf("%w %d", DuplicateMessageIndex, messageIndex)
+ return sess, nil, messageIndex, fmt.Errorf("%w %d", ErrDuplicateMessageIndex, messageIndex)
}
// Normal clients don't care about tracking the ratchet state, so let them bypass the rest of the function
@@ -290,24 +301,24 @@ func (mach *OlmMachine) actuallyDecryptMegolmEvent(ctx context.Context, evt *eve
err = mach.CryptoStore.RedactGroupSession(ctx, sess.RoomID, sess.ID(), "maximum messages reached")
if err != nil {
log.Err(err).Msg("Failed to delete fully used session")
- return sess, plaintext, messageIndex, RatchetError
+ return sess, plaintext, messageIndex, ErrRatchetError
} else {
log.Info().Msg("Deleted fully used session")
}
} else if ratchetCurrentIndex < ratchetTargetIndex && mach.RatchetKeysOnDecrypt {
if err = sess.RatchetTo(ratchetTargetIndex); err != nil {
log.Err(err).Msg("Failed to ratchet session")
- return sess, plaintext, messageIndex, RatchetError
+ return sess, plaintext, messageIndex, ErrRatchetError
} else if err = mach.CryptoStore.PutGroupSession(ctx, sess); err != nil {
log.Err(err).Msg("Failed to store ratcheted session")
- return sess, plaintext, messageIndex, RatchetError
+ return sess, plaintext, messageIndex, ErrRatchetError
} else {
log.Info().Msg("Ratcheted session forward")
}
} else if didModify {
if err = mach.CryptoStore.PutGroupSession(ctx, sess); err != nil {
log.Err(err).Msg("Failed to store updated ratchet safety data")
- return sess, plaintext, messageIndex, RatchetError
+ return sess, plaintext, messageIndex, ErrRatchetError
} else {
log.Debug().Msg("Ratchet safety data changed (ratchet state didn't change)")
}
diff --git a/vendor/maunium.net/go/mautrix/crypto/decryptolm.go b/vendor/maunium.net/go/mautrix/crypto/decryptolm.go
index 30cc4cf..cd02726 100644
--- a/vendor/maunium.net/go/mautrix/crypto/decryptolm.go
+++ b/vendor/maunium.net/go/mautrix/crypto/decryptolm.go
@@ -26,15 +26,27 @@ import (
)
var (
- UnsupportedAlgorithm = errors.New("unsupported event encryption algorithm")
- NotEncryptedForMe = errors.New("olm event doesn't contain ciphertext for this device")
- UnsupportedOlmMessageType = errors.New("unsupported olm message type")
- DecryptionFailedWithMatchingSession = errors.New("decryption failed with matching session")
- DecryptionFailedForNormalMessage = errors.New("decryption failed for normal message")
- SenderMismatch = errors.New("mismatched sender in olm payload")
- RecipientMismatch = errors.New("mismatched recipient in olm payload")
- RecipientKeyMismatch = errors.New("mismatched recipient key in olm payload")
- ErrDuplicateMessage = errors.New("duplicate olm message")
+ ErrUnsupportedAlgorithm = errors.New("unsupported event encryption algorithm")
+ ErrNotEncryptedForMe = errors.New("olm event doesn't contain ciphertext for this device")
+ ErrUnsupportedOlmMessageType = errors.New("unsupported olm message type")
+ ErrDecryptionFailedWithMatchingSession = errors.New("decryption failed with matching session")
+ ErrDecryptionFailedForNormalMessage = errors.New("decryption failed for normal message")
+ ErrSenderMismatch = errors.New("mismatched sender in olm payload")
+ ErrRecipientMismatch = errors.New("mismatched recipient in olm payload")
+ ErrRecipientKeyMismatch = errors.New("mismatched recipient key in olm payload")
+ ErrDuplicateMessage = errors.New("duplicate olm message")
+)
+
+// Deprecated: use variables prefixed with Err
+var (
+ UnsupportedAlgorithm = ErrUnsupportedAlgorithm
+ NotEncryptedForMe = ErrNotEncryptedForMe
+ UnsupportedOlmMessageType = ErrUnsupportedOlmMessageType
+ DecryptionFailedWithMatchingSession = ErrDecryptionFailedWithMatchingSession
+ DecryptionFailedForNormalMessage = ErrDecryptionFailedForNormalMessage
+ SenderMismatch = ErrSenderMismatch
+ RecipientMismatch = ErrRecipientMismatch
+ RecipientKeyMismatch = ErrRecipientKeyMismatch
)
// DecryptedOlmEvent represents an event that was decrypted from an event encrypted with the m.olm.v1.curve25519-aes-sha2 algorithm.
@@ -56,13 +68,13 @@ type DecryptedOlmEvent struct {
func (mach *OlmMachine) decryptOlmEvent(ctx context.Context, evt *event.Event) (*DecryptedOlmEvent, error) {
content, ok := evt.Content.Parsed.(*event.EncryptedEventContent)
if !ok {
- return nil, IncorrectEncryptedContentType
+ return nil, ErrIncorrectEncryptedContentType
} else if content.Algorithm != id.AlgorithmOlmV1 {
- return nil, UnsupportedAlgorithm
+ return nil, ErrUnsupportedAlgorithm
}
ownContent, ok := content.OlmCiphertext[mach.account.IdentityKey()]
if !ok {
- return nil, NotEncryptedForMe
+ return nil, ErrNotEncryptedForMe
}
decrypted, err := mach.decryptAndParseOlmCiphertext(ctx, evt, content.SenderKey, ownContent.Type, ownContent.Body)
if err != nil {
@@ -78,7 +90,7 @@ type OlmEventKeys struct {
func (mach *OlmMachine) decryptAndParseOlmCiphertext(ctx context.Context, evt *event.Event, senderKey id.SenderKey, olmType id.OlmMsgType, ciphertext string) (*DecryptedOlmEvent, error) {
if olmType != id.OlmMsgTypePreKey && olmType != id.OlmMsgTypeMsg {
- return nil, UnsupportedOlmMessageType
+ return nil, ErrUnsupportedOlmMessageType
}
log := mach.machOrContextLog(ctx).With().
@@ -102,11 +114,11 @@ func (mach *OlmMachine) decryptAndParseOlmCiphertext(ctx context.Context, evt *e
}
olmEvt.Type.Class = evt.Type.Class
if evt.Sender != olmEvt.Sender {
- return nil, SenderMismatch
+ return nil, ErrSenderMismatch
} else if mach.Client.UserID != olmEvt.Recipient {
- return nil, RecipientMismatch
+ return nil, ErrRecipientMismatch
} else if mach.account.SigningKey() != olmEvt.RecipientKeys.Ed25519 {
- return nil, RecipientKeyMismatch
+ return nil, ErrRecipientKeyMismatch
}
if len(olmEvt.Content.VeryRaw) > 0 {
@@ -151,7 +163,7 @@ func (mach *OlmMachine) tryDecryptOlmCiphertext(ctx context.Context, sender id.U
plaintext, err := mach.tryDecryptOlmCiphertextWithExistingSession(ctx, senderKey, olmType, ciphertext, ciphertextHash)
if err != nil {
- if err == DecryptionFailedWithMatchingSession {
+ if err == ErrDecryptionFailedWithMatchingSession {
log.Warn().Msg("Found matching session, but decryption failed")
go mach.unwedgeDevice(log, sender, senderKey)
}
@@ -169,10 +181,10 @@ func (mach *OlmMachine) tryDecryptOlmCiphertext(ctx context.Context, sender id.U
// if it isn't one at this point in time anymore, so return early.
if olmType != id.OlmMsgTypePreKey {
go mach.unwedgeDevice(log, sender, senderKey)
- return nil, DecryptionFailedForNormalMessage
+ return nil, ErrDecryptionFailedForNormalMessage
}
- accountBackup, err := mach.account.Internal.Pickle([]byte("tmp"))
+ accountBackup, _ := mach.account.Internal.Pickle([]byte("tmp"))
log.Trace().Msg("Trying to create inbound session")
endTimeTrace = mach.timeTrace(ctx, "creating inbound olm session", time.Second)
session, err := mach.createInboundSession(ctx, senderKey, ciphertext)
@@ -302,7 +314,7 @@ func (mach *OlmMachine) tryDecryptOlmCiphertextWithExistingSession(
Str("session_description", session.Describe()).
Msg("Failed to decrypt olm message")
if olmType == id.OlmMsgTypePreKey {
- return nil, DecryptionFailedWithMatchingSession
+ return nil, ErrDecryptionFailedWithMatchingSession
}
} else {
endTimeTrace = mach.timeTrace(ctx, "updating session in database", time.Second)
@@ -345,7 +357,7 @@ func (mach *OlmMachine) unwedgeDevice(log zerolog.Logger, sender id.UserID, send
ctx := log.WithContext(mach.backgroundCtx)
mach.recentlyUnwedgedLock.Lock()
prevUnwedge, ok := mach.recentlyUnwedged[senderKey]
- delta := time.Now().Sub(prevUnwedge)
+ delta := time.Since(prevUnwedge)
if ok && delta < MinUnwedgeInterval {
log.Debug().
Str("previous_recreation", delta.String()).
diff --git a/vendor/maunium.net/go/mautrix/crypto/devicelist.go b/vendor/maunium.net/go/mautrix/crypto/devicelist.go
index 61a2252..f0d2b12 100644
--- a/vendor/maunium.net/go/mautrix/crypto/devicelist.go
+++ b/vendor/maunium.net/go/mautrix/crypto/devicelist.go
@@ -22,14 +22,23 @@ import (
)
var (
- MismatchingDeviceID = errors.New("mismatching device ID in parameter and keys object")
- MismatchingUserID = errors.New("mismatching user ID in parameter and keys object")
- MismatchingSigningKey = errors.New("received update for device with different signing key")
- NoSigningKeyFound = errors.New("didn't find ed25519 signing key")
- NoIdentityKeyFound = errors.New("didn't find curve25519 identity key")
- InvalidKeySignature = errors.New("invalid signature on device keys")
+ ErrMismatchingDeviceID = errors.New("mismatching device ID in parameter and keys object")
+ ErrMismatchingUserID = errors.New("mismatching user ID in parameter and keys object")
+ ErrMismatchingSigningKey = errors.New("received update for device with different signing key")
+ ErrNoSigningKeyFound = errors.New("didn't find ed25519 signing key")
+ ErrNoIdentityKeyFound = errors.New("didn't find curve25519 identity key")
+ ErrInvalidKeySignature = errors.New("invalid signature on device keys")
+ ErrUserNotTracked = errors.New("user is not tracked")
+)
- ErrUserNotTracked = errors.New("user is not tracked")
+// Deprecated: use variables prefixed with Err
+var (
+ MismatchingDeviceID = ErrMismatchingDeviceID
+ MismatchingUserID = ErrMismatchingUserID
+ MismatchingSigningKey = ErrMismatchingSigningKey
+ NoSigningKeyFound = ErrNoSigningKeyFound
+ NoIdentityKeyFound = ErrNoIdentityKeyFound
+ InvalidKeySignature = ErrInvalidKeySignature
)
func (mach *OlmMachine) LoadDevices(ctx context.Context, user id.UserID) (keys map[id.DeviceID]*id.Device) {
@@ -312,28 +321,28 @@ func (mach *OlmMachine) OnDevicesChanged(ctx context.Context, userID id.UserID)
func (mach *OlmMachine) validateDevice(userID id.UserID, deviceID id.DeviceID, deviceKeys mautrix.DeviceKeys, existing *id.Device) (*id.Device, error) {
if deviceID != deviceKeys.DeviceID {
- return nil, fmt.Errorf("%w (expected %s, got %s)", MismatchingDeviceID, deviceID, deviceKeys.DeviceID)
+ return nil, fmt.Errorf("%w (expected %s, got %s)", ErrMismatchingDeviceID, deviceID, deviceKeys.DeviceID)
} else if userID != deviceKeys.UserID {
- return nil, fmt.Errorf("%w (expected %s, got %s)", MismatchingUserID, userID, deviceKeys.UserID)
+ return nil, fmt.Errorf("%w (expected %s, got %s)", ErrMismatchingUserID, userID, deviceKeys.UserID)
}
signingKey := deviceKeys.Keys.GetEd25519(deviceID)
identityKey := deviceKeys.Keys.GetCurve25519(deviceID)
if signingKey == "" {
- return nil, NoSigningKeyFound
+ return nil, ErrNoSigningKeyFound
} else if identityKey == "" {
- return nil, NoIdentityKeyFound
+ return nil, ErrNoIdentityKeyFound
}
if existing != nil && existing.SigningKey != signingKey {
- return existing, fmt.Errorf("%w (expected %s, got %s)", MismatchingSigningKey, existing.SigningKey, signingKey)
+ return existing, fmt.Errorf("%w (expected %s, got %s)", ErrMismatchingSigningKey, existing.SigningKey, signingKey)
}
ok, err := signatures.VerifySignatureJSON(deviceKeys, userID, deviceID.String(), signingKey)
if err != nil {
return existing, fmt.Errorf("failed to verify signature: %w", err)
} else if !ok {
- return existing, InvalidKeySignature
+ return existing, ErrInvalidKeySignature
}
name, ok := deviceKeys.Unsigned["device_display_name"].(string)
diff --git a/vendor/maunium.net/go/mautrix/crypto/encryptmegolm.go b/vendor/maunium.net/go/mautrix/crypto/encryptmegolm.go
index b3d1961..ea97f76 100644
--- a/vendor/maunium.net/go/mautrix/crypto/encryptmegolm.go
+++ b/vendor/maunium.net/go/mautrix/crypto/encryptmegolm.go
@@ -25,7 +25,12 @@ import (
)
var (
- NoGroupSession = errors.New("no group session created")
+ ErrNoGroupSession = errors.New("no group session created")
+)
+
+// Deprecated: use variables prefixed with Err
+var (
+ NoGroupSession = ErrNoGroupSession
)
func getRawJSON[T any](content json.RawMessage, path ...string) *T {
@@ -82,7 +87,7 @@ type rawMegolmEvent struct {
// IsShareError returns true if the error is caused by the lack of an outgoing megolm session and can be solved with OlmMachine.ShareGroupSession
func IsShareError(err error) bool {
- return err == SessionExpired || err == SessionNotShared || err == NoGroupSession
+ return err == ErrSessionExpired || err == ErrSessionNotShared || err == ErrNoGroupSession
}
func ParseMegolmMessageIndex(ciphertext []byte) (uint, error) {
@@ -120,7 +125,7 @@ func (mach *OlmMachine) EncryptMegolmEventWithStateKey(ctx context.Context, room
if err != nil {
return nil, fmt.Errorf("failed to get outbound group session: %w", err)
} else if session == nil {
- return nil, NoGroupSession
+ return nil, ErrNoGroupSession
}
plaintext, err := json.Marshal(&rawMegolmEvent{
RoomID: roomID,
diff --git a/vendor/maunium.net/go/mautrix/crypto/goolm/account/account.go b/vendor/maunium.net/go/mautrix/crypto/goolm/account/account.go
index 4da08a7..b48843a 100644
--- a/vendor/maunium.net/go/mautrix/crypto/goolm/account/account.go
+++ b/vendor/maunium.net/go/mautrix/crypto/goolm/account/account.go
@@ -334,7 +334,7 @@ func (a *Account) UnpickleLibOlm(buf []byte) error {
if err != nil {
return err
} else if pickledVersion != accountPickleVersionLibOLM && pickledVersion != 3 && pickledVersion != 2 {
- return fmt.Errorf("unpickle account: %w (found version %d)", olm.ErrBadVersion, pickledVersion)
+ return fmt.Errorf("unpickle account: %w (found version %d)", olm.ErrUnknownOlmPickleVersion, pickledVersion)
} else if err = a.IdKeys.Ed25519.UnpickleLibOlm(decoder); err != nil { // read the ed25519 key pair
return err
} else if err = a.IdKeys.Curve25519.UnpickleLibOlm(decoder); err != nil { // read curve25519 key pair
diff --git a/vendor/maunium.net/go/mautrix/crypto/goolm/goolmbase64/base64.go b/vendor/maunium.net/go/mautrix/crypto/goolm/goolmbase64/base64.go
index 061a052..58ee26f 100644
--- a/vendor/maunium.net/go/mautrix/crypto/goolm/goolmbase64/base64.go
+++ b/vendor/maunium.net/go/mautrix/crypto/goolm/goolmbase64/base64.go
@@ -4,7 +4,8 @@ import (
"encoding/base64"
)
-// Deprecated: base64.RawStdEncoding should be used directly
+// These methods should only be used for raw byte operations, never with string conversion
+
func Decode(input []byte) ([]byte, error) {
decoded := make([]byte, base64.RawStdEncoding.DecodedLen(len(input)))
writtenBytes, err := base64.RawStdEncoding.Decode(decoded, input)
@@ -14,7 +15,6 @@ func Decode(input []byte) ([]byte, error) {
return decoded[:writtenBytes], nil
}
-// Deprecated: base64.RawStdEncoding should be used directly
func Encode(input []byte) []byte {
encoded := make([]byte, base64.RawStdEncoding.EncodedLen(len(input)))
base64.RawStdEncoding.Encode(encoded, input)
diff --git a/vendor/maunium.net/go/mautrix/crypto/goolm/libolmpickle/picklejson.go b/vendor/maunium.net/go/mautrix/crypto/goolm/libolmpickle/picklejson.go
index 308e472..f765391 100644
--- a/vendor/maunium.net/go/mautrix/crypto/goolm/libolmpickle/picklejson.go
+++ b/vendor/maunium.net/go/mautrix/crypto/goolm/libolmpickle/picklejson.go
@@ -50,7 +50,7 @@ func UnpickleAsJSON(object any, pickled, key []byte, pickleVersion byte) error {
}
}
if decrypted[0] != pickleVersion {
- return fmt.Errorf("unpickle: %w", olm.ErrWrongPickleVersion)
+ return fmt.Errorf("unpickle: %w", olm.ErrUnknownJSONPickleVersion)
}
err = json.Unmarshal(decrypted[1:], object)
if err != nil {
diff --git a/vendor/maunium.net/go/mautrix/crypto/goolm/message/group_message.go b/vendor/maunium.net/go/mautrix/crypto/goolm/message/group_message.go
index f3d2250..c83540c 100644
--- a/vendor/maunium.net/go/mautrix/crypto/goolm/message/group_message.go
+++ b/vendor/maunium.net/go/mautrix/crypto/goolm/message/group_message.go
@@ -39,7 +39,7 @@ func (r *GroupMessage) Decode(input []byte) (err error) {
return
}
if r.Version != protocolVersion {
- return fmt.Errorf("GroupMessage.Decode: %w", olm.ErrWrongProtocolVersion)
+ return fmt.Errorf("GroupMessage.Decode: %w (got %d, expected %d)", olm.ErrWrongProtocolVersion, r.Version, protocolVersion)
}
for {
diff --git a/vendor/maunium.net/go/mautrix/crypto/goolm/message/message.go b/vendor/maunium.net/go/mautrix/crypto/goolm/message/message.go
index 9ef9363..b161a2d 100644
--- a/vendor/maunium.net/go/mautrix/crypto/goolm/message/message.go
+++ b/vendor/maunium.net/go/mautrix/crypto/goolm/message/message.go
@@ -43,7 +43,7 @@ func (r *Message) Decode(input []byte) (err error) {
return
}
if r.Version != protocolVersion {
- return fmt.Errorf("Message.Decode: %w", olm.ErrWrongProtocolVersion)
+ return fmt.Errorf("Message.Decode: %w (got %d, expected %d)", olm.ErrWrongProtocolVersion, r.Version, protocolVersion)
}
for {
diff --git a/vendor/maunium.net/go/mautrix/crypto/goolm/message/prekey_message.go b/vendor/maunium.net/go/mautrix/crypto/goolm/message/prekey_message.go
index 760be4c..4e3d495 100644
--- a/vendor/maunium.net/go/mautrix/crypto/goolm/message/prekey_message.go
+++ b/vendor/maunium.net/go/mautrix/crypto/goolm/message/prekey_message.go
@@ -48,7 +48,7 @@ func (r *PreKeyMessage) Decode(input []byte) (err error) {
return
}
if r.Version != protocolVersion {
- return fmt.Errorf("PreKeyMessage.Decode: %w", olm.ErrWrongProtocolVersion)
+ return fmt.Errorf("PreKeyMessage.Decode: %w (got %d, expected %d)", olm.ErrWrongProtocolVersion, r.Version, protocolVersion)
}
for {
diff --git a/vendor/maunium.net/go/mautrix/crypto/goolm/message/session_export.go b/vendor/maunium.net/go/mautrix/crypto/goolm/message/session_export.go
index 956868b..d58dbb2 100644
--- a/vendor/maunium.net/go/mautrix/crypto/goolm/message/session_export.go
+++ b/vendor/maunium.net/go/mautrix/crypto/goolm/message/session_export.go
@@ -35,7 +35,7 @@ func (s *MegolmSessionExport) Decode(input []byte) error {
return fmt.Errorf("decrypt: %w", olm.ErrBadInput)
}
if input[0] != sessionExportVersion {
- return fmt.Errorf("decrypt: %w", olm.ErrBadVersion)
+ return fmt.Errorf("decrypt: %w", olm.ErrUnknownOlmPickleVersion)
}
s.Counter = binary.BigEndian.Uint32(input[1:5])
copy(s.RatchetData[:], input[5:133])
diff --git a/vendor/maunium.net/go/mautrix/crypto/goolm/message/session_sharing.go b/vendor/maunium.net/go/mautrix/crypto/goolm/message/session_sharing.go
index 1624094..d04ef15 100644
--- a/vendor/maunium.net/go/mautrix/crypto/goolm/message/session_sharing.go
+++ b/vendor/maunium.net/go/mautrix/crypto/goolm/message/session_sharing.go
@@ -42,7 +42,7 @@ func (s *MegolmSessionSharing) VerifyAndDecode(input []byte) error {
}
s.PublicKey = publicKey
if input[0] != sessionSharingVersion {
- return fmt.Errorf("verify: %w", olm.ErrBadVersion)
+ return fmt.Errorf("verify: %w", olm.ErrUnknownOlmPickleVersion)
}
s.Counter = binary.BigEndian.Uint32(input[1:5])
copy(s.RatchetData[:], input[5:133])
diff --git a/vendor/maunium.net/go/mautrix/crypto/goolm/pk/decryption.go b/vendor/maunium.net/go/mautrix/crypto/goolm/pk/decryption.go
index afb01f7..cdb20eb 100644
--- a/vendor/maunium.net/go/mautrix/crypto/goolm/pk/decryption.go
+++ b/vendor/maunium.net/go/mautrix/crypto/goolm/pk/decryption.go
@@ -103,7 +103,7 @@ func (a *Decryption) UnpickleLibOlm(unpickled []byte) error {
if pickledVersion == decryptionPickleVersionLibOlm {
return a.KeyPair.UnpickleLibOlm(decoder)
} else {
- return fmt.Errorf("unpickle olmSession: %w (found %d, expected %d)", olm.ErrBadVersion, pickledVersion, decryptionPickleVersionLibOlm)
+ return fmt.Errorf("unpickle olmSession: %w (found %d, expected %d)", olm.ErrUnknownOlmPickleVersion, pickledVersion, decryptionPickleVersionLibOlm)
}
}
diff --git a/vendor/maunium.net/go/mautrix/crypto/goolm/pk/encryption.go b/vendor/maunium.net/go/mautrix/crypto/goolm/pk/encryption.go
index 23f67dd..2897d9b 100644
--- a/vendor/maunium.net/go/mautrix/crypto/goolm/pk/encryption.go
+++ b/vendor/maunium.net/go/mautrix/crypto/goolm/pk/encryption.go
@@ -37,6 +37,9 @@ func (e Encryption) Encrypt(plaintext []byte, privateKey crypto.Curve25519Privat
return nil, nil, err
}
cipher, err := aessha2.NewAESSHA2(sharedSecret, nil)
+ if err != nil {
+ return nil, nil, err
+ }
ciphertext, err = cipher.Encrypt(plaintext)
if err != nil {
return nil, nil, err
diff --git a/vendor/maunium.net/go/mautrix/crypto/goolm/ratchet/olm.go b/vendor/maunium.net/go/mautrix/crypto/goolm/ratchet/olm.go
index 229c9bd..9901ada 100644
--- a/vendor/maunium.net/go/mautrix/crypto/goolm/ratchet/olm.go
+++ b/vendor/maunium.net/go/mautrix/crypto/goolm/ratchet/olm.go
@@ -142,7 +142,7 @@ func (r *Ratchet) Decrypt(input []byte) ([]byte, error) {
return nil, err
}
if message.Version != protocolVersion {
- return nil, fmt.Errorf("decrypt: %w", olm.ErrWrongProtocolVersion)
+ return nil, fmt.Errorf("decrypt: %w (got %d, expected %d)", olm.ErrWrongProtocolVersion, message.Version, protocolVersion)
}
if !message.HasCounter || len(message.RatchetKey) == 0 || len(message.Ciphertext) == 0 {
return nil, fmt.Errorf("decrypt: %w", olm.ErrBadMessageFormat)
diff --git a/vendor/maunium.net/go/mautrix/crypto/goolm/session/megolm_inbound_session.go b/vendor/maunium.net/go/mautrix/crypto/goolm/session/megolm_inbound_session.go
index 80dd71c..7ccbd26 100644
--- a/vendor/maunium.net/go/mautrix/crypto/goolm/session/megolm_inbound_session.go
+++ b/vendor/maunium.net/go/mautrix/crypto/goolm/session/megolm_inbound_session.go
@@ -99,7 +99,7 @@ func (o *MegolmInboundSession) getRatchet(messageIndex uint32) (*megolm.Ratchet,
}
if (messageIndex - o.InitialRatchet.Counter) >= uint32(1<<31) {
// the counter is before our initial ratchet - we can't decode this
- return nil, fmt.Errorf("decrypt: %w", olm.ErrRatchetNotAvailable)
+ return nil, fmt.Errorf("decrypt: %w", olm.ErrUnknownMessageIndex)
}
// otherwise, start from the initial ratchet. Take a copy so that we don't overwrite the initial ratchet
copiedRatchet := o.InitialRatchet
@@ -126,7 +126,7 @@ func (o *MegolmInboundSession) Decrypt(ciphertext []byte) ([]byte, uint, error)
return nil, 0, err
}
if msg.Version != protocolVersion {
- return nil, 0, fmt.Errorf("decrypt: %w", olm.ErrWrongProtocolVersion)
+ return nil, 0, fmt.Errorf("decrypt: %w (got %d, expected %d)", olm.ErrWrongProtocolVersion, msg.Version, protocolVersion)
}
if msg.Ciphertext == nil || !msg.HasMessageIndex {
return nil, 0, fmt.Errorf("decrypt: %w", olm.ErrBadMessageFormat)
@@ -206,7 +206,7 @@ func (o *MegolmInboundSession) UnpickleLibOlm(value []byte) error {
return err
}
if pickledVersion != megolmInboundSessionPickleVersionLibOlm && pickledVersion != 1 {
- return fmt.Errorf("unpickle MegolmInboundSession: %w (found version %d)", olm.ErrBadVersion, pickledVersion)
+ return fmt.Errorf("unpickle MegolmInboundSession: %w (found version %d)", olm.ErrUnknownOlmPickleVersion, pickledVersion)
}
if err = o.InitialRatchet.UnpickleLibOlm(decoder); err != nil {
diff --git a/vendor/maunium.net/go/mautrix/crypto/goolm/session/megolm_outbound_session.go b/vendor/maunium.net/go/mautrix/crypto/goolm/session/megolm_outbound_session.go
index 2b8e1c8..7f92353 100644
--- a/vendor/maunium.net/go/mautrix/crypto/goolm/session/megolm_outbound_session.go
+++ b/vendor/maunium.net/go/mautrix/crypto/goolm/session/megolm_outbound_session.go
@@ -101,8 +101,10 @@ func (o *MegolmOutboundSession) Unpickle(pickled, key []byte) error {
func (o *MegolmOutboundSession) UnpickleLibOlm(buf []byte) error {
decoder := libolmpickle.NewDecoder(buf)
pickledVersion, err := decoder.ReadUInt32()
- if pickledVersion != megolmOutboundSessionPickleVersionLibOlm {
- return fmt.Errorf("unpickle MegolmInboundSession: %w (found version %d)", olm.ErrBadVersion, pickledVersion)
+ if err != nil {
+ return fmt.Errorf("unpickle MegolmOutboundSession: failed to read version: %w", err)
+ } else if pickledVersion != megolmOutboundSessionPickleVersionLibOlm {
+ return fmt.Errorf("unpickle MegolmInboundSession: %w (found version %d)", olm.ErrUnknownOlmPickleVersion, pickledVersion)
}
if err = o.Ratchet.UnpickleLibOlm(decoder); err != nil {
return err
diff --git a/vendor/maunium.net/go/mautrix/crypto/goolm/session/olm_session.go b/vendor/maunium.net/go/mautrix/crypto/goolm/session/olm_session.go
index b99ab63..a1cb8d6 100644
--- a/vendor/maunium.net/go/mautrix/crypto/goolm/session/olm_session.go
+++ b/vendor/maunium.net/go/mautrix/crypto/goolm/session/olm_session.go
@@ -168,11 +168,11 @@ func NewInboundOlmSession(identityKeyAlice *crypto.Curve25519PublicKey, received
msg := message.Message{}
err = msg.Decode(oneTimeMsg.Message)
if err != nil {
- return nil, fmt.Errorf("Message decode: %w", err)
+ return nil, fmt.Errorf("message decode: %w", err)
}
if len(msg.RatchetKey) == 0 {
- return nil, fmt.Errorf("Message missing ratchet key: %w", olm.ErrBadMessageFormat)
+ return nil, fmt.Errorf("message missing ratchet key: %w", olm.ErrBadMessageFormat)
}
//Init Ratchet
s.Ratchet.InitializeAsBob(secret, msg.RatchetKey)
@@ -203,7 +203,7 @@ func (s *OlmSession) ID() id.SessionID {
copy(message[crypto.Curve25519PrivateKeyLength:], s.AliceBaseKey)
copy(message[2*crypto.Curve25519PrivateKeyLength:], s.BobOneTimeKey)
hash := sha256.Sum256(message)
- res := id.SessionID(goolmbase64.Encode(hash[:]))
+ res := id.SessionID(base64.RawStdEncoding.EncodeToString(hash[:]))
return res
}
@@ -325,7 +325,7 @@ func (s *OlmSession) Decrypt(crypttext string, msgType id.OlmMsgType) ([]byte, e
if len(crypttext) == 0 {
return nil, fmt.Errorf("decrypt: %w", olm.ErrEmptyInput)
}
- decodedCrypttext, err := goolmbase64.Decode([]byte(crypttext))
+ decodedCrypttext, err := base64.RawStdEncoding.DecodeString(crypttext)
if err != nil {
return nil, err
}
@@ -365,6 +365,9 @@ func (o *OlmSession) Unpickle(pickled, key []byte) error {
func (o *OlmSession) UnpickleLibOlm(buf []byte) error {
decoder := libolmpickle.NewDecoder(buf)
pickledVersion, err := decoder.ReadUInt32()
+ if err != nil {
+ return fmt.Errorf("unpickle olmSession: failed to read version: %w", err)
+ }
var includesChainIndex bool
switch pickledVersion {
@@ -373,7 +376,7 @@ func (o *OlmSession) UnpickleLibOlm(buf []byte) error {
case uint32(0x80000001):
includesChainIndex = true
default:
- return fmt.Errorf("unpickle olmSession: %w (found version %d)", olm.ErrBadVersion, pickledVersion)
+ return fmt.Errorf("unpickle olmSession: %w (found version %d)", olm.ErrUnknownOlmPickleVersion, pickledVersion)
}
if o.ReceivedMessage, err = decoder.ReadBool(); err != nil {
diff --git a/vendor/maunium.net/go/mautrix/crypto/goolm/session/register.go b/vendor/maunium.net/go/mautrix/crypto/goolm/session/register.go
index a88d12f..b95a44a 100644
--- a/vendor/maunium.net/go/mautrix/crypto/goolm/session/register.go
+++ b/vendor/maunium.net/go/mautrix/crypto/goolm/session/register.go
@@ -14,7 +14,7 @@ func Register() {
// Inbound Session
olm.InitInboundGroupSessionFromPickled = func(pickled, key []byte) (olm.InboundGroupSession, error) {
if len(pickled) == 0 {
- return nil, olm.EmptyInput
+ return nil, olm.ErrEmptyInput
}
if len(key) == 0 {
key = []byte(" ")
@@ -23,13 +23,13 @@ func Register() {
}
olm.InitNewInboundGroupSession = func(sessionKey []byte) (olm.InboundGroupSession, error) {
if len(sessionKey) == 0 {
- return nil, olm.EmptyInput
+ return nil, olm.ErrEmptyInput
}
return NewMegolmInboundSession(sessionKey)
}
olm.InitInboundGroupSessionImport = func(sessionKey []byte) (olm.InboundGroupSession, error) {
if len(sessionKey) == 0 {
- return nil, olm.EmptyInput
+ return nil, olm.ErrEmptyInput
}
return NewMegolmInboundSessionFromExport(sessionKey)
}
@@ -40,7 +40,7 @@ func Register() {
// Outbound Session
olm.InitNewOutboundGroupSessionFromPickled = func(pickled, key []byte) (olm.OutboundGroupSession, error) {
if len(pickled) == 0 {
- return nil, olm.EmptyInput
+ return nil, olm.ErrEmptyInput
}
lenKey := len(key)
if lenKey == 0 {
diff --git a/vendor/maunium.net/go/mautrix/crypto/keybackup.go b/vendor/maunium.net/go/mautrix/crypto/keybackup.go
index d8b3d71..ceec1d5 100644
--- a/vendor/maunium.net/go/mautrix/crypto/keybackup.go
+++ b/vendor/maunium.net/go/mautrix/crypto/keybackup.go
@@ -56,11 +56,12 @@ func (mach *OlmMachine) GetAndVerifyLatestKeyBackupVersion(ctx context.Context,
// ...by deriving the public key from a private key that it obtained from a trusted source. Trusted sources for the private
// key include the user entering the key, retrieving the key stored in secret storage, or obtaining the key via secret sharing
// from a verified device belonging to the same user."
- megolmBackupDerivedPublicKey := id.Ed25519(base64.RawStdEncoding.EncodeToString(megolmBackupKey.PublicKey().Bytes()))
- if megolmBackupKey != nil && versionInfo.AuthData.PublicKey == megolmBackupDerivedPublicKey {
- log.Debug().Msg("key backup is trusted based on derived public key")
- return versionInfo, nil
- } else {
+ if megolmBackupKey != nil {
+ megolmBackupDerivedPublicKey := id.Ed25519(base64.RawStdEncoding.EncodeToString(megolmBackupKey.PublicKey().Bytes()))
+ if versionInfo.AuthData.PublicKey == megolmBackupDerivedPublicKey {
+ log.Debug().Msg("Key backup is trusted based on derived public key")
+ return versionInfo, nil
+ }
log.Debug().
Stringer("expected_key", megolmBackupDerivedPublicKey).
Stringer("actual_key", versionInfo.AuthData.PublicKey).
diff --git a/vendor/maunium.net/go/mautrix/crypto/libolm/account.go b/vendor/maunium.net/go/mautrix/crypto/libolm/account.go
index f6f916e..0350f08 100644
--- a/vendor/maunium.net/go/mautrix/crypto/libolm/account.go
+++ b/vendor/maunium.net/go/mautrix/crypto/libolm/account.go
@@ -33,7 +33,7 @@ var _ olm.Account = (*Account)(nil)
// "INVALID_BASE64".
func AccountFromPickled(pickled, key []byte) (*Account, error) {
if len(pickled) == 0 {
- return nil, olm.EmptyInput
+ return nil, olm.ErrEmptyInput
}
a := NewBlankAccount()
return a, a.Unpickle(pickled, key)
@@ -53,7 +53,7 @@ func NewAccount() (*Account, error) {
random := make([]byte, a.createRandomLen()+1)
_, err := rand.Read(random)
if err != nil {
- panic(olm.NotEnoughGoRandom)
+ panic(olm.ErrNotEnoughGoRandom)
}
ret := C.olm_create_account(
(*C.OlmAccount)(a.int),
@@ -128,7 +128,7 @@ func (a *Account) genOneTimeKeysRandomLen(num uint) uint {
// supplied key.
func (a *Account) Pickle(key []byte) ([]byte, error) {
if len(key) == 0 {
- return nil, olm.NoKeyProvided
+ return nil, olm.ErrNoKeyProvided
}
pickled := make([]byte, a.pickleLen())
r := C.olm_pickle_account(
@@ -145,7 +145,7 @@ func (a *Account) Pickle(key []byte) ([]byte, error) {
func (a *Account) Unpickle(pickled, key []byte) error {
if len(key) == 0 {
- return olm.NoKeyProvided
+ return olm.ErrNoKeyProvided
}
r := C.olm_unpickle_account(
(*C.OlmAccount)(a.int),
@@ -198,7 +198,7 @@ func (a *Account) MarshalJSON() ([]byte, error) {
// Deprecated
func (a *Account) UnmarshalJSON(data []byte) error {
if len(data) == 0 || data[0] != '"' || data[len(data)-1] != '"' {
- return olm.InputNotJSONString
+ return olm.ErrInputNotJSONString
}
if a.int == nil {
*a = *NewBlankAccount()
@@ -235,7 +235,7 @@ func (a *Account) IdentityKeys() (id.Ed25519, id.Curve25519, error) {
// Account.
func (a *Account) Sign(message []byte) ([]byte, error) {
if len(message) == 0 {
- panic(olm.EmptyInput)
+ panic(olm.ErrEmptyInput)
}
signature := make([]byte, a.signatureLen())
r := C.olm_account_sign(
@@ -299,7 +299,7 @@ func (a *Account) GenOneTimeKeys(num uint) error {
random := make([]byte, a.genOneTimeKeysRandomLen(num)+1)
_, err := rand.Read(random)
if err != nil {
- return olm.NotEnoughGoRandom
+ return olm.ErrNotEnoughGoRandom
}
r := C.olm_account_generate_one_time_keys(
(*C.OlmAccount)(a.int),
@@ -319,13 +319,13 @@ func (a *Account) GenOneTimeKeys(num uint) error {
// keys couldn't be decoded as base64 then the error will be "INVALID_BASE64"
func (a *Account) NewOutboundSession(theirIdentityKey, theirOneTimeKey id.Curve25519) (olm.Session, error) {
if len(theirIdentityKey) == 0 || len(theirOneTimeKey) == 0 {
- return nil, olm.EmptyInput
+ return nil, olm.ErrEmptyInput
}
s := NewBlankSession()
random := make([]byte, s.createOutboundRandomLen()+1)
_, err := rand.Read(random)
if err != nil {
- panic(olm.NotEnoughGoRandom)
+ panic(olm.ErrNotEnoughGoRandom)
}
theirIdentityKeyCopy := []byte(theirIdentityKey)
theirOneTimeKeyCopy := []byte(theirOneTimeKey)
@@ -357,7 +357,7 @@ func (a *Account) NewOutboundSession(theirIdentityKey, theirOneTimeKey id.Curve2
// time key then the error will be "BAD_MESSAGE_KEY_ID".
func (a *Account) NewInboundSession(oneTimeKeyMsg string) (olm.Session, error) {
if len(oneTimeKeyMsg) == 0 {
- return nil, olm.EmptyInput
+ return nil, olm.ErrEmptyInput
}
s := NewBlankSession()
oneTimeKeyMsgCopy := []byte(oneTimeKeyMsg)
@@ -383,7 +383,7 @@ func (a *Account) NewInboundSession(oneTimeKeyMsg string) (olm.Session, error) {
// time key then the error will be "BAD_MESSAGE_KEY_ID".
func (a *Account) NewInboundSessionFrom(theirIdentityKey *id.Curve25519, oneTimeKeyMsg string) (olm.Session, error) {
if theirIdentityKey == nil || len(oneTimeKeyMsg) == 0 {
- return nil, olm.EmptyInput
+ return nil, olm.ErrEmptyInput
}
theirIdentityKeyCopy := []byte(*theirIdentityKey)
oneTimeKeyMsgCopy := []byte(oneTimeKeyMsg)
diff --git a/vendor/maunium.net/go/mautrix/crypto/libolm/error.go b/vendor/maunium.net/go/mautrix/crypto/libolm/error.go
index 9ca415e..6fb5512 100644
--- a/vendor/maunium.net/go/mautrix/crypto/libolm/error.go
+++ b/vendor/maunium.net/go/mautrix/crypto/libolm/error.go
@@ -11,21 +11,21 @@ import (
)
var errorMap = map[string]error{
- "NOT_ENOUGH_RANDOM": olm.NotEnoughRandom,
- "OUTPUT_BUFFER_TOO_SMALL": olm.OutputBufferTooSmall,
- "BAD_MESSAGE_VERSION": olm.BadMessageVersion,
- "BAD_MESSAGE_FORMAT": olm.BadMessageFormat,
- "BAD_MESSAGE_MAC": olm.BadMessageMAC,
- "BAD_MESSAGE_KEY_ID": olm.BadMessageKeyID,
- "INVALID_BASE64": olm.InvalidBase64,
- "BAD_ACCOUNT_KEY": olm.BadAccountKey,
- "UNKNOWN_PICKLE_VERSION": olm.UnknownPickleVersion,
- "CORRUPTED_PICKLE": olm.CorruptedPickle,
- "BAD_SESSION_KEY": olm.BadSessionKey,
- "UNKNOWN_MESSAGE_INDEX": olm.UnknownMessageIndex,
- "BAD_LEGACY_ACCOUNT_PICKLE": olm.BadLegacyAccountPickle,
- "BAD_SIGNATURE": olm.BadSignature,
- "INPUT_BUFFER_TOO_SMALL": olm.InputBufferTooSmall,
+ "NOT_ENOUGH_RANDOM": olm.ErrLibolmNotEnoughRandom,
+ "OUTPUT_BUFFER_TOO_SMALL": olm.ErrLibolmOutputBufferTooSmall,
+ "BAD_MESSAGE_VERSION": olm.ErrWrongProtocolVersion,
+ "BAD_MESSAGE_FORMAT": olm.ErrBadMessageFormat,
+ "BAD_MESSAGE_MAC": olm.ErrBadMAC,
+ "BAD_MESSAGE_KEY_ID": olm.ErrBadMessageKeyID,
+ "INVALID_BASE64": olm.ErrLibolmInvalidBase64,
+ "BAD_ACCOUNT_KEY": olm.ErrLibolmBadAccountKey,
+ "UNKNOWN_PICKLE_VERSION": olm.ErrUnknownOlmPickleVersion,
+ "CORRUPTED_PICKLE": olm.ErrLibolmCorruptedPickle,
+ "BAD_SESSION_KEY": olm.ErrLibolmBadSessionKey,
+ "UNKNOWN_MESSAGE_INDEX": olm.ErrUnknownMessageIndex,
+ "BAD_LEGACY_ACCOUNT_PICKLE": olm.ErrLibolmBadLegacyAccountPickle,
+ "BAD_SIGNATURE": olm.ErrBadSignature,
+ "INPUT_BUFFER_TOO_SMALL": olm.ErrInputToSmall,
}
func convertError(errCode string) error {
diff --git a/vendor/maunium.net/go/mautrix/crypto/libolm/inboundgroupsession.go b/vendor/maunium.net/go/mautrix/crypto/libolm/inboundgroupsession.go
index 5606475..8815ac3 100644
--- a/vendor/maunium.net/go/mautrix/crypto/libolm/inboundgroupsession.go
+++ b/vendor/maunium.net/go/mautrix/crypto/libolm/inboundgroupsession.go
@@ -31,7 +31,7 @@ var _ olm.InboundGroupSession = (*InboundGroupSession)(nil)
// base64 couldn't be decoded then the error will be "INVALID_BASE64".
func InboundGroupSessionFromPickled(pickled, key []byte) (*InboundGroupSession, error) {
if len(pickled) == 0 {
- return nil, olm.EmptyInput
+ return nil, olm.ErrEmptyInput
}
lenKey := len(key)
if lenKey == 0 {
@@ -48,7 +48,7 @@ func InboundGroupSessionFromPickled(pickled, key []byte) (*InboundGroupSession,
// "OLM_BAD_SESSION_KEY".
func NewInboundGroupSession(sessionKey []byte) (*InboundGroupSession, error) {
if len(sessionKey) == 0 {
- return nil, olm.EmptyInput
+ return nil, olm.ErrEmptyInput
}
s := NewBlankInboundGroupSession()
r := C.olm_init_inbound_group_session(
@@ -69,7 +69,7 @@ func NewInboundGroupSession(sessionKey []byte) (*InboundGroupSession, error) {
// error will be "OLM_BAD_SESSION_KEY".
func InboundGroupSessionImport(sessionKey []byte) (*InboundGroupSession, error) {
if len(sessionKey) == 0 {
- return nil, olm.EmptyInput
+ return nil, olm.ErrEmptyInput
}
s := NewBlankInboundGroupSession()
r := C.olm_import_inbound_group_session(
@@ -124,7 +124,7 @@ func (s *InboundGroupSession) pickleLen() uint {
// InboundGroupSession using the supplied key.
func (s *InboundGroupSession) Pickle(key []byte) ([]byte, error) {
if len(key) == 0 {
- return nil, olm.NoKeyProvided
+ return nil, olm.ErrNoKeyProvided
}
pickled := make([]byte, s.pickleLen())
r := C.olm_pickle_inbound_group_session(
@@ -143,9 +143,9 @@ func (s *InboundGroupSession) Pickle(key []byte) ([]byte, error) {
func (s *InboundGroupSession) Unpickle(pickled, key []byte) error {
if len(key) == 0 {
- return olm.NoKeyProvided
+ return olm.ErrNoKeyProvided
} else if len(pickled) == 0 {
- return olm.EmptyInput
+ return olm.ErrEmptyInput
}
r := C.olm_unpickle_inbound_group_session(
(*C.OlmInboundGroupSession)(s.int),
@@ -200,7 +200,7 @@ func (s *InboundGroupSession) MarshalJSON() ([]byte, error) {
// Deprecated
func (s *InboundGroupSession) UnmarshalJSON(data []byte) error {
if len(data) == 0 || data[0] != '"' || data[len(data)-1] != '"' {
- return olm.InputNotJSONString
+ return olm.ErrInputNotJSONString
}
if s == nil || s.int == nil {
*s = *NewBlankInboundGroupSession()
@@ -217,7 +217,7 @@ func (s *InboundGroupSession) UnmarshalJSON(data []byte) error {
// will be "BAD_MESSAGE_FORMAT".
func (s *InboundGroupSession) decryptMaxPlaintextLen(message []byte) (uint, error) {
if len(message) == 0 {
- return 0, olm.EmptyInput
+ return 0, olm.ErrEmptyInput
}
// olm_group_decrypt_max_plaintext_length destroys the input, so we have to clone it
messageCopy := bytes.Clone(message)
@@ -244,7 +244,7 @@ func (s *InboundGroupSession) decryptMaxPlaintextLen(message []byte) (uint, erro
// was shared with us) the error will be "OLM_UNKNOWN_MESSAGE_INDEX".
func (s *InboundGroupSession) Decrypt(message []byte) ([]byte, uint, error) {
if len(message) == 0 {
- return nil, 0, olm.EmptyInput
+ return nil, 0, olm.ErrEmptyInput
}
decryptMaxPlaintextLen, err := s.decryptMaxPlaintextLen(message)
if err != nil {
diff --git a/vendor/maunium.net/go/mautrix/crypto/libolm/outboundgroupsession.go b/vendor/maunium.net/go/mautrix/crypto/libolm/outboundgroupsession.go
index 646929e..ca5b68f 100644
--- a/vendor/maunium.net/go/mautrix/crypto/libolm/outboundgroupsession.go
+++ b/vendor/maunium.net/go/mautrix/crypto/libolm/outboundgroupsession.go
@@ -84,7 +84,7 @@ func (s *OutboundGroupSession) pickleLen() uint {
// OutboundGroupSession using the supplied key.
func (s *OutboundGroupSession) Pickle(key []byte) ([]byte, error) {
if len(key) == 0 {
- return nil, olm.NoKeyProvided
+ return nil, olm.ErrNoKeyProvided
}
pickled := make([]byte, s.pickleLen())
r := C.olm_pickle_outbound_group_session(
@@ -103,7 +103,7 @@ func (s *OutboundGroupSession) Pickle(key []byte) ([]byte, error) {
func (s *OutboundGroupSession) Unpickle(pickled, key []byte) error {
if len(key) == 0 {
- return olm.NoKeyProvided
+ return olm.ErrNoKeyProvided
}
r := C.olm_unpickle_outbound_group_session(
(*C.OlmOutboundGroupSession)(s.int),
@@ -159,7 +159,7 @@ func (s *OutboundGroupSession) MarshalJSON() ([]byte, error) {
// Deprecated
func (s *OutboundGroupSession) UnmarshalJSON(data []byte) error {
if len(data) == 0 || data[0] != '"' || data[len(data)-1] != '"' {
- return olm.InputNotJSONString
+ return olm.ErrInputNotJSONString
}
if s == nil || s.int == nil {
*s = *NewBlankOutboundGroupSession()
@@ -183,7 +183,7 @@ func (s *OutboundGroupSession) encryptMsgLen(plainTextLen int) uint {
// as base64.
func (s *OutboundGroupSession) Encrypt(plaintext []byte) ([]byte, error) {
if len(plaintext) == 0 {
- return nil, olm.EmptyInput
+ return nil, olm.ErrEmptyInput
}
message := make([]byte, s.encryptMsgLen(len(plaintext)))
r := C.olm_group_encrypt(
diff --git a/vendor/maunium.net/go/mautrix/crypto/libolm/pk.go b/vendor/maunium.net/go/mautrix/crypto/libolm/pk.go
index 3553214..2683cf1 100644
--- a/vendor/maunium.net/go/mautrix/crypto/libolm/pk.go
+++ b/vendor/maunium.net/go/mautrix/crypto/libolm/pk.go
@@ -86,7 +86,7 @@ func NewPKSigning() (*PKSigning, error) {
seed := make([]byte, pkSigningSeedLength())
_, err := rand.Read(seed)
if err != nil {
- panic(olm.NotEnoughGoRandom)
+ panic(olm.ErrNotEnoughGoRandom)
}
pk, err := NewPKSigningFromSeed(seed)
return pk, err
diff --git a/vendor/maunium.net/go/mautrix/crypto/libolm/register.go b/vendor/maunium.net/go/mautrix/crypto/libolm/register.go
index f091d82..ddf8461 100644
--- a/vendor/maunium.net/go/mautrix/crypto/libolm/register.go
+++ b/vendor/maunium.net/go/mautrix/crypto/libolm/register.go
@@ -65,7 +65,7 @@ func Register() {
olm.InitNewOutboundGroupSessionFromPickled = func(pickled, key []byte) (olm.OutboundGroupSession, error) {
if len(pickled) == 0 {
- return nil, olm.EmptyInput
+ return nil, olm.ErrEmptyInput
}
s := NewBlankOutboundGroupSession()
return s, s.Unpickle(pickled, key)
diff --git a/vendor/maunium.net/go/mautrix/crypto/libolm/session.go b/vendor/maunium.net/go/mautrix/crypto/libolm/session.go
index 57e631c..1441df2 100644
--- a/vendor/maunium.net/go/mautrix/crypto/libolm/session.go
+++ b/vendor/maunium.net/go/mautrix/crypto/libolm/session.go
@@ -51,7 +51,7 @@ func sessionSize() uint {
// "INVALID_BASE64".
func SessionFromPickled(pickled, key []byte) (*Session, error) {
if len(pickled) == 0 {
- return nil, olm.EmptyInput
+ return nil, olm.ErrEmptyInput
}
s := NewBlankSession()
return s, s.Unpickle(pickled, key)
@@ -118,7 +118,7 @@ func (s *Session) encryptMsgLen(plainTextLen int) uint {
// will be "BAD_MESSAGE_FORMAT".
func (s *Session) decryptMaxPlaintextLen(message string, msgType id.OlmMsgType) (uint, error) {
if len(message) == 0 {
- return 0, olm.EmptyInput
+ return 0, olm.ErrEmptyInput
}
messageCopy := []byte(message)
r := C.olm_decrypt_max_plaintext_length(
@@ -138,7 +138,7 @@ func (s *Session) decryptMaxPlaintextLen(message string, msgType id.OlmMsgType)
// supplied key.
func (s *Session) Pickle(key []byte) ([]byte, error) {
if len(key) == 0 {
- return nil, olm.NoKeyProvided
+ return nil, olm.ErrNoKeyProvided
}
pickled := make([]byte, s.pickleLen())
r := C.olm_pickle_session(
@@ -158,7 +158,7 @@ func (s *Session) Pickle(key []byte) ([]byte, error) {
// provided key. This function mutates the input pickled data slice.
func (s *Session) Unpickle(pickled, key []byte) error {
if len(key) == 0 {
- return olm.NoKeyProvided
+ return olm.ErrNoKeyProvided
}
r := C.olm_unpickle_session(
(*C.OlmSession)(s.int),
@@ -213,7 +213,7 @@ func (s *Session) MarshalJSON() ([]byte, error) {
// Deprecated
func (s *Session) UnmarshalJSON(data []byte) error {
if len(data) == 0 || data[0] != '"' || data[len(data)-1] != '"' {
- return olm.InputNotJSONString
+ return olm.ErrInputNotJSONString
}
if s == nil || s.int == nil {
*s = *NewBlankSession()
@@ -256,7 +256,7 @@ func (s *Session) HasReceivedMessage() bool {
// decoded then then the error will be "BAD_MESSAGE_FORMAT".
func (s *Session) MatchesInboundSession(oneTimeKeyMsg string) (bool, error) {
if len(oneTimeKeyMsg) == 0 {
- return false, olm.EmptyInput
+ return false, olm.ErrEmptyInput
}
oneTimeKeyMsgCopy := []byte(oneTimeKeyMsg)
r := C.olm_matches_inbound_session(
@@ -284,7 +284,7 @@ func (s *Session) MatchesInboundSession(oneTimeKeyMsg string) (bool, error) {
// decoded then then the error will be "BAD_MESSAGE_FORMAT".
func (s *Session) MatchesInboundSessionFrom(theirIdentityKey, oneTimeKeyMsg string) (bool, error) {
if len(theirIdentityKey) == 0 || len(oneTimeKeyMsg) == 0 {
- return false, olm.EmptyInput
+ return false, olm.ErrEmptyInput
}
theirIdentityKeyCopy := []byte(theirIdentityKey)
oneTimeKeyMsgCopy := []byte(oneTimeKeyMsg)
@@ -325,14 +325,14 @@ func (s *Session) EncryptMsgType() id.OlmMsgType {
// as base64.
func (s *Session) Encrypt(plaintext []byte) (id.OlmMsgType, []byte, error) {
if len(plaintext) == 0 {
- return 0, nil, olm.EmptyInput
+ return 0, nil, olm.ErrEmptyInput
}
// Make the slice be at least length 1
random := make([]byte, s.encryptRandomLen()+1)
_, err := rand.Read(random)
if err != nil {
// TODO can we just return err here?
- return 0, nil, olm.NotEnoughGoRandom
+ return 0, nil, olm.ErrNotEnoughGoRandom
}
messageType := s.EncryptMsgType()
message := make([]byte, s.encryptMsgLen(len(plaintext)))
@@ -362,7 +362,7 @@ func (s *Session) Encrypt(plaintext []byte) (id.OlmMsgType, []byte, error) {
// "BAD_MESSAGE_MAC".
func (s *Session) Decrypt(message string, msgType id.OlmMsgType) ([]byte, error) {
if len(message) == 0 {
- return nil, olm.EmptyInput
+ return nil, olm.ErrEmptyInput
}
decryptMaxPlaintextLen, err := s.decryptMaxPlaintextLen(message, msgType)
if err != nil {
diff --git a/vendor/maunium.net/go/mautrix/crypto/machine.go b/vendor/maunium.net/go/mautrix/crypto/machine.go
index 4d2e388..f8ebe90 100644
--- a/vendor/maunium.net/go/mautrix/crypto/machine.go
+++ b/vendor/maunium.net/go/mautrix/crypto/machine.go
@@ -205,7 +205,7 @@ func (mach *OlmMachine) FlushStore(ctx context.Context) error {
func (mach *OlmMachine) timeTrace(ctx context.Context, thing string, expectedDuration time.Duration) func() {
start := time.Now()
return func() {
- duration := time.Now().Sub(start)
+ duration := time.Since(start)
if duration > expectedDuration {
zerolog.Ctx(ctx).Warn().
Str("action", thing).
diff --git a/vendor/maunium.net/go/mautrix/crypto/olm/errors.go b/vendor/maunium.net/go/mautrix/crypto/olm/errors.go
index 957d792..9e522b2 100644
--- a/vendor/maunium.net/go/mautrix/crypto/olm/errors.go
+++ b/vendor/maunium.net/go/mautrix/crypto/olm/errors.go
@@ -10,50 +10,67 @@ import "errors"
// Those are the most common used errors
var (
- ErrBadSignature = errors.New("bad signature")
- ErrBadMAC = errors.New("bad mac")
- ErrBadMessageFormat = errors.New("bad message format")
- ErrBadVerification = errors.New("bad verification")
- ErrWrongProtocolVersion = errors.New("wrong protocol version")
- ErrEmptyInput = errors.New("empty input")
- ErrNoKeyProvided = errors.New("no key")
- ErrBadMessageKeyID = errors.New("bad message key id")
- ErrRatchetNotAvailable = errors.New("ratchet not available: attempt to decode a message whose index is earlier than our earliest known session key")
- ErrMsgIndexTooHigh = errors.New("message index too high")
- ErrProtocolViolation = errors.New("not protocol message order")
- ErrMessageKeyNotFound = errors.New("message key not found")
- ErrChainTooHigh = errors.New("chain index too high")
- ErrBadInput = errors.New("bad input")
- ErrBadVersion = errors.New("wrong version")
- ErrWrongPickleVersion = errors.New("wrong pickle version")
- ErrInputToSmall = errors.New("input too small (truncated?)")
- ErrOverflow = errors.New("overflow")
+ ErrBadSignature = errors.New("bad signature")
+ ErrBadMAC = errors.New("the message couldn't be decrypted (bad mac)")
+ ErrBadMessageFormat = errors.New("the message couldn't be decoded")
+ ErrBadVerification = errors.New("bad verification")
+ ErrWrongProtocolVersion = errors.New("wrong protocol version")
+ ErrEmptyInput = errors.New("empty input")
+ ErrNoKeyProvided = errors.New("no key provided")
+ ErrBadMessageKeyID = errors.New("the message references an unknown key ID")
+ ErrUnknownMessageIndex = errors.New("attempt to decode a message whose index is earlier than our earliest known session key")
+ ErrMsgIndexTooHigh = errors.New("message index too high")
+ ErrProtocolViolation = errors.New("not protocol message order")
+ ErrMessageKeyNotFound = errors.New("message key not found")
+ ErrChainTooHigh = errors.New("chain index too high")
+ ErrBadInput = errors.New("bad input")
+ ErrUnknownOlmPickleVersion = errors.New("unknown olm pickle version")
+ ErrUnknownJSONPickleVersion = errors.New("unknown JSON pickle version")
+ ErrInputToSmall = errors.New("input too small (truncated?)")
)
// Error codes from go-olm
var (
- EmptyInput = errors.New("empty input")
- NoKeyProvided = errors.New("no pickle key provided")
- NotEnoughGoRandom = errors.New("couldn't get enough randomness from crypto/rand")
- SignatureNotFound = errors.New("input JSON doesn't contain signature from specified device")
- InputNotJSONString = errors.New("input doesn't look like a JSON string")
+ ErrNotEnoughGoRandom = errors.New("couldn't get enough randomness from crypto/rand")
+ ErrInputNotJSONString = errors.New("input doesn't look like a JSON string")
)
// Error codes from olm code
var (
- NotEnoughRandom = errors.New("not enough entropy was supplied")
- OutputBufferTooSmall = errors.New("supplied output buffer is too small")
- BadMessageVersion = errors.New("the message version is unsupported")
- BadMessageFormat = errors.New("the message couldn't be decoded")
- BadMessageMAC = errors.New("the message couldn't be decrypted")
- BadMessageKeyID = errors.New("the message references an unknown key ID")
- InvalidBase64 = errors.New("the input base64 was invalid")
- BadAccountKey = errors.New("the supplied account key is invalid")
- UnknownPickleVersion = errors.New("the pickled object is too new")
- CorruptedPickle = errors.New("the pickled object couldn't be decoded")
- BadSessionKey = errors.New("attempt to initialise an inbound group session from an invalid session key")
- UnknownMessageIndex = errors.New("attempt to decode a message whose index is earlier than our earliest known session key")
- BadLegacyAccountPickle = errors.New("attempt to unpickle an account which uses pickle version 1")
- BadSignature = errors.New("received message had a bad signature")
- InputBufferTooSmall = errors.New("the input data was too small to be valid")
+ ErrLibolmInvalidBase64 = errors.New("the input base64 was invalid")
+
+ ErrLibolmNotEnoughRandom = errors.New("not enough entropy was supplied")
+ ErrLibolmOutputBufferTooSmall = errors.New("supplied output buffer is too small")
+ ErrLibolmBadAccountKey = errors.New("the supplied account key is invalid")
+ ErrLibolmCorruptedPickle = errors.New("the pickled object couldn't be decoded")
+ ErrLibolmBadSessionKey = errors.New("attempt to initialise an inbound group session from an invalid session key")
+ ErrLibolmBadLegacyAccountPickle = errors.New("attempt to unpickle an account which uses pickle version 1")
+)
+
+// Deprecated: use variables prefixed with Err
+var (
+ EmptyInput = ErrEmptyInput
+ BadSignature = ErrBadSignature
+ InvalidBase64 = ErrLibolmInvalidBase64
+ BadMessageKeyID = ErrBadMessageKeyID
+ BadMessageFormat = ErrBadMessageFormat
+ BadMessageVersion = ErrWrongProtocolVersion
+ BadMessageMAC = ErrBadMAC
+ UnknownPickleVersion = ErrUnknownOlmPickleVersion
+ NotEnoughRandom = ErrLibolmNotEnoughRandom
+ OutputBufferTooSmall = ErrLibolmOutputBufferTooSmall
+ BadAccountKey = ErrLibolmBadAccountKey
+ CorruptedPickle = ErrLibolmCorruptedPickle
+ BadSessionKey = ErrLibolmBadSessionKey
+ UnknownMessageIndex = ErrUnknownMessageIndex
+ BadLegacyAccountPickle = ErrLibolmBadLegacyAccountPickle
+ InputBufferTooSmall = ErrInputToSmall
+ NoKeyProvided = ErrNoKeyProvided
+
+ NotEnoughGoRandom = ErrNotEnoughGoRandom
+ InputNotJSONString = ErrInputNotJSONString
+
+ ErrBadVersion = ErrUnknownJSONPickleVersion
+ ErrWrongPickleVersion = ErrUnknownJSONPickleVersion
+ ErrRatchetNotAvailable = ErrUnknownMessageIndex
)
diff --git a/vendor/maunium.net/go/mautrix/crypto/sessions.go b/vendor/maunium.net/go/mautrix/crypto/sessions.go
index aecb041..6b90c99 100644
--- a/vendor/maunium.net/go/mautrix/crypto/sessions.go
+++ b/vendor/maunium.net/go/mautrix/crypto/sessions.go
@@ -18,8 +18,14 @@ import (
)
var (
- SessionNotShared = errors.New("session has not been shared")
- SessionExpired = errors.New("session has expired")
+ ErrSessionNotShared = errors.New("session has not been shared")
+ ErrSessionExpired = errors.New("session has expired")
+)
+
+// Deprecated: use variables prefixed with Err
+var (
+ SessionNotShared = ErrSessionNotShared
+ SessionExpired = ErrSessionExpired
)
// OlmSessionList is a list of OlmSessions.
@@ -255,9 +261,9 @@ func (ogs *OutboundGroupSession) Expired() bool {
func (ogs *OutboundGroupSession) Encrypt(plaintext []byte) ([]byte, error) {
if !ogs.Shared {
- return nil, SessionNotShared
+ return nil, ErrSessionNotShared
} else if ogs.Expired() {
- return nil, SessionExpired
+ return nil, ErrSessionExpired
}
ogs.MessageCount++
ogs.LastEncryptedTime = time.Now()
diff --git a/vendor/maunium.net/go/mautrix/crypto/ssss/client.go b/vendor/maunium.net/go/mautrix/crypto/ssss/client.go
index e30925d..8691d03 100644
--- a/vendor/maunium.net/go/mautrix/crypto/ssss/client.go
+++ b/vendor/maunium.net/go/mautrix/crypto/ssss/client.go
@@ -95,6 +95,22 @@ func (mach *Machine) SetEncryptedAccountData(ctx context.Context, eventType even
return mach.Client.SetAccountData(ctx, eventType.Type, &EncryptedAccountDataEventContent{Encrypted: encrypted})
}
+// SetEncryptedAccountDataWithMetadata encrypts the given data with the given keys and stores it,
+// alongside the unencrypted metadata, on the server.
+func (mach *Machine) SetEncryptedAccountDataWithMetadata(ctx context.Context, eventType event.Type, data []byte, metadata map[string]any, keys ...*Key) error {
+ if len(keys) == 0 {
+ return ErrNoKeyGiven
+ }
+ encrypted := make(map[string]EncryptedKeyData, len(keys))
+ for _, key := range keys {
+ encrypted[key.ID] = key.Encrypt(eventType.Type, data)
+ }
+ return mach.Client.SetAccountData(ctx, eventType.Type, &EncryptedAccountDataEventContent{
+ Encrypted: encrypted,
+ Metadata: metadata,
+ })
+}
+
// GenerateAndUploadKey generates a new SSSS key and stores the metadata on the server.
func (mach *Machine) GenerateAndUploadKey(ctx context.Context, passphrase string) (key *Key, err error) {
key, err = NewKey(passphrase)
diff --git a/vendor/maunium.net/go/mautrix/crypto/ssss/types.go b/vendor/maunium.net/go/mautrix/crypto/ssss/types.go
index 345393b..c08f107 100644
--- a/vendor/maunium.net/go/mautrix/crypto/ssss/types.go
+++ b/vendor/maunium.net/go/mautrix/crypto/ssss/types.go
@@ -57,6 +57,7 @@ type EncryptedKeyData struct {
type EncryptedAccountDataEventContent struct {
Encrypted map[string]EncryptedKeyData `json:"encrypted"`
+ Metadata map[string]any `json:"com.beeper.metadata,omitzero"`
}
func (ed *EncryptedAccountDataEventContent) Decrypt(eventType string, key *Key) ([]byte, error) {
diff --git a/vendor/maunium.net/go/mautrix/error.go b/vendor/maunium.net/go/mautrix/error.go
index 826af17..5ff671e 100644
--- a/vendor/maunium.net/go/mautrix/error.go
+++ b/vendor/maunium.net/go/mautrix/error.go
@@ -85,6 +85,10 @@ var (
ErrResponseTooLong = errors.New("response content length too long")
ErrBodyReadReachedLimit = errors.New("reached response size limit while reading body")
+
+ // Special error that indicates we should retry canceled contexts. Note that on it's own this
+ // is useless, the context itself must also be replaced.
+ ErrContextCancelRetry = errors.New("retry canceled context")
)
// HTTPError An HTTP Error response, which may wrap an underlying native Go Error.
diff --git a/vendor/maunium.net/go/mautrix/event/beeper.go b/vendor/maunium.net/go/mautrix/event/beeper.go
index 95b4a57..75c18aa 100644
--- a/vendor/maunium.net/go/mautrix/event/beeper.go
+++ b/vendor/maunium.net/go/mautrix/event/beeper.go
@@ -53,6 +53,8 @@ type BeeperMessageStatusEventContent struct {
LastRetry id.EventID `json:"last_retry,omitempty"`
+ TargetTxnID string `json:"relates_to_txn_id,omitempty"`
+
MutateEventKey string `json:"mutate_event_key,omitempty"`
// Indicates the set of users to whom the event was delivered. If nil, then
@@ -87,7 +89,17 @@ type BeeperRoomKeyAckEventContent struct {
}
type BeeperChatDeleteEventContent struct {
- DeleteForEveryone bool `json:"delete_for_everyone,omitempty"`
+ DeleteForEveryone bool `json:"delete_for_everyone,omitempty"`
+ FromMessageRequest bool `json:"from_message_request,omitempty"`
+}
+
+type BeeperAcceptMessageRequestEventContent struct {
+}
+
+type BeeperSendStateEventContent struct {
+ Type string `json:"type"`
+ StateKey string `json:"state_key"`
+ Content Content `json:"content"`
}
type IntOrString int
diff --git a/vendor/maunium.net/go/mautrix/event/capabilities.d.ts b/vendor/maunium.net/go/mautrix/event/capabilities.d.ts
index 1fbc961..26aeb34 100644
--- a/vendor/maunium.net/go/mautrix/event/capabilities.d.ts
+++ b/vendor/maunium.net/go/mautrix/event/capabilities.d.ts
@@ -77,6 +77,11 @@ export interface RoomFeatures {
delete_chat?: boolean
/** Whether deleting the chat for all participants is supported. */
delete_chat_for_everyone?: boolean
+ /** What can be done with message requests? */
+ message_request?: {
+ accept_with_message?: CapabilitySupportLevel
+ accept_with_button?: CapabilitySupportLevel
+ }
}
declare type integer = number
diff --git a/vendor/maunium.net/go/mautrix/event/capabilities.go b/vendor/maunium.net/go/mautrix/event/capabilities.go
index 4b7ff18..a86c726 100644
--- a/vendor/maunium.net/go/mautrix/event/capabilities.go
+++ b/vendor/maunium.net/go/mautrix/event/capabilities.go
@@ -61,6 +61,8 @@ type RoomFeatures struct {
DeleteChat bool `json:"delete_chat,omitempty"`
DeleteChatForEveryone bool `json:"delete_chat_for_everyone,omitempty"`
+ MessageRequest *MessageRequestFeatures `json:"message_request,omitempty"`
+
PerMessageProfileRelay bool `json:"-"`
}
@@ -84,6 +86,7 @@ func (rf *RoomFeatures) Clone() *RoomFeatures {
clone.DeleteMaxAge = ptr.Clone(clone.DeleteMaxAge)
clone.DisappearingTimer = clone.DisappearingTimer.Clone()
clone.AllowedReactions = slices.Clone(clone.AllowedReactions)
+ clone.MessageRequest = clone.MessageRequest.Clone()
return &clone
}
@@ -165,6 +168,25 @@ func (dtc *DisappearingTimerCapability) Supports(content *BeeperDisappearingTime
return slices.Contains(dtc.Types, content.Type) && (dtc.Timers == nil || slices.Contains(dtc.Timers, content.Timer))
}
+type MessageRequestFeatures struct {
+ AcceptWithMessage CapabilitySupportLevel `json:"accept_with_message,omitempty"`
+ AcceptWithButton CapabilitySupportLevel `json:"accept_with_button,omitempty"`
+}
+
+func (mrf *MessageRequestFeatures) Clone() *MessageRequestFeatures {
+ return ptr.Clone(mrf)
+}
+
+func (mrf *MessageRequestFeatures) Hash() []byte {
+ if mrf == nil {
+ return nil
+ }
+ hasher := sha256.New()
+ hashValue(hasher, "accept_with_message", mrf.AcceptWithMessage)
+ hashValue(hasher, "accept_with_button", mrf.AcceptWithButton)
+ return hasher.Sum(nil)
+}
+
type CapabilityMsgType = MessageType
// Message types which are used for event capability signaling, but aren't real values for the msgtype field.
@@ -347,6 +369,7 @@ func (rf *RoomFeatures) Hash() []byte {
hashBool(hasher, "mark_as_unread", rf.MarkAsUnread)
hashBool(hasher, "delete_chat", rf.DeleteChat)
hashBool(hasher, "delete_chat_for_everyone", rf.DeleteChatForEveryone)
+ hashValue(hasher, "message_request", rf.MessageRequest)
return hasher.Sum(nil)
}
diff --git a/vendor/maunium.net/go/mautrix/event/content.go b/vendor/maunium.net/go/mautrix/event/content.go
index c0ff51a..4929c6a 100644
--- a/vendor/maunium.net/go/mautrix/event/content.go
+++ b/vendor/maunium.net/go/mautrix/event/content.go
@@ -61,9 +61,11 @@ var TypeMap = map[Type]reflect.Type{
EventUnstablePollStart: reflect.TypeOf(PollStartEventContent{}),
EventUnstablePollResponse: reflect.TypeOf(PollResponseEventContent{}),
- BeeperMessageStatus: reflect.TypeOf(BeeperMessageStatusEventContent{}),
- BeeperTranscription: reflect.TypeOf(BeeperTranscriptionEventContent{}),
- BeeperDeleteChat: reflect.TypeOf(BeeperChatDeleteEventContent{}),
+ BeeperMessageStatus: reflect.TypeOf(BeeperMessageStatusEventContent{}),
+ BeeperTranscription: reflect.TypeOf(BeeperTranscriptionEventContent{}),
+ BeeperDeleteChat: reflect.TypeOf(BeeperChatDeleteEventContent{}),
+ BeeperAcceptMessageRequest: reflect.TypeOf(BeeperAcceptMessageRequestEventContent{}),
+ BeeperSendState: reflect.TypeOf(BeeperSendStateEventContent{}),
AccountDataRoomTags: reflect.TypeOf(TagEventContent{}),
AccountDataDirectChats: reflect.TypeOf(DirectChatsEventContent{}),
diff --git a/vendor/maunium.net/go/mautrix/event/encryption.go b/vendor/maunium.net/go/mautrix/event/encryption.go
index cf9c281..e07944a 100644
--- a/vendor/maunium.net/go/mautrix/event/encryption.go
+++ b/vendor/maunium.net/go/mautrix/event/encryption.go
@@ -63,7 +63,7 @@ func (content *EncryptedEventContent) UnmarshalJSON(data []byte) error {
return json.Unmarshal(content.Ciphertext, &content.OlmCiphertext)
case id.AlgorithmMegolmV1:
if len(content.Ciphertext) == 0 || content.Ciphertext[0] != '"' || content.Ciphertext[len(content.Ciphertext)-1] != '"' {
- return id.InputNotJSONString
+ return id.ErrInputNotJSONString
}
content.MegolmCiphertext = content.Ciphertext[1 : len(content.Ciphertext)-1]
}
diff --git a/vendor/maunium.net/go/mautrix/event/state.go b/vendor/maunium.net/go/mautrix/event/state.go
index 6df3b14..29e0e52 100644
--- a/vendor/maunium.net/go/mautrix/event/state.go
+++ b/vendor/maunium.net/go/mautrix/event/state.go
@@ -231,7 +231,8 @@ type BridgeInfoSection struct {
AvatarURL id.ContentURIString `json:"avatar_url,omitempty"`
ExternalURL string `json:"external_url,omitempty"`
- Receiver string `json:"fi.mau.receiver,omitempty"`
+ Receiver string `json:"fi.mau.receiver,omitempty"`
+ MessageRequest bool `json:"com.beeper.message_request,omitempty"`
}
// BridgeEventContent represents the content of a m.bridge state event.
diff --git a/vendor/maunium.net/go/mautrix/event/type.go b/vendor/maunium.net/go/mautrix/event/type.go
index 56ea82f..f4d7592 100644
--- a/vendor/maunium.net/go/mautrix/event/type.go
+++ b/vendor/maunium.net/go/mautrix/event/type.go
@@ -128,7 +128,7 @@ func (et *Type) GuessClass() TypeClass {
InRoomVerificationKey.Type, InRoomVerificationMAC.Type, InRoomVerificationCancel.Type,
CallInvite.Type, CallCandidates.Type, CallAnswer.Type, CallReject.Type, CallSelectAnswer.Type,
CallNegotiate.Type, CallHangup.Type, BeeperMessageStatus.Type, EventUnstablePollStart.Type, EventUnstablePollResponse.Type,
- EventUnstablePollEnd.Type, BeeperTranscription.Type, BeeperDeleteChat.Type:
+ EventUnstablePollEnd.Type, BeeperTranscription.Type, BeeperDeleteChat.Type, BeeperAcceptMessageRequest.Type:
return MessageEventType
case ToDeviceRoomKey.Type, ToDeviceRoomKeyRequest.Type, ToDeviceForwardedRoomKey.Type, ToDeviceRoomKeyWithheld.Type,
ToDeviceBeeperRoomKeyAck.Type:
@@ -234,9 +234,11 @@ var (
CallNegotiate = Type{"m.call.negotiate", MessageEventType}
CallHangup = Type{"m.call.hangup", MessageEventType}
- BeeperMessageStatus = Type{"com.beeper.message_send_status", MessageEventType}
- BeeperTranscription = Type{"com.beeper.transcription", MessageEventType}
- BeeperDeleteChat = Type{"com.beeper.delete_chat", MessageEventType}
+ BeeperMessageStatus = Type{"com.beeper.message_send_status", MessageEventType}
+ BeeperTranscription = Type{"com.beeper.transcription", MessageEventType}
+ BeeperDeleteChat = Type{"com.beeper.delete_chat", MessageEventType}
+ BeeperAcceptMessageRequest = Type{"com.beeper.accept_message_request", MessageEventType}
+ BeeperSendState = Type{"com.beeper.send_state", MessageEventType}
EventUnstablePollStart = Type{Type: "org.matrix.msc3381.poll.start", Class: MessageEventType}
EventUnstablePollResponse = Type{Type: "org.matrix.msc3381.poll.response", Class: MessageEventType}
diff --git a/vendor/maunium.net/go/mautrix/filter.go b/vendor/maunium.net/go/mautrix/filter.go
index c6c8211..54973da 100644
--- a/vendor/maunium.net/go/mautrix/filter.go
+++ b/vendor/maunium.net/go/mautrix/filter.go
@@ -57,7 +57,7 @@ type FilterPart struct {
// Validate checks if the filter contains valid property values
func (filter *Filter) Validate() error {
if filter.EventFormat != EventFormatClient && filter.EventFormat != EventFormatFederation {
- return errors.New("Bad event_format value. Must be one of [\"client\", \"federation\"]")
+ return errors.New("bad event_format value")
}
return nil
}
diff --git a/vendor/maunium.net/go/mautrix/id/contenturi.go b/vendor/maunium.net/go/mautrix/id/contenturi.go
index e6a313f..be45eb2 100644
--- a/vendor/maunium.net/go/mautrix/id/contenturi.go
+++ b/vendor/maunium.net/go/mautrix/id/contenturi.go
@@ -17,8 +17,14 @@ import (
)
var (
- InvalidContentURI = errors.New("invalid Matrix content URI")
- InputNotJSONString = errors.New("input doesn't look like a JSON string")
+ ErrInvalidContentURI = errors.New("invalid Matrix content URI")
+ ErrInputNotJSONString = errors.New("input doesn't look like a JSON string")
+)
+
+// Deprecated: use variables prefixed with Err
+var (
+ InvalidContentURI = ErrInvalidContentURI
+ InputNotJSONString = ErrInputNotJSONString
)
// ContentURIString is a string that's expected to be a Matrix content URI.
@@ -55,9 +61,9 @@ func ParseContentURI(uri string) (parsed ContentURI, err error) {
if len(uri) == 0 {
return
} else if !strings.HasPrefix(uri, "mxc://") {
- err = InvalidContentURI
+ err = ErrInvalidContentURI
} else if index := strings.IndexRune(uri[6:], '/'); index == -1 || index == len(uri)-7 {
- err = InvalidContentURI
+ err = ErrInvalidContentURI
} else {
parsed.Homeserver = uri[6 : 6+index]
parsed.FileID = uri[6+index+1:]
@@ -71,9 +77,9 @@ func ParseContentURIBytes(uri []byte) (parsed ContentURI, err error) {
if len(uri) == 0 {
return
} else if !bytes.HasPrefix(uri, mxcBytes) {
- err = InvalidContentURI
+ err = ErrInvalidContentURI
} else if index := bytes.IndexRune(uri[6:], '/'); index == -1 || index == len(uri)-7 {
- err = InvalidContentURI
+ err = ErrInvalidContentURI
} else {
parsed.Homeserver = string(uri[6 : 6+index])
parsed.FileID = string(uri[6+index+1:])
@@ -86,7 +92,7 @@ func (uri *ContentURI) UnmarshalJSON(raw []byte) (err error) {
*uri = ContentURI{}
return nil
} else if len(raw) < 2 || raw[0] != '"' || raw[len(raw)-1] != '"' {
- return InputNotJSONString
+ return ErrInputNotJSONString
}
parsed, err := ParseContentURIBytes(raw[1 : len(raw)-1])
if err != nil {
diff --git a/vendor/maunium.net/go/mautrix/id/matrixuri.go b/vendor/maunium.net/go/mautrix/id/matrixuri.go
index 8f5ec84..d5c78bc 100644
--- a/vendor/maunium.net/go/mautrix/id/matrixuri.go
+++ b/vendor/maunium.net/go/mautrix/id/matrixuri.go
@@ -54,7 +54,7 @@ var SigilToPathSegment = map[rune]string{
func (uri *MatrixURI) getQuery() url.Values {
q := make(url.Values)
- if uri.Via != nil && len(uri.Via) > 0 {
+ if len(uri.Via) > 0 {
q["via"] = uri.Via
}
if len(uri.Action) > 0 {
diff --git a/vendor/maunium.net/go/mautrix/id/userid.go b/vendor/maunium.net/go/mautrix/id/userid.go
index 859d235..726a0d5 100644
--- a/vendor/maunium.net/go/mautrix/id/userid.go
+++ b/vendor/maunium.net/go/mautrix/id/userid.go
@@ -219,15 +219,15 @@ func DecodeUserLocalpart(str string) (string, error) {
for i := 0; i < len(strBytes); i++ {
b := strBytes[i]
if !isValidByte(b) {
- return "", fmt.Errorf("Byte pos %d: Invalid byte", i)
+ return "", fmt.Errorf("invalid encoded byte at position %d: %c", i, b)
}
if b == '_' { // next byte is a-z and should be upper-case or is another _ and should be a literal _
if i+1 >= len(strBytes) {
- return "", fmt.Errorf("Byte pos %d: expected _[a-z_] encoding but ran out of string", i)
+ return "", fmt.Errorf("unexpected end of string after underscore at %d", i)
}
if !isValidEscapedChar(strBytes[i+1]) { // invalid escaping
- return "", fmt.Errorf("Byte pos %d: expected _[a-z_] encoding", i)
+ return "", fmt.Errorf("unexpected byte %c after underscore at %d", strBytes[i+1], i)
}
if strBytes[i+1] == '_' {
outputBuffer.WriteByte('_')
@@ -237,7 +237,7 @@ func DecodeUserLocalpart(str string) (string, error) {
i++ // skip next byte since we just handled it
} else if b == '=' { // next 2 bytes are hex and should be buffered ready to be read as utf8
if i+2 >= len(strBytes) {
- return "", fmt.Errorf("Byte pos: %d: expected quote-printable encoding but ran out of string", i)
+ return "", fmt.Errorf("unexpected end of string after equals sign at %d", i)
}
dst := make([]byte, 1)
_, err := hex.Decode(dst, strBytes[i+1:i+3])
diff --git a/vendor/maunium.net/go/mautrix/pushrules/action.go b/vendor/maunium.net/go/mautrix/pushrules/action.go
index 9838e88..b5a884b 100644
--- a/vendor/maunium.net/go/mautrix/pushrules/action.go
+++ b/vendor/maunium.net/go/mautrix/pushrules/action.go
@@ -105,7 +105,7 @@ func (action *PushAction) UnmarshalJSON(raw []byte) error {
if ok {
action.Action = ActionSetTweak
action.Tweak = PushActionTweak(tweak)
- action.Value, _ = val["value"]
+ action.Value = val["value"]
}
}
return nil
diff --git a/vendor/maunium.net/go/mautrix/responses.go b/vendor/maunium.net/go/mautrix/responses.go
index e7b6b75..d822c84 100644
--- a/vendor/maunium.net/go/mautrix/responses.go
+++ b/vendor/maunium.net/go/mautrix/responses.go
@@ -263,10 +263,7 @@ type RespMutualRooms struct {
type RespRoomSummary struct {
PublicRoomInfo
- Membership event.Membership `json:"membership,omitempty"`
- RoomVersion id.RoomVersion `json:"room_version,omitempty"`
- Encryption id.Algorithm `json:"encryption,omitempty"`
- AllowedRoomIDs []id.RoomID `json:"allowed_room_ids,omitempty"`
+ Membership event.Membership `json:"membership,omitempty"`
UnstableRoomVersion id.RoomVersion `json:"im.nheko.summary.room_version,omitempty"`
UnstableRoomVersionOld id.RoomVersion `json:"im.nheko.summary.version,omitempty"`
@@ -685,6 +682,10 @@ type PublicRoomInfo struct {
RoomType event.RoomType `json:"room_type"`
Topic string `json:"topic,omitempty"`
WorldReadable bool `json:"world_readable"`
+
+ RoomVersion id.RoomVersion `json:"room_version,omitempty"`
+ Encryption id.Algorithm `json:"encryption,omitempty"`
+ AllowedRoomIDs []id.RoomID `json:"allowed_room_ids,omitempty"`
}
// RespHierarchy is the JSON response for https://spec.matrix.org/v1.4/client-server-api/#get_matrixclientv1roomsroomidhierarchy
diff --git a/vendor/maunium.net/go/mautrix/room.go b/vendor/maunium.net/go/mautrix/room.go
index c3ddb7e..4292bff 100644
--- a/vendor/maunium.net/go/mautrix/room.go
+++ b/vendor/maunium.net/go/mautrix/room.go
@@ -5,8 +5,6 @@ import (
"maunium.net/go/mautrix/id"
)
-type RoomStateMap = map[event.Type]map[string]*event.Event
-
// Room represents a single Matrix room.
type Room struct {
ID id.RoomID
@@ -25,8 +23,8 @@ func (room Room) UpdateState(evt *event.Event) {
// GetStateEvent returns the state event for the given type/state_key combo, or nil.
func (room Room) GetStateEvent(eventType event.Type, stateKey string) *event.Event {
- stateEventMap, _ := room.State[eventType]
- evt, _ := stateEventMap[stateKey]
+ stateEventMap := room.State[eventType]
+ evt := stateEventMap[stateKey]
return evt
}
diff --git a/vendor/maunium.net/go/mautrix/statestore.go b/vendor/maunium.net/go/mautrix/statestore.go
index c6267c5..2bd498d 100644
--- a/vendor/maunium.net/go/mautrix/statestore.go
+++ b/vendor/maunium.net/go/mautrix/statestore.go
@@ -129,6 +129,7 @@ func NewMemoryStateStore() StateStore {
PowerLevels: make(map[id.RoomID]*event.PowerLevelsEventContent),
Encryption: make(map[id.RoomID]*event.EncryptionEventContent),
Create: make(map[id.RoomID]*event.Event),
+ JoinRules: make(map[id.RoomID]*event.JoinRulesEventContent),
}
}
diff --git a/vendor/maunium.net/go/mautrix/url.go b/vendor/maunium.net/go/mautrix/url.go
index d888956..91b3d49 100644
--- a/vendor/maunium.net/go/mautrix/url.go
+++ b/vendor/maunium.net/go/mautrix/url.go
@@ -98,10 +98,8 @@ func (saup SynapseAdminURLPath) FullPath() []any {
// and appservice user ID set already.
func (cli *Client) BuildURLWithQuery(urlPath PrefixableURLPath, urlQuery map[string]string) string {
return cli.BuildURLWithFullQuery(urlPath, func(q url.Values) {
- if urlQuery != nil {
- for k, v := range urlQuery {
- q.Set(k, v)
- }
+ for k, v := range urlQuery {
+ q.Set(k, v)
}
})
}
diff --git a/vendor/maunium.net/go/mautrix/version.go b/vendor/maunium.net/go/mautrix/version.go
index f6d20c3..46d3342 100644
--- a/vendor/maunium.net/go/mautrix/version.go
+++ b/vendor/maunium.net/go/mautrix/version.go
@@ -8,7 +8,7 @@ import (
"strings"
)
-const Version = "v0.26.0"
+const Version = "v0.26.1"
var GoModVersion = ""
var Commit = ""
diff --git a/vendor/modernc.org/sqlite/AUTHORS b/vendor/modernc.org/sqlite/AUTHORS
index 7b23676..9a3bfef 100644
--- a/vendor/modernc.org/sqlite/AUTHORS
+++ b/vendor/modernc.org/sqlite/AUTHORS
@@ -29,4 +29,4 @@ Saed SayedAhmed
Steffen Butzer
Toni Spets
W. Michael Petullo
-SUSE LLC
+SUSE LLC
\ No newline at end of file
diff --git a/vendor/modernc.org/sqlite/CONTRIBUTORS b/vendor/modernc.org/sqlite/CONTRIBUTORS
index e853421..7fc3587 100644
--- a/vendor/modernc.org/sqlite/CONTRIBUTORS
+++ b/vendor/modernc.org/sqlite/CONTRIBUTORS
@@ -10,6 +10,7 @@ Alexander Menzhinsky
Alexey Palazhchenko
Angus Dippenaar
Artyom Pervukhin
+Adrian Witas
Dan Kortschak
Dan Peterson
David Skinner
diff --git a/vendor/modernc.org/sqlite/README.md b/vendor/modernc.org/sqlite/README.md
index 1616f91..c3a920a 100644
--- a/vendor/modernc.org/sqlite/README.md
+++ b/vendor/modernc.org/sqlite/README.md
@@ -1,7 +1,18 @@
+# ⚠️ Important: Repository Mirroring
+
+**This project is primarily developed on GitLab.** The repository you are currently viewing might be a mirror. Please review the guidelines below based on where you are viewing this:
+
+| Platform | Role | Contributing Guidelines |
+| :--- | :--- | :--- |
+| **GitLab** | **Primary Source** | This is the canonical repository (`cznic/sqlite`). CI pipelines and main development happen here. |
+| **GitHub** | **Mirror** | This is a mirror (`modernc-org/sqlite`). We **do accept** Issues and Pull Requests here for your convenience!
*Note: PRs submitted here will be manually merged into the GitLab source, so please allow extra time for processing.* |
+
+---
+
+

[](https://pkg.go.dev/modernc.org/sqlite)
-
[](https://liberapay.com/jnml/donate)
[](https://liberapay.com/jnml/donate)
[](https://liberapay.com/jnml/donate)
@@ -9,3 +20,31 @@
[The SQLite Drivers Benchmarks Game]
[The SQLite Drivers Benchmarks Game]: https://pkg.go.dev/modernc.org/sqlite-bench#readme-tl-dr-scorecard
+
+Virtual Tables (vtab)
+---------------------
+
+The driver exposes a Go API to implement SQLite virtual table modules in pure Go via the `modernc.org/sqlite/vtab` package. This lets you back SQL tables with arbitrary data sources (e.g., vector indexes, CSV files, remote APIs) and integrate with SQLite’s planner.
+
+- Register: `vtab.RegisterModule(db, name, module)`. Registration applies to new connections only.
+- Schema declaration: Call `ctx.Declare("CREATE TABLE ()")` within `Create` or `Connect`. The driver does not auto-declare schemas, enabling dynamic schemas.
+- Module arguments: `args []string` passed to `Create/Connect` are configuration parsed from `USING module(...)`. They are not treated as columns unless your module chooses to.
+- Planning (BestIndex):
+ - Inspect `info.Constraints` (with `Column`, `Op`, `Usable`, 0-based `ArgIndex`, and `Omit`), `info.OrderBy`, and `info.ColUsed` (bitmask of referenced columns).
+ - Set `ArgIndex` (0-based) to populate `Filter`’s `vals` in the chosen order; set `Omit` to ask SQLite not to re-check a constraint you fully handle.
+- Execution: `Cursor.Filter(idxNum, idxStr, vals)` receives arguments in the order implied by `ArgIndex`.
+- Operators: Common SQLite operators map to `ConstraintOp` (EQ/NE/GT/GE/LT/LE/MATCH/IS/ISNOT/ISNULL/ISNOTNULL/LIKE/GLOB/REGEXP/FUNCTION/LIMIT/OFFSET). Unknown operators map to `OpUnknown`.
+- Errors: Returning an error from vtab methods surfaces a descriptive message to SQLite (e.g., `zErrMsg` for xCreate/xConnect/xBestIndex/xFilter; `sqlite3_result_error` for xColumn).
+
+Examples
+--------
+
+- Vector search (sqlite-vec style):
+ - `CREATE VIRTUAL TABLE vec_docs USING vec(dim=128, metric="cosine")`
+ - Module reads args (e.g., `dim`, `metric`), calls `ctx.Declare("CREATE TABLE vec_docs(id, embedding, content HIDDEN)")`, and implements search via `BestIndex`/`Filter`.
+
+- CSV loader:
+ - `CREATE VIRTUAL TABLE csv_users USING csv(filename="/tmp/users.csv", delimiter=",", header=true)`
+ - Module reads the file header to compute columns, declares them via `ctx.Declare("CREATE TABLE csv_users(name, email, ...)")`, and streams rows via a cursor.
+
+See `vtab` package docs for full API details.
diff --git a/vendor/modernc.org/sqlite/backup.go b/vendor/modernc.org/sqlite/backup.go
new file mode 100644
index 0000000..24c1590
--- /dev/null
+++ b/vendor/modernc.org/sqlite/backup.go
@@ -0,0 +1,65 @@
+// Copyright 2025 The Sqlite Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package sqlite // import "modernc.org/sqlite"
+
+import (
+ "database/sql/driver"
+
+ sqlite3 "modernc.org/sqlite/lib"
+)
+
+// Backup object is used to manage progress and cleanup an online backup. It
+// is returned by NewBackup or NewRestore.
+type Backup struct {
+ srcConn *conn // source database connection
+ dstConn *conn // destination database connection
+ pBackup uintptr // sqlite3_backup object pointer
+}
+
+// Step will copy up to n pages between the source and destination databases
+// specified by the backup object. If n is negative, all remaining source
+// pages are copied.
+// If it successfully copies n pages and there are still more pages to be
+// copied, then the function returns true with no error. If it successfully
+// finishes copying all pages from source to destination, then it returns
+// false with no error. If an error occurs while running, then an error is
+// returned.
+func (b *Backup) Step(n int32) (bool, error) {
+ rc := sqlite3.Xsqlite3_backup_step(b.srcConn.tls, b.pBackup, n)
+ if rc == sqlite3.SQLITE_OK {
+ return true, nil
+ } else if rc == sqlite3.SQLITE_DONE {
+ return false, nil
+ } else {
+ return false, b.srcConn.errstr(rc)
+ }
+}
+
+// Finish releases all resources associated with the Backup object. The Backup
+// object is invalid and may not be used following a call to Finish.
+func (b *Backup) Finish() error {
+ rc := sqlite3.Xsqlite3_backup_finish(b.srcConn.tls, b.pBackup)
+ b.dstConn.Close()
+ if rc == sqlite3.SQLITE_OK {
+ return nil
+ } else {
+ return b.srcConn.errstr(rc)
+ }
+}
+
+// Commit releases all resources associated with the Backup object but does not
+// close the destination database connection.
+//
+// The destination database connection is returned to the caller or an error if raised.
+// It is the responsibility of the caller to handle the connection closure.
+func (b *Backup) Commit() (driver.Conn, error) {
+ rc := sqlite3.Xsqlite3_backup_finish(b.srcConn.tls, b.pBackup)
+
+ if rc == sqlite3.SQLITE_OK {
+ return b.dstConn, nil
+ } else {
+ return nil, b.srcConn.errstr(rc)
+ }
+}
diff --git a/vendor/modernc.org/sqlite/conn.go b/vendor/modernc.org/sqlite/conn.go
new file mode 100644
index 0000000..bd0e2a1
--- /dev/null
+++ b/vendor/modernc.org/sqlite/conn.go
@@ -0,0 +1,1070 @@
+// Copyright 2025 The Sqlite Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package sqlite // import "modernc.org/sqlite"
+
+import (
+ "context"
+ "database/sql/driver"
+ "fmt"
+ "strconv"
+ "strings"
+ "sync"
+ "time"
+ "unsafe"
+
+ "modernc.org/libc"
+ "modernc.org/libc/sys/types"
+ sqlite3 "modernc.org/sqlite/lib"
+)
+
+type conn struct {
+ db uintptr // *sqlite3.Xsqlite3
+ tls *libc.TLS
+
+ // Context handling can cause conn.Close and conn.interrupt to be invoked
+ // concurrently.
+ sync.Mutex
+
+ writeTimeFormat string
+ beginMode string
+ intToTime bool
+ integerTimeFormat string
+}
+
+func newConn(dsn string) (*conn, error) {
+ var query, vfsName string
+
+ // Parse the query parameters from the dsn and them from the dsn if not prefixed by file:
+ // https://github.com/mattn/go-sqlite3/blob/3392062c729d77820afc1f5cae3427f0de39e954/sqlite3.go#L1046
+ // https://github.com/mattn/go-sqlite3/blob/3392062c729d77820afc1f5cae3427f0de39e954/sqlite3.go#L1383
+ pos := strings.IndexRune(dsn, '?')
+ if pos >= 1 {
+ query = dsn[pos+1:]
+ var err error
+ vfsName, err = getVFSName(query)
+ if err != nil {
+ return nil, err
+ }
+
+ if !strings.HasPrefix(dsn, "file:") {
+ dsn = dsn[:pos]
+ }
+ }
+
+ c := &conn{tls: libc.NewTLS()}
+ db, err := c.openV2(
+ dsn,
+ vfsName,
+ sqlite3.SQLITE_OPEN_READWRITE|sqlite3.SQLITE_OPEN_CREATE|
+ sqlite3.SQLITE_OPEN_FULLMUTEX|
+ sqlite3.SQLITE_OPEN_URI,
+ )
+ if err != nil {
+ return nil, err
+ }
+
+ c.db = db
+ if err = c.extendedResultCodes(true); err != nil {
+ c.Close()
+ return nil, err
+ }
+
+ if err = applyQueryParams(c, query); err != nil {
+ c.Close()
+ return nil, err
+ }
+
+ return c, nil
+}
+
+// Attempt to parse s as a time. Return (s, false) if s is not
+// recognized as a valid time encoding.
+func (c *conn) parseTime(s string) (interface{}, bool) {
+ if v, ok := c.parseTimeString(s, strings.Index(s, "m=")); ok {
+ return v, true
+ }
+
+ ts := strings.TrimSuffix(s, "Z")
+
+ for _, f := range parseTimeFormats {
+ t, err := time.Parse(f, ts)
+ if err == nil {
+ return t, true
+ }
+ }
+
+ return s, false
+}
+
+// Attempt to parse s as a time string produced by t.String(). If x > 0 it's
+// the index of substring "m=" within s. Return (s, false) if s is
+// not recognized as a valid time encoding.
+func (c *conn) parseTimeString(s0 string, x int) (interface{}, bool) {
+ s := s0
+ if x > 0 {
+ s = s[:x] // "2006-01-02 15:04:05.999999999 -0700 MST m=+9999" -> "2006-01-02 15:04:05.999999999 -0700 MST "
+ }
+ s = strings.TrimSpace(s)
+ if t, err := time.Parse("2006-01-02 15:04:05.999999999 -0700 MST", s); err == nil {
+ return t, true
+ }
+
+ return s0, false
+}
+
+// writeTimeFormats are the names and formats supported
+// by the `_time_format` DSN query param.
+var writeTimeFormats = map[string]string{
+ "sqlite": parseTimeFormats[0],
+}
+
+func (c *conn) formatTime(t time.Time) string {
+ // Before configurable write time formats were supported,
+ // time.Time.String was used. Maintain that default to
+ // keep existing driver users formatting times the same.
+ if c.writeTimeFormat == "" {
+ return t.String()
+ }
+ return t.Format(c.writeTimeFormat)
+}
+
+// C documentation
+//
+// const void *sqlite3_column_blob(sqlite3_stmt*, int iCol);
+func (c *conn) columnBlob(pstmt uintptr, iCol int) (v []byte, err error) {
+ p := sqlite3.Xsqlite3_column_blob(c.tls, pstmt, int32(iCol))
+ len, err := c.columnBytes(pstmt, iCol)
+ if err != nil {
+ return nil, err
+ }
+
+ if p == 0 || len == 0 {
+ return nil, nil
+ }
+
+ v = make([]byte, len)
+ copy(v, (*libc.RawMem)(unsafe.Pointer(p))[:len:len])
+ return v, nil
+}
+
+// C documentation
+//
+// int sqlite3_column_bytes(sqlite3_stmt*, int iCol);
+func (c *conn) columnBytes(pstmt uintptr, iCol int) (_ int, err error) {
+ v := sqlite3.Xsqlite3_column_bytes(c.tls, pstmt, int32(iCol))
+ return int(v), nil
+}
+
+// C documentation
+//
+// const unsigned char *sqlite3_column_text(sqlite3_stmt*, int iCol);
+func (c *conn) columnText(pstmt uintptr, iCol int) (v string, err error) {
+ p := sqlite3.Xsqlite3_column_text(c.tls, pstmt, int32(iCol))
+ len, err := c.columnBytes(pstmt, iCol)
+ if err != nil {
+ return "", err
+ }
+
+ if p == 0 || len == 0 {
+ return "", nil
+ }
+
+ b := make([]byte, len)
+ copy(b, (*libc.RawMem)(unsafe.Pointer(p))[:len:len])
+ return string(b), nil
+}
+
+// C documentation
+//
+// double sqlite3_column_double(sqlite3_stmt*, int iCol);
+func (c *conn) columnDouble(pstmt uintptr, iCol int) (v float64, err error) {
+ v = sqlite3.Xsqlite3_column_double(c.tls, pstmt, int32(iCol))
+ return v, nil
+}
+
+// C documentation
+//
+// sqlite3_int64 sqlite3_column_int64(sqlite3_stmt*, int iCol);
+func (c *conn) columnInt64(pstmt uintptr, iCol int) (v int64, err error) {
+ v = sqlite3.Xsqlite3_column_int64(c.tls, pstmt, int32(iCol))
+ return v, nil
+}
+
+// C documentation
+//
+// int sqlite3_column_type(sqlite3_stmt*, int iCol);
+func (c *conn) columnType(pstmt uintptr, iCol int) (_ int, err error) {
+ v := sqlite3.Xsqlite3_column_type(c.tls, pstmt, int32(iCol))
+ return int(v), nil
+}
+
+// C documentation
+//
+// const char *sqlite3_column_decltype(sqlite3_stmt*,int);
+func (c *conn) columnDeclType(pstmt uintptr, iCol int) string {
+ return libc.GoString(sqlite3.Xsqlite3_column_decltype(c.tls, pstmt, int32(iCol)))
+}
+
+// C documentation
+//
+// const char *sqlite3_column_name(sqlite3_stmt*, int N);
+func (c *conn) columnName(pstmt uintptr, n int) (string, error) {
+ p := sqlite3.Xsqlite3_column_name(c.tls, pstmt, int32(n))
+ return libc.GoString(p), nil
+}
+
+// C documentation
+//
+// int sqlite3_column_count(sqlite3_stmt *pStmt);
+func (c *conn) columnCount(pstmt uintptr) (_ int, err error) {
+ v := sqlite3.Xsqlite3_column_count(c.tls, pstmt)
+ return int(v), nil
+}
+
+// C documentation
+//
+// sqlite3_int64 sqlite3_last_insert_rowid(sqlite3*);
+func (c *conn) lastInsertRowID() (v int64, _ error) {
+ return sqlite3.Xsqlite3_last_insert_rowid(c.tls, c.db), nil
+}
+
+// C documentation
+//
+// int sqlite3_changes(sqlite3*);
+func (c *conn) changes() (int, error) {
+ v := sqlite3.Xsqlite3_changes(c.tls, c.db)
+ return int(v), nil
+}
+
+// C documentation
+//
+// int sqlite3_step(sqlite3_stmt*);
+func (c *conn) step(pstmt uintptr) (int, error) {
+ for {
+ switch rc := sqlite3.Xsqlite3_step(c.tls, pstmt); rc {
+ case sqliteLockedSharedcache:
+ if err := c.retry(pstmt); err != nil {
+ return sqlite3.SQLITE_LOCKED, err
+ }
+ case
+ sqlite3.SQLITE_DONE,
+ sqlite3.SQLITE_ROW:
+
+ return int(rc), nil
+ default:
+ return int(rc), c.errstr(rc)
+ }
+ }
+}
+
+func (c *conn) retry(pstmt uintptr) error {
+ mu := mutexAlloc(c.tls)
+ (*mutex)(unsafe.Pointer(mu)).Lock()
+ rc := sqlite3.Xsqlite3_unlock_notify(
+ c.tls,
+ c.db,
+ *(*uintptr)(unsafe.Pointer(&struct {
+ f func(*libc.TLS, uintptr, int32)
+ }{unlockNotify})),
+ mu,
+ )
+ if rc == sqlite3.SQLITE_LOCKED { // Deadlock, see https://www.sqlite.org/c3ref/unlock_notify.html
+ (*mutex)(unsafe.Pointer(mu)).Unlock()
+ mutexFree(c.tls, mu)
+ return c.errstr(rc)
+ }
+
+ (*mutex)(unsafe.Pointer(mu)).Lock()
+ (*mutex)(unsafe.Pointer(mu)).Unlock()
+ mutexFree(c.tls, mu)
+ if pstmt != 0 {
+ sqlite3.Xsqlite3_reset(c.tls, pstmt)
+ }
+ return nil
+}
+
+func (c *conn) bind(pstmt uintptr, n int, args []driver.NamedValue) (allocs []uintptr, err error) {
+ defer func() {
+ if err == nil {
+ return
+ }
+
+ for _, v := range allocs {
+ c.free(v)
+ }
+ allocs = nil
+ }()
+
+ for i := 1; i <= n; i++ {
+ name, err := c.bindParameterName(pstmt, i)
+ if err != nil {
+ return allocs, err
+ }
+
+ var found bool
+ var v driver.NamedValue
+ for _, v = range args {
+ if name != "" {
+ // For ?NNN and $NNN params, match if NNN == v.Ordinal.
+ //
+ // Supporting this for $NNN is a special case that makes eg
+ // `select $1, $2, $3 ...` work without needing to use
+ // sql.Named.
+ if (name[0] == '?' || name[0] == '$') && name[1:] == strconv.Itoa(v.Ordinal) {
+ found = true
+ break
+ }
+
+ // sqlite supports '$', '@' and ':' prefixes for string
+ // identifiers and '?' for numeric, so we cannot
+ // combine different prefixes with the same name
+ // because `database/sql` requires variable names
+ // to start with a letter
+ if name[1:] == v.Name[:] {
+ found = true
+ break
+ }
+ } else {
+ if v.Ordinal == i {
+ found = true
+ break
+ }
+ }
+ }
+
+ if !found {
+ if name != "" {
+ return allocs, fmt.Errorf("missing named argument %q", name[1:])
+ }
+
+ return allocs, fmt.Errorf("missing argument with index %d", i)
+ }
+
+ var p uintptr
+ switch x := v.Value.(type) {
+ case int64:
+ if err := c.bindInt64(pstmt, i, x); err != nil {
+ return allocs, err
+ }
+ case float64:
+ if err := c.bindDouble(pstmt, i, x); err != nil {
+ return allocs, err
+ }
+ case bool:
+ v := 0
+ if x {
+ v = 1
+ }
+ if err := c.bindInt(pstmt, i, v); err != nil {
+ return allocs, err
+ }
+ case []byte:
+ if p, err = c.bindBlob(pstmt, i, x); err != nil {
+ return allocs, err
+ }
+ case string:
+ if p, err = c.bindText(pstmt, i, x); err != nil {
+ return allocs, err
+ }
+ case time.Time:
+ switch c.integerTimeFormat {
+ case "unix":
+ if err := c.bindInt64(pstmt, i, x.Unix()); err != nil {
+ return allocs, err
+ }
+ case "unix_milli":
+ if err := c.bindInt64(pstmt, i, x.UnixMilli()); err != nil {
+ return allocs, err
+ }
+ case "unix_micro":
+ if err := c.bindInt64(pstmt, i, x.UnixMicro()); err != nil {
+ return allocs, err
+ }
+ case "unix_nano":
+ if err := c.bindInt64(pstmt, i, x.UnixNano()); err != nil {
+ return allocs, err
+ }
+ default:
+ if p, err = c.bindText(pstmt, i, c.formatTime(x)); err != nil {
+ return allocs, err
+ }
+ }
+
+ case nil:
+ if p, err = c.bindNull(pstmt, i); err != nil {
+ return allocs, err
+ }
+ default:
+ return allocs, fmt.Errorf("sqlite: invalid driver.Value type %T", x)
+ }
+ if p != 0 {
+ allocs = append(allocs, p)
+ }
+ }
+ return allocs, nil
+}
+
+// C documentation
+//
+// int sqlite3_bind_null(sqlite3_stmt*, int);
+func (c *conn) bindNull(pstmt uintptr, idx1 int) (uintptr, error) {
+ if rc := sqlite3.Xsqlite3_bind_null(c.tls, pstmt, int32(idx1)); rc != sqlite3.SQLITE_OK {
+ return 0, c.errstr(rc)
+ }
+
+ return 0, nil
+}
+
+// C documentation
+//
+// int sqlite3_bind_text(sqlite3_stmt*,int,const char*,int,void(*)(void*));
+func (c *conn) bindText(pstmt uintptr, idx1 int, value string) (uintptr, error) {
+ p, err := libc.CString(value)
+ if err != nil {
+ return 0, err
+ }
+
+ if rc := sqlite3.Xsqlite3_bind_text(c.tls, pstmt, int32(idx1), p, int32(len(value)), 0); rc != sqlite3.SQLITE_OK {
+ c.free(p)
+ return 0, c.errstr(rc)
+ }
+
+ return p, nil
+}
+
+// C documentation
+//
+// int sqlite3_bind_int(sqlite3_stmt*, int, int);
+func (c *conn) bindInt(pstmt uintptr, idx1, value int) (err error) {
+ if rc := sqlite3.Xsqlite3_bind_int(c.tls, pstmt, int32(idx1), int32(value)); rc != sqlite3.SQLITE_OK {
+ return c.errstr(rc)
+ }
+
+ return nil
+}
+
+// C documentation
+//
+// int sqlite3_bind_double(sqlite3_stmt*, int, double);
+func (c *conn) bindDouble(pstmt uintptr, idx1 int, value float64) (err error) {
+ if rc := sqlite3.Xsqlite3_bind_double(c.tls, pstmt, int32(idx1), value); rc != 0 {
+ return c.errstr(rc)
+ }
+
+ return nil
+}
+
+// C documentation
+//
+// int sqlite3_bind_int64(sqlite3_stmt*, int, sqlite3_int64);
+func (c *conn) bindInt64(pstmt uintptr, idx1 int, value int64) (err error) {
+ if rc := sqlite3.Xsqlite3_bind_int64(c.tls, pstmt, int32(idx1), value); rc != sqlite3.SQLITE_OK {
+ return c.errstr(rc)
+ }
+
+ return nil
+}
+
+// C documentation
+//
+// const char *sqlite3_bind_parameter_name(sqlite3_stmt*, int);
+func (c *conn) bindParameterName(pstmt uintptr, i int) (string, error) {
+ p := sqlite3.Xsqlite3_bind_parameter_name(c.tls, pstmt, int32(i))
+ return libc.GoString(p), nil
+}
+
+// C documentation
+//
+// int sqlite3_bind_parameter_count(sqlite3_stmt*);
+func (c *conn) bindParameterCount(pstmt uintptr) (_ int, err error) {
+ r := sqlite3.Xsqlite3_bind_parameter_count(c.tls, pstmt)
+ return int(r), nil
+}
+
+// C documentation
+//
+// int sqlite3_finalize(sqlite3_stmt *pStmt);
+func (c *conn) finalize(pstmt uintptr) error {
+ if rc := sqlite3.Xsqlite3_finalize(c.tls, pstmt); rc != sqlite3.SQLITE_OK {
+ return c.errstr(rc)
+ }
+
+ return nil
+}
+
+// C documentation
+//
+// int sqlite3_prepare_v2(
+// sqlite3 *db, /* Database handle */
+// const char *zSql, /* SQL statement, UTF-8 encoded */
+// int nByte, /* Maximum length of zSql in bytes. */
+// sqlite3_stmt **ppStmt, /* OUT: Statement handle */
+// const char **pzTail /* OUT: Pointer to unused portion of zSql */
+// );
+func (c *conn) prepareV2(zSQL *uintptr) (pstmt uintptr, err error) {
+ var ppstmt, pptail uintptr
+
+ defer func() {
+ c.free(ppstmt)
+ c.free(pptail)
+ }()
+
+ if ppstmt, err = c.malloc(int(ptrSize)); err != nil {
+ return 0, err
+ }
+
+ if pptail, err = c.malloc(int(ptrSize)); err != nil {
+ return 0, err
+ }
+
+ for {
+ // https://gitlab.com/cznic/sqlite/-/issues/236
+ // trc("Xsqlite3_prepare_v2(`%s`)", libc.GoString(*zSQL))
+ switch rc := sqlite3.Xsqlite3_prepare_v2(c.tls, c.db, *zSQL, -1, ppstmt, pptail); rc {
+ case sqlite3.SQLITE_OK:
+ *zSQL = *(*uintptr)(unsafe.Pointer(pptail))
+ return *(*uintptr)(unsafe.Pointer(ppstmt)), nil
+ case sqliteLockedSharedcache:
+ if err := c.retry(0); err != nil {
+ return 0, err
+ }
+ default:
+ return 0, c.errstr(rc)
+ }
+ }
+}
+
+// C documentation
+//
+// void sqlite3_interrupt(sqlite3*);
+func (c *conn) interrupt(pdb uintptr) (err error) {
+ c.Lock() // Defend against race with .Close invoked by context handling.
+
+ defer c.Unlock()
+
+ if c.tls != nil {
+ sqlite3.Xsqlite3_interrupt(c.tls, pdb)
+ }
+ return nil
+}
+
+// C documentation
+//
+// int sqlite3_extended_result_codes(sqlite3*, int onoff);
+func (c *conn) extendedResultCodes(on bool) error {
+ if rc := sqlite3.Xsqlite3_extended_result_codes(c.tls, c.db, libc.Bool32(on)); rc != sqlite3.SQLITE_OK {
+ return c.errstr(rc)
+ }
+
+ return nil
+}
+
+// C documentation
+//
+// int sqlite3_open_v2(
+// const char *filename, /* Database filename (UTF-8) */
+// sqlite3 **ppDb, /* OUT: SQLite db handle */
+// int flags, /* Flags */
+// const char *zVfs /* Name of VFS module to use */
+// );
+func (c *conn) openV2(name, vfsName string, flags int32) (uintptr, error) {
+ var p, s, vfs uintptr
+
+ defer func() {
+ if p != 0 {
+ c.free(p)
+ }
+ if s != 0 {
+ c.free(s)
+ }
+ if vfs != 0 {
+ c.free(vfs)
+ }
+ }()
+
+ p, err := c.malloc(int(ptrSize))
+ if err != nil {
+ return 0, err
+ }
+
+ if s, err = libc.CString(name); err != nil {
+ return 0, err
+ }
+
+ if vfsName != "" {
+ if vfs, err = libc.CString(vfsName); err != nil {
+ return 0, err
+ }
+ }
+
+ if rc := sqlite3.Xsqlite3_open_v2(c.tls, s, p, flags, vfs); rc != sqlite3.SQLITE_OK {
+ return 0, c.errstr(rc)
+ }
+
+ return *(*uintptr)(unsafe.Pointer(p)), nil
+}
+
+func (c *conn) malloc(n int) (uintptr, error) {
+ if p := libc.Xmalloc(c.tls, types.Size_t(n)); p != 0 || n == 0 {
+ return p, nil
+ }
+
+ return 0, fmt.Errorf("sqlite: cannot allocate %d bytes of memory", n)
+}
+
+func (c *conn) free(p uintptr) {
+ if p != 0 {
+ libc.Xfree(c.tls, p)
+ }
+}
+
+// C documentation
+//
+// const char *sqlite3_errstr(int);
+func (c *conn) errstr(rc int32) error {
+ p := sqlite3.Xsqlite3_errstr(c.tls, rc)
+ str := libc.GoString(p)
+ p = sqlite3.Xsqlite3_errmsg(c.tls, c.db)
+ var s string
+ if rc == sqlite3.SQLITE_BUSY {
+ s = " (SQLITE_BUSY)"
+ }
+ switch msg := libc.GoString(p); {
+ case msg == str:
+ return &Error{msg: fmt.Sprintf("%s (%v)%s", str, rc, s), code: int(rc)}
+ default:
+ return &Error{msg: fmt.Sprintf("%s: %s (%v)%s", str, msg, rc, s), code: int(rc)}
+ }
+}
+
+// Begin starts a transaction.
+//
+// Deprecated: Drivers should implement ConnBeginTx instead (or additionally).
+func (c *conn) Begin() (dt driver.Tx, err error) {
+ if dmesgs {
+ defer func() {
+ dmesg("conn %p: (driver.Tx %p, err %v)", c, dt, err)
+ }()
+ }
+ return c.begin(context.Background(), driver.TxOptions{})
+}
+
+func (c *conn) begin(ctx context.Context, opts driver.TxOptions) (t driver.Tx, err error) {
+ return newTx(ctx, c, opts)
+}
+
+// Close invalidates and potentially stops any current prepared statements and
+// transactions, marking this connection as no longer in use.
+//
+// Because the sql package maintains a free pool of connections and only calls
+// Close when there's a surplus of idle connections, it shouldn't be necessary
+// for drivers to do their own connection caching.
+func (c *conn) Close() (err error) {
+ if dmesgs {
+ defer func() {
+ dmesg("conn %p: err %v", c, err)
+ }()
+ }
+ c.Lock() // Defend against race with .interrupt invoked by context handling.
+
+ defer c.Unlock()
+
+ if c.db != 0 {
+ if err := c.closeV2(c.db); err != nil {
+ return err
+ }
+
+ c.db = 0
+ }
+
+ if c.tls != nil {
+ c.tls.Close()
+ c.tls = nil
+ }
+ return nil
+}
+
+// C documentation
+//
+// int sqlite3_close_v2(sqlite3*);
+func (c *conn) closeV2(db uintptr) error {
+ if rc := sqlite3.Xsqlite3_close_v2(c.tls, db); rc != sqlite3.SQLITE_OK {
+ return c.errstr(rc)
+ }
+
+ return nil
+}
+
+// ResetSession is called prior to executing a query on the connection if the
+// connection has been used before. If the driver returns ErrBadConn the
+// connection is discarded.
+func (c *conn) ResetSession(ctx context.Context) error {
+ if !c.usable() {
+ return driver.ErrBadConn
+ }
+
+ return nil
+}
+
+// IsValid is called prior to placing the connection into the connection pool.
+// The connection will be discarded if false is returned.
+func (c *conn) IsValid() bool {
+ return c.usable()
+}
+
+func (c *conn) usable() bool {
+ return c.db != 0 && sqlite3.Xsqlite3_is_interrupted(c.tls, c.db) == 0
+}
+
+type userDefinedFunction struct {
+ zFuncName uintptr
+ nArg int32
+ eTextRep int32
+ pApp uintptr
+
+ scalar bool
+ freeOnce sync.Once
+}
+
+func (c *conn) createFunctionInternal(fun *userDefinedFunction) error {
+ var rc int32
+
+ if fun.scalar {
+ rc = sqlite3.Xsqlite3_create_function(
+ c.tls,
+ c.db,
+ fun.zFuncName,
+ fun.nArg,
+ fun.eTextRep,
+ fun.pApp,
+ cFuncPointer(funcTrampoline),
+ 0,
+ 0,
+ )
+ } else {
+ rc = sqlite3.Xsqlite3_create_window_function(
+ c.tls,
+ c.db,
+ fun.zFuncName,
+ fun.nArg,
+ fun.eTextRep,
+ fun.pApp,
+ cFuncPointer(stepTrampoline),
+ cFuncPointer(finalTrampoline),
+ cFuncPointer(valueTrampoline),
+ cFuncPointer(inverseTrampoline),
+ 0,
+ )
+ }
+
+ if rc != sqlite3.SQLITE_OK {
+ return c.errstr(rc)
+ }
+ return nil
+}
+
+func (c *conn) createCollationInternal(coll *collation) error {
+ rc := sqlite3.Xsqlite3_create_collation_v2(
+ c.tls,
+ c.db,
+ coll.zName,
+ coll.enc,
+ coll.pApp,
+ cFuncPointer(collationTrampoline),
+ 0,
+ )
+ if rc != sqlite3.SQLITE_OK {
+ return c.errstr(rc)
+ }
+ return nil
+}
+
+// Execer is an optional interface that may be implemented by a Conn.
+//
+// If a Conn does not implement Execer, the sql package's DB.Exec will first
+// prepare a query, execute the statement, and then close the statement.
+//
+// Exec may return ErrSkip.
+//
+// Deprecated: Drivers should implement ExecerContext instead.
+func (c *conn) Exec(query string, args []driver.Value) (dr driver.Result, err error) {
+ if dmesgs {
+ defer func() {
+ dmesg("conn %p, query %q, args %v: (driver.Result %p, err %v)", c, query, args, dr, err)
+ }()
+ }
+ return c.exec(context.Background(), query, toNamedValues(args))
+}
+
+func (c *conn) exec(ctx context.Context, query string, args []driver.NamedValue) (r driver.Result, err error) {
+ s, err := c.prepare(ctx, query)
+ if err != nil {
+ return nil, err
+ }
+
+ defer func() {
+ if err2 := s.Close(); err2 != nil && err == nil {
+ err = err2
+ }
+ }()
+
+ return s.(*stmt).exec(ctx, args)
+}
+
+// Prepare returns a prepared statement, bound to this connection.
+func (c *conn) Prepare(query string) (ds driver.Stmt, err error) {
+ if dmesgs {
+ defer func() {
+ dmesg("conn %p, query %q: (driver.Stmt %p, err %v)", c, query, ds, err)
+ }()
+ }
+ return c.prepare(context.Background(), query)
+}
+
+func (c *conn) prepare(ctx context.Context, query string) (s driver.Stmt, err error) {
+ //TODO use ctx
+ return newStmt(c, query)
+}
+
+// Queryer is an optional interface that may be implemented by a Conn.
+//
+// If a Conn does not implement Queryer, the sql package's DB.Query will first
+// prepare a query, execute the statement, and then close the statement.
+//
+// Query may return ErrSkip.
+//
+// Deprecated: Drivers should implement QueryerContext instead.
+func (c *conn) Query(query string, args []driver.Value) (dr driver.Rows, err error) {
+ if dmesgs {
+ defer func() {
+ dmesg("conn %p, query %q, args %v: (driver.Rows %p, err %v)", c, query, args, dr, err)
+ }()
+ }
+ return c.query(context.Background(), query, toNamedValues(args))
+}
+
+func (c *conn) query(ctx context.Context, query string, args []driver.NamedValue) (r driver.Rows, err error) {
+ // Use newStmt directly. c.prepare wraps this, but we need the concrete *stmt type
+ // to manipulate the handle ownership below.
+ s, err := newStmt(c, query)
+ if err != nil {
+ return nil, err
+ }
+
+ r, err = s.query(ctx, args)
+ if err != nil {
+ s.Close()
+ return nil, err
+ }
+
+ // Fix for TestIssue118 / One-Shot Query Crash:
+ // If the statement was cached (optimized path in newStmt), s.pstmt is valid.
+ // s.query() sets r.reuseStmt = true by default for cached statements.
+ //
+ // However, since this is a transient statement created just for this query (db.Query),
+ // s.Close() will be called immediately below. We must transfer ownership of the
+ // sqlite statement handle to the rows object so it isn't finalized yet.
+ if s.pstmt != 0 {
+ // Steal the handle from the statement so s.Close() doesn't finalize it.
+ s.pstmt = 0
+
+ // Instruct rows to finalize the statement when done, rather than resetting it.
+ r.(*rows).reuseStmt = false
+ }
+
+ // s.Close() now only frees the C-string allocation (psql), skipping the pstmt finalize
+ // because we set s.pstmt to 0.
+ if err := s.Close(); err != nil {
+ r.Close()
+ return nil, err
+ }
+
+ return r, nil
+}
+
+// Serialize returns a serialization of the main database. For an ordinary on-disk
+// database file, the serialization is just a copy of the disk file. For an in-memory
+// database or a "TEMP" database, the serialization is the same sequence of bytes
+// which would be written to disk if that database where backed up to disk.
+func (c *conn) Serialize() (v []byte, err error) {
+ pLen := c.tls.Alloc(8)
+ defer c.tls.Free(8)
+
+ zSchema := sqlite3.Xsqlite3_db_name(c.tls, c.db, 0)
+ if zSchema == 0 {
+ return nil, fmt.Errorf("failed to get main db name")
+ }
+
+ pBuf := sqlite3.Xsqlite3_serialize(c.tls, c.db, zSchema, pLen, 0)
+ bufLen := *(*sqlite3.Sqlite3_int64)(unsafe.Pointer(pLen))
+ if pBuf != 0 {
+ defer sqlite3.Xsqlite3_free(c.tls, pBuf)
+ }
+ if bufLen <= 0 {
+ return nil, fmt.Errorf("invalid length returned: %d", bufLen)
+ } else if pBuf == 0 || bufLen == 0 {
+ return nil, nil
+ }
+
+ v = make([]byte, bufLen)
+ copy(v, (*libc.RawMem)(unsafe.Pointer(pBuf))[:bufLen:bufLen])
+ return v, nil
+}
+
+// Deserialize restore a database from the content returned by Serialize.
+func (c *conn) Deserialize(buf []byte) (err error) {
+ bufLen := len(buf)
+ pBuf := c.tls.Alloc(bufLen) // free will be done if it fails or on close, must not be freed here
+
+ copy((*libc.RawMem)(unsafe.Pointer(pBuf))[:bufLen:bufLen], buf)
+
+ zSchema := sqlite3.Xsqlite3_db_name(c.tls, c.db, 0)
+ if zSchema == 0 {
+ return fmt.Errorf("failed to get main db name")
+ }
+
+ rc := sqlite3.Xsqlite3_deserialize(c.tls, c.db, zSchema, pBuf, int64(bufLen), int64(bufLen), sqlite3.SQLITE_DESERIALIZE_RESIZEABLE|sqlite3.SQLITE_DESERIALIZE_FREEONCLOSE)
+ if rc != sqlite3.SQLITE_OK {
+ return c.errstr(rc)
+ }
+ return nil
+}
+
+// NewBackup returns a Backup object that will create an online backup of
+// current database to the databased pointed by the passed URI.
+func (c *conn) NewBackup(dstUri string) (*Backup, error) {
+ dstConn, err := newConn(dstUri)
+ if err != nil {
+ return nil, err
+ }
+ backup, err := c.backup(dstConn, false)
+ if err != nil {
+ dstConn.Close()
+ }
+ return backup, err
+}
+
+// NewRestore returns a Backup object that will restore a backup to current
+// database from the databased pointed by the passed URI.
+func (c *conn) NewRestore(srcUri string) (*Backup, error) {
+ srcConn, err := newConn(srcUri)
+ if err != nil {
+ return nil, err
+ }
+ backup, err := c.backup(srcConn, true)
+ if err != nil {
+ srcConn.Close()
+ }
+ return backup, err
+}
+
+func (c *conn) backup(remoteConn *conn, restore bool) (_ *Backup, finalErr error) {
+ srcSchema := sqlite3.Xsqlite3_db_name(c.tls, c.db, 0)
+ if srcSchema == 0 {
+ return nil, fmt.Errorf("failed to get main source db name")
+ }
+
+ dstSchema := sqlite3.Xsqlite3_db_name(remoteConn.tls, remoteConn.db, 0)
+ if dstSchema == 0 {
+ return nil, fmt.Errorf("failed to get main destination db name")
+ }
+
+ var pBackup uintptr
+ if restore {
+ pBackup = sqlite3.Xsqlite3_backup_init(c.tls, c.db, srcSchema, remoteConn.db, dstSchema)
+ } else {
+ pBackup = sqlite3.Xsqlite3_backup_init(c.tls, remoteConn.db, dstSchema, c.db, srcSchema)
+ }
+ if pBackup <= 0 {
+ rc := sqlite3.Xsqlite3_errcode(c.tls, remoteConn.db)
+ return nil, c.errstr(rc)
+ }
+
+ return &Backup{srcConn: c, dstConn: remoteConn, pBackup: pBackup}, nil
+}
+
+// C documentation
+//
+// int sqlite3_limit(sqlite3*, int id, int newVal);
+func (c *conn) limit(id int, newVal int) int {
+ return int(sqlite3.Xsqlite3_limit(c.tls, c.db, int32(id), int32(newVal)))
+}
+
+// C documentation
+//
+// int sqlite3_bind_blob(sqlite3_stmt*, int, const void*, int n, void(*)(void*));
+func (c *conn) bindBlob(pstmt uintptr, idx1 int, value []byte) (uintptr, error) {
+ if value == nil {
+ if rc := sqlite3.Xsqlite3_bind_null(c.tls, pstmt, int32(idx1)); rc != sqlite3.SQLITE_OK {
+ return 0, c.errstr(rc)
+ }
+ return 0, nil
+ }
+
+ p, err := c.malloc(len(value))
+ if err != nil {
+ return 0, err
+ }
+ if len(value) != 0 {
+ copy((*libc.RawMem)(unsafe.Pointer(p))[:len(value):len(value)], value)
+ }
+ if rc := sqlite3.Xsqlite3_bind_blob(c.tls, pstmt, int32(idx1), p, int32(len(value)), 0); rc != sqlite3.SQLITE_OK {
+ c.free(p)
+ return 0, c.errstr(rc)
+ }
+
+ return p, nil
+}
+
+// Ping implements driver.Pinger
+func (c *conn) Ping(ctx context.Context) (err error) {
+ if dmesgs {
+ defer func() {
+ dmesg("conn %p, ctx %p: err %v", c, ctx, err)
+ }()
+ }
+ _, err = c.ExecContext(ctx, "select 1", nil)
+ return err
+}
+
+// BeginTx implements driver.ConnBeginTx
+func (c *conn) BeginTx(ctx context.Context, opts driver.TxOptions) (dt driver.Tx, err error) {
+ if dmesgs {
+ defer func() {
+ dmesg("conn %p, ctx %p, opts %+v: (driver.Tx %v, err %v)", c, ctx, opts, dt, err)
+ }()
+ }
+ return c.begin(ctx, opts)
+}
+
+// PrepareContext implements driver.ConnPrepareContext
+func (c *conn) PrepareContext(ctx context.Context, query string) (ds driver.Stmt, err error) {
+ if dmesgs {
+ defer func() {
+ dmesg("conn %p, ctx %p, query %q: (driver.Stmt %v, err %v)", c, ctx, query, ds, err)
+ }()
+ }
+ return c.prepare(ctx, query)
+}
+
+// ExecContext implements driver.ExecerContext
+func (c *conn) ExecContext(ctx context.Context, query string, args []driver.NamedValue) (dr driver.Result, err error) {
+ if dmesgs {
+ defer func() {
+ dmesg("conn %p, ctx %p, query %q, args %v: (driver.Result %p, err %v)", c, ctx, query, args, dr, err)
+ }()
+ }
+ return c.exec(ctx, query, args)
+}
+
+// QueryContext implements driver.QueryerContext
+func (c *conn) QueryContext(ctx context.Context, query string, args []driver.NamedValue) (dr driver.Rows, err error) {
+ if dmesgs {
+ defer func() {
+ dmesg("conn %p, ctx %p, query %q, args %v: (driver.Rows %p, err %v)", c, ctx, query, args, dr, err)
+ }()
+ }
+ return c.query(ctx, query, args)
+}
diff --git a/vendor/modernc.org/sqlite/doc.go b/vendor/modernc.org/sqlite/doc.go
index 34c1037..4d58eb2 100644
--- a/vendor/modernc.org/sqlite/doc.go
+++ b/vendor/modernc.org/sqlite/doc.go
@@ -58,7 +58,7 @@
// - 2025-10-10 v1.39.1: Upgrade to SQLite 3.50.4.
//
// - 2025-06-09 v1.38.0: Upgrade to SQLite 3.50.1.
-//
+//
// - 2025-02-26 v1.36.0: Upgrade to SQLite 3.49.0.
//
// - 2024-11-16 v1.34.0: Implement ResetSession and IsValid methods in connection
diff --git a/vendor/modernc.org/sqlite/driver.go b/vendor/modernc.org/sqlite/driver.go
new file mode 100644
index 0000000..0421200
--- /dev/null
+++ b/vendor/modernc.org/sqlite/driver.go
@@ -0,0 +1,120 @@
+// Copyright 2025 The Sqlite Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package sqlite // import "modernc.org/sqlite"
+
+import (
+ "database/sql/driver"
+ "fmt"
+
+ "modernc.org/sqlite/vtab"
+)
+
+// Driver implements database/sql/driver.Driver.
+type Driver struct {
+ // user defined functions that are added to every new connection on Open
+ udfs map[string]*userDefinedFunction
+ // collations that are added to every new connection on Open
+ collations map[string]*collation
+ // connection hooks are called after a connection is opened
+ connectionHooks []ConnectionHookFn
+ // modules holds registered virtual table modules that should be added to
+ // every new connection on Open.
+ modules map[string]vtab.Module
+}
+
+var d = &Driver{
+ udfs: make(map[string]*userDefinedFunction, 0),
+ collations: make(map[string]*collation, 0),
+ connectionHooks: make([]ConnectionHookFn, 0),
+ modules: make(map[string]vtab.Module, 0),
+}
+
+func newDriver() *Driver { return d }
+
+// Open returns a new connection to the database. The name is a string in a
+// driver-specific format.
+//
+// Open may return a cached connection (one previously closed), but doing so is
+// unnecessary; the sql package maintains a pool of idle connections for
+// efficient re-use.
+//
+// The returned connection is only used by one goroutine at a time.
+//
+// The name may be a filename, e.g., "/tmp/mydata.sqlite", or a URI, in which
+// case it may include a '?' followed by one or more query parameters.
+// For example, "file:///tmp/mydata.sqlite?_pragma=foreign_keys(1)&_time_format=sqlite".
+// The supported query parameters are:
+//
+// _pragma: Each value will be run as a "PRAGMA ..." statement (with the PRAGMA
+// keyword added for you). May be specified more than once, '&'-separated. For more
+// information on supported PRAGMAs see: https://www.sqlite.org/pragma.html
+//
+// _time_format: The name of a format to use when writing time values to the
+// database. Currently the only supported value is "sqlite", which corresponds
+// to format 7 from https://www.sqlite.org/lang_datefunc.html#time_values,
+// including the timezone specifier. If this parameter is not specified, then
+// the default String() format will be used.
+//
+// _time_integer_format: The name of a integer format to use when writing time values.
+// By default, the time is stored as string and the format can be set with _time_format
+// parameter. If _time_integer_format is set, the time will be stored as an integer and
+// the integer value will depend on the integer format.
+// If you decide to set both _time_format and _time_integer_format, the time will be
+// converted as integer and the _time_format value will be ignored.
+// Currently the supported value are "unix","unix_milli", "unix_micro" and "unix_nano",
+// which corresponds to seconds, milliseconds, microseconds or nanoseconds
+// since unixepoch (1 January 1970 00:00:00 UTC).
+//
+// _inttotime: Enable conversion of time column (DATE, DATETIME,TIMESTAMP) from integer
+// to time if the field contain integer (int64).
+//
+// _txlock: The locking behavior to use when beginning a transaction. May be
+// "deferred" (the default), "immediate", or "exclusive" (case insensitive). See:
+// https://www.sqlite.org/lang_transaction.html#deferred_immediate_and_exclusive_transactions
+func (d *Driver) Open(name string) (conn driver.Conn, err error) {
+ if dmesgs {
+ defer func() {
+ dmesg("name %q: (driver.Conn %p, err %v)", name, conn, err)
+ }()
+ }
+ c, err := newConn(name)
+ if err != nil {
+ return nil, err
+ }
+
+ for _, udf := range d.udfs {
+ if err = c.createFunctionInternal(udf); err != nil {
+ c.Close()
+ return nil, err
+ }
+ }
+ for _, coll := range d.collations {
+ if err = c.createCollationInternal(coll); err != nil {
+ c.Close()
+ return nil, err
+ }
+ }
+ for _, connHookFn := range d.connectionHooks {
+ if err = connHookFn(c, name); err != nil {
+ c.Close()
+ return nil, fmt.Errorf("connection hook: %w", err)
+ }
+ }
+ // Register any vtab modules with this connection.
+ // Note: vtab module registration applies to new connections only. If a
+ // module is registered after a connection has been opened, that existing
+ // connection will not see the module; open a new connection to use it.
+ if err := c.registerModules(); err != nil {
+ c.Close()
+ return nil, err
+ }
+ return c, nil
+}
+
+// RegisterConnectionHook registers a function to be called after each connection
+// is opened. This is called after all the connection has been set up.
+func (d *Driver) RegisterConnectionHook(fn ConnectionHookFn) {
+ d.connectionHooks = append(d.connectionHooks, fn)
+}
diff --git a/vendor/modernc.org/sqlite/error.go b/vendor/modernc.org/sqlite/error.go
new file mode 100644
index 0000000..a4f42f6
--- /dev/null
+++ b/vendor/modernc.org/sqlite/error.go
@@ -0,0 +1,75 @@
+// Copyright 2025 The Sqlite Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package sqlite // import "modernc.org/sqlite"
+
+import (
+ sqlite3 "modernc.org/sqlite/lib"
+)
+
+// Error represents sqlite library error code.
+type Error struct {
+ msg string
+ code int
+}
+
+// Error implements error.
+func (e *Error) Error() string { return e.msg }
+
+// Code returns the sqlite result code for this error.
+func (e *Error) Code() int { return e.code }
+
+var (
+ // ErrorCodeString maps Error.Code() to its string representation.
+ ErrorCodeString = map[int]string{
+ sqlite3.SQLITE_ABORT: "Callback routine requested an abort (SQLITE_ABORT)",
+ sqlite3.SQLITE_AUTH: "Authorization denied (SQLITE_AUTH)",
+ sqlite3.SQLITE_BUSY: "The database file is locked (SQLITE_BUSY)",
+ sqlite3.SQLITE_CANTOPEN: "Unable to open the database file (SQLITE_CANTOPEN)",
+ sqlite3.SQLITE_CONSTRAINT: "Abort due to constraint violation (SQLITE_CONSTRAINT)",
+ sqlite3.SQLITE_CORRUPT: "The database disk image is malformed (SQLITE_CORRUPT)",
+ sqlite3.SQLITE_DONE: "sqlite3_step() has finished executing (SQLITE_DONE)",
+ sqlite3.SQLITE_EMPTY: "Internal use only (SQLITE_EMPTY)",
+ sqlite3.SQLITE_ERROR: "Generic error (SQLITE_ERROR)",
+ sqlite3.SQLITE_FORMAT: "Not used (SQLITE_FORMAT)",
+ sqlite3.SQLITE_FULL: "Insertion failed because database is full (SQLITE_FULL)",
+ sqlite3.SQLITE_INTERNAL: "Internal logic error in SQLite (SQLITE_INTERNAL)",
+ sqlite3.SQLITE_INTERRUPT: "Operation terminated by sqlite3_interrupt()(SQLITE_INTERRUPT)",
+ sqlite3.SQLITE_IOERR | (1 << 8): "(SQLITE_IOERR_READ)",
+ sqlite3.SQLITE_IOERR | (10 << 8): "(SQLITE_IOERR_DELETE)",
+ sqlite3.SQLITE_IOERR | (11 << 8): "(SQLITE_IOERR_BLOCKED)",
+ sqlite3.SQLITE_IOERR | (12 << 8): "(SQLITE_IOERR_NOMEM)",
+ sqlite3.SQLITE_IOERR | (13 << 8): "(SQLITE_IOERR_ACCESS)",
+ sqlite3.SQLITE_IOERR | (14 << 8): "(SQLITE_IOERR_CHECKRESERVEDLOCK)",
+ sqlite3.SQLITE_IOERR | (15 << 8): "(SQLITE_IOERR_LOCK)",
+ sqlite3.SQLITE_IOERR | (16 << 8): "(SQLITE_IOERR_CLOSE)",
+ sqlite3.SQLITE_IOERR | (17 << 8): "(SQLITE_IOERR_DIR_CLOSE)",
+ sqlite3.SQLITE_IOERR | (2 << 8): "(SQLITE_IOERR_SHORT_READ)",
+ sqlite3.SQLITE_IOERR | (3 << 8): "(SQLITE_IOERR_WRITE)",
+ sqlite3.SQLITE_IOERR | (4 << 8): "(SQLITE_IOERR_FSYNC)",
+ sqlite3.SQLITE_IOERR | (5 << 8): "(SQLITE_IOERR_DIR_FSYNC)",
+ sqlite3.SQLITE_IOERR | (6 << 8): "(SQLITE_IOERR_TRUNCATE)",
+ sqlite3.SQLITE_IOERR | (7 << 8): "(SQLITE_IOERR_FSTAT)",
+ sqlite3.SQLITE_IOERR | (8 << 8): "(SQLITE_IOERR_UNLOCK)",
+ sqlite3.SQLITE_IOERR | (9 << 8): "(SQLITE_IOERR_RDLOCK)",
+ sqlite3.SQLITE_IOERR: "Some kind of disk I/O error occurred (SQLITE_IOERR)",
+ sqlite3.SQLITE_LOCKED | (1 << 8): "(SQLITE_LOCKED_SHAREDCACHE)",
+ sqlite3.SQLITE_LOCKED: "A table in the database is locked (SQLITE_LOCKED)",
+ sqlite3.SQLITE_MISMATCH: "Data type mismatch (SQLITE_MISMATCH)",
+ sqlite3.SQLITE_MISUSE: "Library used incorrectly (SQLITE_MISUSE)",
+ sqlite3.SQLITE_NOLFS: "Uses OS features not supported on host (SQLITE_NOLFS)",
+ sqlite3.SQLITE_NOMEM: "A malloc() failed (SQLITE_NOMEM)",
+ sqlite3.SQLITE_NOTADB: "File opened that is not a database file (SQLITE_NOTADB)",
+ sqlite3.SQLITE_NOTFOUND: "Unknown opcode in sqlite3_file_control() (SQLITE_NOTFOUND)",
+ sqlite3.SQLITE_NOTICE: "Notifications from sqlite3_log() (SQLITE_NOTICE)",
+ sqlite3.SQLITE_PERM: "Access permission denied (SQLITE_PERM)",
+ sqlite3.SQLITE_PROTOCOL: "Database lock protocol error (SQLITE_PROTOCOL)",
+ sqlite3.SQLITE_RANGE: "2nd parameter to sqlite3_bind out of range (SQLITE_RANGE)",
+ sqlite3.SQLITE_READONLY: "Attempt to write a readonly database (SQLITE_READONLY)",
+ sqlite3.SQLITE_ROW: "sqlite3_step() has another row ready (SQLITE_ROW)",
+ sqlite3.SQLITE_SCHEMA: "The database schema changed (SQLITE_SCHEMA)",
+ sqlite3.SQLITE_TOOBIG: "String or BLOB exceeds size limit (SQLITE_TOOBIG)",
+ sqlite3.SQLITE_WARNING: "Warnings from sqlite3_log() (SQLITE_WARNING)",
+ }
+)
diff --git a/vendor/modernc.org/sqlite/lib/sqlite_darwin_amd64.go b/vendor/modernc.org/sqlite/lib/sqlite_darwin_amd64.go
index 1079f5f..847d6a7 100644
--- a/vendor/modernc.org/sqlite/lib/sqlite_darwin_amd64.go
+++ b/vendor/modernc.org/sqlite/lib/sqlite_darwin_amd64.go
@@ -227735,4 +227735,3 @@ type Sqlite3_index_info = sqlite3_index_info
type Sqlite3_module = sqlite3_module
type Sqlite3_vtab = sqlite3_vtab
type Sqlite3_vtab_cursor = sqlite3_vtab_cursor
-
diff --git a/vendor/modernc.org/sqlite/lib/sqlite_darwin_arm64.go b/vendor/modernc.org/sqlite/lib/sqlite_darwin_arm64.go
index 6a63273..df82bb9 100644
--- a/vendor/modernc.org/sqlite/lib/sqlite_darwin_arm64.go
+++ b/vendor/modernc.org/sqlite/lib/sqlite_darwin_arm64.go
@@ -227308,4 +227308,3 @@ type Sqlite3_index_info = sqlite3_index_info
type Sqlite3_module = sqlite3_module
type Sqlite3_vtab = sqlite3_vtab
type Sqlite3_vtab_cursor = sqlite3_vtab_cursor
-
diff --git a/vendor/modernc.org/sqlite/lib/sqlite_freebsd_amd64.go b/vendor/modernc.org/sqlite/lib/sqlite_freebsd_amd64.go
index ffb049e..d553a52 100644
--- a/vendor/modernc.org/sqlite/lib/sqlite_freebsd_amd64.go
+++ b/vendor/modernc.org/sqlite/lib/sqlite_freebsd_amd64.go
@@ -221564,4 +221564,3 @@ type Sqlite3_index_info = sqlite3_index_info
type Sqlite3_module = sqlite3_module
type Sqlite3_vtab = sqlite3_vtab
type Sqlite3_vtab_cursor = sqlite3_vtab_cursor
-
diff --git a/vendor/modernc.org/sqlite/lib/sqlite_freebsd_arm64.go b/vendor/modernc.org/sqlite/lib/sqlite_freebsd_arm64.go
index e32db26..238f333 100644
--- a/vendor/modernc.org/sqlite/lib/sqlite_freebsd_arm64.go
+++ b/vendor/modernc.org/sqlite/lib/sqlite_freebsd_arm64.go
@@ -221577,4 +221577,3 @@ type Sqlite3_index_info = sqlite3_index_info
type Sqlite3_module = sqlite3_module
type Sqlite3_vtab = sqlite3_vtab
type Sqlite3_vtab_cursor = sqlite3_vtab_cursor
-
diff --git a/vendor/modernc.org/sqlite/lib/sqlite_linux_386.go b/vendor/modernc.org/sqlite/lib/sqlite_linux_386.go
index 8b34111..ce1dd56 100644
--- a/vendor/modernc.org/sqlite/lib/sqlite_linux_386.go
+++ b/vendor/modernc.org/sqlite/lib/sqlite_linux_386.go
@@ -221713,4 +221713,3 @@ type Sqlite3_index_info = sqlite3_index_info
type Sqlite3_module = sqlite3_module
type Sqlite3_vtab = sqlite3_vtab
type Sqlite3_vtab_cursor = sqlite3_vtab_cursor
-
diff --git a/vendor/modernc.org/sqlite/lib/sqlite_linux_amd64.go b/vendor/modernc.org/sqlite/lib/sqlite_linux_amd64.go
index 0f3932a..b67cafd 100644
--- a/vendor/modernc.org/sqlite/lib/sqlite_linux_amd64.go
+++ b/vendor/modernc.org/sqlite/lib/sqlite_linux_amd64.go
@@ -221726,4 +221726,3 @@ type Sqlite3_index_info = sqlite3_index_info
type Sqlite3_module = sqlite3_module
type Sqlite3_vtab = sqlite3_vtab
type Sqlite3_vtab_cursor = sqlite3_vtab_cursor
-
diff --git a/vendor/modernc.org/sqlite/lib/sqlite_linux_arm.go b/vendor/modernc.org/sqlite/lib/sqlite_linux_arm.go
index 17ccb37..877ac9b 100644
--- a/vendor/modernc.org/sqlite/lib/sqlite_linux_arm.go
+++ b/vendor/modernc.org/sqlite/lib/sqlite_linux_arm.go
@@ -222010,4 +222010,3 @@ type Sqlite3_index_info = sqlite3_index_info
type Sqlite3_module = sqlite3_module
type Sqlite3_vtab = sqlite3_vtab
type Sqlite3_vtab_cursor = sqlite3_vtab_cursor
-
diff --git a/vendor/modernc.org/sqlite/lib/sqlite_linux_arm64.go b/vendor/modernc.org/sqlite/lib/sqlite_linux_arm64.go
index 8d7fd60..b1c0f9c 100644
--- a/vendor/modernc.org/sqlite/lib/sqlite_linux_arm64.go
+++ b/vendor/modernc.org/sqlite/lib/sqlite_linux_arm64.go
@@ -221716,4 +221716,3 @@ type Sqlite3_index_info = sqlite3_index_info
type Sqlite3_module = sqlite3_module
type Sqlite3_vtab = sqlite3_vtab
type Sqlite3_vtab_cursor = sqlite3_vtab_cursor
-
diff --git a/vendor/modernc.org/sqlite/lib/sqlite_linux_loong64.go b/vendor/modernc.org/sqlite/lib/sqlite_linux_loong64.go
index 049a348..376d8b6 100644
--- a/vendor/modernc.org/sqlite/lib/sqlite_linux_loong64.go
+++ b/vendor/modernc.org/sqlite/lib/sqlite_linux_loong64.go
@@ -221815,4 +221815,3 @@ type Sqlite3_index_info = sqlite3_index_info
type Sqlite3_module = sqlite3_module
type Sqlite3_vtab = sqlite3_vtab
type Sqlite3_vtab_cursor = sqlite3_vtab_cursor
-
diff --git a/vendor/modernc.org/sqlite/lib/sqlite_linux_ppc64le.go b/vendor/modernc.org/sqlite/lib/sqlite_linux_ppc64le.go
index 8117bdf..d2012c7 100644
--- a/vendor/modernc.org/sqlite/lib/sqlite_linux_ppc64le.go
+++ b/vendor/modernc.org/sqlite/lib/sqlite_linux_ppc64le.go
@@ -221763,4 +221763,3 @@ type Sqlite3_index_info = sqlite3_index_info
type Sqlite3_module = sqlite3_module
type Sqlite3_vtab = sqlite3_vtab
type Sqlite3_vtab_cursor = sqlite3_vtab_cursor
-
diff --git a/vendor/modernc.org/sqlite/lib/sqlite_linux_riscv64.go b/vendor/modernc.org/sqlite/lib/sqlite_linux_riscv64.go
index f3a6bca..5eeb2fb 100644
--- a/vendor/modernc.org/sqlite/lib/sqlite_linux_riscv64.go
+++ b/vendor/modernc.org/sqlite/lib/sqlite_linux_riscv64.go
@@ -221709,4 +221709,3 @@ type Sqlite3_index_info = sqlite3_index_info
type Sqlite3_module = sqlite3_module
type Sqlite3_vtab = sqlite3_vtab
type Sqlite3_vtab_cursor = sqlite3_vtab_cursor
-
diff --git a/vendor/modernc.org/sqlite/lib/sqlite_linux_s390x.go b/vendor/modernc.org/sqlite/lib/sqlite_linux_s390x.go
index 9b766c8..4821927 100644
--- a/vendor/modernc.org/sqlite/lib/sqlite_linux_s390x.go
+++ b/vendor/modernc.org/sqlite/lib/sqlite_linux_s390x.go
@@ -221663,4 +221663,3 @@ type Sqlite3_index_info = sqlite3_index_info
type Sqlite3_module = sqlite3_module
type Sqlite3_vtab = sqlite3_vtab
type Sqlite3_vtab_cursor = sqlite3_vtab_cursor
-
diff --git a/vendor/modernc.org/sqlite/lib/sqlite_windows.go b/vendor/modernc.org/sqlite/lib/sqlite_windows.go
index 5b3a68f..2dd9f66 100644
--- a/vendor/modernc.org/sqlite/lib/sqlite_windows.go
+++ b/vendor/modernc.org/sqlite/lib/sqlite_windows.go
@@ -295017,4 +295017,3 @@ type Sqlite3_index_info = sqlite3_index_info
type Sqlite3_module = sqlite3_module
type Sqlite3_vtab = sqlite3_vtab
type Sqlite3_vtab_cursor = sqlite3_vtab_cursor
-
diff --git a/vendor/modernc.org/sqlite/lib/sqlite_windows_386.go b/vendor/modernc.org/sqlite/lib/sqlite_windows_386.go
index 4cdc532..0a65da1 100644
--- a/vendor/modernc.org/sqlite/lib/sqlite_windows_386.go
+++ b/vendor/modernc.org/sqlite/lib/sqlite_windows_386.go
@@ -294909,4 +294909,3 @@ type Sqlite3_index_info = sqlite3_index_info
type Sqlite3_module = sqlite3_module
type Sqlite3_vtab = sqlite3_vtab
type Sqlite3_vtab_cursor = sqlite3_vtab_cursor
-
diff --git a/vendor/modernc.org/sqlite/result.go b/vendor/modernc.org/sqlite/result.go
new file mode 100644
index 0000000..84ca991
--- /dev/null
+++ b/vendor/modernc.org/sqlite/result.go
@@ -0,0 +1,42 @@
+// Copyright 2025 The Sqlite Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package sqlite // import "modernc.org/sqlite"
+
+type result struct {
+ lastInsertID int64
+ rowsAffected int
+}
+
+func newResult(c *conn) (_ *result, err error) {
+ r := &result{}
+ if r.rowsAffected, err = c.changes(); err != nil {
+ return nil, err
+ }
+
+ if r.lastInsertID, err = c.lastInsertRowID(); err != nil {
+ return nil, err
+ }
+
+ return r, nil
+}
+
+// LastInsertId returns the database's auto-generated ID after, for example, an
+// INSERT into a table with primary key.
+func (r *result) LastInsertId() (int64, error) {
+ if r == nil {
+ return 0, nil
+ }
+
+ return r.lastInsertID, nil
+}
+
+// RowsAffected returns the number of rows affected by the query.
+func (r *result) RowsAffected() (int64, error) {
+ if r == nil {
+ return 0, nil
+ }
+
+ return int64(r.rowsAffected), nil
+}
diff --git a/vendor/modernc.org/sqlite/rows.go b/vendor/modernc.org/sqlite/rows.go
new file mode 100644
index 0000000..3da7031
--- /dev/null
+++ b/vendor/modernc.org/sqlite/rows.go
@@ -0,0 +1,282 @@
+// Copyright 2025 The Sqlite Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package sqlite // import "modernc.org/sqlite"
+
+import (
+ "database/sql/driver"
+ "fmt"
+ "io"
+ "math"
+ "reflect"
+ "strings"
+ "time"
+
+ sqlite3 "modernc.org/sqlite/lib"
+)
+
+type rows struct {
+ allocs []uintptr
+ c *conn
+ columns []string
+ pstmt uintptr
+
+ doStep bool
+ empty bool
+ reuseStmt bool // If true, Close() resets instead of finalizing
+}
+
+func newRows(c *conn, pstmt uintptr, allocs []uintptr, empty bool) (r *rows, err error) {
+ r = &rows{c: c, pstmt: pstmt, allocs: allocs, empty: empty}
+
+ defer func() {
+ if err != nil {
+ r.Close()
+ r = nil
+ }
+ }()
+
+ n, err := c.columnCount(pstmt)
+ if err != nil {
+ return nil, err
+ }
+
+ r.columns = make([]string, n)
+ for i := range r.columns {
+ if r.columns[i], err = r.c.columnName(pstmt, i); err != nil {
+ return nil, err
+ }
+ }
+
+ return r, nil
+}
+
+// Close closes the rows iterator.
+func (r *rows) Close() (err error) {
+ for _, v := range r.allocs {
+ r.c.free(v)
+ }
+ r.allocs = nil
+
+ if r.reuseStmt {
+ // Reset the statement for reuse instead of finalizing it
+ if e := r.c.reset(r.pstmt); e != nil {
+ return e
+ }
+ return r.c.clearBindings(r.pstmt)
+ }
+
+ return r.c.finalize(r.pstmt)
+}
+
+// Columns returns the names of the columns. The number of columns of the
+// result is inferred from the length of the slice. If a particular column name
+// isn't known, an empty string should be returned for that entry.
+func (r *rows) Columns() (c []string) {
+ return r.columns
+}
+
+// Next is called to populate the next row of data into the provided slice. The
+// provided slice will be the same size as the Columns() are wide.
+//
+// Next should return io.EOF when there are no more rows.
+func (r *rows) Next(dest []driver.Value) (err error) {
+ if r.empty {
+ return io.EOF
+ }
+
+ rc := sqlite3.SQLITE_ROW
+ if r.doStep {
+ if rc, err = r.c.step(r.pstmt); err != nil {
+ return err
+ }
+ }
+
+ r.doStep = true
+ switch rc {
+ case sqlite3.SQLITE_ROW:
+ if g, e := len(dest), len(r.columns); g != e {
+ return fmt.Errorf("sqlite: Next: have %v destination values, expected %v", g, e)
+ }
+
+ for i := range dest {
+ ct, err := r.c.columnType(r.pstmt, i)
+ if err != nil {
+ return err
+ }
+
+ switch ct {
+ case sqlite3.SQLITE_INTEGER:
+ v, err := r.c.columnInt64(r.pstmt, i)
+ if err != nil {
+ return err
+ }
+
+ if !r.c.intToTime {
+ dest[i] = v
+ } else {
+ // Inspired by mattn/go-sqlite3:
+ // https://github.com/mattn/go-sqlite3/blob/f76bae4b0044cbba8fb2c72b8e4559e8fbcffd86/sqlite3.go#L2254-L2262
+ // but we put make this compatibility optional behind a DSN
+ // query parameter, because this changes API behavior, so an
+ // opt-in is needed.
+ switch r.ColumnTypeDatabaseTypeName(i) {
+ case "DATE", "DATETIME", "TIMESTAMP":
+ // Is it a seconds timestamp or a milliseconds
+ // timestamp?
+ if v > 1e12 || v < -1e12 {
+ // time.Unix expects nanoseconds, but this is a
+ // milliseconds timestamp, so convert ms->ns.
+ v *= int64(time.Millisecond)
+ dest[i] = time.Unix(0, v).UTC()
+ } else {
+ dest[i] = time.Unix(v, 0)
+ }
+ default:
+ dest[i] = v
+ }
+ }
+ case sqlite3.SQLITE_FLOAT:
+ v, err := r.c.columnDouble(r.pstmt, i)
+ if err != nil {
+ return err
+ }
+
+ dest[i] = v
+ case sqlite3.SQLITE_TEXT:
+ v, err := r.c.columnText(r.pstmt, i)
+ if err != nil {
+ return err
+ }
+
+ switch r.ColumnTypeDatabaseTypeName(i) {
+ case "DATE", "DATETIME", "TIMESTAMP":
+ dest[i], _ = r.c.parseTime(v)
+ default:
+ dest[i] = v
+ }
+ case sqlite3.SQLITE_BLOB:
+ v, err := r.c.columnBlob(r.pstmt, i)
+ if err != nil {
+ return err
+ }
+
+ dest[i] = v
+ case sqlite3.SQLITE_NULL:
+ dest[i] = nil
+ default:
+ return fmt.Errorf("internal error: rc %d", rc)
+ }
+ }
+ return nil
+ case sqlite3.SQLITE_DONE:
+ return io.EOF
+ default:
+ return r.c.errstr(int32(rc))
+ }
+}
+
+// RowsColumnTypeDatabaseTypeName may be implemented by Rows. It should return
+// the database system type name without the length. Type names should be
+// uppercase. Examples of returned types: "VARCHAR", "NVARCHAR", "VARCHAR2",
+// "CHAR", "TEXT", "DECIMAL", "SMALLINT", "INT", "BIGINT", "BOOL", "[]BIGINT",
+// "JSONB", "XML", "TIMESTAMP".
+func (r *rows) ColumnTypeDatabaseTypeName(index int) string {
+ return strings.ToUpper(r.c.columnDeclType(r.pstmt, index))
+}
+
+// RowsColumnTypeLength may be implemented by Rows. It should return the length
+// of the column type if the column is a variable length type. If the column is
+// not a variable length type ok should return false. If length is not limited
+// other than system limits, it should return math.MaxInt64. The following are
+// examples of returned values for various types:
+//
+// TEXT (math.MaxInt64, true)
+// varchar(10) (10, true)
+// nvarchar(10) (10, true)
+// decimal (0, false)
+// int (0, false)
+// bytea(30) (30, true)
+func (r *rows) ColumnTypeLength(index int) (length int64, ok bool) {
+ t, err := r.c.columnType(r.pstmt, index)
+ if err != nil {
+ return 0, false
+ }
+
+ switch t {
+ case sqlite3.SQLITE_INTEGER:
+ return 0, false
+ case sqlite3.SQLITE_FLOAT:
+ return 0, false
+ case sqlite3.SQLITE_TEXT:
+ return math.MaxInt64, true
+ case sqlite3.SQLITE_BLOB:
+ return math.MaxInt64, true
+ case sqlite3.SQLITE_NULL:
+ return 0, false
+ default:
+ return 0, false
+ }
+}
+
+// RowsColumnTypeNullable may be implemented by Rows. The nullable value should
+// be true if it is known the column may be null, or false if the column is
+// known to be not nullable. If the column nullability is unknown, ok should be
+// false.
+func (r *rows) ColumnTypeNullable(index int) (nullable, ok bool) {
+ return true, true
+}
+
+// RowsColumnTypePrecisionScale may be implemented by Rows. It should return
+// the precision and scale for decimal types. If not applicable, ok should be
+// false. The following are examples of returned values for various types:
+//
+// decimal(38, 4) (38, 4, true)
+// int (0, 0, false)
+// decimal (math.MaxInt64, math.MaxInt64, true)
+func (r *rows) ColumnTypePrecisionScale(index int) (precision, scale int64, ok bool) {
+ return 0, 0, false
+}
+
+// RowsColumnTypeScanType may be implemented by Rows. It should return the
+// value type that can be used to scan types into. For example, the database
+// column type "bigint" this should return "reflect.TypeOf(int64(0))".
+func (r *rows) ColumnTypeScanType(index int) reflect.Type {
+ t, err := r.c.columnType(r.pstmt, index)
+ if err != nil {
+ return reflect.TypeOf("")
+ }
+
+ switch t {
+ case sqlite3.SQLITE_INTEGER:
+ switch strings.ToLower(r.c.columnDeclType(r.pstmt, index)) {
+ case "boolean":
+ return reflect.TypeOf(false)
+ case "date", "datetime", "time", "timestamp":
+ return reflect.TypeOf(time.Time{})
+ default:
+ return reflect.TypeOf(int64(0))
+ }
+ case sqlite3.SQLITE_FLOAT:
+ return reflect.TypeOf(float64(0))
+ case sqlite3.SQLITE_TEXT:
+ return reflect.TypeOf("")
+ case sqlite3.SQLITE_BLOB:
+ return reflect.TypeOf([]byte(nil))
+ case sqlite3.SQLITE_NULL:
+ return reflect.TypeOf(nil)
+ default:
+ return reflect.TypeOf("")
+ }
+}
+
+// C documentation
+//
+// int sqlite3_reset(sqlite3_stmt *pStmt);
+func (c *conn) reset(pstmt uintptr) error {
+ if rc := sqlite3.Xsqlite3_reset(c.tls, pstmt); rc != sqlite3.SQLITE_OK {
+ return c.errstr(rc)
+ }
+ return nil
+}
diff --git a/vendor/modernc.org/sqlite/sqlite.go b/vendor/modernc.org/sqlite/sqlite.go
index 01e6a03..d175293 100644
--- a/vendor/modernc.org/sqlite/sqlite.go
+++ b/vendor/modernc.org/sqlite/sqlite.go
@@ -12,11 +12,8 @@ import (
"database/sql/driver"
"errors"
"fmt"
- "io"
- "math"
"math/bits"
"net/url"
- "reflect"
"runtime"
"sort"
"strconv"
@@ -56,267 +53,10 @@ const (
sqliteLockedSharedcache = sqlite3.SQLITE_LOCKED | (1 << 8)
)
-// https://gitlab.com/cznic/sqlite/-/issues/199
-func init() {
- sqlite3.PatchIssue199()
-}
-
-// Error represents sqlite library error code.
-type Error struct {
- msg string
- code int
-}
-
-// Error implements error.
-func (e *Error) Error() string { return e.msg }
-
-// Code returns the sqlite result code for this error.
-func (e *Error) Code() int { return e.code }
-
-var (
- // ErrorCodeString maps Error.Code() to its string representation.
- ErrorCodeString = map[int]string{
- sqlite3.SQLITE_ABORT: "Callback routine requested an abort (SQLITE_ABORT)",
- sqlite3.SQLITE_AUTH: "Authorization denied (SQLITE_AUTH)",
- sqlite3.SQLITE_BUSY: "The database file is locked (SQLITE_BUSY)",
- sqlite3.SQLITE_CANTOPEN: "Unable to open the database file (SQLITE_CANTOPEN)",
- sqlite3.SQLITE_CONSTRAINT: "Abort due to constraint violation (SQLITE_CONSTRAINT)",
- sqlite3.SQLITE_CORRUPT: "The database disk image is malformed (SQLITE_CORRUPT)",
- sqlite3.SQLITE_DONE: "sqlite3_step() has finished executing (SQLITE_DONE)",
- sqlite3.SQLITE_EMPTY: "Internal use only (SQLITE_EMPTY)",
- sqlite3.SQLITE_ERROR: "Generic error (SQLITE_ERROR)",
- sqlite3.SQLITE_FORMAT: "Not used (SQLITE_FORMAT)",
- sqlite3.SQLITE_FULL: "Insertion failed because database is full (SQLITE_FULL)",
- sqlite3.SQLITE_INTERNAL: "Internal logic error in SQLite (SQLITE_INTERNAL)",
- sqlite3.SQLITE_INTERRUPT: "Operation terminated by sqlite3_interrupt()(SQLITE_INTERRUPT)",
- sqlite3.SQLITE_IOERR | (1 << 8): "(SQLITE_IOERR_READ)",
- sqlite3.SQLITE_IOERR | (10 << 8): "(SQLITE_IOERR_DELETE)",
- sqlite3.SQLITE_IOERR | (11 << 8): "(SQLITE_IOERR_BLOCKED)",
- sqlite3.SQLITE_IOERR | (12 << 8): "(SQLITE_IOERR_NOMEM)",
- sqlite3.SQLITE_IOERR | (13 << 8): "(SQLITE_IOERR_ACCESS)",
- sqlite3.SQLITE_IOERR | (14 << 8): "(SQLITE_IOERR_CHECKRESERVEDLOCK)",
- sqlite3.SQLITE_IOERR | (15 << 8): "(SQLITE_IOERR_LOCK)",
- sqlite3.SQLITE_IOERR | (16 << 8): "(SQLITE_IOERR_CLOSE)",
- sqlite3.SQLITE_IOERR | (17 << 8): "(SQLITE_IOERR_DIR_CLOSE)",
- sqlite3.SQLITE_IOERR | (2 << 8): "(SQLITE_IOERR_SHORT_READ)",
- sqlite3.SQLITE_IOERR | (3 << 8): "(SQLITE_IOERR_WRITE)",
- sqlite3.SQLITE_IOERR | (4 << 8): "(SQLITE_IOERR_FSYNC)",
- sqlite3.SQLITE_IOERR | (5 << 8): "(SQLITE_IOERR_DIR_FSYNC)",
- sqlite3.SQLITE_IOERR | (6 << 8): "(SQLITE_IOERR_TRUNCATE)",
- sqlite3.SQLITE_IOERR | (7 << 8): "(SQLITE_IOERR_FSTAT)",
- sqlite3.SQLITE_IOERR | (8 << 8): "(SQLITE_IOERR_UNLOCK)",
- sqlite3.SQLITE_IOERR | (9 << 8): "(SQLITE_IOERR_RDLOCK)",
- sqlite3.SQLITE_IOERR: "Some kind of disk I/O error occurred (SQLITE_IOERR)",
- sqlite3.SQLITE_LOCKED | (1 << 8): "(SQLITE_LOCKED_SHAREDCACHE)",
- sqlite3.SQLITE_LOCKED: "A table in the database is locked (SQLITE_LOCKED)",
- sqlite3.SQLITE_MISMATCH: "Data type mismatch (SQLITE_MISMATCH)",
- sqlite3.SQLITE_MISUSE: "Library used incorrectly (SQLITE_MISUSE)",
- sqlite3.SQLITE_NOLFS: "Uses OS features not supported on host (SQLITE_NOLFS)",
- sqlite3.SQLITE_NOMEM: "A malloc() failed (SQLITE_NOMEM)",
- sqlite3.SQLITE_NOTADB: "File opened that is not a database file (SQLITE_NOTADB)",
- sqlite3.SQLITE_NOTFOUND: "Unknown opcode in sqlite3_file_control() (SQLITE_NOTFOUND)",
- sqlite3.SQLITE_NOTICE: "Notifications from sqlite3_log() (SQLITE_NOTICE)",
- sqlite3.SQLITE_PERM: "Access permission denied (SQLITE_PERM)",
- sqlite3.SQLITE_PROTOCOL: "Database lock protocol error (SQLITE_PROTOCOL)",
- sqlite3.SQLITE_RANGE: "2nd parameter to sqlite3_bind out of range (SQLITE_RANGE)",
- sqlite3.SQLITE_READONLY: "Attempt to write a readonly database (SQLITE_READONLY)",
- sqlite3.SQLITE_ROW: "sqlite3_step() has another row ready (SQLITE_ROW)",
- sqlite3.SQLITE_SCHEMA: "The database schema changed (SQLITE_SCHEMA)",
- sqlite3.SQLITE_TOOBIG: "String or BLOB exceeds size limit (SQLITE_TOOBIG)",
- sqlite3.SQLITE_WARNING: "Warnings from sqlite3_log() (SQLITE_WARNING)",
- }
-)
-
func init() {
sql.Register(driverName, newDriver())
-}
+ sqlite3.PatchIssue199() // https://gitlab.com/cznic/sqlite/-/issues/199
-type result struct {
- lastInsertID int64
- rowsAffected int
-}
-
-func newResult(c *conn) (_ *result, err error) {
- r := &result{}
- if r.rowsAffected, err = c.changes(); err != nil {
- return nil, err
- }
-
- if r.lastInsertID, err = c.lastInsertRowID(); err != nil {
- return nil, err
- }
-
- return r, nil
-}
-
-// LastInsertId returns the database's auto-generated ID after, for example, an
-// INSERT into a table with primary key.
-func (r *result) LastInsertId() (int64, error) {
- if r == nil {
- return 0, nil
- }
-
- return r.lastInsertID, nil
-}
-
-// RowsAffected returns the number of rows affected by the query.
-func (r *result) RowsAffected() (int64, error) {
- if r == nil {
- return 0, nil
- }
-
- return int64(r.rowsAffected), nil
-}
-
-type rows struct {
- allocs []uintptr
- c *conn
- columns []string
- pstmt uintptr
-
- doStep bool
- empty bool
-}
-
-func newRows(c *conn, pstmt uintptr, allocs []uintptr, empty bool) (r *rows, err error) {
- r = &rows{c: c, pstmt: pstmt, allocs: allocs, empty: empty}
-
- defer func() {
- if err != nil {
- r.Close()
- r = nil
- }
- }()
-
- n, err := c.columnCount(pstmt)
- if err != nil {
- return nil, err
- }
-
- r.columns = make([]string, n)
- for i := range r.columns {
- if r.columns[i], err = r.c.columnName(pstmt, i); err != nil {
- return nil, err
- }
- }
-
- return r, nil
-}
-
-// Close closes the rows iterator.
-func (r *rows) Close() (err error) {
- for _, v := range r.allocs {
- r.c.free(v)
- }
- r.allocs = nil
- return r.c.finalize(r.pstmt)
-}
-
-// Columns returns the names of the columns. The number of columns of the
-// result is inferred from the length of the slice. If a particular column name
-// isn't known, an empty string should be returned for that entry.
-func (r *rows) Columns() (c []string) {
- return r.columns
-}
-
-// Next is called to populate the next row of data into the provided slice. The
-// provided slice will be the same size as the Columns() are wide.
-//
-// Next should return io.EOF when there are no more rows.
-func (r *rows) Next(dest []driver.Value) (err error) {
- if r.empty {
- return io.EOF
- }
-
- rc := sqlite3.SQLITE_ROW
- if r.doStep {
- if rc, err = r.c.step(r.pstmt); err != nil {
- return err
- }
- }
-
- r.doStep = true
- switch rc {
- case sqlite3.SQLITE_ROW:
- if g, e := len(dest), len(r.columns); g != e {
- return fmt.Errorf("sqlite: Next: have %v destination values, expected %v", g, e)
- }
-
- for i := range dest {
- ct, err := r.c.columnType(r.pstmt, i)
- if err != nil {
- return err
- }
-
- switch ct {
- case sqlite3.SQLITE_INTEGER:
- v, err := r.c.columnInt64(r.pstmt, i)
- if err != nil {
- return err
- }
-
- if !r.c.intToTime {
- dest[i] = v
- } else {
- // Inspired by mattn/go-sqlite3:
- // https://github.com/mattn/go-sqlite3/blob/f76bae4b0044cbba8fb2c72b8e4559e8fbcffd86/sqlite3.go#L2254-L2262
- // but we put make this compatibility optional behind a DSN
- // query parameter, because this changes API behavior, so an
- // opt-in is needed.
- switch r.ColumnTypeDatabaseTypeName(i) {
- case "DATE", "DATETIME", "TIMESTAMP":
- // Is it a seconds timestamp or a milliseconds
- // timestamp?
- if v > 1e12 || v < -1e12 {
- // time.Unix expects nanoseconds, but this is a
- // milliseconds timestamp, so convert ms->ns.
- v *= int64(time.Millisecond)
- dest[i] = time.Unix(0, v).UTC()
- } else {
- dest[i] = time.Unix(v, 0)
- }
- default:
- dest[i] = v
- }
- }
- case sqlite3.SQLITE_FLOAT:
- v, err := r.c.columnDouble(r.pstmt, i)
- if err != nil {
- return err
- }
-
- dest[i] = v
- case sqlite3.SQLITE_TEXT:
- v, err := r.c.columnText(r.pstmt, i)
- if err != nil {
- return err
- }
-
- switch r.ColumnTypeDatabaseTypeName(i) {
- case "DATE", "DATETIME", "TIMESTAMP":
- dest[i], _ = r.c.parseTime(v)
- default:
- dest[i] = v
- }
- case sqlite3.SQLITE_BLOB:
- v, err := r.c.columnBlob(r.pstmt, i)
- if err != nil {
- return err
- }
-
- dest[i] = v
- case sqlite3.SQLITE_NULL:
- dest[i] = nil
- default:
- return fmt.Errorf("internal error: rc %d", rc)
- }
- }
- return nil
- case sqlite3.SQLITE_DONE:
- return io.EOF
- default:
- return r.c.errstr(int32(rc))
- }
}
// Inspired by mattn/go-sqlite3: https://github.com/mattn/go-sqlite3/blob/ab91e934/sqlite3.go#L210-L226
@@ -332,472 +72,6 @@ var parseTimeFormats = []string{
"2006-01-02",
}
-// Attempt to parse s as a time. Return (s, false) if s is not
-// recognized as a valid time encoding.
-func (c *conn) parseTime(s string) (interface{}, bool) {
- if v, ok := c.parseTimeString(s, strings.Index(s, "m=")); ok {
- return v, true
- }
-
- ts := strings.TrimSuffix(s, "Z")
-
- for _, f := range parseTimeFormats {
- t, err := time.Parse(f, ts)
- if err == nil {
- return t, true
- }
- }
-
- return s, false
-}
-
-// Attempt to parse s as a time string produced by t.String(). If x > 0 it's
-// the index of substring "m=" within s. Return (s, false) if s is
-// not recognized as a valid time encoding.
-func (c *conn) parseTimeString(s0 string, x int) (interface{}, bool) {
- s := s0
- if x > 0 {
- s = s[:x] // "2006-01-02 15:04:05.999999999 -0700 MST m=+9999" -> "2006-01-02 15:04:05.999999999 -0700 MST "
- }
- s = strings.TrimSpace(s)
- if t, err := time.Parse("2006-01-02 15:04:05.999999999 -0700 MST", s); err == nil {
- return t, true
- }
-
- return s0, false
-}
-
-// writeTimeFormats are the names and formats supported
-// by the `_time_format` DSN query param.
-var writeTimeFormats = map[string]string{
- "sqlite": parseTimeFormats[0],
-}
-
-func (c *conn) formatTime(t time.Time) string {
- // Before configurable write time formats were supported,
- // time.Time.String was used. Maintain that default to
- // keep existing driver users formatting times the same.
- if c.writeTimeFormat == "" {
- return t.String()
- }
- return t.Format(c.writeTimeFormat)
-}
-
-// RowsColumnTypeDatabaseTypeName may be implemented by Rows. It should return
-// the database system type name without the length. Type names should be
-// uppercase. Examples of returned types: "VARCHAR", "NVARCHAR", "VARCHAR2",
-// "CHAR", "TEXT", "DECIMAL", "SMALLINT", "INT", "BIGINT", "BOOL", "[]BIGINT",
-// "JSONB", "XML", "TIMESTAMP".
-func (r *rows) ColumnTypeDatabaseTypeName(index int) string {
- return strings.ToUpper(r.c.columnDeclType(r.pstmt, index))
-}
-
-// RowsColumnTypeLength may be implemented by Rows. It should return the length
-// of the column type if the column is a variable length type. If the column is
-// not a variable length type ok should return false. If length is not limited
-// other than system limits, it should return math.MaxInt64. The following are
-// examples of returned values for various types:
-//
-// TEXT (math.MaxInt64, true)
-// varchar(10) (10, true)
-// nvarchar(10) (10, true)
-// decimal (0, false)
-// int (0, false)
-// bytea(30) (30, true)
-func (r *rows) ColumnTypeLength(index int) (length int64, ok bool) {
- t, err := r.c.columnType(r.pstmt, index)
- if err != nil {
- return 0, false
- }
-
- switch t {
- case sqlite3.SQLITE_INTEGER:
- return 0, false
- case sqlite3.SQLITE_FLOAT:
- return 0, false
- case sqlite3.SQLITE_TEXT:
- return math.MaxInt64, true
- case sqlite3.SQLITE_BLOB:
- return math.MaxInt64, true
- case sqlite3.SQLITE_NULL:
- return 0, false
- default:
- return 0, false
- }
-}
-
-// RowsColumnTypeNullable may be implemented by Rows. The nullable value should
-// be true if it is known the column may be null, or false if the column is
-// known to be not nullable. If the column nullability is unknown, ok should be
-// false.
-func (r *rows) ColumnTypeNullable(index int) (nullable, ok bool) {
- return true, true
-}
-
-// RowsColumnTypePrecisionScale may be implemented by Rows. It should return
-// the precision and scale for decimal types. If not applicable, ok should be
-// false. The following are examples of returned values for various types:
-//
-// decimal(38, 4) (38, 4, true)
-// int (0, 0, false)
-// decimal (math.MaxInt64, math.MaxInt64, true)
-func (r *rows) ColumnTypePrecisionScale(index int) (precision, scale int64, ok bool) {
- return 0, 0, false
-}
-
-// RowsColumnTypeScanType may be implemented by Rows. It should return the
-// value type that can be used to scan types into. For example, the database
-// column type "bigint" this should return "reflect.TypeOf(int64(0))".
-func (r *rows) ColumnTypeScanType(index int) reflect.Type {
- t, err := r.c.columnType(r.pstmt, index)
- if err != nil {
- return reflect.TypeOf("")
- }
-
- switch t {
- case sqlite3.SQLITE_INTEGER:
- switch strings.ToLower(r.c.columnDeclType(r.pstmt, index)) {
- case "boolean":
- return reflect.TypeOf(false)
- case "date", "datetime", "time", "timestamp":
- return reflect.TypeOf(time.Time{})
- default:
- return reflect.TypeOf(int64(0))
- }
- case sqlite3.SQLITE_FLOAT:
- return reflect.TypeOf(float64(0))
- case sqlite3.SQLITE_TEXT:
- return reflect.TypeOf("")
- case sqlite3.SQLITE_BLOB:
- return reflect.TypeOf([]byte(nil))
- case sqlite3.SQLITE_NULL:
- return reflect.TypeOf(nil)
- default:
- return reflect.TypeOf("")
- }
-}
-
-type stmt struct {
- c *conn
- psql uintptr
-}
-
-func newStmt(c *conn, sql string) (*stmt, error) {
- p, err := libc.CString(sql)
- if err != nil {
- return nil, err
- }
- stm := stmt{c: c, psql: p}
-
- return &stm, nil
-}
-
-// Close closes the statement.
-//
-// As of Go 1.1, a Stmt will not be closed if it's in use by any queries.
-func (s *stmt) Close() (err error) {
- s.c.free(s.psql)
- s.psql = 0
- return nil
-}
-
-// Exec executes a query that doesn't return rows, such as an INSERT or UPDATE.
-//
-// Deprecated: Drivers should implement StmtExecContext instead (or
-// additionally).
-func (s *stmt) Exec(args []driver.Value) (driver.Result, error) { //TODO StmtExecContext
- return s.exec(context.Background(), toNamedValues(args))
-}
-
-// toNamedValues converts []driver.Value to []driver.NamedValue
-func toNamedValues(vals []driver.Value) (r []driver.NamedValue) {
- r = make([]driver.NamedValue, len(vals))
- for i, val := range vals {
- r[i] = driver.NamedValue{Value: val, Ordinal: i + 1}
- }
- return r
-}
-
-func (s *stmt) exec(ctx context.Context, args []driver.NamedValue) (r driver.Result, err error) {
- var pstmt uintptr
- var done int32
- if ctx != nil {
- if ctxDone := ctx.Done(); ctxDone != nil {
- select {
- case <-ctxDone:
- return nil, ctx.Err()
- default:
- }
- defer interruptOnDone(ctx, s.c, &done)()
- }
- }
-
- defer func() {
- if ctx != nil && atomic.LoadInt32(&done) != 0 {
- r, err = nil, ctx.Err()
- }
- if pstmt != 0 {
- // ensure stmt finalized.
- e := s.c.finalize(pstmt)
-
- if err == nil && e != nil {
- // prioritize original
- // returned error.
- err = e
- }
- }
- }()
-
- for psql := s.psql; *(*byte)(unsafe.Pointer(psql)) != 0 && atomic.LoadInt32(&done) == 0; {
- if pstmt, err = s.c.prepareV2(&psql); err != nil {
- return nil, err
- }
-
- if pstmt == 0 {
- continue
- }
- err = func() (err error) {
- n, err := s.c.bindParameterCount(pstmt)
- if err != nil {
- return err
- }
-
- if n != 0 {
- allocs, err := s.c.bind(pstmt, n, args)
- if err != nil {
- return err
- }
-
- if len(allocs) != 0 {
- defer func() {
- for _, v := range allocs {
- s.c.free(v)
- }
- }()
- }
- }
-
- rc, err := s.c.step(pstmt)
- if err != nil {
- return err
- }
-
- switch rc & 0xff {
- case sqlite3.SQLITE_DONE, sqlite3.SQLITE_ROW:
- r, err = newResult(s.c)
- default:
- return s.c.errstr(int32(rc))
- }
-
- return nil
- }()
-
- e := s.c.finalize(pstmt)
- pstmt = 0 // done with
-
- if err == nil && e != nil {
- // prioritize original
- // returned error.
- err = e
- }
-
- if err != nil {
- return nil, err
- }
- }
- return r, err
-}
-
-// NumInput returns the number of placeholder parameters.
-//
-// If NumInput returns >= 0, the sql package will sanity check argument counts
-// from callers and return errors to the caller before the statement's Exec or
-// Query methods are called.
-//
-// NumInput may also return -1, if the driver doesn't know its number of
-// placeholders. In that case, the sql package will not sanity check Exec or
-// Query argument counts.
-func (s *stmt) NumInput() (n int) {
- return -1
-}
-
-// Query executes a query that may return rows, such as a
-// SELECT.
-//
-// Deprecated: Drivers should implement StmtQueryContext instead (or
-// additionally).
-func (s *stmt) Query(args []driver.Value) (driver.Rows, error) { //TODO StmtQueryContext
- return s.query(context.Background(), toNamedValues(args))
-}
-
-func (s *stmt) query(ctx context.Context, args []driver.NamedValue) (r driver.Rows, err error) {
- var pstmt uintptr
- var done int32
- if ctx != nil {
- if ctxDone := ctx.Done(); ctxDone != nil {
- select {
- case <-ctxDone:
- return nil, ctx.Err()
- default:
- }
- defer interruptOnDone(ctx, s.c, &done)()
- }
- }
-
- var allocs []uintptr
-
- defer func() {
- if ctx != nil && atomic.LoadInt32(&done) != 0 {
- if r != nil {
- r.Close()
- }
- r, err = nil, ctx.Err()
- } else if r == nil && err == nil {
- r, err = newRows(s.c, pstmt, allocs, true)
- }
-
- if pstmt != 0 {
- // ensure stmt finalized.
- e := s.c.finalize(pstmt)
-
- if err == nil && e != nil {
- // prioritize original
- // returned error.
- err = e
- }
- }
-
- }()
-
- for psql := s.psql; *(*byte)(unsafe.Pointer(psql)) != 0 && atomic.LoadInt32(&done) == 0; {
- if pstmt, err = s.c.prepareV2(&psql); err != nil {
- return nil, err
- }
-
- if pstmt == 0 {
- continue
- }
-
- err = func() (err error) {
- n, err := s.c.bindParameterCount(pstmt)
- if err != nil {
- return err
- }
-
- if n != 0 {
- if allocs, err = s.c.bind(pstmt, n, args); err != nil {
- return err
- }
- }
-
- rc, err := s.c.step(pstmt)
- if err != nil {
- return err
- }
-
- switch rc & 0xff {
- case sqlite3.SQLITE_ROW:
- if r != nil {
- r.Close()
- }
- if r, err = newRows(s.c, pstmt, allocs, false); err != nil {
- return err
- }
-
- pstmt = 0
- return nil
- case sqlite3.SQLITE_DONE:
- if r == nil {
- if r, err = newRows(s.c, pstmt, allocs, true); err != nil {
- return err
- }
- pstmt = 0
- return nil
- }
-
- // nop
- default:
- return s.c.errstr(int32(rc))
- }
-
- if *(*byte)(unsafe.Pointer(psql)) == 0 {
- if r != nil {
- r.Close()
- }
- if r, err = newRows(s.c, pstmt, allocs, true); err != nil {
- return err
- }
-
- pstmt = 0
- }
- return nil
- }()
-
- e := s.c.finalize(pstmt)
- pstmt = 0 // done with
-
- if err == nil && e != nil {
- // prioritize original
- // returned error.
- err = e
- }
-
- if err != nil {
- return nil, err
- }
- }
- return r, err
-}
-
-type tx struct {
- c *conn
-}
-
-func newTx(ctx context.Context, c *conn, opts driver.TxOptions) (*tx, error) {
- r := &tx{c: c}
-
- sql := "begin"
- if !opts.ReadOnly && c.beginMode != "" {
- sql = "begin " + c.beginMode
- }
-
- if err := r.exec(ctx, sql); err != nil {
- return nil, err
- }
-
- return r, nil
-}
-
-// Commit implements driver.Tx.
-func (t *tx) Commit() (err error) {
- return t.exec(context.Background(), "commit")
-}
-
-// Rollback implements driver.Tx.
-func (t *tx) Rollback() (err error) {
- return t.exec(context.Background(), "rollback")
-}
-
-func (t *tx) exec(ctx context.Context, sql string) (err error) {
- psql, err := libc.CString(sql)
- if err != nil {
- return err
- }
-
- defer t.c.free(psql)
- //TODO use t.conn.ExecContext() instead
-
- if ctx != nil && ctx.Done() != nil {
- defer interruptOnDone(ctx, t.c, nil)()
- }
-
- if rc := sqlite3.Xsqlite3_exec(t.c.tls, t.c.db, psql, 0, 0, 0); rc != sqlite3.SQLITE_OK {
- return t.c.errstr(rc)
- }
-
- return nil
-}
-
// interruptOnDone sets up a goroutine to interrupt the provided db when the
// context is canceled, and returns a function the caller must defer so it
// doesn't interrupt after the caller finishes.
@@ -835,66 +109,6 @@ func interruptOnDone(
}
}
-type conn struct {
- db uintptr // *sqlite3.Xsqlite3
- tls *libc.TLS
-
- // Context handling can cause conn.Close and conn.interrupt to be invoked
- // concurrently.
- sync.Mutex
-
- writeTimeFormat string
- beginMode string
- intToTime bool
- integerTimeFormat string
-}
-
-func newConn(dsn string) (*conn, error) {
- var query, vfsName string
-
- // Parse the query parameters from the dsn and them from the dsn if not prefixed by file:
- // https://github.com/mattn/go-sqlite3/blob/3392062c729d77820afc1f5cae3427f0de39e954/sqlite3.go#L1046
- // https://github.com/mattn/go-sqlite3/blob/3392062c729d77820afc1f5cae3427f0de39e954/sqlite3.go#L1383
- pos := strings.IndexRune(dsn, '?')
- if pos >= 1 {
- query = dsn[pos+1:]
- var err error
- vfsName, err = getVFSName(query)
- if err != nil {
- return nil, err
- }
-
- if !strings.HasPrefix(dsn, "file:") {
- dsn = dsn[:pos]
- }
- }
-
- c := &conn{tls: libc.NewTLS()}
- db, err := c.openV2(
- dsn,
- vfsName,
- sqlite3.SQLITE_OPEN_READWRITE|sqlite3.SQLITE_OPEN_CREATE|
- sqlite3.SQLITE_OPEN_FULLMUTEX|
- sqlite3.SQLITE_OPEN_URI,
- )
- if err != nil {
- return nil, err
- }
-
- c.db = db
- if err = c.extendedResultCodes(true); err != nil {
- c.Close()
- return nil, err
- }
-
- if err = applyQueryParams(c, query); err != nil {
- c.Close()
- return nil, err
- }
-
- return c, nil
-}
-
func getVFSName(query string) (r string, err error) {
q, err := url.ParseQuery(query)
if err != nil {
@@ -983,161 +197,6 @@ func applyQueryParams(c *conn, query string) error {
return nil
}
-// C documentation
-//
-// const void *sqlite3_column_blob(sqlite3_stmt*, int iCol);
-func (c *conn) columnBlob(pstmt uintptr, iCol int) (v []byte, err error) {
- p := sqlite3.Xsqlite3_column_blob(c.tls, pstmt, int32(iCol))
- len, err := c.columnBytes(pstmt, iCol)
- if err != nil {
- return nil, err
- }
-
- if p == 0 || len == 0 {
- return nil, nil
- }
-
- v = make([]byte, len)
- copy(v, (*libc.RawMem)(unsafe.Pointer(p))[:len:len])
- return v, nil
-}
-
-// C documentation
-//
-// int sqlite3_column_bytes(sqlite3_stmt*, int iCol);
-func (c *conn) columnBytes(pstmt uintptr, iCol int) (_ int, err error) {
- v := sqlite3.Xsqlite3_column_bytes(c.tls, pstmt, int32(iCol))
- return int(v), nil
-}
-
-// C documentation
-//
-// const unsigned char *sqlite3_column_text(sqlite3_stmt*, int iCol);
-func (c *conn) columnText(pstmt uintptr, iCol int) (v string, err error) {
- p := sqlite3.Xsqlite3_column_text(c.tls, pstmt, int32(iCol))
- len, err := c.columnBytes(pstmt, iCol)
- if err != nil {
- return "", err
- }
-
- if p == 0 || len == 0 {
- return "", nil
- }
-
- b := make([]byte, len)
- copy(b, (*libc.RawMem)(unsafe.Pointer(p))[:len:len])
- return string(b), nil
-}
-
-// C documentation
-//
-// double sqlite3_column_double(sqlite3_stmt*, int iCol);
-func (c *conn) columnDouble(pstmt uintptr, iCol int) (v float64, err error) {
- v = sqlite3.Xsqlite3_column_double(c.tls, pstmt, int32(iCol))
- return v, nil
-}
-
-// C documentation
-//
-// sqlite3_int64 sqlite3_column_int64(sqlite3_stmt*, int iCol);
-func (c *conn) columnInt64(pstmt uintptr, iCol int) (v int64, err error) {
- v = sqlite3.Xsqlite3_column_int64(c.tls, pstmt, int32(iCol))
- return v, nil
-}
-
-// C documentation
-//
-// int sqlite3_column_type(sqlite3_stmt*, int iCol);
-func (c *conn) columnType(pstmt uintptr, iCol int) (_ int, err error) {
- v := sqlite3.Xsqlite3_column_type(c.tls, pstmt, int32(iCol))
- return int(v), nil
-}
-
-// C documentation
-//
-// const char *sqlite3_column_decltype(sqlite3_stmt*,int);
-func (c *conn) columnDeclType(pstmt uintptr, iCol int) string {
- return libc.GoString(sqlite3.Xsqlite3_column_decltype(c.tls, pstmt, int32(iCol)))
-}
-
-// C documentation
-//
-// const char *sqlite3_column_name(sqlite3_stmt*, int N);
-func (c *conn) columnName(pstmt uintptr, n int) (string, error) {
- p := sqlite3.Xsqlite3_column_name(c.tls, pstmt, int32(n))
- return libc.GoString(p), nil
-}
-
-// C documentation
-//
-// int sqlite3_column_count(sqlite3_stmt *pStmt);
-func (c *conn) columnCount(pstmt uintptr) (_ int, err error) {
- v := sqlite3.Xsqlite3_column_count(c.tls, pstmt)
- return int(v), nil
-}
-
-// C documentation
-//
-// sqlite3_int64 sqlite3_last_insert_rowid(sqlite3*);
-func (c *conn) lastInsertRowID() (v int64, _ error) {
- return sqlite3.Xsqlite3_last_insert_rowid(c.tls, c.db), nil
-}
-
-// C documentation
-//
-// int sqlite3_changes(sqlite3*);
-func (c *conn) changes() (int, error) {
- v := sqlite3.Xsqlite3_changes(c.tls, c.db)
- return int(v), nil
-}
-
-// C documentation
-//
-// int sqlite3_step(sqlite3_stmt*);
-func (c *conn) step(pstmt uintptr) (int, error) {
- for {
- switch rc := sqlite3.Xsqlite3_step(c.tls, pstmt); rc {
- case sqliteLockedSharedcache:
- if err := c.retry(pstmt); err != nil {
- return sqlite3.SQLITE_LOCKED, err
- }
- case
- sqlite3.SQLITE_DONE,
- sqlite3.SQLITE_ROW:
-
- return int(rc), nil
- default:
- return int(rc), c.errstr(rc)
- }
- }
-}
-
-func (c *conn) retry(pstmt uintptr) error {
- mu := mutexAlloc(c.tls)
- (*mutex)(unsafe.Pointer(mu)).Lock()
- rc := sqlite3.Xsqlite3_unlock_notify(
- c.tls,
- c.db,
- *(*uintptr)(unsafe.Pointer(&struct {
- f func(*libc.TLS, uintptr, int32)
- }{unlockNotify})),
- mu,
- )
- if rc == sqlite3.SQLITE_LOCKED { // Deadlock, see https://www.sqlite.org/c3ref/unlock_notify.html
- (*mutex)(unsafe.Pointer(mu)).Unlock()
- mutexFree(c.tls, mu)
- return c.errstr(rc)
- }
-
- (*mutex)(unsafe.Pointer(mu)).Lock()
- (*mutex)(unsafe.Pointer(mu)).Unlock()
- mutexFree(c.tls, mu)
- if pstmt != 0 {
- sqlite3.Xsqlite3_reset(c.tls, pstmt)
- }
- return nil
-}
-
func unlockNotify(t *libc.TLS, ppArg uintptr, nArg int32) {
for i := int32(0); i < nArg; i++ {
mu := *(*uintptr)(unsafe.Pointer(ppArg))
@@ -1146,437 +205,6 @@ func unlockNotify(t *libc.TLS, ppArg uintptr, nArg int32) {
}
}
-func (c *conn) bind(pstmt uintptr, n int, args []driver.NamedValue) (allocs []uintptr, err error) {
- defer func() {
- if err == nil {
- return
- }
-
- for _, v := range allocs {
- c.free(v)
- }
- allocs = nil
- }()
-
- for i := 1; i <= n; i++ {
- name, err := c.bindParameterName(pstmt, i)
- if err != nil {
- return allocs, err
- }
-
- var found bool
- var v driver.NamedValue
- for _, v = range args {
- if name != "" {
- // For ?NNN and $NNN params, match if NNN == v.Ordinal.
- //
- // Supporting this for $NNN is a special case that makes eg
- // `select $1, $2, $3 ...` work without needing to use
- // sql.Named.
- if (name[0] == '?' || name[0] == '$') && name[1:] == strconv.Itoa(v.Ordinal) {
- found = true
- break
- }
-
- // sqlite supports '$', '@' and ':' prefixes for string
- // identifiers and '?' for numeric, so we cannot
- // combine different prefixes with the same name
- // because `database/sql` requires variable names
- // to start with a letter
- if name[1:] == v.Name[:] {
- found = true
- break
- }
- } else {
- if v.Ordinal == i {
- found = true
- break
- }
- }
- }
-
- if !found {
- if name != "" {
- return allocs, fmt.Errorf("missing named argument %q", name[1:])
- }
-
- return allocs, fmt.Errorf("missing argument with index %d", i)
- }
-
- var p uintptr
- switch x := v.Value.(type) {
- case int64:
- if err := c.bindInt64(pstmt, i, x); err != nil {
- return allocs, err
- }
- case float64:
- if err := c.bindDouble(pstmt, i, x); err != nil {
- return allocs, err
- }
- case bool:
- v := 0
- if x {
- v = 1
- }
- if err := c.bindInt(pstmt, i, v); err != nil {
- return allocs, err
- }
- case []byte:
- if p, err = c.bindBlob(pstmt, i, x); err != nil {
- return allocs, err
- }
- case string:
- if p, err = c.bindText(pstmt, i, x); err != nil {
- return allocs, err
- }
- case time.Time:
- switch c.integerTimeFormat {
- case "unix":
- if err := c.bindInt64(pstmt, i, x.Unix()); err != nil {
- return allocs, err
- }
- case "unix_milli":
- if err := c.bindInt64(pstmt, i, x.UnixMilli()); err != nil {
- return allocs, err
- }
- case "unix_micro":
- if err := c.bindInt64(pstmt, i, x.UnixMicro()); err != nil {
- return allocs, err
- }
- case "unix_nano":
- if err := c.bindInt64(pstmt, i, x.UnixNano()); err != nil {
- return allocs, err
- }
- default:
- if p, err = c.bindText(pstmt, i, c.formatTime(x)); err != nil {
- return allocs, err
- }
- }
-
- case nil:
- if p, err = c.bindNull(pstmt, i); err != nil {
- return allocs, err
- }
- default:
- return allocs, fmt.Errorf("sqlite: invalid driver.Value type %T", x)
- }
- if p != 0 {
- allocs = append(allocs, p)
- }
- }
- return allocs, nil
-}
-
-// C documentation
-//
-// int sqlite3_bind_null(sqlite3_stmt*, int);
-func (c *conn) bindNull(pstmt uintptr, idx1 int) (uintptr, error) {
- if rc := sqlite3.Xsqlite3_bind_null(c.tls, pstmt, int32(idx1)); rc != sqlite3.SQLITE_OK {
- return 0, c.errstr(rc)
- }
-
- return 0, nil
-}
-
-// C documentation
-//
-// int sqlite3_bind_text(sqlite3_stmt*,int,const char*,int,void(*)(void*));
-func (c *conn) bindText(pstmt uintptr, idx1 int, value string) (uintptr, error) {
- p, err := libc.CString(value)
- if err != nil {
- return 0, err
- }
-
- if rc := sqlite3.Xsqlite3_bind_text(c.tls, pstmt, int32(idx1), p, int32(len(value)), 0); rc != sqlite3.SQLITE_OK {
- c.free(p)
- return 0, c.errstr(rc)
- }
-
- return p, nil
-}
-
-// C documentation
-//
-// int sqlite3_bind_int(sqlite3_stmt*, int, int);
-func (c *conn) bindInt(pstmt uintptr, idx1, value int) (err error) {
- if rc := sqlite3.Xsqlite3_bind_int(c.tls, pstmt, int32(idx1), int32(value)); rc != sqlite3.SQLITE_OK {
- return c.errstr(rc)
- }
-
- return nil
-}
-
-// C documentation
-//
-// int sqlite3_bind_double(sqlite3_stmt*, int, double);
-func (c *conn) bindDouble(pstmt uintptr, idx1 int, value float64) (err error) {
- if rc := sqlite3.Xsqlite3_bind_double(c.tls, pstmt, int32(idx1), value); rc != 0 {
- return c.errstr(rc)
- }
-
- return nil
-}
-
-// C documentation
-//
-// int sqlite3_bind_int64(sqlite3_stmt*, int, sqlite3_int64);
-func (c *conn) bindInt64(pstmt uintptr, idx1 int, value int64) (err error) {
- if rc := sqlite3.Xsqlite3_bind_int64(c.tls, pstmt, int32(idx1), value); rc != sqlite3.SQLITE_OK {
- return c.errstr(rc)
- }
-
- return nil
-}
-
-// C documentation
-//
-// const char *sqlite3_bind_parameter_name(sqlite3_stmt*, int);
-func (c *conn) bindParameterName(pstmt uintptr, i int) (string, error) {
- p := sqlite3.Xsqlite3_bind_parameter_name(c.tls, pstmt, int32(i))
- return libc.GoString(p), nil
-}
-
-// C documentation
-//
-// int sqlite3_bind_parameter_count(sqlite3_stmt*);
-func (c *conn) bindParameterCount(pstmt uintptr) (_ int, err error) {
- r := sqlite3.Xsqlite3_bind_parameter_count(c.tls, pstmt)
- return int(r), nil
-}
-
-// C documentation
-//
-// int sqlite3_finalize(sqlite3_stmt *pStmt);
-func (c *conn) finalize(pstmt uintptr) error {
- if rc := sqlite3.Xsqlite3_finalize(c.tls, pstmt); rc != sqlite3.SQLITE_OK {
- return c.errstr(rc)
- }
-
- return nil
-}
-
-// C documentation
-//
-// int sqlite3_prepare_v2(
-// sqlite3 *db, /* Database handle */
-// const char *zSql, /* SQL statement, UTF-8 encoded */
-// int nByte, /* Maximum length of zSql in bytes. */
-// sqlite3_stmt **ppStmt, /* OUT: Statement handle */
-// const char **pzTail /* OUT: Pointer to unused portion of zSql */
-// );
-func (c *conn) prepareV2(zSQL *uintptr) (pstmt uintptr, err error) {
- var ppstmt, pptail uintptr
-
- defer func() {
- c.free(ppstmt)
- c.free(pptail)
- }()
-
- if ppstmt, err = c.malloc(int(ptrSize)); err != nil {
- return 0, err
- }
-
- if pptail, err = c.malloc(int(ptrSize)); err != nil {
- return 0, err
- }
-
- for {
- switch rc := sqlite3.Xsqlite3_prepare_v2(c.tls, c.db, *zSQL, -1, ppstmt, pptail); rc {
- case sqlite3.SQLITE_OK:
- *zSQL = *(*uintptr)(unsafe.Pointer(pptail))
- return *(*uintptr)(unsafe.Pointer(ppstmt)), nil
- case sqliteLockedSharedcache:
- if err := c.retry(0); err != nil {
- return 0, err
- }
- default:
- return 0, c.errstr(rc)
- }
- }
-}
-
-// C documentation
-//
-// void sqlite3_interrupt(sqlite3*);
-func (c *conn) interrupt(pdb uintptr) (err error) {
- c.Lock() // Defend against race with .Close invoked by context handling.
-
- defer c.Unlock()
-
- if c.tls != nil {
- sqlite3.Xsqlite3_interrupt(c.tls, pdb)
- }
- return nil
-}
-
-// C documentation
-//
-// int sqlite3_extended_result_codes(sqlite3*, int onoff);
-func (c *conn) extendedResultCodes(on bool) error {
- if rc := sqlite3.Xsqlite3_extended_result_codes(c.tls, c.db, libc.Bool32(on)); rc != sqlite3.SQLITE_OK {
- return c.errstr(rc)
- }
-
- return nil
-}
-
-// C documentation
-//
-// int sqlite3_open_v2(
-// const char *filename, /* Database filename (UTF-8) */
-// sqlite3 **ppDb, /* OUT: SQLite db handle */
-// int flags, /* Flags */
-// const char *zVfs /* Name of VFS module to use */
-// );
-func (c *conn) openV2(name, vfsName string, flags int32) (uintptr, error) {
- var p, s, vfs uintptr
-
- defer func() {
- if p != 0 {
- c.free(p)
- }
- if s != 0 {
- c.free(s)
- }
- if vfs != 0 {
- c.free(vfs)
- }
- }()
-
- p, err := c.malloc(int(ptrSize))
- if err != nil {
- return 0, err
- }
-
- if s, err = libc.CString(name); err != nil {
- return 0, err
- }
-
- if vfsName != "" {
- if vfs, err = libc.CString(vfsName); err != nil {
- return 0, err
- }
- }
-
- if rc := sqlite3.Xsqlite3_open_v2(c.tls, s, p, flags, vfs); rc != sqlite3.SQLITE_OK {
- return 0, c.errstr(rc)
- }
-
- return *(*uintptr)(unsafe.Pointer(p)), nil
-}
-
-func (c *conn) malloc(n int) (uintptr, error) {
- if p := libc.Xmalloc(c.tls, types.Size_t(n)); p != 0 || n == 0 {
- return p, nil
- }
-
- return 0, fmt.Errorf("sqlite: cannot allocate %d bytes of memory", n)
-}
-
-func (c *conn) free(p uintptr) {
- if p != 0 {
- libc.Xfree(c.tls, p)
- }
-}
-
-// C documentation
-//
-// const char *sqlite3_errstr(int);
-func (c *conn) errstr(rc int32) error {
- p := sqlite3.Xsqlite3_errstr(c.tls, rc)
- str := libc.GoString(p)
- p = sqlite3.Xsqlite3_errmsg(c.tls, c.db)
- var s string
- if rc == sqlite3.SQLITE_BUSY {
- s = " (SQLITE_BUSY)"
- }
- switch msg := libc.GoString(p); {
- case msg == str:
- return &Error{msg: fmt.Sprintf("%s (%v)%s", str, rc, s), code: int(rc)}
- default:
- return &Error{msg: fmt.Sprintf("%s: %s (%v)%s", str, msg, rc, s), code: int(rc)}
- }
-}
-
-// Begin starts a transaction.
-//
-// Deprecated: Drivers should implement ConnBeginTx instead (or additionally).
-func (c *conn) Begin() (dt driver.Tx, err error) {
- if dmesgs {
- defer func() {
- dmesg("conn %p: (driver.Tx %p, err %v)", c, dt, err)
- }()
- }
- return c.begin(context.Background(), driver.TxOptions{})
-}
-
-func (c *conn) begin(ctx context.Context, opts driver.TxOptions) (t driver.Tx, err error) {
- return newTx(ctx, c, opts)
-}
-
-// Close invalidates and potentially stops any current prepared statements and
-// transactions, marking this connection as no longer in use.
-//
-// Because the sql package maintains a free pool of connections and only calls
-// Close when there's a surplus of idle connections, it shouldn't be necessary
-// for drivers to do their own connection caching.
-func (c *conn) Close() (err error) {
- if dmesgs {
- defer func() {
- dmesg("conn %p: err %v", c, err)
- }()
- }
- c.Lock() // Defend against race with .interrupt invoked by context handling.
-
- defer c.Unlock()
-
- if c.db != 0 {
- if err := c.closeV2(c.db); err != nil {
- return err
- }
-
- c.db = 0
- }
-
- if c.tls != nil {
- c.tls.Close()
- c.tls = nil
- }
- return nil
-}
-
-// C documentation
-//
-// int sqlite3_close_v2(sqlite3*);
-func (c *conn) closeV2(db uintptr) error {
- if rc := sqlite3.Xsqlite3_close_v2(c.tls, db); rc != sqlite3.SQLITE_OK {
- return c.errstr(rc)
- }
-
- return nil
-}
-
-// ResetSession is called prior to executing a query on the connection if the
-// connection has been used before. If the driver returns ErrBadConn the
-// connection is discarded.
-func (c *conn) ResetSession(ctx context.Context) error {
- if !c.usable() {
- return driver.ErrBadConn
- }
-
- return nil
-}
-
-// IsValid is called prior to placing the connection into the connection pool.
-// The connection will be discarded if false is returned.
-func (c *conn) IsValid() bool {
- return c.usable()
-}
-
-func (c *conn) usable() bool {
- return c.db != 0 && sqlite3.Xsqlite3_is_interrupted(c.tls, c.db) == 0
-}
-
// FunctionImpl describes an [application-defined SQL function]. If Scalar is
// set, it is treated as a scalar function; otherwise, it is treated as an
// aggregate function using MakeAggregate.
@@ -1635,53 +263,6 @@ type AggregateFunction interface {
Final(ctx *FunctionContext)
}
-type userDefinedFunction struct {
- zFuncName uintptr
- nArg int32
- eTextRep int32
- pApp uintptr
-
- scalar bool
- freeOnce sync.Once
-}
-
-func (c *conn) createFunctionInternal(fun *userDefinedFunction) error {
- var rc int32
-
- if fun.scalar {
- rc = sqlite3.Xsqlite3_create_function(
- c.tls,
- c.db,
- fun.zFuncName,
- fun.nArg,
- fun.eTextRep,
- fun.pApp,
- cFuncPointer(funcTrampoline),
- 0,
- 0,
- )
- } else {
- rc = sqlite3.Xsqlite3_create_window_function(
- c.tls,
- c.db,
- fun.zFuncName,
- fun.nArg,
- fun.eTextRep,
- fun.pApp,
- cFuncPointer(stepTrampoline),
- cFuncPointer(finalTrampoline),
- cFuncPointer(valueTrampoline),
- cFuncPointer(inverseTrampoline),
- 0,
- )
- }
-
- if rc != sqlite3.SQLITE_OK {
- return c.errstr(rc)
- }
- return nil
-}
-
type collation struct {
zName uintptr
pApp uintptr
@@ -1751,241 +332,6 @@ func registerCollation(
return nil
}
-func (c *conn) createCollationInternal(coll *collation) error {
- rc := sqlite3.Xsqlite3_create_collation_v2(
- c.tls,
- c.db,
- coll.zName,
- coll.enc,
- coll.pApp,
- cFuncPointer(collationTrampoline),
- 0,
- )
- if rc != sqlite3.SQLITE_OK {
- return c.errstr(rc)
- }
- return nil
-}
-
-// Execer is an optional interface that may be implemented by a Conn.
-//
-// If a Conn does not implement Execer, the sql package's DB.Exec will first
-// prepare a query, execute the statement, and then close the statement.
-//
-// Exec may return ErrSkip.
-//
-// Deprecated: Drivers should implement ExecerContext instead.
-func (c *conn) Exec(query string, args []driver.Value) (dr driver.Result, err error) {
- if dmesgs {
- defer func() {
- dmesg("conn %p, query %q, args %v: (driver.Result %p, err %v)", c, query, args, dr, err)
- }()
- }
- return c.exec(context.Background(), query, toNamedValues(args))
-}
-
-func (c *conn) exec(ctx context.Context, query string, args []driver.NamedValue) (r driver.Result, err error) {
- s, err := c.prepare(ctx, query)
- if err != nil {
- return nil, err
- }
-
- defer func() {
- if err2 := s.Close(); err2 != nil && err == nil {
- err = err2
- }
- }()
-
- return s.(*stmt).exec(ctx, args)
-}
-
-// Prepare returns a prepared statement, bound to this connection.
-func (c *conn) Prepare(query string) (ds driver.Stmt, err error) {
- if dmesgs {
- defer func() {
- dmesg("conn %p, query %q: (driver.Stmt %p, err %v)", c, query, ds, err)
- }()
- }
- return c.prepare(context.Background(), query)
-}
-
-func (c *conn) prepare(ctx context.Context, query string) (s driver.Stmt, err error) {
- //TODO use ctx
- return newStmt(c, query)
-}
-
-// Queryer is an optional interface that may be implemented by a Conn.
-//
-// If a Conn does not implement Queryer, the sql package's DB.Query will first
-// prepare a query, execute the statement, and then close the statement.
-//
-// Query may return ErrSkip.
-//
-// Deprecated: Drivers should implement QueryerContext instead.
-func (c *conn) Query(query string, args []driver.Value) (dr driver.Rows, err error) {
- if dmesgs {
- defer func() {
- dmesg("conn %p, query %q, args %v: (driver.Rows %p, err %v)", c, query, args, dr, err)
- }()
- }
- return c.query(context.Background(), query, toNamedValues(args))
-}
-
-func (c *conn) query(ctx context.Context, query string, args []driver.NamedValue) (r driver.Rows, err error) {
- s, err := c.prepare(ctx, query)
- if err != nil {
- return nil, err
- }
-
- defer func() {
- if err2 := s.Close(); err2 != nil && err == nil {
- err = err2
- }
- }()
-
- return s.(*stmt).query(ctx, args)
-}
-
-// Serialize returns a serialization of the main database. For an ordinary on-disk
-// database file, the serialization is just a copy of the disk file. For an in-memory
-// database or a "TEMP" database, the serialization is the same sequence of bytes
-// which would be written to disk if that database where backed up to disk.
-func (c *conn) Serialize() (v []byte, err error) {
- pLen := c.tls.Alloc(8)
- defer c.tls.Free(8)
-
- zSchema := sqlite3.Xsqlite3_db_name(c.tls, c.db, 0)
- if zSchema == 0 {
- return nil, fmt.Errorf("failed to get main db name")
- }
-
- pBuf := sqlite3.Xsqlite3_serialize(c.tls, c.db, zSchema, pLen, 0)
- bufLen := *(*sqlite3.Sqlite3_int64)(unsafe.Pointer(pLen))
- if pBuf != 0 {
- defer sqlite3.Xsqlite3_free(c.tls, pBuf)
- }
- if bufLen <= 0 {
- return nil, fmt.Errorf("invalid length returned: %d", bufLen)
- } else if pBuf == 0 || bufLen == 0 {
- return nil, nil
- }
-
- v = make([]byte, bufLen)
- copy(v, (*libc.RawMem)(unsafe.Pointer(pBuf))[:bufLen:bufLen])
- return v, nil
-}
-
-// Deserialize restore a database from the content returned by Serialize.
-func (c *conn) Deserialize(buf []byte) (err error) {
- bufLen := len(buf)
- pBuf := c.tls.Alloc(bufLen) // free will be done if it fails or on close, must not be freed here
-
- copy((*libc.RawMem)(unsafe.Pointer(pBuf))[:bufLen:bufLen], buf)
-
- zSchema := sqlite3.Xsqlite3_db_name(c.tls, c.db, 0)
- if zSchema == 0 {
- return fmt.Errorf("failed to get main db name")
- }
-
- rc := sqlite3.Xsqlite3_deserialize(c.tls, c.db, zSchema, pBuf, int64(bufLen), int64(bufLen), sqlite3.SQLITE_DESERIALIZE_RESIZEABLE|sqlite3.SQLITE_DESERIALIZE_FREEONCLOSE)
- if rc != sqlite3.SQLITE_OK {
- return c.errstr(rc)
- }
- return nil
-}
-
-// Backup object is used to manage progress and cleanup an online backup. It
-// is returned by NewBackup or NewRestore.
-type Backup struct {
- srcConn *conn // source database connection
- dstConn *conn // destination database connection
- pBackup uintptr // sqlite3_backup object pointer
-}
-
-// NewBackup returns a Backup object that will create an online backup of
-// current database to the databased pointed by the passed URI.
-func (c *conn) NewBackup(dstUri string) (*Backup, error) {
- dstConn, err := newConn(dstUri)
- if err != nil {
- return nil, err
- }
- backup, err := c.backup(dstConn, false)
- if err != nil {
- dstConn.Close()
- }
- return backup, err
-}
-
-// NewRestore returns a Backup object that will restore a backup to current
-// database from the databased pointed by the passed URI.
-func (c *conn) NewRestore(srcUri string) (*Backup, error) {
- srcConn, err := newConn(srcUri)
- if err != nil {
- return nil, err
- }
- backup, err := c.backup(srcConn, true)
- if err != nil {
- srcConn.Close()
- }
- return backup, err
-}
-
-func (c *conn) backup(remoteConn *conn, restore bool) (_ *Backup, finalErr error) {
- srcSchema := sqlite3.Xsqlite3_db_name(c.tls, c.db, 0)
- if srcSchema == 0 {
- return nil, fmt.Errorf("failed to get main source db name")
- }
-
- dstSchema := sqlite3.Xsqlite3_db_name(remoteConn.tls, remoteConn.db, 0)
- if dstSchema == 0 {
- return nil, fmt.Errorf("failed to get main destination db name")
- }
-
- var pBackup uintptr
- if restore {
- pBackup = sqlite3.Xsqlite3_backup_init(c.tls, c.db, srcSchema, remoteConn.db, dstSchema)
- } else {
- pBackup = sqlite3.Xsqlite3_backup_init(c.tls, remoteConn.db, dstSchema, c.db, srcSchema)
- }
- if pBackup <= 0 {
- rc := sqlite3.Xsqlite3_errcode(c.tls, remoteConn.db)
- return nil, c.errstr(rc)
- }
-
- return &Backup{srcConn: c, dstConn: remoteConn, pBackup: pBackup}, nil
-}
-
-// Step will copy up to n pages between the source and destination databases
-// specified by the backup object. If n is negative, all remaining source
-// pages are copied.
-// If it successfully copies n pages and there are still more pages to be
-// copied, then the function returns true with no error. If it successfully
-// finishes copying all pages from source to destination, then it returns
-// false with no error. If an error occurs while running, then an error is
-// returned.
-func (b *Backup) Step(n int32) (bool, error) {
- rc := sqlite3.Xsqlite3_backup_step(b.srcConn.tls, b.pBackup, n)
- if rc == sqlite3.SQLITE_OK {
- return true, nil
- } else if rc == sqlite3.SQLITE_DONE {
- return false, nil
- } else {
- return false, b.srcConn.errstr(rc)
- }
-}
-
-// Finish releases all resources associated with the Backup object. The Backup
-// object is invalid and may not be used following a call to Finish.
-func (b *Backup) Finish() error {
- rc := sqlite3.Xsqlite3_backup_finish(b.srcConn.tls, b.pBackup)
- b.dstConn.Close()
- if rc == sqlite3.SQLITE_OK {
- return nil
- } else {
- return b.srcConn.errstr(rc)
- }
-}
-
type ExecQuerierContext interface {
driver.ExecerContext
driver.QueryerContext
@@ -1997,21 +343,6 @@ type HookRegisterer interface {
RegisterRollbackHook(RollbackHookFn)
}
-// Commit releases all resources associated with the Backup object but does not
-// close the destination database connection.
-//
-// The destination database connection is returned to the caller or an error if raised.
-// It is the responsibility of the caller to handle the connection closure.
-func (b *Backup) Commit() (driver.Conn, error) {
- rc := sqlite3.Xsqlite3_backup_finish(b.srcConn.tls, b.pBackup)
-
- if rc == sqlite3.SQLITE_OK {
- return b.dstConn, nil
- } else {
- return nil, b.srcConn.errstr(rc)
- }
-}
-
// ConnectionHookFn function type for a connection hook on the Driver. Connection
// hooks are called after the connection has been set up.
type ConnectionHookFn func(
@@ -2019,96 +350,6 @@ type ConnectionHookFn func(
dsn string,
) error
-// Driver implements database/sql/driver.Driver.
-type Driver struct {
- // user defined functions that are added to every new connection on Open
- udfs map[string]*userDefinedFunction
- // collations that are added to every new connection on Open
- collations map[string]*collation
- // connection hooks are called after a connection is opened
- connectionHooks []ConnectionHookFn
-}
-
-var d = &Driver{
- udfs: make(map[string]*userDefinedFunction, 0),
- collations: make(map[string]*collation, 0),
- connectionHooks: make([]ConnectionHookFn, 0),
-}
-
-func newDriver() *Driver { return d }
-
-// Open returns a new connection to the database. The name is a string in a
-// driver-specific format.
-//
-// Open may return a cached connection (one previously closed), but doing so is
-// unnecessary; the sql package maintains a pool of idle connections for
-// efficient re-use.
-//
-// The returned connection is only used by one goroutine at a time.
-//
-// The name may be a filename, e.g., "/tmp/mydata.sqlite", or a URI, in which
-// case it may include a '?' followed by one or more query parameters.
-// For example, "file:///tmp/mydata.sqlite?_pragma=foreign_keys(1)&_time_format=sqlite".
-// The supported query parameters are:
-//
-// _pragma: Each value will be run as a "PRAGMA ..." statement (with the PRAGMA
-// keyword added for you). May be specified more than once, '&'-separated. For more
-// information on supported PRAGMAs see: https://www.sqlite.org/pragma.html
-//
-// _time_format: The name of a format to use when writing time values to the
-// database. Currently the only supported value is "sqlite", which corresponds
-// to format 7 from https://www.sqlite.org/lang_datefunc.html#time_values,
-// including the timezone specifier. If this parameter is not specified, then
-// the default String() format will be used.
-//
-// _time_integer_format: The name of a integer format to use when writing time values.
-// By default, the time is stored as string and the format can be set with _time_format
-// parameter. If _time_integer_format is set, the time will be stored as an integer and
-// the integer value will depend on the integer format.
-// If you decide to set both _time_format and _time_integer_format, the time will be
-// converted as integer and the _time_format value will be ignored.
-// Currently the supported value are "unix","unix_milli", "unix_micro" and "unix_nano",
-// which corresponds to seconds, milliseconds, microseconds or nanoseconds
-// since unixepoch (1 January 1970 00:00:00 UTC).
-//
-// _inttotime: Enable conversion of time column (DATE, DATETIME,TIMESTAMP) from integer
-// to time if the field contain integer (int64).
-//
-// _txlock: The locking behavior to use when beginning a transaction. May be
-// "deferred" (the default), "immediate", or "exclusive" (case insensitive). See:
-// https://www.sqlite.org/lang_transaction.html#deferred_immediate_and_exclusive_transactions
-func (d *Driver) Open(name string) (conn driver.Conn, err error) {
- if dmesgs {
- defer func() {
- dmesg("name %q: (driver.Conn %p, err %v)", name, conn, err)
- }()
- }
- c, err := newConn(name)
- if err != nil {
- return nil, err
- }
-
- for _, udf := range d.udfs {
- if err = c.createFunctionInternal(udf); err != nil {
- c.Close()
- return nil, err
- }
- }
- for _, coll := range d.collations {
- if err = c.createCollationInternal(coll); err != nil {
- c.Close()
- return nil, err
- }
- }
- for _, connHookFn := range d.connectionHooks {
- if err = connHookFn(c, name); err != nil {
- c.Close()
- return nil, fmt.Errorf("connection hook: %w", err)
- }
- }
- return c, nil
-}
-
// FunctionContext represents the context user defined functions execute in.
// Fields and/or methods of this type may get addedd in the future.
type FunctionContext struct {
@@ -2260,12 +501,6 @@ func registerFunction(
return nil
}
-// RegisterConnectionHook registers a function to be called after each connection
-// is opened. This is called after all the connection has been set up.
-func (d *Driver) RegisterConnectionHook(fn ConnectionHookFn) {
- d.connectionHooks = append(d.connectionHooks, fn)
-}
-
// RegisterConnectionHook registers a function to be called after each connection
// is opened. This is called after all the connection has been set up.
func RegisterConnectionHook(fn ConnectionHookFn) {
@@ -2512,6 +747,21 @@ func funcTrampoline(tls *libc.TLS, ctx uintptr, argc int32, argv uintptr) {
}
}
+// sqlite3AllocCString allocates a NUL-terminated copy of s using SQLite's
+// memory allocator (sqlite3_malloc). The caller must arrange for SQLite to
+// free the returned pointer via sqlite3_free.
+func sqlite3AllocCString(tls *libc.TLS, s string) uintptr {
+ n := len(s) + 1
+ p := sqlite3.Xsqlite3_malloc(tls, int32(n))
+ if p == 0 {
+ return 0
+ }
+ mem := (*libc.RawMem)(unsafe.Pointer(p))[:n:n]
+ copy(mem, []byte(s))
+ mem[n-1] = 0
+ return p
+}
+
func stepTrampoline(tls *libc.TLS, ctx uintptr, argc int32, argv uintptr) {
impl, _ := makeAggregate(tls, ctx)
if impl == nil {
@@ -2604,13 +854,6 @@ func collationTrampoline(tls *libc.TLS, pApp uintptr, nLeft int32, zLeft uintptr
}
}
-// C documentation
-//
-// int sqlite3_limit(sqlite3*, int id, int newVal);
-func (c *conn) limit(id int, newVal int) int {
- return int(sqlite3.Xsqlite3_limit(c.tls, c.db, int32(id), int32(newVal)))
-}
-
// Limit calls sqlite3_limit, see the docs at
// https://www.sqlite.org/c3ref/limit.html for details.
//
@@ -2631,29 +874,3 @@ func Limit(c *sql.Conn, id int, newVal int) (r int, err error) {
return r, err
}
-
-// C documentation
-//
-// int sqlite3_bind_blob(sqlite3_stmt*, int, const void*, int n, void(*)(void*));
-func (c *conn) bindBlob(pstmt uintptr, idx1 int, value []byte) (uintptr, error) {
- if value == nil {
- if rc := sqlite3.Xsqlite3_bind_null(c.tls, pstmt, int32(idx1)); rc != sqlite3.SQLITE_OK {
- return 0, c.errstr(rc)
- }
- return 0, nil
- }
-
- p, err := c.malloc(len(value))
- if err != nil {
- return 0, err
- }
- if len(value) != 0 {
- copy((*libc.RawMem)(unsafe.Pointer(p))[:len(value):len(value)], value)
- }
- if rc := sqlite3.Xsqlite3_bind_blob(c.tls, pstmt, int32(idx1), p, int32(len(value)), 0); rc != sqlite3.SQLITE_OK {
- c.free(p)
- return 0, c.errstr(rc)
- }
-
- return p, nil
-}
diff --git a/vendor/modernc.org/sqlite/sqlite_go18.go b/vendor/modernc.org/sqlite/sqlite_go18.go
deleted file mode 100644
index 6e720e8..0000000
--- a/vendor/modernc.org/sqlite/sqlite_go18.go
+++ /dev/null
@@ -1,84 +0,0 @@
-// Copyright 2017 The Sqlite Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-//go:build go1.8
-// +build go1.8
-
-package sqlite // import "modernc.org/sqlite"
-
-import (
- "context"
- "database/sql/driver"
-)
-
-// Ping implements driver.Pinger
-func (c *conn) Ping(ctx context.Context) (err error) {
- if dmesgs {
- defer func() {
- dmesg("conn %p, ctx %p: err %v", c, ctx, err)
- }()
- }
- _, err = c.ExecContext(ctx, "select 1", nil)
- return err
-}
-
-// BeginTx implements driver.ConnBeginTx
-func (c *conn) BeginTx(ctx context.Context, opts driver.TxOptions) (dt driver.Tx, err error) {
- if dmesgs {
- defer func() {
- dmesg("conn %p, ctx %p, opts %+v: (driver.Tx %v, err %v)", c, ctx, opts, dt, err)
- }()
- }
- return c.begin(ctx, opts)
-}
-
-// PrepareContext implements driver.ConnPrepareContext
-func (c *conn) PrepareContext(ctx context.Context, query string) (ds driver.Stmt, err error) {
- if dmesgs {
- defer func() {
- dmesg("conn %p, ctx %p, query %q: (driver.Stmt %v, err %v)", c, ctx, query, ds, err)
- }()
- }
- return c.prepare(ctx, query)
-}
-
-// ExecContext implements driver.ExecerContext
-func (c *conn) ExecContext(ctx context.Context, query string, args []driver.NamedValue) (dr driver.Result, err error) {
- if dmesgs {
- defer func() {
- dmesg("conn %p, ctx %p, query %q, args %v: (driver.Result %p, err %v)", c, ctx, query, args, dr, err)
- }()
- }
- return c.exec(ctx, query, args)
-}
-
-// QueryContext implements driver.QueryerContext
-func (c *conn) QueryContext(ctx context.Context, query string, args []driver.NamedValue) (dr driver.Rows, err error) {
- if dmesgs {
- defer func() {
- dmesg("conn %p, ctx %p, query %q, args %v: (driver.Rows %p, err %v)", c, ctx, query, args, dr, err)
- }()
- }
- return c.query(ctx, query, args)
-}
-
-// ExecContext implements driver.StmtExecContext
-func (s *stmt) ExecContext(ctx context.Context, args []driver.NamedValue) (dr driver.Result, err error) {
- if dmesgs {
- defer func() {
- dmesg("stmt %p, ctx %p, args %v: (driver.Result %p, err %v)", s, ctx, args, dr, err)
- }()
- }
- return s.exec(ctx, args)
-}
-
-// QueryContext implements driver.StmtQueryContext
-func (s *stmt) QueryContext(ctx context.Context, args []driver.NamedValue) (dr driver.Rows, err error) {
- if dmesgs {
- defer func() {
- dmesg("stmt %p, ctx %p, args %v: (driver.Rows %p, err %v)", s, ctx, args, dr, err)
- }()
- }
- return s.query(ctx, args)
-}
diff --git a/vendor/modernc.org/sqlite/stmt.go b/vendor/modernc.org/sqlite/stmt.go
new file mode 100644
index 0000000..f585205
--- /dev/null
+++ b/vendor/modernc.org/sqlite/stmt.go
@@ -0,0 +1,472 @@
+// Copyright 2025 The Sqlite Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package sqlite // import "modernc.org/sqlite"
+
+import (
+ "context"
+ "database/sql/driver"
+ "sync/atomic"
+ "unsafe"
+
+ "modernc.org/libc"
+ sqlite3 "modernc.org/sqlite/lib"
+)
+
+type stmt struct {
+ c *conn
+ psql uintptr
+ pstmt uintptr // The cached SQLite statement handle
+}
+
+func newStmt(c *conn, sql string) (*stmt, error) {
+ p, err := libc.CString(sql)
+ if err != nil {
+ return nil, err
+ }
+ s := &stmt{c: c, psql: p}
+
+ // Attempt to prepare the statement immediately
+ // We make a copy of the pointer because prepareV2 advances it
+ psql := p
+ pstmt, err := c.prepareV2(&psql)
+ if err != nil {
+ c.free(p)
+ return nil, err
+ }
+
+ // Check if there is trailing SQL (indicating a script/multi-statement)
+ // If *psql (the tail) is 0, we consumed the whole string.
+ hasTail := *(*byte)(unsafe.Pointer(psql)) != 0
+ if pstmt != 0 && !hasTail {
+ // Optimization: Single statement. Cache it.
+ s.pstmt = pstmt
+ return s, nil
+ }
+
+ // It is either a script (hasTail) or a comment-only string (pstmt==0).
+ // For scripts: Finalize now. We will re-parse iteratively in Exec/Query
+ // to handle the multiple statements correctly using the existing loop logic.
+ if pstmt != 0 {
+ if err := c.finalize(pstmt); err != nil {
+ c.free(p)
+ return nil, err
+ }
+ }
+
+ return s, nil
+}
+
+// Close closes the statement.
+//
+// As of Go 1.1, a Stmt will not be closed if it's in use by any queries.
+func (s *stmt) Close() (err error) {
+ if s.pstmt != 0 {
+ if e := s.c.finalize(s.pstmt); e != nil {
+ err = e
+ }
+ s.pstmt = 0
+ }
+ if s.psql != 0 {
+ s.c.free(s.psql)
+ s.psql = 0
+ }
+ return err
+}
+
+// Exec executes a query that doesn't return rows, such as an INSERT or UPDATE.
+//
+// Deprecated: Drivers should implement StmtExecContext instead (or
+// additionally).
+func (s *stmt) Exec(args []driver.Value) (driver.Result, error) { //TODO StmtExecContext
+ return s.exec(context.Background(), toNamedValues(args))
+}
+
+// toNamedValues converts []driver.Value to []driver.NamedValue
+func toNamedValues(vals []driver.Value) (r []driver.NamedValue) {
+ r = make([]driver.NamedValue, len(vals))
+ for i, val := range vals {
+ r[i] = driver.NamedValue{Value: val, Ordinal: i + 1}
+ }
+ return r
+}
+
+func (s *stmt) exec(ctx context.Context, args []driver.NamedValue) (r driver.Result, err error) {
+ var pstmt uintptr
+ var done int32
+ if ctx != nil {
+ if ctxDone := ctx.Done(); ctxDone != nil {
+ select {
+ case <-ctxDone:
+ return nil, ctx.Err()
+ default:
+ }
+ defer interruptOnDone(ctx, s.c, &done)()
+ }
+ }
+
+ defer func() {
+ if ctx != nil && atomic.LoadInt32(&done) != 0 {
+ r, err = nil, ctx.Err()
+ }
+ if pstmt != 0 {
+ // ensure stmt finalized.
+ e := s.c.finalize(pstmt)
+
+ if err == nil && e != nil {
+ // prioritize original
+ // returned error.
+ err = e
+ }
+ }
+ }()
+
+ // OPTIMIZED PATH: Single Cached Statement
+ if s.pstmt != 0 {
+ err = func() error {
+ // Bind
+ n, err := s.c.bindParameterCount(s.pstmt)
+ if err != nil {
+ return err
+ }
+ if n != 0 {
+ allocs, err := s.c.bind(s.pstmt, n, args)
+ if err != nil {
+ return err
+ }
+ // Free allocations after step
+ if len(allocs) != 0 {
+ defer func() {
+ for _, v := range allocs {
+ s.c.free(v)
+ }
+ }()
+ }
+ }
+
+ // Step
+ rc, err := s.c.step(s.pstmt)
+ if err != nil {
+ return err
+ }
+
+ // Handle Result
+ switch rc & 0xff {
+ case sqlite3.SQLITE_DONE, sqlite3.SQLITE_ROW:
+ r, err = newResult(s.c)
+ default:
+ return s.c.errstr(int32(rc))
+ }
+ return nil
+ }()
+
+ // RESET (Crucial: Do not finalize)
+ // We must reset the VM to allow reuse.
+ // We also clear bindings to prevent leaking memory or state to next call.
+ if resetErr := s.c.reset(s.pstmt); resetErr != nil && err == nil {
+ err = resetErr
+ }
+ if clearErr := s.c.clearBindings(s.pstmt); clearErr != nil && err == nil {
+ err = clearErr
+ }
+ return r, err
+ }
+
+ // FALLBACK PATH: Multi-statement script
+ for psql := s.psql; *(*byte)(unsafe.Pointer(psql)) != 0 && atomic.LoadInt32(&done) == 0; {
+ if pstmt, err = s.c.prepareV2(&psql); err != nil {
+ return nil, err
+ }
+
+ if pstmt == 0 {
+ continue
+ }
+ err = func() (err error) {
+ n, err := s.c.bindParameterCount(pstmt)
+ if err != nil {
+ return err
+ }
+
+ if n != 0 {
+ allocs, err := s.c.bind(pstmt, n, args)
+ if err != nil {
+ return err
+ }
+
+ if len(allocs) != 0 {
+ defer func() {
+ for _, v := range allocs {
+ s.c.free(v)
+ }
+ }()
+ }
+ }
+
+ rc, err := s.c.step(pstmt)
+ if err != nil {
+ return err
+ }
+
+ switch rc & 0xff {
+ case sqlite3.SQLITE_DONE, sqlite3.SQLITE_ROW:
+ r, err = newResult(s.c)
+ default:
+ return s.c.errstr(int32(rc))
+ }
+
+ return nil
+ }()
+
+ e := s.c.finalize(pstmt)
+ pstmt = 0 // done with
+
+ if err == nil && e != nil {
+ // prioritize original
+ // returned error.
+ err = e
+ }
+
+ if err != nil {
+ return nil, err
+ }
+ }
+ return r, err
+}
+
+// NumInput returns the number of placeholder parameters.
+//
+// If NumInput returns >= 0, the sql package will sanity check argument counts
+// from callers and return errors to the caller before the statement's Exec or
+// Query methods are called.
+//
+// NumInput may also return -1, if the driver doesn't know its number of
+// placeholders. In that case, the sql package will not sanity check Exec or
+// Query argument counts.
+func (s *stmt) NumInput() (n int) {
+ return -1
+}
+
+// Query executes a query that may return rows, such as a
+// SELECT.
+//
+// Deprecated: Drivers should implement StmtQueryContext instead (or
+// additionally).
+func (s *stmt) Query(args []driver.Value) (driver.Rows, error) { //TODO StmtQueryContext
+ return s.query(context.Background(), toNamedValues(args))
+}
+
+func (s *stmt) query(ctx context.Context, args []driver.NamedValue) (r driver.Rows, err error) {
+ var pstmt uintptr
+ var done int32
+ if ctx != nil {
+ if ctxDone := ctx.Done(); ctxDone != nil {
+ select {
+ case <-ctxDone:
+ return nil, ctx.Err()
+ default:
+ }
+ defer interruptOnDone(ctx, s.c, &done)()
+ }
+ }
+
+ var allocs []uintptr
+
+ defer func() {
+ if ctx != nil && atomic.LoadInt32(&done) != 0 {
+ if r != nil {
+ r.Close()
+ }
+ r, err = nil, ctx.Err()
+ } else if r == nil && err == nil {
+ r, err = newRows(s.c, pstmt, allocs, true)
+ }
+
+ if pstmt != 0 {
+ // ensure stmt finalized.
+ e := s.c.finalize(pstmt)
+
+ if err == nil && e != nil {
+ // prioritize original
+ // returned error.
+ err = e
+ }
+ }
+
+ }()
+
+ // OPTIMIZED PATH: Single Cached Statement
+ if s.pstmt != 0 {
+ // Bind
+ n, err := s.c.bindParameterCount(s.pstmt)
+ if err != nil {
+ return nil, err
+ }
+ if n != 0 {
+ if allocs, err = s.c.bind(s.pstmt, n, args); err != nil {
+ return nil, err
+ }
+ }
+
+ // Step
+ rc, err := s.c.step(s.pstmt)
+ if err != nil {
+ // On error, we must free allocs manually because 'newRows' won't take ownership
+ for _, v := range allocs {
+ s.c.free(v)
+ }
+ s.c.reset(s.pstmt)
+ s.c.clearBindings(s.pstmt)
+ return nil, err
+ }
+
+ // Handle Result
+ switch rc & 0xff {
+ case sqlite3.SQLITE_ROW:
+ // Pass reuseStmt=true
+ if r, err = newRows(s.c, s.pstmt, allocs, false); err != nil {
+ s.c.reset(s.pstmt)
+ s.c.clearBindings(s.pstmt)
+ return nil, err
+ }
+ r.(*rows).reuseStmt = true
+ return r, nil
+
+ case sqlite3.SQLITE_DONE:
+ // No rows. Reset immediately.
+ // We still return a rows object (empty), but we can reset the stmt now
+ // because the empty rows object won't call step() again.
+ // However, standard newRows behavior expects a valid stmt to get columns.
+ // Let's rely on newRows to read columns, then it returns.
+
+ // Actually, if we pass reuseStmt=true to an empty set,
+ // rows.Close() will eventually reset it.
+ if r, err = newRows(s.c, s.pstmt, allocs, true); err != nil {
+ s.c.reset(s.pstmt)
+ s.c.clearBindings(s.pstmt)
+ return nil, err
+ }
+ r.(*rows).reuseStmt = true
+ return r, nil
+
+ default:
+ // Error case
+ for _, v := range allocs {
+ s.c.free(v)
+ }
+ s.c.reset(s.pstmt)
+ s.c.clearBindings(s.pstmt)
+ return nil, s.c.errstr(int32(rc))
+ }
+ }
+
+ // FALLBACK PATH: Multi-statement script
+ for psql := s.psql; *(*byte)(unsafe.Pointer(psql)) != 0 && atomic.LoadInt32(&done) == 0; {
+ if pstmt, err = s.c.prepareV2(&psql); err != nil {
+ return nil, err
+ }
+
+ if pstmt == 0 {
+ continue
+ }
+
+ err = func() (err error) {
+ n, err := s.c.bindParameterCount(pstmt)
+ if err != nil {
+ return err
+ }
+
+ if n != 0 {
+ if allocs, err = s.c.bind(pstmt, n, args); err != nil {
+ return err
+ }
+ }
+
+ rc, err := s.c.step(pstmt)
+ if err != nil {
+ return err
+ }
+
+ switch rc & 0xff {
+ case sqlite3.SQLITE_ROW:
+ if r != nil {
+ r.Close()
+ }
+ if r, err = newRows(s.c, pstmt, allocs, false); err != nil {
+ return err
+ }
+
+ pstmt = 0
+ return nil
+ case sqlite3.SQLITE_DONE:
+ if r == nil {
+ if r, err = newRows(s.c, pstmt, allocs, true); err != nil {
+ return err
+ }
+ pstmt = 0
+ return nil
+ }
+
+ // nop
+ default:
+ return s.c.errstr(int32(rc))
+ }
+
+ if *(*byte)(unsafe.Pointer(psql)) == 0 {
+ if r != nil {
+ r.Close()
+ }
+ if r, err = newRows(s.c, pstmt, allocs, true); err != nil {
+ return err
+ }
+
+ pstmt = 0
+ }
+ return nil
+ }()
+
+ e := s.c.finalize(pstmt)
+ pstmt = 0 // done with
+
+ if err == nil && e != nil {
+ // prioritize original
+ // returned error.
+ err = e
+ }
+
+ if err != nil {
+ return nil, err
+ }
+ }
+ return r, err
+}
+
+// ExecContext implements driver.StmtExecContext
+func (s *stmt) ExecContext(ctx context.Context, args []driver.NamedValue) (dr driver.Result, err error) {
+ if dmesgs {
+ defer func() {
+ dmesg("stmt %p, ctx %p, args %v: (driver.Result %p, err %v)", s, ctx, args, dr, err)
+ }()
+ }
+ return s.exec(ctx, args)
+}
+
+// QueryContext implements driver.StmtQueryContext
+func (s *stmt) QueryContext(ctx context.Context, args []driver.NamedValue) (dr driver.Rows, err error) {
+ if dmesgs {
+ defer func() {
+ dmesg("stmt %p, ctx %p, args %v: (driver.Rows %p, err %v)", s, ctx, args, dr, err)
+ }()
+ }
+ return s.query(ctx, args)
+}
+
+// C documentation
+//
+// int sqlite3_clear_bindings(sqlite3_stmt*);
+func (c *conn) clearBindings(pstmt uintptr) error {
+ if rc := sqlite3.Xsqlite3_clear_bindings(c.tls, pstmt); rc != sqlite3.SQLITE_OK {
+ return c.errstr(rc)
+ }
+ return nil
+}
diff --git a/vendor/modernc.org/sqlite/tx.go b/vendor/modernc.org/sqlite/tx.go
new file mode 100644
index 0000000..710664f
--- /dev/null
+++ b/vendor/modernc.org/sqlite/tx.go
@@ -0,0 +1,62 @@
+// Copyright 2025 The Sqlite Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package sqlite // import "modernc.org/sqlite"
+
+import (
+ "context"
+ "database/sql/driver"
+
+ "modernc.org/libc"
+ sqlite3 "modernc.org/sqlite/lib"
+)
+
+type tx struct {
+ c *conn
+}
+
+func newTx(ctx context.Context, c *conn, opts driver.TxOptions) (*tx, error) {
+ r := &tx{c: c}
+
+ sql := "begin"
+ if !opts.ReadOnly && c.beginMode != "" {
+ sql = "begin " + c.beginMode
+ }
+
+ if err := r.exec(ctx, sql); err != nil {
+ return nil, err
+ }
+
+ return r, nil
+}
+
+// Commit implements driver.Tx.
+func (t *tx) Commit() (err error) {
+ return t.exec(context.Background(), "commit")
+}
+
+// Rollback implements driver.Tx.
+func (t *tx) Rollback() (err error) {
+ return t.exec(context.Background(), "rollback")
+}
+
+func (t *tx) exec(ctx context.Context, sql string) (err error) {
+ psql, err := libc.CString(sql)
+ if err != nil {
+ return err
+ }
+
+ defer t.c.free(psql)
+ //TODO use t.conn.ExecContext() instead
+
+ if ctx != nil && ctx.Done() != nil {
+ defer interruptOnDone(ctx, t.c, nil)()
+ }
+
+ if rc := sqlite3.Xsqlite3_exec(t.c.tls, t.c.db, psql, 0, 0, 0); rc != sqlite3.SQLITE_OK {
+ return t.c.errstr(rc)
+ }
+
+ return nil
+}
diff --git a/vendor/modernc.org/sqlite/vtab.go b/vendor/modernc.org/sqlite/vtab.go
new file mode 100644
index 0000000..6fe1fed
--- /dev/null
+++ b/vendor/modernc.org/sqlite/vtab.go
@@ -0,0 +1,872 @@
+// Copyright 2025 The Sqlite Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package sqlite // import "modernc.org/sqlite"
+
+import (
+ "fmt"
+ "math"
+ "sync"
+ "unsafe"
+
+ "modernc.org/libc"
+ sqlite3 "modernc.org/sqlite/lib"
+ "modernc.org/sqlite/vtab"
+)
+
+func init() {
+ vtab.SetRegisterFunc(registerModule)
+}
+
+var (
+ // vtabModules tracks Go virtual table modules registered via the vtab
+ // package. Each module is identified by an integer ID used as pAux when
+ // calling sqlite3_create_module_v2, so that trampolines can recover the
+ // Go Module implementation.
+ vtabModules = struct {
+ mu sync.RWMutex
+ m map[uintptr]*goModule
+ ids idGen
+ // name2id keeps stable IDs per module name to avoid unbounded growth
+ // across connections.
+ name2id map[string]uintptr
+ }{
+ m: make(map[uintptr]*goModule),
+ name2id: make(map[string]uintptr),
+ }
+
+ // nativeModules holds sqlite3_module instances for registered modules. We
+ // keep them in Go memory so their addresses remain stable for the C layer.
+ nativeModules = struct {
+ mu sync.RWMutex
+ m map[string]*sqlite3.Sqlite3_module
+ }{
+ m: make(map[string]*sqlite3.Sqlite3_module),
+ }
+
+ // vtabTables maps sqlite3_vtab* (pVtab) to the corresponding Go Table.
+ vtabTables = struct {
+ mu sync.RWMutex
+ m map[uintptr]*goTable
+ }{
+ m: make(map[uintptr]*goTable),
+ }
+
+ // vtabCursors maps sqlite3_vtab_cursor* (pCursor) to the corresponding Go
+ // Cursor.
+ vtabCursors = struct {
+ mu sync.RWMutex
+ m map[uintptr]*goCursor
+ }{
+ m: make(map[uintptr]*goCursor),
+ }
+)
+
+// goModule wraps a vtab.Module implementation with its name.
+type goModule struct {
+ name string
+ impl vtab.Module
+}
+
+// goTable wraps a vtab.Table implementation and remembers its module.
+type goTable struct {
+ mod *goModule
+ impl vtab.Table
+}
+
+// goCursor wraps a vtab.Cursor implementation and remembers its table.
+type goCursor struct {
+ table *goTable
+ impl vtab.Cursor
+}
+
+// Use aliases of the underlying lib types so field layouts remain correct.
+type cIndexConstraint = sqlite3.Tsqlite3_index_constraint
+type cIndexOrderBy = sqlite3.Tsqlite3_index_orderby
+type cConstraintUsage = sqlite3.Tsqlite3_index_constraint_usage
+
+// registerModule is installed as the hook for vtab.RegisterModule.
+func registerModule(name string, m vtab.Module) error {
+ if _, exists := d.modules[name]; exists {
+ return fmt.Errorf("sqlite: module %q already registered", name)
+ }
+ d.modules[name] = m
+ return nil
+}
+
+// registerModules installs all globally registered vtab modules on this
+// connection by calling sqlite3_create_module_v2 for each one.
+func (c *conn) registerModules() error {
+ for name, mod := range d.modules {
+ if err := c.registerSingleModule(name, mod); err != nil {
+ return err
+ }
+ }
+ return nil
+}
+
+func (c *conn) registerSingleModule(name string, m vtab.Module) error {
+ // Allocate or reuse a stable ID for this module name and remember the Go implementation.
+ vtabModules.mu.Lock()
+ modID, ok := vtabModules.name2id[name]
+ if !ok {
+ modID = vtabModules.ids.next()
+ vtabModules.name2id[name] = modID
+ }
+ vtabModules.m[modID] = &goModule{name: name, impl: m}
+ vtabModules.mu.Unlock()
+
+ nativeModules.mu.Lock()
+ defer nativeModules.mu.Unlock()
+ if _, exists := nativeModules.m[name]; exists {
+ // Module struct already created; nothing more to do for this connection.
+ return nil
+ }
+
+ // Build a sqlite3_module descriptor with trampolines.
+ mod := &sqlite3.Sqlite3_module{}
+ mod.FiVersion = 1
+ mod.FxCreate = cFuncPointer(vtabCreateTrampoline)
+ mod.FxConnect = cFuncPointer(vtabConnectTrampoline)
+ mod.FxBestIndex = cFuncPointer(vtabBestIndexTrampoline)
+ mod.FxDisconnect = cFuncPointer(vtabDisconnectTrampoline)
+ mod.FxDestroy = cFuncPointer(vtabDestroyTrampoline)
+ mod.FxOpen = cFuncPointer(vtabOpenTrampoline)
+ mod.FxClose = cFuncPointer(vtabCloseTrampoline)
+ mod.FxFilter = cFuncPointer(vtabFilterTrampoline)
+ mod.FxNext = cFuncPointer(vtabNextTrampoline)
+ mod.FxEof = cFuncPointer(vtabEofTrampoline)
+ mod.FxColumn = cFuncPointer(vtabColumnTrampoline)
+ mod.FxRowid = cFuncPointer(vtabRowidTrampoline)
+ mod.FxFindFunction = cFuncPointer(vtabFindFunctionTrampoline)
+ mod.FxRename = cFuncPointer(vtabRenameTrampoline)
+ mod.FxUpdate = cFuncPointer(vtabUpdateTrampoline)
+ mod.FxBegin = cFuncPointer(vtabBeginTrampoline)
+ mod.FxSync = cFuncPointer(vtabSyncTrampoline)
+ mod.FxCommit = cFuncPointer(vtabCommitTrampoline)
+ mod.FxRollback = cFuncPointer(vtabRollbackTrampoline)
+ mod.FxSavepoint = cFuncPointer(vtabSavepointTrampoline)
+ mod.FxRelease = cFuncPointer(vtabReleaseTrampoline)
+ mod.FxRollbackTo = cFuncPointer(vtabRollbackToTrampoline)
+
+ nativeModules.m[name] = mod
+
+ // Prepare C string for module name.
+ zName, err := libc.CString(name)
+ if err != nil {
+ return err
+ }
+ defer libc.Xfree(c.tls, zName)
+
+ // Register the module with this connection.
+ if rc := sqlite3.Xsqlite3_create_module_v2(c.tls, c.db, zName, uintptr(unsafe.Pointer(mod)), modID, 0); rc != sqlite3.SQLITE_OK {
+ return fmt.Errorf("create_module %q: %w", name, c.errstr(rc))
+ }
+ return nil
+}
+
+// vtabCreateTrampoline is the xCreate callback. It invokes the corresponding
+// Go vtab.Module.Create method, declares a default schema based on argv, and
+// allocates a sqlite3_vtab.
+func vtabCreateTrampoline(tls *libc.TLS, db uintptr, pAux uintptr, argc int32, argv uintptr, ppVtab uintptr, pzErr uintptr) int32 {
+ gm := lookupGoModule(pAux)
+ if gm == nil {
+ setVtabError(tls, pzErr, fmt.Sprintf("vtab: unknown module id %d", pAux))
+ return sqlite3.SQLITE_ERROR
+ }
+ args := extractVtabArgs(tls, argc, argv)
+ ctx := vtab.NewContext(func(schema string) error {
+ zSchema, err := libc.CString(schema)
+ if err != nil {
+ return err
+ }
+ defer libc.Xfree(tls, zSchema)
+ if rc := sqlite3.Xsqlite3_declare_vtab(tls, db, zSchema); rc != sqlite3.SQLITE_OK {
+ return fmt.Errorf("declare_vtab failed: rc=%d", rc)
+ }
+ return nil
+ })
+ tbl, err := gm.impl.Create(ctx, args)
+ if err != nil {
+ setVtabError(tls, pzErr, err.Error())
+ return sqlite3.SQLITE_ERROR
+ }
+ sz := unsafe.Sizeof(sqlite3.Sqlite3_vtab{})
+ p := sqlite3.Xsqlite3_malloc(tls, int32(sz))
+ if p == 0 {
+ setVtabError(tls, pzErr, "vtab: out of memory")
+ return sqlite3.SQLITE_NOMEM
+ }
+ mem := (*libc.RawMem)(unsafe.Pointer(p))[:sz:sz]
+ for i := range mem {
+ mem[i] = 0
+ }
+ *(*uintptr)(unsafe.Pointer(ppVtab)) = p
+
+ gt := &goTable{mod: gm, impl: tbl}
+ vtabTables.mu.Lock()
+ vtabTables.m[p] = gt
+ vtabTables.mu.Unlock()
+ return sqlite3.SQLITE_OK
+}
+
+// vtabConnectTrampoline is the xConnect callback. It mirrors
+// vtabCreateTrampoline but calls Module.Connect.
+func vtabConnectTrampoline(tls *libc.TLS, db uintptr, pAux uintptr, argc int32, argv uintptr, ppVtab uintptr, pzErr uintptr) int32 {
+ gm := lookupGoModule(pAux)
+ if gm == nil {
+ setVtabError(tls, pzErr, fmt.Sprintf("vtab: unknown module id %d", pAux))
+ return sqlite3.SQLITE_ERROR
+ }
+ args := extractVtabArgs(tls, argc, argv)
+ ctx := vtab.NewContext(func(schema string) error {
+ zSchema, err := libc.CString(schema)
+ if err != nil {
+ return err
+ }
+ defer libc.Xfree(tls, zSchema)
+ if rc := sqlite3.Xsqlite3_declare_vtab(tls, db, zSchema); rc != sqlite3.SQLITE_OK {
+ return fmt.Errorf("declare_vtab failed: rc=%d", rc)
+ }
+ return nil
+ })
+ tbl, err := gm.impl.Connect(ctx, args)
+ if err != nil {
+ setVtabError(tls, pzErr, err.Error())
+ return sqlite3.SQLITE_ERROR
+ }
+ sz := unsafe.Sizeof(sqlite3.Sqlite3_vtab{})
+ p := sqlite3.Xsqlite3_malloc(tls, int32(sz))
+ if p == 0 {
+ setVtabError(tls, pzErr, "vtab: out of memory")
+ return sqlite3.SQLITE_NOMEM
+ }
+ mem := (*libc.RawMem)(unsafe.Pointer(p))[:sz:sz]
+ for i := range mem {
+ mem[i] = 0
+ }
+ *(*uintptr)(unsafe.Pointer(ppVtab)) = p
+
+ gt := &goTable{mod: gm, impl: tbl}
+ vtabTables.mu.Lock()
+ vtabTables.m[p] = gt
+ vtabTables.mu.Unlock()
+ return sqlite3.SQLITE_OK
+}
+
+// vtabBestIndexTrampoline maps sqlite3_index_info to vtab.IndexInfo and
+// delegates to Table.BestIndex. It also mirrors constraint and ORDER BY
+// information into the Go structure.
+func vtabBestIndexTrampoline(tls *libc.TLS, pVtab uintptr, pInfo uintptr) int32 {
+ vtabTables.mu.RLock()
+ gt := vtabTables.m[pVtab]
+ vtabTables.mu.RUnlock()
+ if gt == nil {
+ return sqlite3.SQLITE_ERROR
+ }
+
+ idx := (*sqlite3.Sqlite3_index_info)(unsafe.Pointer(pInfo))
+ info := &vtab.IndexInfo{}
+
+ // Populate Constraints from sqlite3_index_info.aConstraint.
+ if idx.FnConstraint > 0 && idx.FaConstraint != 0 {
+ n := int(idx.FnConstraint)
+ cs := make([]vtab.Constraint, 0, n)
+ base := idx.FaConstraint
+ sz := unsafe.Sizeof(cIndexConstraint{})
+ for i := 0; i < n; i++ {
+ c := (*cIndexConstraint)(unsafe.Pointer(base + uintptr(i)*sz))
+ op := vtab.OpUnknown
+ switch int32(c.Fop) {
+ case sqlite3.SQLITE_INDEX_CONSTRAINT_EQ:
+ op = vtab.OpEQ
+ case sqlite3.SQLITE_INDEX_CONSTRAINT_GT:
+ op = vtab.OpGT
+ case sqlite3.SQLITE_INDEX_CONSTRAINT_LE:
+ op = vtab.OpLE
+ case sqlite3.SQLITE_INDEX_CONSTRAINT_LT:
+ op = vtab.OpLT
+ case sqlite3.SQLITE_INDEX_CONSTRAINT_GE:
+ op = vtab.OpGE
+ case sqlite3.SQLITE_INDEX_CONSTRAINT_MATCH:
+ op = vtab.OpMATCH
+ case sqlite3.SQLITE_INDEX_CONSTRAINT_NE:
+ op = vtab.OpNE
+ case sqlite3.SQLITE_INDEX_CONSTRAINT_IS:
+ op = vtab.OpIS
+ case sqlite3.SQLITE_INDEX_CONSTRAINT_ISNOT:
+ op = vtab.OpISNOT
+ case sqlite3.SQLITE_INDEX_CONSTRAINT_ISNULL:
+ op = vtab.OpISNULL
+ case sqlite3.SQLITE_INDEX_CONSTRAINT_ISNOTNULL:
+ op = vtab.OpISNOTNULL
+ case sqlite3.SQLITE_INDEX_CONSTRAINT_LIKE:
+ op = vtab.OpLIKE
+ case sqlite3.SQLITE_INDEX_CONSTRAINT_GLOB:
+ op = vtab.OpGLOB
+ case sqlite3.SQLITE_INDEX_CONSTRAINT_REGEXP:
+ op = vtab.OpREGEXP
+ case sqlite3.SQLITE_INDEX_CONSTRAINT_FUNCTION:
+ op = vtab.OpFUNCTION
+ case sqlite3.SQLITE_INDEX_CONSTRAINT_LIMIT:
+ op = vtab.OpLIMIT
+ case sqlite3.SQLITE_INDEX_CONSTRAINT_OFFSET:
+ op = vtab.OpOFFSET
+ }
+ cs = append(cs, vtab.Constraint{
+ Column: int(c.FiColumn),
+ Op: op,
+ Usable: c.Fusable != 0,
+ ArgIndex: -1, // 0-based; -1 means ignore
+ Omit: false,
+ })
+ }
+ info.Constraints = cs
+ }
+
+ // Populate OrderBy from sqlite3_index_info.aOrderBy.
+ if idx.FnOrderBy > 0 && idx.FaOrderBy != 0 {
+ n := int(idx.FnOrderBy)
+ obs := make([]vtab.OrderBy, 0, n)
+ base := idx.FaOrderBy
+ sz := unsafe.Sizeof(cIndexOrderBy{})
+ for i := 0; i < n; i++ {
+ ob := (*cIndexOrderBy)(unsafe.Pointer(base + uintptr(i)*sz))
+ obs = append(obs, vtab.OrderBy{
+ Column: int(ob.FiColumn),
+ Desc: ob.Fdesc != 0,
+ })
+ }
+ info.OrderBy = obs
+ }
+
+ // Populate ColUsed and idxFlags for module visibility.
+ if idx.FcolUsed != 0 {
+ info.ColUsed = uint64(idx.FcolUsed)
+ }
+ if idx.FidxFlags != 0 {
+ info.IdxFlags = int(idx.FidxFlags)
+ }
+
+ if err := gt.impl.BestIndex(info); err != nil {
+ // Report error via zErrMsg on pVtab.
+ setVtabZErrMsg(tls, pVtab, err.Error())
+ return sqlite3.SQLITE_ERROR
+ }
+
+ // Propagate any ArgIndex assignments back into aConstraintUsage so that
+ // SQLite will populate xFilter's argv[] accordingly.
+ if idx.FnConstraint > 0 && idx.FaConstraintUsage != 0 && len(info.Constraints) > 0 {
+ n := int(idx.FnConstraint)
+ base := idx.FaConstraintUsage
+ sz := unsafe.Sizeof(cConstraintUsage{})
+ for i := 0; i < n && i < len(info.Constraints); i++ {
+ cu := (*cConstraintUsage)(unsafe.Pointer(base + uintptr(i)*sz))
+ argIndex := info.Constraints[i].ArgIndex
+ if argIndex >= 0 {
+ // Go ArgIndex is 0-based; SQLite wants 1-based.
+ cu.FargvIndex = int32(argIndex + 1)
+ }
+ if info.Constraints[i].Omit {
+ cu.Fomit = 1
+ }
+ }
+ }
+ // Guard against int32 overflow: SQLite expects idxNum as int32.
+ if info.IdxNum < math.MinInt32 || info.IdxNum > math.MaxInt32 {
+ setVtabZErrMsg(tls, pVtab, fmt.Sprintf("vtab: IdxNum %d out of int32 range", info.IdxNum))
+ return sqlite3.SQLITE_ERROR
+ }
+ idx.FidxNum = int32(info.IdxNum)
+ if info.IdxStr != "" {
+ // Allocate using SQLite allocator because needToFreeIdxStr=1 instructs
+ // SQLite to free the string with sqlite3_free.
+ z := sqlite3AllocCString(tls, info.IdxStr)
+ if z != 0 {
+ idx.FidxStr = z
+ idx.FneedToFreeIdxStr = 1
+ }
+ }
+ if info.OrderByConsumed {
+ idx.ForderByConsumed = 1
+ }
+ if info.IdxFlags != 0 {
+ idx.FidxFlags = int32(info.IdxFlags)
+ }
+ if info.EstimatedCost != 0 {
+ idx.FestimatedCost = info.EstimatedCost
+ }
+ if info.EstimatedRows != 0 {
+ idx.FestimatedRows = sqlite3.Sqlite3_int64(info.EstimatedRows)
+ }
+ return sqlite3.SQLITE_OK
+}
+
+// vtabDisconnectTrampoline is xDisconnect. It frees the sqlite3_vtab and
+// calls Table.Disconnect.
+func vtabDisconnectTrampoline(tls *libc.TLS, pVtab uintptr) int32 {
+ vtabTables.mu.RLock()
+ gt := vtabTables.m[pVtab]
+ vtabTables.mu.RUnlock()
+ if gt != nil {
+ _ = gt.impl.Disconnect()
+ vtabTables.mu.Lock()
+ delete(vtabTables.m, pVtab)
+ vtabTables.mu.Unlock()
+ }
+ sqlite3.Xsqlite3_free(tls, pVtab)
+ return sqlite3.SQLITE_OK
+}
+
+// vtabDestroyTrampoline is xDestroy. Currently identical to Disconnect.
+func vtabDestroyTrampoline(tls *libc.TLS, pVtab uintptr) int32 {
+ vtabTables.mu.RLock()
+ gt := vtabTables.m[pVtab]
+ vtabTables.mu.RUnlock()
+ if gt != nil {
+ _ = gt.impl.Destroy()
+ vtabTables.mu.Lock()
+ delete(vtabTables.m, pVtab)
+ vtabTables.mu.Unlock()
+ }
+ sqlite3.Xsqlite3_free(tls, pVtab)
+ return sqlite3.SQLITE_OK
+}
+
+// vtabOpenTrampoline is xOpen. It allocates an empty sqlite3_vtab_cursor and
+// creates a Go Cursor via Table.Open.
+func vtabOpenTrampoline(tls *libc.TLS, pVtab uintptr, ppCursor uintptr) int32 {
+ vtabTables.mu.RLock()
+ gt := vtabTables.m[pVtab]
+ vtabTables.mu.RUnlock()
+ if gt == nil {
+ return sqlite3.SQLITE_ERROR
+ }
+
+ curImpl, err := gt.impl.Open()
+ if err != nil {
+ return sqlite3.SQLITE_ERROR
+ }
+
+ sz := unsafe.Sizeof(sqlite3.Sqlite3_vtab_cursor{})
+ p := sqlite3.Xsqlite3_malloc(tls, int32(sz))
+ if p == 0 {
+ return sqlite3.SQLITE_NOMEM
+ }
+ mem := (*libc.RawMem)(unsafe.Pointer(p))[:sz:sz]
+ for i := range mem {
+ mem[i] = 0
+ }
+ *(*uintptr)(unsafe.Pointer(ppCursor)) = p
+
+ // Link cursor back to its vtab so error reporting can set zErrMsg.
+ cur := (*sqlite3.Sqlite3_vtab_cursor)(unsafe.Pointer(p))
+ cur.FpVtab = pVtab
+
+ gc := &goCursor{table: gt, impl: curImpl}
+ vtabCursors.mu.Lock()
+ vtabCursors.m[p] = gc
+ vtabCursors.mu.Unlock()
+ return sqlite3.SQLITE_OK
+}
+
+// vtabCloseTrampoline is xClose. It frees the sqlite3_vtab_cursor and calls
+// Cursor.Close.
+func vtabCloseTrampoline(tls *libc.TLS, pCursor uintptr) int32 {
+ vtabCursors.mu.RLock()
+ gc := vtabCursors.m[pCursor]
+ vtabCursors.mu.RUnlock()
+ if gc != nil {
+ _ = gc.impl.Close()
+ vtabCursors.mu.Lock()
+ delete(vtabCursors.m, pCursor)
+ vtabCursors.mu.Unlock()
+ }
+ sqlite3.Xsqlite3_free(tls, pCursor)
+ return sqlite3.SQLITE_OK
+}
+
+// vtabFilterTrampoline is xFilter.
+func vtabFilterTrampoline(tls *libc.TLS, pCursor uintptr, idxNum int32, idxStr uintptr, argc int32, argv uintptr) int32 {
+ vtabCursors.mu.RLock()
+ gc := vtabCursors.m[pCursor]
+ vtabCursors.mu.RUnlock()
+ if gc == nil {
+ return sqlite3.SQLITE_ERROR
+ }
+
+ var idxStrGo string
+ if idxStr != 0 {
+ idxStrGo = libc.GoString(idxStr)
+ }
+ vals := functionArgs(tls, argc, argv)
+ if err := gc.impl.Filter(int(idxNum), idxStrGo, vals); err != nil {
+ // Set zErrMsg on the associated vtab for better diagnostics.
+ if pCursor != 0 {
+ cur := (*sqlite3.Sqlite3_vtab_cursor)(unsafe.Pointer(pCursor))
+ if cur.FpVtab != 0 {
+ setVtabZErrMsg(tls, cur.FpVtab, err.Error())
+ }
+ }
+ return sqlite3.SQLITE_ERROR
+ }
+ return sqlite3.SQLITE_OK
+}
+
+// vtabNextTrampoline is xNext.
+func vtabNextTrampoline(tls *libc.TLS, pCursor uintptr) int32 {
+ _ = tls
+ vtabCursors.mu.RLock()
+ gc := vtabCursors.m[pCursor]
+ vtabCursors.mu.RUnlock()
+ if gc == nil {
+ return sqlite3.SQLITE_ERROR
+ }
+ if err := gc.impl.Next(); err != nil {
+ return sqlite3.SQLITE_ERROR
+ }
+ return sqlite3.SQLITE_OK
+}
+
+// vtabEofTrampoline is xEof.
+func vtabEofTrampoline(tls *libc.TLS, pCursor uintptr) int32 {
+ _ = tls
+ vtabCursors.mu.RLock()
+ gc := vtabCursors.m[pCursor]
+ vtabCursors.mu.RUnlock()
+ if gc == nil || gc.impl.Eof() {
+ return 1
+ }
+ return 0
+}
+
+// vtabColumnTrampoline is xColumn.
+func vtabColumnTrampoline(tls *libc.TLS, pCursor uintptr, ctx uintptr, iCol int32) int32 {
+ vtabCursors.mu.RLock()
+ gc := vtabCursors.m[pCursor]
+ vtabCursors.mu.RUnlock()
+ if gc == nil {
+ sqlite3.Xsqlite3_result_null(tls, ctx)
+ return sqlite3.SQLITE_OK
+ }
+ val, err := gc.impl.Column(int(iCol))
+ if err != nil {
+ // Report via result error on the context.
+ z, cerr := libc.CString(err.Error())
+ if cerr == nil {
+ defer libc.Xfree(tls, z)
+ sqlite3.Xsqlite3_result_error(tls, ctx, z, -1)
+ sqlite3.Xsqlite3_result_error_code(tls, ctx, sqlite3.SQLITE_ERROR)
+ } else {
+ sqlite3.Xsqlite3_result_error_code(tls, ctx, sqlite3.SQLITE_ERROR)
+ }
+ return sqlite3.SQLITE_ERROR
+ }
+ if err := functionReturnValue(tls, ctx, val); err != nil {
+ // Include a descriptive error message for easier debugging
+ // (e.g., unsupported type conversions).
+ if err != nil {
+ z, cerr := libc.CString(err.Error())
+ if cerr == nil {
+ defer libc.Xfree(tls, z)
+ sqlite3.Xsqlite3_result_error(tls, ctx, z, -1)
+ }
+ }
+ sqlite3.Xsqlite3_result_error_code(tls, ctx, sqlite3.SQLITE_ERROR)
+ return sqlite3.SQLITE_ERROR
+ }
+ return sqlite3.SQLITE_OK
+}
+
+// vtabRowidTrampoline is xRowid.
+func vtabRowidTrampoline(tls *libc.TLS, pCursor uintptr, pRowid uintptr) int32 {
+ _ = tls
+ vtabCursors.mu.RLock()
+ gc := vtabCursors.m[pCursor]
+ vtabCursors.mu.RUnlock()
+ if gc == nil {
+ *(*int64)(unsafe.Pointer(pRowid)) = 0
+ return sqlite3.SQLITE_OK
+ }
+ rowid, err := gc.impl.Rowid()
+ if err != nil {
+ *(*int64)(unsafe.Pointer(pRowid)) = 0
+ return sqlite3.SQLITE_ERROR
+ }
+ *(*int64)(unsafe.Pointer(pRowid)) = rowid
+ return sqlite3.SQLITE_OK
+}
+
+func lookupGoModule(id uintptr) *goModule {
+ vtabModules.mu.RLock()
+ defer vtabModules.mu.RUnlock()
+ return vtabModules.m[id]
+}
+
+func extractVtabArgs(tls *libc.TLS, argc int32, argv uintptr) []string {
+ args := make([]string, argc)
+ for i := int32(0); i < argc; i++ {
+ cstr := *(*uintptr)(unsafe.Pointer(argv + uintptr(i)*unsafe.Sizeof(uintptr(0))))
+ args[i] = libc.GoString(cstr)
+ }
+ return args
+}
+
+func setVtabError(tls *libc.TLS, pzErr uintptr, msg string) {
+ if pzErr == 0 {
+ return
+ }
+ z := sqlite3AllocCString(tls, msg)
+ if z == 0 {
+ return
+ }
+ *(*uintptr)(unsafe.Pointer(pzErr)) = z
+}
+
+// setVtabZErrMsg sets pVtab->zErrMsg to a newly allocated C string containing
+// msg. SQLite will free this pointer.
+func setVtabZErrMsg(tls *libc.TLS, pVtab uintptr, msg string) {
+ if pVtab == 0 {
+ return
+ }
+ vt := (*sqlite3.Sqlite3_vtab)(unsafe.Pointer(pVtab))
+ if vt.FzErrMsg != 0 {
+ sqlite3.Xsqlite3_free(tls, vt.FzErrMsg)
+ vt.FzErrMsg = 0
+ }
+ z := sqlite3AllocCString(tls, msg)
+ if z == 0 {
+ return
+ }
+ vt.FzErrMsg = z
+}
+
+// Optional vtab callbacks
+
+// vtabFindFunctionTrampoline is xFindFunction. We currently do not expose a
+// Go surface for per-table SQL functions; report not found (return 0).
+func vtabFindFunctionTrampoline(tls *libc.TLS, pVtab uintptr, nArg int32, zName uintptr, pxFunc uintptr, ppArg uintptr) int32 {
+ _ = tls
+ _ = pVtab
+ _ = nArg
+ _ = zName
+ if pxFunc != 0 {
+ *(*uintptr)(unsafe.Pointer(pxFunc)) = 0
+ }
+ if ppArg != 0 {
+ *(*uintptr)(unsafe.Pointer(ppArg)) = 0
+ }
+ return 0 // not found
+}
+
+// vtabRenameTrampoline is xRename. Calls Table.Rename if implemented.
+func vtabRenameTrampoline(tls *libc.TLS, pVtab uintptr, zNew uintptr) int32 {
+ vtabTables.mu.RLock()
+ gt := vtabTables.m[pVtab]
+ vtabTables.mu.RUnlock()
+ if gt == nil {
+ return sqlite3.SQLITE_ERROR
+ }
+ name := libc.GoString(zNew)
+ if r, ok := gt.impl.(interface{ Rename(string) error }); ok {
+ if err := r.Rename(name); err != nil {
+ setVtabZErrMsg(tls, pVtab, err.Error())
+ return sqlite3.SQLITE_ERROR
+ }
+ }
+ return sqlite3.SQLITE_OK
+}
+
+// vtabUpdateTrampoline is xUpdate. Not supported by default; report read-only.
+func vtabUpdateTrampoline(tls *libc.TLS, pVtab uintptr, argc int32, argv uintptr, pRowid uintptr) int32 {
+ vtabTables.mu.RLock()
+ gt := vtabTables.m[pVtab]
+ vtabTables.mu.RUnlock()
+ if gt == nil {
+ return sqlite3.SQLITE_ERROR
+ }
+ upd, ok := gt.impl.(interface {
+ Insert(cols []vtab.Value, rowid *int64) error
+ Update(oldRowid int64, cols []vtab.Value, newRowid *int64) error
+ Delete(oldRowid int64) error
+ })
+ if !ok {
+ return sqlite3.SQLITE_READONLY
+ }
+
+ // DELETE: argc == 1; argv[0]=oldRowid
+ if argc == 1 {
+ valPtr := *(*uintptr)(unsafe.Pointer(argv))
+ oldRowid := int64(0)
+ if sqlite3.Xsqlite3_value_type(tls, valPtr) != sqlite3.SQLITE_NULL {
+ oldRowid = int64(sqlite3.Xsqlite3_value_int64(tls, valPtr))
+ }
+ if err := upd.Delete(oldRowid); err != nil {
+ setVtabZErrMsg(tls, pVtab, err.Error())
+ return sqlite3.SQLITE_ERROR
+ }
+ return sqlite3.SQLITE_OK
+ }
+
+ // INSERT or UPDATE: argc == N+2. argv[0]=oldRowid (NULL for insert),
+ // argv[1..N]=column values, argv[N+1]=newRowid (or desired rowid for insert, may be NULL).
+ if argc < 3 {
+ return sqlite3.SQLITE_MISUSE
+ }
+ nCols := argc - 2
+ // Extract column values
+ colsPtr := argv + uintptr(1)*sqliteValPtrSize
+ cols := functionArgs(tls, nCols, colsPtr)
+
+ // Determine old/new rowid
+ oldPtr := *(*uintptr)(unsafe.Pointer(argv + uintptr(0)*sqliteValPtrSize))
+ newPtr := *(*uintptr)(unsafe.Pointer(argv + uintptr(argc-1)*sqliteValPtrSize))
+
+ oldIsNull := sqlite3.Xsqlite3_value_type(tls, oldPtr) == sqlite3.SQLITE_NULL
+ newIsNull := sqlite3.Xsqlite3_value_type(tls, newPtr) == sqlite3.SQLITE_NULL
+
+ if oldIsNull {
+ // INSERT
+ var rid int64
+ if !newIsNull {
+ rid = int64(sqlite3.Xsqlite3_value_int64(tls, newPtr))
+ }
+ if err := upd.Insert(cols, &rid); err != nil {
+ setVtabZErrMsg(tls, pVtab, err.Error())
+ return sqlite3.SQLITE_ERROR
+ }
+ if pRowid != 0 {
+ *(*int64)(unsafe.Pointer(pRowid)) = rid
+ }
+ return sqlite3.SQLITE_OK
+ }
+
+ // UPDATE
+ oldRowid := int64(sqlite3.Xsqlite3_value_int64(tls, oldPtr))
+ var newRid int64
+ if !newIsNull {
+ newRid = int64(sqlite3.Xsqlite3_value_int64(tls, newPtr))
+ }
+ if err := upd.Update(oldRowid, cols, &newRid); err != nil {
+ setVtabZErrMsg(tls, pVtab, err.Error())
+ return sqlite3.SQLITE_ERROR
+ }
+ if pRowid != 0 && newRid != 0 {
+ *(*int64)(unsafe.Pointer(pRowid)) = newRid
+ }
+ return sqlite3.SQLITE_OK
+}
+
+// Transactional callbacks
+func vtabBeginTrampoline(tls *libc.TLS, pVtab uintptr) int32 {
+ vtabTables.mu.RLock()
+ gt := vtabTables.m[pVtab]
+ vtabTables.mu.RUnlock()
+ if gt == nil {
+ return sqlite3.SQLITE_ERROR
+ }
+ if tr, ok := gt.impl.(interface{ Begin() error }); ok {
+ if err := tr.Begin(); err != nil {
+ setVtabZErrMsg(tls, pVtab, err.Error())
+ return sqlite3.SQLITE_ERROR
+ }
+ }
+ return sqlite3.SQLITE_OK
+}
+
+func vtabSyncTrampoline(tls *libc.TLS, pVtab uintptr) int32 {
+ vtabTables.mu.RLock()
+ gt := vtabTables.m[pVtab]
+ vtabTables.mu.RUnlock()
+ if gt == nil {
+ return sqlite3.SQLITE_ERROR
+ }
+ if tr, ok := gt.impl.(interface{ Sync() error }); ok {
+ if err := tr.Sync(); err != nil {
+ setVtabZErrMsg(tls, pVtab, err.Error())
+ return sqlite3.SQLITE_ERROR
+ }
+ }
+ return sqlite3.SQLITE_OK
+}
+
+func vtabCommitTrampoline(tls *libc.TLS, pVtab uintptr) int32 {
+ vtabTables.mu.RLock()
+ gt := vtabTables.m[pVtab]
+ vtabTables.mu.RUnlock()
+ if gt == nil {
+ return sqlite3.SQLITE_ERROR
+ }
+ if tr, ok := gt.impl.(interface{ Commit() error }); ok {
+ if err := tr.Commit(); err != nil {
+ setVtabZErrMsg(tls, pVtab, err.Error())
+ return sqlite3.SQLITE_ERROR
+ }
+ }
+ return sqlite3.SQLITE_OK
+}
+
+func vtabRollbackTrampoline(tls *libc.TLS, pVtab uintptr) int32 {
+ vtabTables.mu.RLock()
+ gt := vtabTables.m[pVtab]
+ vtabTables.mu.RUnlock()
+ if gt == nil {
+ return sqlite3.SQLITE_ERROR
+ }
+ if tr, ok := gt.impl.(interface{ Rollback() error }); ok {
+ if err := tr.Rollback(); err != nil {
+ setVtabZErrMsg(tls, pVtab, err.Error())
+ return sqlite3.SQLITE_ERROR
+ }
+ }
+ return sqlite3.SQLITE_OK
+}
+
+func vtabSavepointTrampoline(tls *libc.TLS, pVtab uintptr, i int32) int32 {
+ vtabTables.mu.RLock()
+ gt := vtabTables.m[pVtab]
+ vtabTables.mu.RUnlock()
+ if gt == nil {
+ return sqlite3.SQLITE_ERROR
+ }
+ if tr, ok := gt.impl.(interface{ Savepoint(int) error }); ok {
+ if err := tr.Savepoint(int(i)); err != nil {
+ setVtabZErrMsg(tls, pVtab, err.Error())
+ return sqlite3.SQLITE_ERROR
+ }
+ }
+ return sqlite3.SQLITE_OK
+}
+
+func vtabReleaseTrampoline(tls *libc.TLS, pVtab uintptr, i int32) int32 {
+ vtabTables.mu.RLock()
+ gt := vtabTables.m[pVtab]
+ vtabTables.mu.RUnlock()
+ if gt == nil {
+ return sqlite3.SQLITE_ERROR
+ }
+ if tr, ok := gt.impl.(interface{ Release(int) error }); ok {
+ if err := tr.Release(int(i)); err != nil {
+ setVtabZErrMsg(tls, pVtab, err.Error())
+ return sqlite3.SQLITE_ERROR
+ }
+ }
+ return sqlite3.SQLITE_OK
+}
+
+func vtabRollbackToTrampoline(tls *libc.TLS, pVtab uintptr, i int32) int32 {
+ vtabTables.mu.RLock()
+ gt := vtabTables.m[pVtab]
+ vtabTables.mu.RUnlock()
+ if gt == nil {
+ return sqlite3.SQLITE_ERROR
+ }
+ if tr, ok := gt.impl.(interface{ RollbackTo(int) error }); ok {
+ if err := tr.RollbackTo(int(i)); err != nil {
+ setVtabZErrMsg(tls, pVtab, err.Error())
+ return sqlite3.SQLITE_ERROR
+ }
+ }
+ return sqlite3.SQLITE_OK
+}
diff --git a/vendor/modernc.org/sqlite/vtab/doc.go b/vendor/modernc.org/sqlite/vtab/doc.go
new file mode 100644
index 0000000..e0cdf0a
--- /dev/null
+++ b/vendor/modernc.org/sqlite/vtab/doc.go
@@ -0,0 +1,53 @@
+// Package vtab defines a Go-facing API for implementing SQLite virtual table
+// modules on top of the modernc.org/sqlite driver.
+//
+// It is intentionally small and generic so that external projects can
+// implement virtual tables without depending on the translated C internals.
+package vtab
+
+// API notes
+//
+// - Schema declaration: Modules must call Context.Declare from within Create
+// or Connect to declare the virtual table schema (a CREATE TABLE statement).
+// The driver no longer auto-declares based on USING(...) args to support
+// dynamic schemas (e.g., CSV headers).
+//
+// - Constraint operators: ConstraintOp includes OpUnknown for operators that
+// are not recognized. The driver maps common SQLite operators including EQ,
+// NE, GT, GE, LT, LE, MATCH, IS/ISNOT, ISNULL/ISNOTNULL, LIKE, GLOB, REGEXP,
+// FUNCTION, LIMIT, and OFFSET.
+//
+// - ArgIndex: Set as 0-based in Go to indicate which position in argv[] should
+// receive a constraint value. The driver adds +1 when communicating with
+// SQLite (which is 1-based). Use -1 (default) to ignore.
+//
+// - Omit: Set Constraint.Omit to ask SQLite to not re-evaluate that constraint
+// in the parent query if the virtual table fully handles it.
+//
+// - ColUsed: IndexInfo.ColUsed provides a bitmask of columns referenced by the
+// query. Bit N indicates column N is used.
+//
+// - IdxFlags: IndexInfo.IdxFlags allows modules to set planning flags.
+// Currently, IndexScanUnique (mirrors SQLITE_INDEX_SCAN_UNIQUE) indicates
+// the plan will visit at most one row. This can help the optimizer.
+//
+// Optional interfaces
+//
+// - Updater: Implement on your Table to support writes via xUpdate.
+// Insert(cols, *rowid), Update(oldRowid, cols, *newRowid), Delete(oldRowid).
+// The trampoline maps SQLite xUpdate’s calling convention to these methods.
+//
+// - Renamer: Implement Rename(newName string) on your Table to handle xRename.
+// If unimplemented, rename is treated as a no-op.
+//
+// - Transactional: Implement Begin/Sync/Commit/Rollback/Savepoint/Release/
+// RollbackTo as needed. Unimplemented methods are treated as no-ops.
+// These callbacks let writable or advanced modules coordinate with SQLite
+// transaction boundaries.
+//
+// Re-entrancy cautions
+// - Avoid executing SQL on the same connection from within vtab methods
+// (Create/Connect/BestIndex/Filter/etc.). SQLite virtual table callbacks run
+// inside the engine and issuing re-entrant SQL on the same connection can
+// lead to deadlocks or undefined behavior. If a module requires issuing SQL,
+// consider using a separate connection and document the concurrency model.
diff --git a/vendor/modernc.org/sqlite/vtab/vtab.go b/vendor/modernc.org/sqlite/vtab/vtab.go
new file mode 100644
index 0000000..f003dcd
--- /dev/null
+++ b/vendor/modernc.org/sqlite/vtab/vtab.go
@@ -0,0 +1,245 @@
+package vtab
+
+import (
+ "database/sql"
+ "database/sql/driver"
+ "errors"
+)
+
+// Value is the value type passed to and from virtual table cursors. It
+// aliases database/sql/driver.Value to avoid exposing low-level details to
+// module authors while remaining compatible with the driver.
+type Value = driver.Value
+
+// Context carries information that a Module may need when creating or
+// connecting a table instance. It intentionally does not expose *sql.DB to
+// avoid leaking database/sql internals into the vtab API. Additional fields
+// may be added in the future as needed.
+type Context struct {
+ declare func(string) error
+}
+
+// Declare must be called by a module from within Create or Connect to declare
+// the schema of the virtual table. The provided SQL must be a CREATE TABLE
+// statement describing the exposed columns.
+//
+// The engine installs this callback so that the declaration is executed in the
+// correct context. Calling Declare outside of Create/Connect may fail.
+func (c Context) Declare(schema string) error {
+ if c.declare == nil {
+ return errors.New("vtab: declare not available in this context")
+ }
+ return c.declare(schema)
+}
+
+// NewContext is used by the engine to create a Context bound to the current
+// xCreate/xConnect call. External modules should not need to call this.
+func NewContext(declare func(string) error) Context { return Context{declare: declare} }
+
+// Module represents a virtual table module, analogous to sqlite3_module in
+// the SQLite C API. Implementations are responsible for creating and
+// connecting table instances.
+type Module interface {
+ // Create is called to create a new virtual table. args corresponds to the
+ // argv array passed to xCreate in the SQLite C API: it contains the module
+ // name, the database name, the table name, and module arguments.
+ Create(ctx Context, args []string) (Table, error)
+
+ // Connect is called to connect to an existing virtual table. Its
+ // semantics mirror xConnect in the SQLite C API.
+ Connect(ctx Context, args []string) (Table, error)
+}
+
+// Table represents a single virtual table instance (the Go analogue of
+// sqlite3_vtab and its associated methods).
+type Table interface {
+ // BestIndex allows the virtual table to inform SQLite about which
+ // constraints and orderings it can efficiently support. The IndexInfo
+ // structure mirrors sqlite3_index_info.
+ BestIndex(info *IndexInfo) error
+
+ // Open creates a new cursor for scanning the table.
+ Open() (Cursor, error)
+
+ // Disconnect is called to disconnect from a table instance (xDisconnect).
+ Disconnect() error
+
+ // Destroy is called when a table is dropped (xDestroy).
+ Destroy() error
+}
+
+// Renamer can be implemented by a Table to handle xRename.
+type Renamer interface {
+ Rename(newName string) error
+}
+
+// Transactional can be implemented by a Table to handle transaction-related
+// callbacks. Methods are optional; unimplemented methods are treated as no-op.
+type Transactional interface {
+ Begin() error
+ Sync() error
+ Commit() error
+ Rollback() error
+ Savepoint(i int) error
+ Release(i int) error
+ RollbackTo(i int) error
+}
+
+// Cursor represents a cursor over a virtual table (sqlite3_vtab_cursor).
+type Cursor interface {
+ // Filter corresponds to xFilter. idxNum and idxStr are the chosen index
+ // number and string; vals are the constraint arguments.
+ Filter(idxNum int, idxStr string, vals []Value) error
+
+ // Next advances the cursor to the next row (xNext).
+ Next() error
+
+ // Eof reports whether the cursor is past the last row (xEof != 0).
+ Eof() bool
+
+ // Column returns the value of the specified column in the current row
+ // (xColumn).
+ Column(col int) (Value, error)
+
+ // Rowid returns the current rowid (xRowid).
+ Rowid() (int64, error)
+
+ // Close closes the cursor (xClose).
+ Close() error
+}
+
+// Updater can be implemented by a Table to support writes via xUpdate.
+//
+// Semantics follow SQLite's xUpdate:
+// - Delete: Delete(oldRowid) is called.
+// - Insert: Insert(cols, rowid) is called. *rowid may contain a desired rowid
+// (if provided by SQL) and should be set to the final rowid of the new row.
+// - Update: Update(oldRowid, cols, newRowid) is called. *newRowid may be set
+// to the final rowid of the updated row when changed.
+type Updater interface {
+ Insert(cols []Value, rowid *int64) error
+ Update(oldRowid int64, cols []Value, newRowid *int64) error
+ Delete(oldRowid int64) error
+}
+
+// ConstraintOp describes the operator used in a constraint on a virtual
+// table column. It loosely mirrors the op field of sqlite3_index_constraint.
+type ConstraintOp int
+
+const (
+ // OpUnknown indicates an operator that is not recognized or not mapped.
+ // Modules should treat this conservatively.
+ OpUnknown ConstraintOp = iota
+ OpEQ
+ OpGT
+ OpLE
+ OpLT
+ OpGE
+ OpMATCH // "MATCH" operator (e.g. for FTS or KNN semantics)
+ OpNE
+ OpIS
+ OpISNOT
+ OpISNULL
+ OpISNOTNULL
+ OpLIKE
+ OpGLOB
+ OpREGEXP
+ OpFUNCTION
+ OpLIMIT
+ OpOFFSET
+)
+
+// Constraint describes a single WHERE-clause constraint that SQLite is
+// considering pushing down to the virtual table.
+type Constraint struct {
+ Column int
+ Op ConstraintOp
+ Usable bool
+ // ArgIndex selects which position in argv[] (0-based) should contain the
+ // RHS value for this constraint when Filter is called. Set to -1 to ignore.
+ ArgIndex int
+ // Omit requests SQLite to omit the corresponding constraint from the
+ // parent query if the virtual table fully handles it.
+ Omit bool
+}
+
+// OrderBy describes a single ORDER BY term for a query involving a virtual
+// table.
+type OrderBy struct {
+ Column int
+ Desc bool
+}
+
+// IndexInfo holds information about constraints and orderings for a virtual
+// table query. It is the Go analogue of sqlite3_index_info.
+type IndexInfo struct {
+ Constraints []Constraint
+ OrderBy []OrderBy
+
+ // IdxNum selects the query plan chosen in BestIndex. This value is passed
+ // back to Cursor.Filter. Note: SQLite stores this as a 32-bit signed
+ // integer (int32). Implementations must ensure IdxNum fits within the
+ // int32 range; values outside of int32 will cause an error in the driver
+ // to avoid silent truncation.
+ IdxNum int64
+ IdxStr string
+ // IdxFlags provides extra information about the chosen plan.
+ // Set to IndexScanUnique to indicate the plan visits at most one row.
+ IdxFlags int
+ OrderByConsumed bool
+ EstimatedCost float64
+ EstimatedRows int64
+ // ColUsed is a bitmask indicating which columns are used by the query.
+ // Bit N is set if column N is referenced.
+ ColUsed uint64
+}
+
+// Index flag values for IndexInfo.IdxFlags.
+const (
+ // IndexScanUnique mirrors SQLITE_INDEX_SCAN_UNIQUE and indicates that the
+ // chosen plan will visit at most one row.
+ IndexScanUnique = 1
+)
+
+// ErrNotImplemented is returned by RegisterModule when the underlying engine
+// has not yet installed a registration hook. External projects can depend on
+// the vtab API surface before the low-level bridge to sqlite3_create_module
+// is fully wired; once the engine sets the hook via SetRegisterFunc,
+// RegisterModule will forward calls to it.
+var ErrNotImplemented = errors.New("vtab: RegisterModule not wired into engine")
+
+// registerHook is installed by the engine package via SetRegisterFunc. It is
+// invoked by RegisterModule to perform the actual module registration.
+var registerHook func(name string, m Module) error
+
+// SetRegisterFunc is intended to be called by the engine package to provide
+// the concrete implementation of module registration. External callers
+// should use RegisterModule instead.
+func SetRegisterFunc(fn func(name string, m Module) error) { registerHook = fn }
+
+// RegisterModule registers a virtual table module with the provided *sql.DB.
+//
+// Registration applies to new connections only. Existing open connections will
+// not be updated to include newly registered modules.
+//
+// Registration is performed when opening a new connection. If the underlying
+// sqlite3_create_module_v2 call fails, opening the connection fails and returns
+// that error. This fail-fast behavior prevents partially-initialized
+// connections when a module cannot be installed.
+//
+// The db parameter is currently unused by the engine; it is available so
+// module implementations can capture it if they need a *sql.DB for their own
+// internal queries.
+func RegisterModule(db *sql.DB, name string, m Module) error {
+ _ = db
+ if registerHook == nil {
+ return ErrNotImplemented
+ }
+ if name == "" {
+ return errors.New("vtab: module name must be non-empty")
+ }
+ if m == nil {
+ return errors.New("vtab: module implementation is nil")
+ }
+ return registerHook(name, m)
+}
diff --git a/vendor/modules.txt b/vendor/modules.txt
index ae9fa64..5165383 100644
--- a/vendor/modules.txt
+++ b/vendor/modules.txt
@@ -24,7 +24,7 @@ github.com/buger/jsonparser
# github.com/cention-sany/utf7 v0.0.0-20170124080048-26cad61bd60a
## explicit
github.com/cention-sany/utf7
-# github.com/clipperhouse/displaywidth v0.6.1
+# github.com/clipperhouse/displaywidth v0.6.2
## explicit; go 1.18
github.com/clipperhouse/displaywidth
# github.com/clipperhouse/stringish v0.1.1
@@ -84,7 +84,7 @@ github.com/fatih/color
## explicit; go 1.17
github.com/fsnotify/fsnotify
github.com/fsnotify/fsnotify/internal
-# github.com/gabriel-vasile/mimetype v1.4.11
+# github.com/gabriel-vasile/mimetype v1.4.12
## explicit; go 1.21
github.com/gabriel-vasile/mimetype
github.com/gabriel-vasile/mimetype/internal/charset
@@ -241,7 +241,7 @@ github.com/yuin/goldmark/renderer
github.com/yuin/goldmark/renderer/html
github.com/yuin/goldmark/text
github.com/yuin/goldmark/util
-# go.mau.fi/util v0.9.3
+# go.mau.fi/util v0.9.4
## explicit; go 1.24.0
go.mau.fi/util/base58
go.mau.fi/util/confusable
@@ -276,7 +276,7 @@ golang.org/x/crypto/internal/poly1305
golang.org/x/crypto/pbkdf2
golang.org/x/crypto/ssh
golang.org/x/crypto/ssh/internal/bcrypt_pbkdf
-# golang.org/x/exp v0.0.0-20251125195548-87e1e737ad39
+# golang.org/x/exp v0.0.0-20251219203646-944ab1f22d93
## explicit; go 1.24.0
golang.org/x/exp/constraints
golang.org/x/exp/maps
@@ -321,7 +321,7 @@ golang.org/x/text/transform
golang.org/x/text/unicode/bidi
golang.org/x/text/unicode/norm
golang.org/x/text/width
-# golang.org/x/tools v0.39.0
+# golang.org/x/tools v0.40.0
## explicit; go 1.24.0
golang.org/x/tools/go/ast/astutil
golang.org/x/tools/go/buildutil
@@ -330,7 +330,7 @@ golang.org/x/tools/go/loader
# gopkg.in/yaml.v2 v2.4.0
## explicit; go 1.15
gopkg.in/yaml.v2
-# maunium.net/go/mautrix v0.26.0
+# maunium.net/go/mautrix v0.26.1
## explicit; go 1.24.0
maunium.net/go/mautrix
maunium.net/go/mautrix/crypto
@@ -398,7 +398,8 @@ modernc.org/mathutil
# modernc.org/memory v1.11.0
## explicit; go 1.23.0
modernc.org/memory
-# modernc.org/sqlite v1.40.1
+# modernc.org/sqlite v1.41.0
## explicit; go 1.24.0
modernc.org/sqlite
modernc.org/sqlite/lib
+modernc.org/sqlite/vtab