make it work with shared secret auth

This commit is contained in:
Aine 2025-03-03 20:49:53 +02:00
parent 2994ff9ede
commit 3fb18e0bab
No known key found for this signature in database
GPG key ID: 34969C908CCA2804
28 changed files with 243055 additions and 185711 deletions

View file

@ -52,7 +52,7 @@ env vars
* **POSTMOOGLE_HOMESERVER** - homeserver url, eg: `https://matrix.example.com`
* **POSTMOOGLE_LOGIN** - user login, localpart when logging in with password (e.g., `moogle`), OR full MXID when using shared secret (e.g., `@moogle:example.com`)
* **POSTMOOGLE_PASSWORD** - user password, alternatively you may use shared secret
* **POSTMOOGLE_SHAREDSECRET** - alternative to password, shared secret ([details](https://github.com/devture/matrix-synapse-shared-secret-auth))
* **POSTMOOGLE_SHAREDSECRET** - alternative to password, shared secret ([details](https://github.com/devture/matrix-synapse-shared-secret-auth)). Note: switch between password and shared secret authentication may result in encryption issues. If you face such issues, please report them
* **POSTMOOGLE_DOMAINS** - space separated list of SMTP domains to listen for new emails. The first domain acts as the default domain, all other as aliases
<details>

10
go.mod
View file

@ -13,7 +13,7 @@ require (
github.com/etkecc/go-fswatcher v1.0.1
github.com/etkecc/go-healthchecks/v2 v2.2.2
github.com/etkecc/go-kit v1.5.0
github.com/etkecc/go-linkpearl v0.0.0-20250217075507-d5e511599d5c
github.com/etkecc/go-linkpearl v0.0.0-20250303184705-04344d9c1d56
github.com/etkecc/go-mxidwc v1.0.1
github.com/etkecc/go-secgen v1.4.0
github.com/etkecc/go-validator/v2 v2.2.4
@ -28,9 +28,9 @@ require (
github.com/raja/argon2pw v1.0.2-0.20210910183755-a391af63bd39
github.com/rs/zerolog v1.33.0
github.com/swaggo/swag v1.16.3
golang.org/x/exp v0.0.0-20250215185904-eff6e970281f
golang.org/x/exp v0.0.0-20250228200357-dead58393ab7
maunium.net/go/mautrix v0.23.1
modernc.org/sqlite v1.35.0
modernc.org/sqlite v1.36.0
)
require (
@ -59,7 +59,7 @@ require (
github.com/mikesmitty/edkey v0.0.0-20170222072505-3356ea4e686a // indirect
github.com/ncruces/go-strftime v0.1.9 // indirect
github.com/olekukonko/tablewriter v0.0.5 // indirect
github.com/petermattis/goid v0.0.0-20250211185408-f2b9d978cd7a // indirect
github.com/petermattis/goid v0.0.0-20250303134427-723919f7f203 // indirect
github.com/pkg/errors v0.9.1 // indirect
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec // indirect
github.com/rivo/uniseg v0.4.7 // indirect
@ -70,7 +70,7 @@ require (
github.com/tidwall/sjson v1.2.5 // indirect
github.com/yuin/goldmark v1.7.8 // indirect
go.mau.fi/util v0.8.5 // indirect
golang.org/x/crypto v0.33.0 // indirect
golang.org/x/crypto v0.35.0 // indirect
golang.org/x/net v0.35.0 // indirect
golang.org/x/sys v0.30.0 // indirect
golang.org/x/text v0.22.0 // indirect

20
go.sum
View file

@ -38,8 +38,8 @@ github.com/etkecc/go-healthchecks/v2 v2.2.2 h1:YV7e+Ga8JY3aZX4Qf6Q1Ca+DnqbT5Drjl
github.com/etkecc/go-healthchecks/v2 v2.2.2/go.mod h1:IowWGN4F6By6z0eh63+639OscylgtdvT9ITjfN6hnZA=
github.com/etkecc/go-kit v1.5.0 h1:i7QxpWxgoIBEDbUW5dbaDHnwbVXDCHw3Y5B9Xm++v0k=
github.com/etkecc/go-kit v1.5.0/go.mod h1:yikghi8YaYbTjRXNtx82g0LFv90YqZi2vLf5Chw0ysg=
github.com/etkecc/go-linkpearl v0.0.0-20250217075507-d5e511599d5c h1:fjRauzmHqH42Dq8BKIe5y4RcGzQnF+/OQdm/uyXp12U=
github.com/etkecc/go-linkpearl v0.0.0-20250217075507-d5e511599d5c/go.mod h1:NydJ3vV/L1muFhXphAlgFcrPHAC3knjlJFoQkZgp+AE=
github.com/etkecc/go-linkpearl v0.0.0-20250303184705-04344d9c1d56 h1:pK3o/Y6AeTFo1SimIJUScgnr/4dpHw8FSfv+XmJ3OFE=
github.com/etkecc/go-linkpearl v0.0.0-20250303184705-04344d9c1d56/go.mod h1:GKu1fpjx/rQOaFiAssg8rQLQKA2S35hBj6Q1sjFHE0Q=
github.com/etkecc/go-mxidwc v1.0.1 h1:t4Kq3FxSlQjt1i7RpzE5q3cOWjJ0vrTzzGZRSpgh8mg=
github.com/etkecc/go-mxidwc v1.0.1/go.mod h1:WFlntcH4mdual/gNi6X7a6rSJERNuLjdrwM3K/tucQA=
github.com/etkecc/go-secgen v1.4.0 h1:PapLpen3aIqG2LDu+U6KWDb4SMW2UGuvetpJjd86yUc=
@ -124,8 +124,8 @@ github.com/ncruces/go-strftime v0.1.9/go.mod h1:Fwc5htZGVVkseilnfgOVb9mKy6w1naJm
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno=
github.com/olekukonko/tablewriter v0.0.5 h1:P2Ga83D34wi1o9J6Wh1mRuqd4mF/x/lgBS7N7AbDhec=
github.com/olekukonko/tablewriter v0.0.5/go.mod h1:hPp6KlRPjbx+hW8ykQs1w3UBbZlj6HuIJcUGPhkA7kY=
github.com/petermattis/goid v0.0.0-20250211185408-f2b9d978cd7a h1:ckxP/kGzsxvxXo8jO6E/0QJ8MMmwI7IRj4Fys9QbAZA=
github.com/petermattis/goid v0.0.0-20250211185408-f2b9d978cd7a/go.mod h1:pxMtw7cyUw6B2bRH0ZBANSPg+AoSud1I1iyJHI69jH4=
github.com/petermattis/goid v0.0.0-20250303134427-723919f7f203 h1:E7Kmf11E4K7B5hDti2K2NqPb1nlYlGYsu02S1JNd/Bs=
github.com/petermattis/goid v0.0.0-20250303134427-723919f7f203/go.mod h1:pxMtw7cyUw6B2bRH0ZBANSPg+AoSud1I1iyJHI69jH4=
github.com/pingcap/errors v0.11.4 h1:lFuQV/oaUMGcD2tqt+01ROSmJs75VG1ToEOkZIZ4nE4=
github.com/pingcap/errors v0.11.4/go.mod h1:Oi8TUi2kEtXXLMJk9l1cGmz20kV3TaQ0usTwv5KuLY8=
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
@ -169,10 +169,10 @@ go.mau.fi/util v0.8.5 h1:PwCAAtcfK0XxZ4sdErJyfBMkTEWoQU33aB7QqDDzQRI=
go.mau.fi/util v0.8.5/go.mod h1:Ycug9mrbztlahHPEJ6H5r8Nu/xqZaWbE5vPHVWmfz6M=
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.33.0 h1:IOBPskki6Lysi0lo9qQvbxiQ+FvsCC/YWOecCHAixus=
golang.org/x/crypto v0.33.0/go.mod h1:bVdXmD7IV/4GdElGPozy6U7lWdRXA4qyRVGJV57uQ5M=
golang.org/x/exp v0.0.0-20250215185904-eff6e970281f h1:oFMYAjX0867ZD2jcNiLBrI9BdpmEkvPyi5YrBGXbamg=
golang.org/x/exp v0.0.0-20250215185904-eff6e970281f/go.mod h1:BHOTPb3L19zxehTsLoJXVaTktb06DFgmdW6Wb9s8jqk=
golang.org/x/crypto v0.35.0 h1:b15kiHdrGCHrP6LvwaQ3c03kgNhhiMgvlhxHQhmg2Xs=
golang.org/x/crypto v0.35.0/go.mod h1:dy7dXNW32cAb/6/PRuTNsix8T+vJAqvuIy5Bli/x0YQ=
golang.org/x/exp v0.0.0-20250228200357-dead58393ab7 h1:aWwlzYV971S4BXRS9AmqwDLAD85ouC6X+pocatKY58c=
golang.org/x/exp v0.0.0-20250228200357-dead58393ab7/go.mod h1:BHOTPb3L19zxehTsLoJXVaTktb06DFgmdW6Wb9s8jqk=
golang.org/x/mod v0.23.0 h1:Zb7khfcRGKk+kqfxFaP5tZqCnDZMjC5VtUBs87Hr6QM=
golang.org/x/mod v0.23.0/go.mod h1:6SkKJ3Xj0I0BrPOZoBy3bdMptDDU9oJrpohJ3eWZ1fY=
golang.org/x/net v0.0.0-20180911220305-26e67e76b6c3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
@ -230,8 +230,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.35.0 h1:yQps4fegMnZFdphtzlfQTCNBWtS0CZv48pRpW3RFHRw=
modernc.org/sqlite v1.35.0/go.mod h1:9cr2sicr7jIaWTBKQmAxQLfBv9LL0su4ZTEV+utt3ic=
modernc.org/sqlite v1.36.0 h1:EQXNRn4nIS+gfsKeUTymHIz1waxuv5BzU7558dHSfH8=
modernc.org/sqlite v1.36.0/go.mod h1:7MPwH7Z6bREicF9ZVUR78P1IKuxfZ8mRIDHD0iD+8TU=
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=

View file

@ -4,8 +4,6 @@ run:
issues-exit-code: 1
tests: true
build-tags: []
skip-dirs-use-default: true
skip-files: []
modules-download-mode: readonly
output:
@ -118,6 +116,7 @@ linters:
issues:
exclude-dirs-use-default: true
exclude-dirs:
- mocks
exclude-rules:

View file

@ -32,5 +32,6 @@ go lp.Start()
* Zero configuration session restores
* Zero configuration room and user account data encryption with AES GCM (both keys and values)
* Zero configuration room and user account data caching
* [Shared Secret Auth](https://github.com/devture/matrix-synapse-shared-secret-auth) support
* Threads support
* All wrapped components exported

View file

@ -12,6 +12,7 @@ import (
"maunium.net/go/mautrix/crypto"
"maunium.net/go/mautrix/crypto/cryptohelper"
"maunium.net/go/mautrix/event"
"maunium.net/go/mautrix/id"
)
const (
@ -107,7 +108,11 @@ func New(cfg *Config) (*Linkpearl, error) {
return nil, err
}
db.Log = dbutil.ZeroLogger(cfg.Logger)
lp.ch, err = cryptohelper.NewCryptoHelper(lp.api, []byte(cfg.Login), db)
localpart := id.UserID(cfg.Login).Localpart()
if localpart == "" {
localpart = cfg.Login
}
lp.ch, err = cryptohelper.NewCryptoHelper(lp.api, []byte(localpart), db)
if err != nil {
return nil, err
}

View file

@ -20,6 +20,22 @@ func EventRelatesTo(evt *event.Event) *event.RelatesTo {
return RelatesTo(EventParent(evt.ID, relatable))
}
// EventReplaceID returns replace_id of a matrix event (if any)
// i.e. when the evt was replaced by another event, this returns the ID of the replacing event
func EventReplaceID(evt *event.Event) id.EventID {
ParseContent(evt, nil)
relatable, ok := evt.Content.Parsed.(event.Relatable)
if !ok {
return ""
}
relation := relatable.GetRelatesTo()
if relation == nil {
return ""
}
return relation.GetReplaceID()
}
// RelatesTo returns relation object of a matrix event (either threads with reply-to fallback or plain reply-to)
func RelatesTo(parentID id.EventID, noThreads ...bool) *event.RelatesTo {
if parentID == "" {

View file

@ -25,6 +25,11 @@ const debugHandshake = false
// quickly.
const chanSize = 16
// maxPendingPackets sets the maximum number of packets to queue while waiting
// for KEX to complete. This limits the total pending data to maxPendingPackets
// * maxPacket bytes, which is ~16.8MB.
const maxPendingPackets = 64
// keyingTransport is a packet based transport that supports key
// changes. It need not be thread-safe. It should pass through
// msgNewKeys in both directions.
@ -73,11 +78,19 @@ type handshakeTransport struct {
incoming chan []byte
readError error
mu sync.Mutex
writeError error
sentInitPacket []byte
sentInitMsg *kexInitMsg
pendingPackets [][]byte // Used when a key exchange is in progress.
mu sync.Mutex
// Condition for the above mutex. It is used to notify a completed key
// exchange or a write failure. Writes can wait for this condition while a
// key exchange is in progress.
writeCond *sync.Cond
writeError error
sentInitPacket []byte
sentInitMsg *kexInitMsg
// Used to queue writes when a key exchange is in progress. The length is
// limited by pendingPacketsSize. Once full, writes will block until the key
// exchange is completed or an error occurs. If not empty, it is emptied
// all at once when the key exchange is completed in kexLoop.
pendingPackets [][]byte
writePacketsLeft uint32
writeBytesLeft int64
userAuthComplete bool // whether the user authentication phase is complete
@ -134,6 +147,7 @@ func newHandshakeTransport(conn keyingTransport, config *Config, clientVersion,
config: config,
}
t.writeCond = sync.NewCond(&t.mu)
t.resetReadThresholds()
t.resetWriteThresholds()
@ -260,6 +274,7 @@ func (t *handshakeTransport) recordWriteError(err error) {
defer t.mu.Unlock()
if t.writeError == nil && err != nil {
t.writeError = err
t.writeCond.Broadcast()
}
}
@ -363,6 +378,8 @@ write:
}
}
t.pendingPackets = t.pendingPackets[:0]
// Unblock writePacket if waiting for KEX.
t.writeCond.Broadcast()
t.mu.Unlock()
}
@ -577,11 +594,20 @@ func (t *handshakeTransport) writePacket(p []byte) error {
}
if t.sentInitMsg != nil {
// Copy the packet so the writer can reuse the buffer.
cp := make([]byte, len(p))
copy(cp, p)
t.pendingPackets = append(t.pendingPackets, cp)
return nil
if len(t.pendingPackets) < maxPendingPackets {
// Copy the packet so the writer can reuse the buffer.
cp := make([]byte, len(p))
copy(cp, p)
t.pendingPackets = append(t.pendingPackets, cp)
return nil
}
for t.sentInitMsg != nil {
// Block and wait for KEX to complete or an error.
t.writeCond.Wait()
if t.writeError != nil {
return t.writeError
}
}
}
if t.writeBytesLeft > 0 {
@ -598,6 +624,7 @@ func (t *handshakeTransport) writePacket(p []byte) error {
if err := t.pushPacket(p); err != nil {
t.writeError = err
t.writeCond.Broadcast()
}
return nil

View file

@ -6,6 +6,8 @@
// with type parameters.
package constraints
import "cmp"
// Signed is a constraint that permits any signed integer type.
// If future releases of Go add new predeclared signed integer types,
// this constraint will be modified to include them.
@ -47,6 +49,6 @@ type Complex interface {
// this constraint will be modified to include them.
//
// This type is redundant since Go 1.21 introduced [cmp.Ordered].
type Ordered interface {
Integer | Float | ~string
}
//
//go:fix inline
type Ordered = cmp.Ordered

30
vendor/golang.org/x/exp/maps/maps.go generated vendored
View file

@ -7,17 +7,13 @@ package maps
import "maps"
// TODO(adonovan): when https://go.dev/issue/32816 is accepted, all of
// these functions except Keys and Values should be annotated
// (provisionally with "//go:fix inline") so that tools can safely and
// automatically replace calls to exp/maps with calls to std maps by
// inlining them.
// Keys returns the keys of the map m.
// The keys will be in an indeterminate order.
//
// The simplest true equivalent using the standard library is:
//
// slices.AppendSeq(make([]K, 0, len(m)), maps.Keys(m))
func Keys[M ~map[K]V, K comparable, V any](m M) []K {
// The simplest true equivalent using std is:
// return slices.AppendSeq(make([]K, 0, len(m)), maps.Keys(m)).
r := make([]K, 0, len(m))
for k := range m {
@ -28,9 +24,11 @@ func Keys[M ~map[K]V, K comparable, V any](m M) []K {
// Values returns the values of the map m.
// The values will be in an indeterminate order.
//
// The simplest true equivalent using the standard library is:
//
// slices.AppendSeq(make([]V, 0, len(m)), maps.Values(m))
func Values[M ~map[K]V, K comparable, V any](m M) []V {
// The simplest true equivalent using std is:
// return slices.AppendSeq(make([]V, 0, len(m)), maps.Values(m)).
r := make([]V, 0, len(m))
for _, v := range m {
@ -41,23 +39,31 @@ func Values[M ~map[K]V, K comparable, V any](m M) []V {
// Equal reports whether two maps contain the same key/value pairs.
// Values are compared using ==.
//
//go:fix inline
func Equal[M1, M2 ~map[K]V, K, V comparable](m1 M1, m2 M2) bool {
return maps.Equal(m1, m2)
}
// EqualFunc is like Equal, but compares values using eq.
// Keys are still compared with ==.
//
//go:fix inline
func EqualFunc[M1 ~map[K]V1, M2 ~map[K]V2, K comparable, V1, V2 any](m1 M1, m2 M2, eq func(V1, V2) bool) bool {
return maps.EqualFunc(m1, m2, eq)
}
// Clear removes all entries from m, leaving it empty.
//
//go:fix inline
func Clear[M ~map[K]V, K comparable, V any](m M) {
clear(m)
}
// Clone returns a copy of m. This is a shallow clone:
// the new keys and values are set using ordinary assignment.
//
//go:fix inline
func Clone[M ~map[K]V, K comparable, V any](m M) M {
return maps.Clone(m)
}
@ -66,11 +72,15 @@ func Clone[M ~map[K]V, K comparable, V any](m M) M {
// When a key in src is already present in dst,
// the value in dst will be overwritten by the value associated
// with the key in src.
//
//go:fix inline
func Copy[M1 ~map[K]V, M2 ~map[K]V, K comparable, V any](dst M1, src M2) {
maps.Copy(dst, src)
}
// DeleteFunc deletes any key/value pairs from m for which del returns true.
//
//go:fix inline
func DeleteFunc[M ~map[K]V, K comparable, V any](m M, del func(K, V) bool) {
maps.DeleteFunc(m, del)
}

View file

@ -10,16 +10,13 @@ import (
"slices"
)
// TODO(adonovan): when https://go.dev/issue/32816 is accepted, all of
// these functions should be annotated (provisionally with "//go:fix
// inline") so that tools can safely and automatically replace calls
// to exp/slices with calls to std slices by inlining them.
// Equal reports whether two slices are equal: the same length and all
// elements equal. If the lengths are different, Equal returns false.
// Otherwise, the elements are compared in increasing index order, and the
// comparison stops at the first unequal pair.
// Floating point NaNs are not considered equal.
//
//go:fix inline
func Equal[S ~[]E, E comparable](s1, s2 S) bool {
return slices.Equal(s1, s2)
}
@ -29,6 +26,8 @@ func Equal[S ~[]E, E comparable](s1, s2 S) bool {
// EqualFunc returns false. Otherwise, the elements are compared in
// increasing index order, and the comparison stops at the first index
// for which eq returns false.
//
//go:fix inline
func EqualFunc[S1 ~[]E1, S2 ~[]E2, E1, E2 any](s1 S1, s2 S2, eq func(E1, E2) bool) bool {
return slices.EqualFunc(s1, s2, eq)
}
@ -40,6 +39,8 @@ func EqualFunc[S1 ~[]E1, S2 ~[]E2, E1, E2 any](s1 S1, s2 S2, eq func(E1, E2) boo
// If both slices are equal until one of them ends, the shorter slice is
// considered less than the longer one.
// The result is 0 if s1 == s2, -1 if s1 < s2, and +1 if s1 > s2.
//
//go:fix inline
func Compare[S ~[]E, E cmp.Ordered](s1, s2 S) int {
return slices.Compare(s1, s2)
}
@ -49,29 +50,39 @@ func Compare[S ~[]E, E cmp.Ordered](s1, s2 S) int {
// The result is the first non-zero result of cmp; if cmp always
// returns 0 the result is 0 if len(s1) == len(s2), -1 if len(s1) < len(s2),
// and +1 if len(s1) > len(s2).
//
//go:fix inline
func CompareFunc[S1 ~[]E1, S2 ~[]E2, E1, E2 any](s1 S1, s2 S2, cmp func(E1, E2) int) int {
return slices.CompareFunc(s1, s2, cmp)
}
// Index returns the index of the first occurrence of v in s,
// or -1 if not present.
//
//go:fix inline
func Index[S ~[]E, E comparable](s S, v E) int {
return slices.Index(s, v)
}
// IndexFunc returns the first index i satisfying f(s[i]),
// or -1 if none do.
//
//go:fix inline
func IndexFunc[S ~[]E, E any](s S, f func(E) bool) int {
return slices.IndexFunc(s, f)
}
// Contains reports whether v is present in s.
//
//go:fix inline
func Contains[S ~[]E, E comparable](s S, v E) bool {
return slices.Contains(s, v)
}
// ContainsFunc reports whether at least one
// element e of s satisfies f(e).
//
//go:fix inline
func ContainsFunc[S ~[]E, E any](s S, f func(E) bool) bool {
return slices.ContainsFunc(s, f)
}
@ -83,6 +94,8 @@ func ContainsFunc[S ~[]E, E any](s S, f func(E) bool) bool {
// and r[i+len(v)] == value originally at r[i].
// Insert panics if i is out of range.
// This function is O(len(s) + len(v)).
//
//go:fix inline
func Insert[S ~[]E, E any](s S, i int, v ...E) S {
return slices.Insert(s, i, v...)
}
@ -92,6 +105,8 @@ func Insert[S ~[]E, E any](s S, i int, v ...E) S {
// Delete is O(len(s)-i), so if many items must be deleted, it is better to
// make a single call deleting them all together than to delete one at a time.
// Delete zeroes the elements s[len(s)-(j-i):len(s)].
//
//go:fix inline
func Delete[S ~[]E, E any](s S, i, j int) S {
return slices.Delete(s, i, j)
}
@ -99,6 +114,8 @@ func Delete[S ~[]E, E any](s S, i, j int) S {
// DeleteFunc removes any elements from s for which del returns true,
// returning the modified slice.
// DeleteFunc zeroes the elements between the new length and the original length.
//
//go:fix inline
func DeleteFunc[S ~[]E, E any](s S, del func(E) bool) S {
return slices.DeleteFunc(s, del)
}
@ -106,12 +123,16 @@ func DeleteFunc[S ~[]E, E any](s S, del func(E) bool) S {
// Replace replaces the elements s[i:j] by the given v, and returns the
// modified slice. Replace panics if s[i:j] is not a valid slice of s.
// When len(v) < (j-i), Replace zeroes the elements between the new length and the original length.
//
//go:fix inline
func Replace[S ~[]E, E any](s S, i, j int, v ...E) S {
return slices.Replace(s, i, j, v...)
}
// Clone returns a copy of the slice.
// The elements are copied using assignment, so this is a shallow clone.
//
//go:fix inline
func Clone[S ~[]E, E any](s S) S {
return slices.Clone(s)
}
@ -121,6 +142,8 @@ func Clone[S ~[]E, E any](s S) S {
// Compact modifies the contents of the slice s and returns the modified slice,
// which may have a smaller length.
// Compact zeroes the elements between the new length and the original length.
//
//go:fix inline
func Compact[S ~[]E, E comparable](s S) S {
return slices.Compact(s)
}
@ -128,6 +151,8 @@ func Compact[S ~[]E, E comparable](s S) S {
// CompactFunc is like [Compact] but uses an equality function to compare elements.
// For runs of elements that compare equal, CompactFunc keeps the first one.
// CompactFunc zeroes the elements between the new length and the original length.
//
//go:fix inline
func CompactFunc[S ~[]E, E any](s S, eq func(E, E) bool) S {
return slices.CompactFunc(s, eq)
}
@ -136,16 +161,22 @@ func CompactFunc[S ~[]E, E any](s S, eq func(E, E) bool) S {
// another n elements. After Grow(n), at least n elements can be appended
// to the slice without another allocation. If n is negative or too large to
// allocate the memory, Grow panics.
//
//go:fix inline
func Grow[S ~[]E, E any](s S, n int) S {
return slices.Grow(s, n)
}
// Clip removes unused capacity from the slice, returning s[:len(s):len(s)].
//
//go:fix inline
func Clip[S ~[]E, E any](s S) S {
return slices.Clip(s)
}
// Reverse reverses the elements of the slice in place.
//
//go:fix inline
func Reverse[S ~[]E, E any](s S) {
slices.Reverse(s)
}

View file

@ -9,11 +9,10 @@ import (
"slices"
)
// TODO(adonovan): add a "//go:fix inline" annotation to each function
// in this file; see https://go.dev/issue/32816.
// Sort sorts a slice of any ordered type in ascending order.
// When sorting floating-point numbers, NaNs are ordered before other values.
//
//go:fix inline
func Sort[S ~[]E, E cmp.Ordered](x S) {
slices.Sort(x)
}
@ -27,23 +26,31 @@ func Sort[S ~[]E, E cmp.Ordered](x S) {
// SortFunc requires that cmp is a strict weak ordering.
// See https://en.wikipedia.org/wiki/Weak_ordering#Strict_weak_orderings.
// To indicate 'uncomparable', return 0 from the function.
//
//go:fix inline
func SortFunc[S ~[]E, E any](x S, cmp func(a, b E) int) {
slices.SortFunc(x, cmp)
}
// SortStableFunc sorts the slice x while keeping the original order of equal
// elements, using cmp to compare elements in the same way as [SortFunc].
//
//go:fix inline
func SortStableFunc[S ~[]E, E any](x S, cmp func(a, b E) int) {
slices.SortStableFunc(x, cmp)
}
// IsSorted reports whether x is sorted in ascending order.
//
//go:fix inline
func IsSorted[S ~[]E, E cmp.Ordered](x S) bool {
return slices.IsSorted(x)
}
// IsSortedFunc reports whether x is sorted in ascending order, with cmp as the
// comparison function as defined by [SortFunc].
//
//go:fix inline
func IsSortedFunc[S ~[]E, E any](x S, cmp func(a, b E) int) bool {
return slices.IsSortedFunc(x, cmp)
}
@ -51,6 +58,8 @@ func IsSortedFunc[S ~[]E, E any](x S, cmp func(a, b E) int) bool {
// Min returns the minimal value in x. It panics if x is empty.
// For floating-point numbers, Min propagates NaNs (any NaN value in x
// forces the output to be NaN).
//
//go:fix inline
func Min[S ~[]E, E cmp.Ordered](x S) E {
return slices.Min(x)
}
@ -58,6 +67,8 @@ func Min[S ~[]E, E cmp.Ordered](x S) E {
// MinFunc returns the minimal value in x, using cmp to compare elements.
// It panics if x is empty. If there is more than one minimal element
// according to the cmp function, MinFunc returns the first one.
//
//go:fix inline
func MinFunc[S ~[]E, E any](x S, cmp func(a, b E) int) E {
return slices.MinFunc(x, cmp)
}
@ -65,6 +76,8 @@ func MinFunc[S ~[]E, E any](x S, cmp func(a, b E) int) E {
// Max returns the maximal value in x. It panics if x is empty.
// For floating-point E, Max propagates NaNs (any NaN value in x
// forces the output to be NaN).
//
//go:fix inline
func Max[S ~[]E, E cmp.Ordered](x S) E {
return slices.Max(x)
}
@ -72,6 +85,8 @@ func Max[S ~[]E, E cmp.Ordered](x S) E {
// MaxFunc returns the maximal value in x, using cmp to compare elements.
// It panics if x is empty. If there is more than one maximal element
// according to the cmp function, MaxFunc returns the first one.
//
//go:fix inline
func MaxFunc[S ~[]E, E any](x S, cmp func(a, b E) int) E {
return slices.MaxFunc(x, cmp)
}
@ -80,6 +95,8 @@ func MaxFunc[S ~[]E, E any](x S, cmp func(a, b E) int) E {
// where target is found, or the position where target would appear in the
// sort order; it also returns a bool saying whether the target is really found
// in the slice. The slice must be sorted in increasing order.
//
//go:fix inline
func BinarySearch[S ~[]E, E cmp.Ordered](x S, target E) (int, bool) {
return slices.BinarySearch(x, target)
}
@ -91,6 +108,8 @@ func BinarySearch[S ~[]E, E cmp.Ordered](x S, target E) (int, bool) {
// or a positive number if the slice element follows the target.
// cmp must implement the same ordering as the slice, such that if
// cmp(a, t) < 0 and cmp(b, t) >= 0, then a must precede b in the slice.
//
//go:fix inline
func BinarySearchFunc[S ~[]E, E, T any](x S, target T, cmp func(E, T) int) (int, bool) {
return slices.BinarySearchFunc(x, target, cmp)
}

32
vendor/modernc.org/sqlite/doc.go generated vendored
View file

@ -27,21 +27,21 @@
//
// OS Arch SQLite version
// ------------------------------
// darwin amd64 3.46.0
// darwin arm64 3.46.0
// freebsd amd64 3.46.0
// freebsd arm64 3.46.0
// linux 386 3.46.0
// linux amd64 3.46.0
// linux arm 3.46.0
// linux arm64 3.46.0
// linux loong64 3.46.0
// linux ppc64le 3.46.0
// linux riscv64 3.46.0
// linux s390x 3.46.0
// windows 386 3.46.0
// windows amd64 3.46.0
// windows arm64 3.46.0
// darwin amd64 3.49.0
// darwin arm64 3.49.0
// freebsd amd64 3.49.0
// freebsd arm64 3.49.0
// linux 386 3.49.0
// linux amd64 3.49.0
// linux arm 3.49.0
// linux arm64 3.49.0
// linux loong64 3.49.0
// linux ppc64le 3.49.0
// linux riscv64 3.49.0
// linux s390x 3.49.0
// windows 386 3.49.0
// windows amd64 3.49.0
// windows arm64 3.49.0
//
// # Builders
//
@ -51,6 +51,8 @@
//
// # Changelog
//
// - 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
//
// - 2024-07-22 v1.31.0: Support windows/386.

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

12
vendor/modules.txt vendored
View file

@ -49,7 +49,7 @@ github.com/etkecc/go-healthchecks/v2
# github.com/etkecc/go-kit v1.5.0
## explicit; go 1.22
github.com/etkecc/go-kit
# github.com/etkecc/go-linkpearl v0.0.0-20250217075507-d5e511599d5c
# github.com/etkecc/go-linkpearl v0.0.0-20250303184705-04344d9c1d56
## explicit; go 1.23.0
github.com/etkecc/go-linkpearl
# github.com/etkecc/go-mxidwc v1.0.1
@ -154,7 +154,7 @@ github.com/ncruces/go-strftime
# github.com/olekukonko/tablewriter v0.0.5
## explicit; go 1.12
github.com/olekukonko/tablewriter
# github.com/petermattis/goid v0.0.0-20250211185408-f2b9d978cd7a
# github.com/petermattis/goid v0.0.0-20250303134427-723919f7f203
## explicit; go 1.17
github.com/petermattis/goid
# github.com/pkg/errors v0.9.1
@ -222,8 +222,8 @@ go.mau.fi/util/jsontime
go.mau.fi/util/ptr
go.mau.fi/util/random
go.mau.fi/util/retryafter
# golang.org/x/crypto v0.33.0
## explicit; go 1.20
# golang.org/x/crypto v0.35.0
## explicit; go 1.23.0
golang.org/x/crypto/argon2
golang.org/x/crypto/blake2b
golang.org/x/crypto/blowfish
@ -236,7 +236,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-20250215185904-eff6e970281f
# golang.org/x/exp v0.0.0-20250228200357-dead58393ab7
## explicit; go 1.23.0
golang.org/x/exp/constraints
golang.org/x/exp/maps
@ -355,7 +355,7 @@ modernc.org/mathutil
# modernc.org/memory v1.8.2
## explicit; go 1.21
modernc.org/memory
# modernc.org/sqlite v1.35.0
# modernc.org/sqlite v1.36.0
## explicit; go 1.21
modernc.org/sqlite
modernc.org/sqlite/lib