Fuckit I'm sick of reinventing the wheel.
"golang.org/x/time/rate"
"github.com/anacrolix/torrent/bencode"
+ "github.com/anacrolix/torrent/internal/check"
"github.com/anacrolix/torrent/internal/limiter"
"github.com/anacrolix/torrent/iplist"
"github.com/anacrolix/torrent/metainfo"
return nil
}
-const check = false
-
func (p *Peer) initUpdateRequestsTimer() {
- if check {
+ if check.Enabled {
if p.updateRequestsTimer != nil {
panic(p.updateRequestsTimer)
}
--- /dev/null
+package check
+
+// A flag for doing extra checks at runtime that are potentially expensive. Should be enabled for
+// testing and debugging.
+var Enabled = false
--- /dev/null
+//go:build go1.21
+
+package check
+
+import "testing"
+
+func init() {
+ if testing.Testing() {
+ Enabled = true
+ }
+}
--- /dev/null
+package nestedmaps
+
+type next[NK comparable, M ~map[NK]NV, NV any] struct {
+ last Path[M]
+ key NK
+}
+
+func (me next[NK, CV, NV]) Exists() bool {
+ _, ok := me.last.Get()[me.key]
+ return ok
+}
+
+func (me next[NK, CV, NV]) Get() NV {
+ return me.last.Get()[me.key]
+}
+
+func (me next[NK, CV, NV]) Set(value NV) {
+ if me.last.Get() == nil {
+ me.last.Set(make(CV))
+ }
+ me.last.Get()[me.key] = value
+}
+
+func (me next[NK, CV, NV]) Delete() {
+ m := me.last.Get()
+ delete(m, me.key)
+ if len(m) == 0 {
+ me.last.Delete()
+ }
+}
+
+func Next[K comparable, M ~map[K]V, V any](
+ last Path[M],
+ key K,
+) Path[V] {
+ ret := next[K, M, V]{}
+ ret.last = last
+ ret.key = key
+ return ret
+}
+
+type root[K comparable, V any, M ~map[K]V] struct {
+ m *M
+}
+
+func (me root[K, V, M]) Exists() bool {
+ return *me.m != nil
+}
+
+func (me root[K, V, M]) Get() M {
+ return *me.m
+}
+
+func (me root[K, V, M]) Set(value M) {
+ *me.m = value
+}
+
+func (me root[K, V, M]) Delete() {
+ *me.m = nil
+}
+
+func Begin[K comparable, M ~map[K]V, V any](m *M) Path[M] {
+ ret := root[K, V, M]{}
+ ret.m = m
+ return ret
+}
+
+type Path[V any] interface {
+ Set(V)
+ Get() V
+ Exists() bool
+ Delete()
+}
--- /dev/null
+package nestedmaps
+
+import (
+ "testing"
+
+ qt "github.com/frankban/quicktest"
+
+ g "github.com/anacrolix/generics"
+)
+
+func TestNestedMaps(t *testing.T) {
+ c := qt.New(t)
+ var nest map[string]map[*int]map[byte][]int64
+ intKey := g.PtrTo(420)
+ var root = Begin(&nest)
+ var first = Next(root, "answer")
+ var second = Next(first, intKey)
+ var last = Next(second, 69)
+ c.Assert(root.Exists(), qt.IsFalse)
+ c.Assert(first.Exists(), qt.IsFalse)
+ c.Assert(second.Exists(), qt.IsFalse)
+ c.Assert(last.Exists(), qt.IsFalse)
+ last.Set([]int64{4, 8, 15, 16, 23, 42})
+ c.Assert(root.Exists(), qt.IsTrue)
+ c.Assert(first.Exists(), qt.IsTrue)
+ c.Assert(second.Exists(), qt.IsTrue)
+ c.Assert(last.Exists(), qt.IsTrue)
+ c.Assert(Next(second, 70).Exists(), qt.IsFalse)
+ secondIntKey := g.PtrTo(1337)
+ secondPath := Next(Next(Next(Begin(&nest), "answer"), secondIntKey), 42)
+ secondPath.Set(nil)
+ c.Assert(secondPath.Exists(), qt.IsTrue)
+ last.Delete()
+ c.Assert(last.Exists(), qt.IsFalse)
+ c.Assert(second.Exists(), qt.IsFalse)
+ c.Assert(root.Exists(), qt.IsTrue)
+ c.Assert(first.Exists(), qt.IsTrue)
+ // See if we get panics deleting an already deleted item.
+ last.Delete()
+ secondPath.Delete()
+ c.Assert(root.Exists(), qt.IsFalse)
+}
--- /dev/null
+package panicif
+
+import "fmt"
+
+func NotEqual[T comparable](a, b T) {
+ if a != b {
+ panic(fmt.Sprintf("%v != %v", a, b))
+ }
+}
"github.com/anacrolix/torrent/bencode"
"github.com/anacrolix/torrent/common"
+ "github.com/anacrolix/torrent/internal/check"
"github.com/anacrolix/torrent/metainfo"
pp "github.com/anacrolix/torrent/peer_protocol"
utHolepunch "github.com/anacrolix/torrent/peer_protocol/ut-holepunch"
}
func (t *Torrent) assertPendingRequests() {
- if !check {
+ if !check.Enabled {
return
}
// var actual pendingRequests