mirror of
https://hubproxy.babadafafafafa.cn/https://github.com/yunionio/cloudpods.git
synced 2026-09-20 08:03:53 +08:00
fix(torrent): vendor update for support risc-v (#23700)
This commit is contained in:
110
go.mod
110
go.mod
@@ -7,7 +7,7 @@ require (
|
||||
github.com/360EntSecGroup-Skylar/excelize v1.4.0
|
||||
github.com/LeeEirc/terminalparser v0.0.0-20240205084113-fbf78c8480f2
|
||||
github.com/aliyun/alibaba-cloud-sdk-go v1.61.684
|
||||
github.com/anacrolix/torrent v0.0.0-20181129073333-cc531b8c4a80
|
||||
github.com/anacrolix/torrent v1.57.0
|
||||
github.com/benbjohnson/clock v1.0.0
|
||||
github.com/bitly/go-simplejson v0.5.0
|
||||
github.com/c-bata/go-prompt v0.2.4
|
||||
@@ -20,7 +20,7 @@ require (
|
||||
github.com/docker/spdystream v0.0.0-20160310174837-449fdfce4d96
|
||||
github.com/eggsampler/acme/v3 v3.6.2
|
||||
github.com/fernet/fernet-go v0.0.0-20180830025343-9eac43b88a5e
|
||||
github.com/fsnotify/fsnotify v1.4.9
|
||||
github.com/fsnotify/fsnotify v1.5.4
|
||||
github.com/ghodss/yaml v1.0.0
|
||||
github.com/gin-gonic/gin v1.7.7
|
||||
github.com/go-ldap/ldap/v3 v3.1.5
|
||||
@@ -32,7 +32,7 @@ require (
|
||||
github.com/google/uuid v1.6.0
|
||||
github.com/googollee/go-socket.io v0.0.0-20181214084611-0ad7206c347a
|
||||
github.com/gorilla/mux v1.8.0
|
||||
github.com/gorilla/websocket v1.4.1
|
||||
github.com/gorilla/websocket v1.5.0
|
||||
github.com/gosuri/uitable v0.0.0-20160404203958-36ee7e946282
|
||||
github.com/hako/durafmt v0.0.0-20180520121703-7b7ae1e72ead
|
||||
github.com/influxdata/influxql v1.1.0
|
||||
@@ -132,19 +132,28 @@ require (
|
||||
github.com/Microsoft/azure-vhd-utils v0.0.0-20181115010904-44cbada2ece3 // indirect
|
||||
github.com/Microsoft/go-winio v0.6.2 // indirect
|
||||
github.com/Microsoft/hcsshim v0.8.14 // indirect
|
||||
github.com/RoaringBitmap/roaring v0.4.16 // indirect
|
||||
github.com/RoaringBitmap/roaring v1.2.3 // indirect
|
||||
github.com/Shopify/sarama v1.20.0 // indirect
|
||||
github.com/Shopify/toxiproxy v2.1.4+incompatible // indirect
|
||||
github.com/StackExchange/wmi v1.2.1 // indirect
|
||||
github.com/VividCortex/ewma v1.1.1 // indirect
|
||||
github.com/ajwerner/btree v0.0.0-20211221152037-f427b3e689c0 // indirect
|
||||
github.com/alecthomas/atomic v0.1.0-alpha2 // indirect
|
||||
github.com/aliyun/aliyun-oss-go-sdk v2.0.4+incompatible // indirect
|
||||
github.com/anacrolix/dht v0.0.0-20181129074040-b09db78595aa // indirect
|
||||
github.com/anacrolix/go-libutp v0.0.0-20180808010927-aebbeb60ea05 // indirect
|
||||
github.com/anacrolix/log v0.0.0-20180808012509-286fcf906b48 // indirect
|
||||
github.com/anacrolix/missinggo v0.0.0-20181129073415-3237bf955fed // indirect
|
||||
github.com/anacrolix/mmsg v0.0.0-20180808012353-5adb2c1127c0 // indirect
|
||||
github.com/anacrolix/sync v0.0.0-20180808010631-44578de4e778 // indirect
|
||||
github.com/anacrolix/utp v0.0.0-20180219060659-9e0e1d1d0572 // indirect
|
||||
github.com/anacrolix/chansync v0.4.1-0.20240627045151-1aa1ac392fe8 // indirect
|
||||
github.com/anacrolix/dht/v2 v2.19.2-0.20221121215055-066ad8494444 // indirect
|
||||
github.com/anacrolix/envpprof v1.3.0 // indirect
|
||||
github.com/anacrolix/generics v0.0.2-0.20240227122613-f95486179cab // indirect
|
||||
github.com/anacrolix/go-libutp v1.3.1 // indirect
|
||||
github.com/anacrolix/log v0.15.3-0.20240627045001-cd912c641d83 // indirect
|
||||
github.com/anacrolix/missinggo v1.3.0 // indirect
|
||||
github.com/anacrolix/missinggo/perf v1.0.0 // indirect
|
||||
github.com/anacrolix/missinggo/v2 v2.7.3 // indirect
|
||||
github.com/anacrolix/mmsg v1.0.0 // indirect
|
||||
github.com/anacrolix/multiless v0.3.0 // indirect
|
||||
github.com/anacrolix/stm v0.4.0 // indirect
|
||||
github.com/anacrolix/sync v0.5.1 // indirect
|
||||
github.com/anacrolix/upnp v0.1.4 // indirect
|
||||
github.com/anacrolix/utp v0.1.0 // indirect
|
||||
github.com/aokoli/goutils v1.0.1 // indirect
|
||||
github.com/apache/thrift v0.13.0 // indirect
|
||||
github.com/aws/aws-sdk-go v1.39.0 // indirect
|
||||
@@ -170,12 +179,13 @@ require (
|
||||
github.com/bahlo/generic-list-go v0.2.0 // indirect
|
||||
github.com/basgys/goxml2json v1.1.1-0.20181031222924-996d9fc8d313 // indirect
|
||||
github.com/beevik/etree v1.1.0 // indirect
|
||||
github.com/benbjohnson/immutable v0.3.0 // indirect
|
||||
github.com/beorn7/perks v1.0.1 // indirect
|
||||
github.com/bits-and-blooms/bitset v1.2.2 // indirect
|
||||
github.com/blang/semver v3.5.1+incompatible // indirect
|
||||
github.com/bmizerany/assert v0.0.0-20160611221934-b7ed37b82869 // indirect
|
||||
github.com/boltdb/bolt v1.3.1 // indirect
|
||||
github.com/boombuler/barcode v1.0.1-0.20190219062509-6c824513bacc // indirect
|
||||
github.com/bradfitz/iter v0.0.0-20140124041915-454541ec3da2 // indirect
|
||||
github.com/bradfitz/iter v0.0.0-20191230175014-e8f45d346db8 // indirect
|
||||
github.com/buger/jsonparser v1.1.1 // indirect
|
||||
github.com/cespare/xxhash v1.1.0 // indirect
|
||||
github.com/cespare/xxhash/v2 v2.2.0 // indirect
|
||||
@@ -203,17 +213,17 @@ require (
|
||||
github.com/eapache/go-resiliency v1.1.0 // indirect
|
||||
github.com/eapache/go-xerial-snappy v0.0.0-20180814174437-776d5712da21 // indirect
|
||||
github.com/eapache/queue v1.1.0 // indirect
|
||||
github.com/edsrzf/mmap-go v1.0.0 // indirect
|
||||
github.com/elgatito/upnp v0.0.0-20180711183757-2f244d205f9a // indirect
|
||||
github.com/edsrzf/mmap-go v1.1.0 // indirect
|
||||
github.com/euank/go-kmsg-parser v2.0.0+incompatible // indirect
|
||||
github.com/farsightsec/golang-framestream v0.0.0-20181102145529-8a0cb8ba8710 // indirect
|
||||
github.com/fatih/color v1.13.0 // indirect
|
||||
github.com/felixge/httpsnoop v1.0.4 // indirect
|
||||
github.com/flynn/go-shlex v0.0.0-20150515145356-3f9db97f8568 // indirect
|
||||
github.com/gin-contrib/sse v0.1.0 // indirect
|
||||
github.com/glycerine/go-unsnap-stream v0.0.0-20181221182339-f9677308dec2 // indirect
|
||||
github.com/go-asn1-ber/asn1-ber v1.5.8-0.20250403174932-29230038a667 // indirect
|
||||
github.com/go-logfmt/logfmt v0.5.0 // indirect
|
||||
github.com/go-llsqlite/adapter v0.0.0-20230927005056-7f5ce7f0c916 // indirect
|
||||
github.com/go-llsqlite/crawshaw v0.5.2-0.20240425034140-f30eb7704568 // indirect
|
||||
github.com/go-logfmt/logfmt v0.5.1 // indirect
|
||||
github.com/go-logr/logr v1.4.2 // indirect
|
||||
github.com/go-logr/stdr v1.2.2 // indirect
|
||||
github.com/go-ole/go-ole v1.2.6 // indirect
|
||||
@@ -228,7 +238,7 @@ require (
|
||||
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect
|
||||
github.com/golang/protobuf v1.5.4 // indirect
|
||||
github.com/golang/snappy v0.0.4 // indirect
|
||||
github.com/google/btree v1.0.1 // indirect
|
||||
github.com/google/btree v1.1.2 // indirect
|
||||
github.com/google/go-querystring v1.0.0 // indirect
|
||||
github.com/google/gofuzz v1.1.0 // indirect
|
||||
github.com/google/s2a-go v0.1.7 // indirect
|
||||
@@ -236,9 +246,9 @@ require (
|
||||
github.com/googleapis/gax-go/v2 v2.12.2 // indirect
|
||||
github.com/googleapis/gnostic v0.4.1 // indirect
|
||||
github.com/googollee/go-engine.io v0.0.0-20180829091931-e2f255711dcb // indirect
|
||||
github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1 // indirect
|
||||
github.com/gopherjs/gopherjs v0.0.0-20190910122728-9d188e94fb99 // indirect
|
||||
github.com/grpc-ecosystem/grpc-opentracing v0.0.0-20180507213350-8e809c8a8645 // indirect
|
||||
github.com/huandu/xstrings v1.2.0 // indirect
|
||||
github.com/huandu/xstrings v1.3.2 // indirect
|
||||
github.com/huaweicloud/huaweicloud-sdk-go v1.0.26 // indirect
|
||||
github.com/icholy/digest v1.1.0 // indirect
|
||||
github.com/imdario/mergo v0.3.6 // indirect
|
||||
@@ -250,18 +260,18 @@ require (
|
||||
github.com/jtolds/gls v4.20.0+incompatible // indirect
|
||||
github.com/kardianos/osext v0.0.0-20190222173326-2bc1f35cddc0 // indirect
|
||||
github.com/karrick/godirwalk v1.16.1 // indirect
|
||||
github.com/klauspost/cpuid/v2 v2.0.9 // indirect
|
||||
github.com/klauspost/cpuid/v2 v2.2.3 // indirect
|
||||
github.com/kr/fs v0.1.0 // indirect
|
||||
github.com/ks3sdklib/aws-sdk-go v1.8.1 // indirect
|
||||
github.com/leodido/go-urn v1.2.0 // indirect
|
||||
github.com/lestrrat-go/iter v0.0.0-20200422075355-fc1769541911 // indirect
|
||||
github.com/lestrrat-go/pdebug v0.0.0-20200204225717-4d6bd78da58d // indirect
|
||||
github.com/lestrrat/go-pdebug v0.0.0-20180220043741-569c97477ae8 // indirect
|
||||
github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0 // indirect
|
||||
github.com/lufia/plan9stats v0.0.0-20220913051719-115f729f3c8c // indirect
|
||||
github.com/ma314smith/signedxml v0.0.0-20210628192057-abc5b481ae1c // indirect
|
||||
github.com/mailru/easyjson v0.7.7 // indirect
|
||||
github.com/mattn/go-colorable v0.1.9 // indirect
|
||||
github.com/mattn/go-isatty v0.0.14 // indirect
|
||||
github.com/mattn/go-isatty v0.0.16 // indirect
|
||||
github.com/mattn/go-runewidth v0.0.13 // indirect
|
||||
github.com/mattn/go-tty v0.0.0-20181127064339-e4f871175a2f // indirect
|
||||
github.com/matttproud/golang_protobuf_extensions v1.0.2-0.20181231171920-c182affec369 // indirect
|
||||
@@ -270,6 +280,7 @@ require (
|
||||
github.com/mgutz/ansi v0.0.0-20170206155736-9520e82c474b // indirect
|
||||
github.com/mindprince/gonvml v0.0.0-20190828220739-9ebdce4bb989 // indirect
|
||||
github.com/minio/minio-go/v6 v6.0.33 // indirect
|
||||
github.com/minio/sha256-simd v1.0.0 // indirect
|
||||
github.com/mistifyio/go-zfs v2.1.2-0.20190413222219-f784269be439+incompatible // indirect
|
||||
github.com/mitchellh/go-homedir v1.1.0 // indirect
|
||||
github.com/moby/sys/mountinfo v0.1.3 // indirect
|
||||
@@ -279,10 +290,12 @@ require (
|
||||
github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826 // indirect
|
||||
github.com/mozillazg/go-httpheader v0.2.1 // indirect
|
||||
github.com/mozillazg/go-pinyin v0.19.0 // indirect
|
||||
github.com/mr-tron/base58 v1.2.0 // indirect
|
||||
github.com/mrunalp/fileutils v0.0.0-20200520151820-abd8a0e76976 // indirect
|
||||
github.com/mschoch/smat v0.0.0-20160514031455-90eadee771ae // indirect
|
||||
github.com/mschoch/smat v0.2.0 // indirect
|
||||
github.com/multiformats/go-multihash v0.2.3 // indirect
|
||||
github.com/multiformats/go-varint v0.0.6 // indirect
|
||||
github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f // indirect
|
||||
github.com/op/go-logging v0.0.0-20160315200505-970db520ece7 // indirect
|
||||
github.com/opencontainers/go-digest v1.0.0 // indirect
|
||||
github.com/opencontainers/image-spec v1.0.1 // indirect
|
||||
github.com/opencontainers/runc v1.0.0-rc92 // indirect
|
||||
@@ -292,20 +305,39 @@ require (
|
||||
github.com/opentracing/opentracing-go v1.0.2 // indirect
|
||||
github.com/openzipkin/zipkin-go-opentracing v0.3.4 // indirect
|
||||
github.com/oracle/oci-go-sdk v24.3.0+incompatible // indirect
|
||||
github.com/philhofer/fwd v1.0.0 // indirect
|
||||
github.com/pierrec/lz4 v2.6.1+incompatible // indirect
|
||||
github.com/pion/datachannel v1.5.2 // indirect
|
||||
github.com/pion/dtls/v2 v2.2.4 // indirect
|
||||
github.com/pion/ice/v2 v2.2.6 // indirect
|
||||
github.com/pion/interceptor v0.1.11 // indirect
|
||||
github.com/pion/logging v0.2.2 // indirect
|
||||
github.com/pion/mdns v0.0.5 // indirect
|
||||
github.com/pion/randutil v0.1.0 // indirect
|
||||
github.com/pion/rtcp v1.2.9 // indirect
|
||||
github.com/pion/rtp v1.7.13 // indirect
|
||||
github.com/pion/sctp v1.8.2 // indirect
|
||||
github.com/pion/sdp/v3 v3.0.5 // indirect
|
||||
github.com/pion/srtp/v2 v2.0.9 // indirect
|
||||
github.com/pion/stun v0.3.5 // indirect
|
||||
github.com/pion/transport v0.13.1 // indirect
|
||||
github.com/pion/transport/v2 v2.0.0 // indirect
|
||||
github.com/pion/turn/v2 v2.0.8 // indirect
|
||||
github.com/pion/udp v0.1.4 // indirect
|
||||
github.com/pion/webrtc/v3 v3.1.42 // indirect
|
||||
github.com/pkg/term v1.0.0 // indirect
|
||||
github.com/pmezard/go-difflib v1.0.0 // indirect
|
||||
github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c // indirect
|
||||
github.com/prometheus/client_golang v1.12.1 // indirect
|
||||
github.com/power-devops/perfstat v0.0.0-20220216144756-c35f1ee13d7c // indirect
|
||||
github.com/prometheus/client_golang v1.12.2 // indirect
|
||||
github.com/prometheus/client_model v0.2.0 // indirect
|
||||
github.com/prometheus/common v0.32.1 // indirect
|
||||
github.com/prometheus/common v0.35.0 // indirect
|
||||
github.com/prometheus/procfs v0.7.3 // indirect
|
||||
github.com/protolambda/ctxlock v0.1.0 // indirect
|
||||
github.com/rcrowley/go-metrics v0.0.0-20181016184325-3113b8401b8a // indirect
|
||||
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec // indirect
|
||||
github.com/richardlehane/mscfb v1.0.4 // indirect
|
||||
github.com/richardlehane/msoleps v1.0.3 // indirect
|
||||
github.com/rivo/uniseg v0.2.0 // indirect
|
||||
github.com/ryszard/goskiplist v0.0.0-20150312221310-2dfbae5fcf46 // indirect
|
||||
github.com/rs/dnscache v0.0.0-20211102005908-e0241e321417 // indirect
|
||||
github.com/seccomp/libseccomp-golang v0.9.1 // indirect
|
||||
github.com/smartystreets/assertions v1.2.0 // indirect
|
||||
github.com/spaolacci/murmur3 v1.1.0 // indirect
|
||||
@@ -316,16 +348,15 @@ require (
|
||||
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common v1.0.413 // indirect
|
||||
github.com/tencentyun/cos-go-sdk-v5 v0.7.24 // indirect
|
||||
github.com/texttheater/golang-levenshtein v0.0.0-20180516184445-d188e65d659e // indirect
|
||||
github.com/tinylib/msgp v1.1.0 // indirect
|
||||
github.com/tidwall/btree v1.6.0 // indirect
|
||||
github.com/tklauser/go-sysconf v0.3.10 // indirect
|
||||
github.com/tklauser/numcpus v0.4.0 // indirect
|
||||
github.com/tklauser/numcpus v0.5.0 // indirect
|
||||
github.com/ugorji/go/codec v1.1.7 // indirect
|
||||
github.com/ulikunitz/xz v0.5.12 // indirect
|
||||
github.com/vmware/govmomi v0.37.1 // indirect
|
||||
github.com/volcengine/ve-tos-golang-sdk/v2 v2.6.2 // indirect
|
||||
github.com/volcengine/volc-sdk-golang v1.0.23 // indirect
|
||||
github.com/willf/bitset v1.1.11-0.20200630133818-d5bec3311243 // indirect
|
||||
github.com/willf/bloom v2.0.3+incompatible // indirect
|
||||
github.com/wk8/go-ordered-map/v2 v2.1.8 // indirect
|
||||
github.com/xuri/efp v0.0.0-20220603152613-6918739fd470 // indirect
|
||||
github.com/xuri/nfp v0.0.0-20220409054826-5e722a1d9e22 // indirect
|
||||
@@ -339,9 +370,10 @@ require (
|
||||
go.opentelemetry.io/otel v1.23.0 // indirect
|
||||
go.opentelemetry.io/otel/metric v1.23.0 // indirect
|
||||
go.opentelemetry.io/otel/trace v1.23.0 // indirect
|
||||
go.uber.org/atomic v1.7.0 // indirect
|
||||
go.uber.org/multierr v1.6.0 // indirect
|
||||
go.uber.org/atomic v1.10.0 // indirect
|
||||
go.uber.org/multierr v1.8.0 // indirect
|
||||
go.uber.org/zap v1.17.0 // indirect
|
||||
golang.org/x/exp v0.0.0-20240506185415-9bf2ced13842 // indirect
|
||||
golang.org/x/oauth2 v0.17.0 // indirect
|
||||
golang.org/x/term v0.18.0 // indirect
|
||||
google.golang.org/api v0.167.0 // indirect
|
||||
@@ -353,8 +385,14 @@ require (
|
||||
gopkg.in/inf.v0 v0.9.1 // indirect
|
||||
gopkg.in/ini.v1 v1.62.0 // indirect
|
||||
k8s.io/utils v0.0.0-20201110183641-67b214c5f920 // indirect
|
||||
lukechampine.com/blake3 v1.1.6 // indirect
|
||||
modernc.org/libc v1.22.3 // indirect
|
||||
modernc.org/mathutil v1.5.0 // indirect
|
||||
modernc.org/memory v1.5.0 // indirect
|
||||
modernc.org/sqlite v1.21.1 // indirect
|
||||
sigs.k8s.io/structured-merge-diff/v4 v4.0.1 // indirect
|
||||
sigs.k8s.io/yaml v1.2.0 // indirect
|
||||
zombiezen.com/go/sqlite v0.13.1 // indirect
|
||||
)
|
||||
|
||||
replace github.com/influxdata/promql/v2 => github.com/zexi/promql/v2 v2.12.1
|
||||
|
||||
362
go.sum
362
go.sum
@@ -43,7 +43,11 @@ cloud.google.com/go/storage v1.8.0/go.mod h1:Wv1Oy7z6Yz3DshWRJFhqM/UCfaWIRTdp0RX
|
||||
cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9ullr3+Kg0=
|
||||
cloud.google.com/go/storage v1.39.1 h1:MvraqHKhogCOTXTlct/9C3K3+Uy2jBmFYb3/Sp6dVtY=
|
||||
cloud.google.com/go/storage v1.39.1/go.mod h1:xK6xZmxZmo+fyP7+DEF6FhNc24/JAe95OLyOHCXFH1o=
|
||||
crawshaw.io/iox v0.0.0-20181124134642-c51c3df30797/go.mod h1:sXBiorCo8c46JlQV3oXPKINnZ8mcqnye1EkVkqsectk=
|
||||
crawshaw.io/sqlite v0.3.2/go.mod h1:igAO5JulrQ1DbdZdtVq48mnZUBAPOeFzer7VhDWNtW4=
|
||||
dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU=
|
||||
filippo.io/edwards25519 v1.0.0-rc.1 h1:m0VOOB23frXZvAOK44usCgLWvtsxIoMCTBGJZlpmGfU=
|
||||
filippo.io/edwards25519 v1.0.0-rc.1/go.mod h1:N1IkdkCkiLB6tki+MYJoSx2JTY9NUlxZE7eHn5EwJns=
|
||||
gitee.com/chunanyong/dm v1.8.14 h1:1S9+aD0fY/HXkcm8dKh2HjYsDlcdXNG+4IOX9JtrSjA=
|
||||
gitee.com/chunanyong/dm v1.8.14/go.mod h1:EPRJnuPFgbyOFgJ0TRYCTGzhq+ZT4wdyaj/GW/LLcNg=
|
||||
github.com/360EntSecGroup-Skylar/excelize v1.4.0 h1:43rak9uafmwSJpXfFO1heKQph8tP3nlfWJWFQQtW1R0=
|
||||
@@ -106,8 +110,11 @@ github.com/PuerkitoBio/purell v1.0.0/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbt
|
||||
github.com/PuerkitoBio/urlesc v0.0.0-20160726150825-5bd2802263f2/go.mod h1:uGdkoq3SwY9Y+13GIhn11/XLaGBb4BfwItxLd5jeuXE=
|
||||
github.com/QcloudApi/qcloud_sign_golang v0.0.0-20141224014652-e4130a326409/go.mod h1:1pk82RBxDY/JZnPQrtqHlUFfCctgdorsd9M06fMynOM=
|
||||
github.com/RoaringBitmap/roaring v0.4.7/go.mod h1:8khRDP4HmeXns4xIj9oGrKSz7XTQiJx2zgh7AcNke4w=
|
||||
github.com/RoaringBitmap/roaring v0.4.16 h1:NholfewybRLOwACgfqfzn/N5xa6keKNs4fP00t0cwLo=
|
||||
github.com/RoaringBitmap/roaring v0.4.16/go.mod h1:8khRDP4HmeXns4xIj9oGrKSz7XTQiJx2zgh7AcNke4w=
|
||||
github.com/RoaringBitmap/roaring v0.4.17/go.mod h1:D3qVegWTmfCaX4Bl5CrBE9hfrSrrXIr8KVNvRsDi1NI=
|
||||
github.com/RoaringBitmap/roaring v0.4.23/go.mod h1:D0gp8kJQgE1A4LQ5wFLggQEyvDi06Mq5mKs52e1TwOo=
|
||||
github.com/RoaringBitmap/roaring v1.2.3 h1:yqreLINqIrX22ErkKI0vY47/ivtJr6n+kMhVOVmhWBY=
|
||||
github.com/RoaringBitmap/roaring v1.2.3/go.mod h1:plvDsJQpxOC5bw8LRteu/MLWHsHez/3y6cubLI4/1yE=
|
||||
github.com/Shopify/sarama v1.19.0/go.mod h1:FVkBWblsNy7DGZRfXLU0O9RCGt5g3g3yEuWXgklEdEo=
|
||||
github.com/Shopify/sarama v1.20.0 h1:wAMHhl1lGRlobeoV/xOKpbqD2OQsOvY4A/vIOGroIe8=
|
||||
github.com/Shopify/sarama v1.20.0/go.mod h1:FVkBWblsNy7DGZRfXLU0O9RCGt5g3g3yEuWXgklEdEo=
|
||||
github.com/Shopify/toxiproxy v2.1.4+incompatible h1:TKdv8HiTLgE5wdJuEML90aBgNWsokNbMijUGhmcoBJc=
|
||||
@@ -117,6 +124,14 @@ github.com/StackExchange/wmi v1.2.1/go.mod h1:rcmrprowKIVzvc+NUiLncP2uuArMWLCbu9
|
||||
github.com/VividCortex/ewma v1.1.1 h1:MnEK4VOv6n0RSY4vtRe3h11qjxL3+t0B8yOL8iMXdcM=
|
||||
github.com/VividCortex/ewma v1.1.1/go.mod h1:2Tkkvm3sRDVXaiyucHiACn4cqf7DpdyLvmxzcbUokwA=
|
||||
github.com/a8m/mark v0.1.1-0.20170507133748-44f2db618845/go.mod h1:c8Mh99Cw82nrsAnPgxQSZHkswVOJF7/MqZb1ZdvriLM=
|
||||
github.com/ajwerner/btree v0.0.0-20211221152037-f427b3e689c0 h1:byYvvbfSo3+9efR4IeReh77gVs4PnNDR3AMOE9NJ7a0=
|
||||
github.com/ajwerner/btree v0.0.0-20211221152037-f427b3e689c0/go.mod h1:q37NoqncT41qKc048STsifIt69LfUJ8SrWWcz/yam5k=
|
||||
github.com/alecthomas/assert/v2 v2.0.0-alpha3 h1:pcHeMvQ3OMstAWgaeaXIAL8uzB9xMm2zlxt+/4ml8lk=
|
||||
github.com/alecthomas/assert/v2 v2.0.0-alpha3/go.mod h1:+zD0lmDXTeQj7TgDgCt0ePWxb0hMC1G+PGTsTCv1B9o=
|
||||
github.com/alecthomas/atomic v0.1.0-alpha2 h1:dqwXmax66gXvHhsOS4pGPZKqYOlTkapELkLb3MNdlH8=
|
||||
github.com/alecthomas/atomic v0.1.0-alpha2/go.mod h1:zD6QGEyw49HIq19caJDc2NMXAy8rNi9ROrxtMXATfyI=
|
||||
github.com/alecthomas/repr v0.0.0-20210801044451-80ca428c5142 h1:8Uy0oSf5co/NZXje7U1z8Mpep++QJOldL2hs/sBQf48=
|
||||
github.com/alecthomas/repr v0.0.0-20210801044451-80ca428c5142/go.mod h1:2kn6fqh/zIyPLmm3ugklbEi5hg5wS435eygvNfaDQL8=
|
||||
github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
|
||||
github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
|
||||
github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
|
||||
@@ -126,43 +141,65 @@ github.com/aliyun/alibaba-cloud-sdk-go v1.61.684 h1:MHqPW0la4Op96JGMkpB7Kxrz0Se5
|
||||
github.com/aliyun/alibaba-cloud-sdk-go v1.61.684/go.mod h1:pUKYbK5JQ+1Dfxk80P0qxGqe5dkxDoabbZS7zOcouyA=
|
||||
github.com/aliyun/aliyun-oss-go-sdk v2.0.4+incompatible h1:EaK5256H3ELiyaq5O/Zwd6fnghD6DqmZDQmmzzJklUU=
|
||||
github.com/aliyun/aliyun-oss-go-sdk v2.0.4+incompatible/go.mod h1:T/Aws4fEfogEE9v+HPhhw+CntffsBHJ8nXQCwKr0/g8=
|
||||
github.com/anacrolix/dht v0.0.0-20180412060941-24cbf25b72a4/go.mod h1:hQfX2BrtuQsLQMYQwsypFAab/GvHg8qxwVi4OJdR1WI=
|
||||
github.com/anacrolix/dht v0.0.0-20181127122252-acaa69c368bb/go.mod h1:Z/mP+H70xwnUv957UXVkTrzYRhKs0mGjS0lyqS331g4=
|
||||
github.com/anacrolix/dht v0.0.0-20181129074040-b09db78595aa h1:5RyX9Tvqa9oewlJhFihkxe8biS0ojTlrNU3ryqm5g2s=
|
||||
github.com/anacrolix/dht v0.0.0-20181129074040-b09db78595aa/go.mod h1:Ayu4t+5TsHQ07/P8XzRJqVofv7lU4R1ZTT7KW5+SPFA=
|
||||
github.com/anacrolix/envpprof v0.0.0-20180404065416-323002cec2fa h1:xCaATLKmn39QqLs3tUZYr6eKvezJV+FYvVOLTklxK6U=
|
||||
github.com/anacrolix/chansync v0.4.1-0.20240627045151-1aa1ac392fe8 h1:eyb0bBaQKMOh5Se/Qg54shijc8K4zpQiOjEhKFADkQM=
|
||||
github.com/anacrolix/chansync v0.4.1-0.20240627045151-1aa1ac392fe8/go.mod h1:DZsatdsdXxD0WiwcGl0nJVwyjCKMDv+knl1q2iBjA2k=
|
||||
github.com/anacrolix/dht/v2 v2.19.2-0.20221121215055-066ad8494444 h1:8V0K09lrGoeT2KRJNOtspA7q+OMxGwQqK/Ug0IiaaRE=
|
||||
github.com/anacrolix/dht/v2 v2.19.2-0.20221121215055-066ad8494444/go.mod h1:MctKM1HS5YYDb3F30NGJxLE+QPuqWoT5ReW/4jt8xew=
|
||||
github.com/anacrolix/envpprof v0.0.0-20180404065416-323002cec2fa/go.mod h1:KgHhUaQMc8cC0+cEflSgCFNFbKwi5h54gqtVn8yhP7c=
|
||||
github.com/anacrolix/go-libutp v0.0.0-20180522111405-6baeb806518d/go.mod h1:beQSaSxwH2d9Eeu5ijrEnHei5Qhk+J6cDm1QkWFru4E=
|
||||
github.com/anacrolix/go-libutp v0.0.0-20180725071407-34b43d880940/go.mod h1:szRMvnqPPC0VKbIRVoImO5gjJj8OZCYdixSrDEo1TzM=
|
||||
github.com/anacrolix/go-libutp v0.0.0-20180808010927-aebbeb60ea05 h1:Zoniih3jyqtr3I0xFoMvw1USWpg+CbI/zOrcLudr0lc=
|
||||
github.com/anacrolix/go-libutp v0.0.0-20180808010927-aebbeb60ea05/go.mod h1:POY/GPlrFKRxnOKH1sGAB+NBWMoP+sI+hHJxgcgWbWw=
|
||||
github.com/anacrolix/log v0.0.0-20180412014343-2323884b361d/go.mod h1:sf/7c2aTldL6sRQj/4UKyjgVZBu2+M2z9wf7MmwPiew=
|
||||
github.com/anacrolix/log v0.0.0-20180808012509-286fcf906b48 h1:aHwCj9Q6sjQOq5sC8Bzylt7GCAvt+D5MPEpkD6TeXxU=
|
||||
github.com/anacrolix/log v0.0.0-20180808012509-286fcf906b48/go.mod h1:sf/7c2aTldL6sRQj/4UKyjgVZBu2+M2z9wf7MmwPiew=
|
||||
github.com/anacrolix/missinggo v0.0.0-20180522035225-b4a5853e62ff/go.mod h1:b0p+7cn+rWMIphK1gDH2hrDuwGOcbB6V4VXeSsEfHVk=
|
||||
github.com/anacrolix/missinggo v0.0.0-20180621131740-7fc7cfea16ea/go.mod h1:kwGiTUTZ0+p4vAz3VbAI5a30t2YbvemcmspjKwrAz5s=
|
||||
github.com/anacrolix/envpprof v1.0.0/go.mod h1:KgHhUaQMc8cC0+cEflSgCFNFbKwi5h54gqtVn8yhP7c=
|
||||
github.com/anacrolix/envpprof v1.1.0/go.mod h1:My7T5oSqVfEn4MD4Meczkw/f5lSIndGAKu/0SM/rkf4=
|
||||
github.com/anacrolix/envpprof v1.3.0 h1:WJt9bpuT7A/CDCxPOv/eeZqHWlle/Y0keJUvc6tcJDk=
|
||||
github.com/anacrolix/envpprof v1.3.0/go.mod h1:7QIG4CaX1uexQ3tqd5+BRa/9e2D02Wcertl6Yh0jCB0=
|
||||
github.com/anacrolix/generics v0.0.0-20230113004304-d6428d516633/go.mod h1:ff2rHB/joTV03aMSSn/AZNnaIpUw0h3njetGsaXcMy8=
|
||||
github.com/anacrolix/generics v0.0.2-0.20240227122613-f95486179cab h1:MvuAC/UJtcohN6xWc8zYXSZfllh1LVNepQ0R3BCX5I4=
|
||||
github.com/anacrolix/generics v0.0.2-0.20240227122613-f95486179cab/go.mod h1:ff2rHB/joTV03aMSSn/AZNnaIpUw0h3njetGsaXcMy8=
|
||||
github.com/anacrolix/go-libutp v1.3.1 h1:idJzreNLl+hNjGC3ZnUOjujEaryeOGgkwHLqSGoige0=
|
||||
github.com/anacrolix/go-libutp v1.3.1/go.mod h1:heF41EC8kN0qCLMokLBVkB8NXiLwx3t8R8810MTNI5o=
|
||||
github.com/anacrolix/log v0.3.0/go.mod h1:lWvLTqzAnCWPJA08T2HCstZi0L1y2Wyvm3FJgwU9jwU=
|
||||
github.com/anacrolix/log v0.6.0/go.mod h1:lWvLTqzAnCWPJA08T2HCstZi0L1y2Wyvm3FJgwU9jwU=
|
||||
github.com/anacrolix/log v0.13.1/go.mod h1:D4+CvN8SnruK6zIFS/xPoRJmtvtnxs+CSfDQ+BFxZ68=
|
||||
github.com/anacrolix/log v0.14.2/go.mod h1:1OmJESOtxQGNMlUO5rcv96Vpp9mfMqXXbe2RdinFLdY=
|
||||
github.com/anacrolix/log v0.15.3-0.20240627045001-cd912c641d83 h1:9o/yVzzLzYaBDFx8B27yhkvBLhNnRAuSTK7Y+yZKVtU=
|
||||
github.com/anacrolix/log v0.15.3-0.20240627045001-cd912c641d83/go.mod h1:xvHjsYWWP7yO8PZwtuIp/k0DBlu07pSJqH4SEC78Vwc=
|
||||
github.com/anacrolix/lsan v0.0.0-20211126052245-807000409a62 h1:P04VG6Td13FHMgS5ZBcJX23NPC/fiC4cp9bXwYujdYM=
|
||||
github.com/anacrolix/lsan v0.0.0-20211126052245-807000409a62/go.mod h1:66cFKPCO7Sl4vbFnAaSq7e4OXtdMhRSBagJGWgmpJbM=
|
||||
github.com/anacrolix/missinggo v0.0.0-20180725070939-60ef2fbf63df/go.mod h1:kwGiTUTZ0+p4vAz3VbAI5a30t2YbvemcmspjKwrAz5s=
|
||||
github.com/anacrolix/missinggo v0.0.0-20181127231911-72d14a94053a/go.mod h1:IN+9GUe7OxKMIs/XeXEbT/rMUolmJzmlZiXHS7FwD/Y=
|
||||
github.com/anacrolix/missinggo v0.0.0-20181129073415-3237bf955fed h1:pMzstxgUXooGmNxZnjFSsnjtFd7s81sNI7L2pzEuWWs=
|
||||
github.com/anacrolix/missinggo v0.0.0-20181129073415-3237bf955fed/go.mod h1:IN+9GUe7OxKMIs/XeXEbT/rMUolmJzmlZiXHS7FwD/Y=
|
||||
github.com/anacrolix/missinggo v1.1.0/go.mod h1:MBJu3Sk/k3ZfGYcS7z18gwfu72Ey/xopPFJJbTi5yIo=
|
||||
github.com/anacrolix/missinggo v1.1.2-0.20190815015349-b888af804467/go.mod h1:MBJu3Sk/k3ZfGYcS7z18gwfu72Ey/xopPFJJbTi5yIo=
|
||||
github.com/anacrolix/missinggo v1.2.1/go.mod h1:J5cMhif8jPmFoC3+Uvob3OXXNIhOUikzMt+uUjeM21Y=
|
||||
github.com/anacrolix/missinggo v1.3.0 h1:06HlMsudotL7BAELRZs0yDZ4yVXsHXGi323QBjAVASw=
|
||||
github.com/anacrolix/missinggo v1.3.0/go.mod h1:bqHm8cE8xr+15uVfMG3BFui/TxyB6//H5fwlq/TeqMc=
|
||||
github.com/anacrolix/missinggo/perf v1.0.0 h1:7ZOGYziGEBytW49+KmYGTaNfnwUqP1HBsy6BqESAJVw=
|
||||
github.com/anacrolix/missinggo/perf v1.0.0/go.mod h1:ljAFWkBuzkO12MQclXzZrosP5urunoLS0Cbvb4V0uMQ=
|
||||
github.com/anacrolix/missinggo/v2 v2.2.0/go.mod h1:o0jgJoYOyaoYQ4E2ZMISVa9c88BbUBVQQW4QeRkNCGY=
|
||||
github.com/anacrolix/missinggo/v2 v2.5.1/go.mod h1:WEjqh2rmKECd0t1VhQkLGTdIWXO6f6NLjp5GlMZ+6FA=
|
||||
github.com/anacrolix/missinggo/v2 v2.7.3 h1:Ee//CmZBMadeNiYB/hHo9ly2PFOEZ4Fhsbnug3rDAIE=
|
||||
github.com/anacrolix/missinggo/v2 v2.7.3/go.mod h1:mIEtp9pgaXqt8VQ3NQxFOod/eQ1H0D1XsZzKUQfwtac=
|
||||
github.com/anacrolix/mmsg v0.0.0-20180515031531-a4a3ba1fc8bb/go.mod h1:x2/ErsYUmT77kezS63+wzZp8E3byYB0gzirM/WMBLfw=
|
||||
github.com/anacrolix/mmsg v0.0.0-20180808012353-5adb2c1127c0 h1:Fa1XqqLW62lQzEDlNA+QcdJbkfJcxQN0YC8983kj5tU=
|
||||
github.com/anacrolix/mmsg v0.0.0-20180808012353-5adb2c1127c0/go.mod h1:x8kRaJY/dCrY9Al0PEcj1mb/uFHwP6GCJ9fLl4thEPc=
|
||||
github.com/anacrolix/sync v0.0.0-20171108081538-eee974e4f8c1/go.mod h1:+u91KiUuf0lyILI6x3n/XrW7iFROCZCG+TjgK8nW52w=
|
||||
github.com/anacrolix/sync v0.0.0-20180611022320-3c4cb11f5a01/go.mod h1:+u91KiUuf0lyILI6x3n/XrW7iFROCZCG+TjgK8nW52w=
|
||||
github.com/anacrolix/sync v0.0.0-20180725074606-fda11526ff08/go.mod h1:+u91KiUuf0lyILI6x3n/XrW7iFROCZCG+TjgK8nW52w=
|
||||
github.com/anacrolix/sync v0.0.0-20180808010631-44578de4e778 h1:XpCDEixzXOB8yaTW/4YBzKrJdMcFI0DzpPTYNv75wzk=
|
||||
github.com/anacrolix/mmsg v1.0.0 h1:btC7YLjOn29aTUAExJiVUhQOuf/8rhm+/nWCMAnL3Hg=
|
||||
github.com/anacrolix/mmsg v1.0.0/go.mod h1:x8kRaJY/dCrY9Al0PEcj1mb/uFHwP6GCJ9fLl4thEPc=
|
||||
github.com/anacrolix/multiless v0.3.0 h1:5Bu0DZncjE4e06b9r1Ap2tUY4Au0NToBP5RpuEngSis=
|
||||
github.com/anacrolix/multiless v0.3.0/go.mod h1:TrCLEZfIDbMVfLoQt5tOoiBS/uq4y8+ojuEVVvTNPX4=
|
||||
github.com/anacrolix/stm v0.2.0/go.mod h1:zoVQRvSiGjGoTmbM0vSLIiaKjWtNPeTvXUSdJQA4hsg=
|
||||
github.com/anacrolix/stm v0.4.0 h1:tOGvuFwaBjeu1u9X1eIh9TX8OEedEiEQ1se1FjhFnXY=
|
||||
github.com/anacrolix/stm v0.4.0/go.mod h1:GCkwqWoAsP7RfLW+jw+Z0ovrt2OO7wRzcTtFYMYY5t8=
|
||||
github.com/anacrolix/sync v0.0.0-20180808010631-44578de4e778/go.mod h1:s735Etp3joe/voe2sdaXLcqDdJSay1O0OPnM0ystjqk=
|
||||
github.com/anacrolix/sync v0.3.0/go.mod h1:BbecHL6jDSExojhNtgTFSBcdGerzNc64tz3DCOj/I0g=
|
||||
github.com/anacrolix/sync v0.5.1 h1:FbGju6GqSjzVoTgcXTUKkF041lnZkG5P0C3T5RL3SGc=
|
||||
github.com/anacrolix/sync v0.5.1/go.mod h1:BbecHL6jDSExojhNtgTFSBcdGerzNc64tz3DCOj/I0g=
|
||||
github.com/anacrolix/tagflag v0.0.0-20180109131632-2146c8d41bf0/go.mod h1:1m2U/K6ZT+JZG0+bdMK6qauP49QT4wE5pmhJXOKKCHw=
|
||||
github.com/anacrolix/tagflag v0.0.0-20180605133421-f477c8c2f14c/go.mod h1:1m2U/K6ZT+JZG0+bdMK6qauP49QT4wE5pmhJXOKKCHw=
|
||||
github.com/anacrolix/torrent v0.0.0-20180622074351-fefeef4ee9eb/go.mod h1:3vcFVxgOASslNXHdivT8spyMRBanMCenHRpe0u5vpBs=
|
||||
github.com/anacrolix/torrent v0.0.0-20181129073333-cc531b8c4a80 h1:LnqSEnVSkn8Z4Flz/s2AR78OcLQCqz356xmTMxJgPws=
|
||||
github.com/anacrolix/torrent v0.0.0-20181129073333-cc531b8c4a80/go.mod h1:AYCt8S7XNEn0Oq+bIZYUfma6/USBjugDp4nynaHQBTE=
|
||||
github.com/anacrolix/utp v0.0.0-20180219060659-9e0e1d1d0572 h1:kpt6TQTVi6gognY+svubHfxxpq0DLU9AfTQyZVc3UOc=
|
||||
github.com/anacrolix/utp v0.0.0-20180219060659-9e0e1d1d0572/go.mod h1:MDwc+vsGEq7RMw6lr2GKOEqjWny5hO5OZXRVNaBJ2Dk=
|
||||
github.com/anacrolix/tagflag v1.0.0/go.mod h1:1m2U/K6ZT+JZG0+bdMK6qauP49QT4wE5pmhJXOKKCHw=
|
||||
github.com/anacrolix/tagflag v1.1.0/go.mod h1:Scxs9CV10NQatSmbyjqmqmeQNwGzlNe0CMUMIxqHIG8=
|
||||
github.com/anacrolix/torrent v1.57.0 h1:SSt03wiThSohEIGJzSIjYV/n0TWbJVAMmHdGOmcTzY4=
|
||||
github.com/anacrolix/torrent v1.57.0/go.mod h1:SQZfGq/OCMMyIRCNfTpv9E/go4eE9WJR/YY7eC2HYok=
|
||||
github.com/anacrolix/upnp v0.1.4 h1:+2t2KA6QOhm/49zeNyeVwDu1ZYS9dB9wfxyVvh/wk7U=
|
||||
github.com/anacrolix/upnp v0.1.4/go.mod h1:Qyhbqo69gwNWvEk1xNTXsS5j7hMHef9hdr984+9fIic=
|
||||
github.com/anacrolix/utp v0.1.0 h1:FOpQOmIwYsnENnz7tAGohA+r6iXpRjrq8ssKSre2Cp4=
|
||||
github.com/anacrolix/utp v0.1.0/go.mod h1:MDwc+vsGEq7RMw6lr2GKOEqjWny5hO5OZXRVNaBJ2Dk=
|
||||
github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY=
|
||||
github.com/aokoli/goutils v1.0.1 h1:7fpzNGoJ3VA8qcrm++XEE1QUe0mIwNeLa02Nwq7RDkg=
|
||||
github.com/aokoli/goutils v1.0.1/go.mod h1:SijmP0QR8LtwsmDs8Yii5Z/S4trXFGFC2oO5g9DP+DQ=
|
||||
github.com/apache/thrift v0.12.0/go.mod h1:cp2SuWMxlEZw2r+iP2GNCdIi4C1qmUzdZFSVb+bacwQ=
|
||||
github.com/apache/thrift v0.13.0 h1:5hryIiq9gtn+MiLVn0wP37kb/uTeRZgN08WoCsAhIhI=
|
||||
github.com/apache/thrift v0.13.0/go.mod h1:cp2SuWMxlEZw2r+iP2GNCdIi4C1qmUzdZFSVb+bacwQ=
|
||||
github.com/avast/retry-go v3.0.0+incompatible/go.mod h1:XtSnn+n/sHqQIpZ10K1qAevBhOOCWBLXXy3hyiqqBrY=
|
||||
@@ -217,24 +254,30 @@ github.com/beevik/etree v1.1.0 h1:T0xke/WvNtMoCqgzPhkX2r4rjY3GDZFi+FjpRZY2Jbs=
|
||||
github.com/beevik/etree v1.1.0/go.mod h1:r8Aw8JqVegEf0w2fDnATrX9VpkMcyFeM0FhwO62wh+A=
|
||||
github.com/benbjohnson/clock v1.0.0 h1:78Jk/r6m4wCi6sndMpty7A//t4dw/RW5fV4ZgDVfX1w=
|
||||
github.com/benbjohnson/clock v1.0.0/go.mod h1:bGMdMPoPVvcYyt1gHDf4J2KE153Yf9BuiUKYMaxlTDM=
|
||||
github.com/benbjohnson/immutable v0.2.0/go.mod h1:uc6OHo6PN2++n98KHLxW8ef4W42ylHiQSENghE1ezxI=
|
||||
github.com/benbjohnson/immutable v0.3.0 h1:TVRhuZx2wG9SZ0LRdqlbs9S5BZ6Y24hJEHTCgWHZEIw=
|
||||
github.com/benbjohnson/immutable v0.3.0/go.mod h1:uc6OHo6PN2++n98KHLxW8ef4W42ylHiQSENghE1ezxI=
|
||||
github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q=
|
||||
github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8=
|
||||
github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM=
|
||||
github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw=
|
||||
github.com/bitly/go-simplejson v0.5.0 h1:6IH+V8/tVMab511d5bn4M7EwGXZf9Hj6i2xSwkNEM+Y=
|
||||
github.com/bitly/go-simplejson v0.5.0/go.mod h1:cXHtHw4XUPsvGaxgjIAn8PhEWG9NfngEKAMDJEczWVA=
|
||||
github.com/bits-and-blooms/bitset v1.2.0/go.mod h1:gIdJ4wp64HaoK2YrL1Q5/N7Y16edYb8uY+O0FJTyyDA=
|
||||
github.com/bits-and-blooms/bitset v1.2.2 h1:J5gbX05GpMdBjCvQ9MteIg2KKDExr7DrgK+Yc15FvIk=
|
||||
github.com/bits-and-blooms/bitset v1.2.2/go.mod h1:gIdJ4wp64HaoK2YrL1Q5/N7Y16edYb8uY+O0FJTyyDA=
|
||||
github.com/bkaradzic/go-lz4 v1.0.0 h1:RXc4wYsyz985CkXXeX04y4VnZFGG8Rd43pRaHsOXAKk=
|
||||
github.com/bkaradzic/go-lz4 v1.0.0/go.mod h1:0YdlkowM3VswSROI7qDxhRvJ3sLhlFrRRwjwegp5jy4=
|
||||
github.com/blang/semver v3.5.1+incompatible h1:cQNTCjp13qL8KC3Nbxr/y2Bqb63oX6wdnnjpJbkM4JQ=
|
||||
github.com/blang/semver v3.5.1+incompatible/go.mod h1:kRBLl5iJ+tD4TcOOxsy/0fnwebNt5EWlYSAyrTnjyyk=
|
||||
github.com/bmizerany/assert v0.0.0-20160611221934-b7ed37b82869 h1:DDGfHa7BWjL4YnC6+E63dPcxHo2sUxDIu8g3QgEJdRY=
|
||||
github.com/bmizerany/assert v0.0.0-20160611221934-b7ed37b82869/go.mod h1:Ekp36dRnpXw/yCqJaO+ZrUyxD+3VXMFFr56k5XYrpB4=
|
||||
github.com/boltdb/bolt v1.3.1 h1:JQmyP4ZBrce+ZQu0dY660FMfatumYDLun9hBCUVIkF4=
|
||||
github.com/boltdb/bolt v1.3.1/go.mod h1:clJnj/oiGkjum5o1McbSZDSLxVThjynRyGBgiAx27Ps=
|
||||
github.com/boombuler/barcode v1.0.1-0.20190219062509-6c824513bacc h1:biVzkmvwrH8WK8raXaxBx6fRVTlJILwEwQGL1I/ByEI=
|
||||
github.com/boombuler/barcode v1.0.1-0.20190219062509-6c824513bacc/go.mod h1:paBWMcWSl3LHKBqUq+rly7CNSldXjb2rDl3JlRe0mD8=
|
||||
github.com/bradfitz/iter v0.0.0-20140124041915-454541ec3da2 h1:1B/+1BcRhOMG1KH/YhNIU8OppSWk5d/NGyfRla88CuY=
|
||||
github.com/bradfitz/iter v0.0.0-20140124041915-454541ec3da2/go.mod h1:PyRFw1Lt2wKX4ZVSQ2mk+PeDa1rxyObEDlApuIsUKuo=
|
||||
github.com/bradfitz/iter v0.0.0-20190303215204-33e6a9893b0c/go.mod h1:PyRFw1Lt2wKX4ZVSQ2mk+PeDa1rxyObEDlApuIsUKuo=
|
||||
github.com/bradfitz/iter v0.0.0-20191230175014-e8f45d346db8 h1:GKTyiRCL6zVf5wWaqKnf+7Qs6GbEPfd4iMOitWzXJx8=
|
||||
github.com/bradfitz/iter v0.0.0-20191230175014-e8f45d346db8/go.mod h1:spo1JLcs67NmW1aVLEgtA8Yy1elc+X8y5SRW1sFW4Og=
|
||||
github.com/buger/jsonparser v1.1.1 h1:2PnMjfWD7wBILjqQbt530v576A/cAbQvEW9gGIpYMUs=
|
||||
github.com/buger/jsonparser v1.1.1/go.mod h1:6RYKKt7H4d4+iWqouImQ9R2FZql3VbhNgx27UK13J/0=
|
||||
github.com/c-bata/go-prompt v0.2.4 h1:7pKUJ3CUgzdu1HJeWhNRkpVyY/NnlJhM/7d6YgHNOao=
|
||||
@@ -334,14 +377,11 @@ github.com/eapache/go-xerial-snappy v0.0.0-20180814174437-776d5712da21 h1:YEetp8
|
||||
github.com/eapache/go-xerial-snappy v0.0.0-20180814174437-776d5712da21/go.mod h1:+020luEh2TKB4/GOp8oxxtq0Daoen/Cii55CzbTV6DU=
|
||||
github.com/eapache/queue v1.1.0 h1:YOEu7KNc61ntiQlcEeUIoDTJ2o8mQznoNvUhiigpIqc=
|
||||
github.com/eapache/queue v1.1.0/go.mod h1:6eCeP0CKFpHLu8blIFXhExK/dRa7WDZfr6jVFPTqq+I=
|
||||
github.com/edsrzf/mmap-go v0.0.0-20170320065105-0bce6a688712/go.mod h1:YO35OhQPt3KJa3ryjFM5Bs14WD66h8eGKpfaBNrHW5M=
|
||||
github.com/edsrzf/mmap-go v1.0.0 h1:CEBF7HpRnUCSJgGUb5h1Gm7e3VkmVDrR8lvWVLtrOFw=
|
||||
github.com/edsrzf/mmap-go v1.0.0/go.mod h1:YO35OhQPt3KJa3ryjFM5Bs14WD66h8eGKpfaBNrHW5M=
|
||||
github.com/edsrzf/mmap-go v1.1.0 h1:6EUwBLQ/Mcr1EYLE4Tn1VdW1A4ckqCQWZBw8Hr0kjpQ=
|
||||
github.com/edsrzf/mmap-go v1.1.0/go.mod h1:19H/e8pUPLicwkyNgOykDXkJ9F0MHE+Z52B8EIth78Q=
|
||||
github.com/eggsampler/acme/v3 v3.6.2 h1:gvyZbQ92wNQLDASVftGpHEdFwPSfg0+17P0lLt09Tp8=
|
||||
github.com/eggsampler/acme/v3 v3.6.2/go.mod h1:/qh0rKC/Dh7Jj+p4So7DbWmFNzC4dpcpK53r226Fhuo=
|
||||
github.com/elazarl/goproxy v0.0.0-20180725130230-947c36da3153/go.mod h1:/Zj4wYkgs4iZTTu3o/KG3Itv/qCCa8VVMlb3i9OVuzc=
|
||||
github.com/elgatito/upnp v0.0.0-20180711183757-2f244d205f9a h1:2Zw3pxDRTs4nX1WCLAEm27UN0hvjZSge7EaUUQexRZw=
|
||||
github.com/elgatito/upnp v0.0.0-20180711183757-2f244d205f9a/go.mod h1:afkYpY8JAIL4341N7Zj9xJ5yTovsg6BkWfBFlCzIoF4=
|
||||
github.com/emicklei/go-restful v0.0.0-20170410110728-ff4f55a20633/go.mod h1:otzb+WCGbkyDHkqmQmT5YD2WR4BBwUdeQoFo8l/7tVs=
|
||||
github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
|
||||
github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
|
||||
@@ -364,11 +404,14 @@ github.com/fernet/fernet-go v0.0.0-20180830025343-9eac43b88a5e h1:P10tZmVD2XclAa
|
||||
github.com/fernet/fernet-go v0.0.0-20180830025343-9eac43b88a5e/go.mod h1:2H9hjfbpSMHwY503FclkV/lZTBh2YlOmLLSda12uL8c=
|
||||
github.com/flynn/go-shlex v0.0.0-20150515145356-3f9db97f8568 h1:BHsljHzVlRcyQhjrss6TZTdY2VfCqZPbv5k3iBFa2ZQ=
|
||||
github.com/flynn/go-shlex v0.0.0-20150515145356-3f9db97f8568/go.mod h1:xEzjJPgXI435gkrCt3MPfRiAkVrwSbHsst4LCFVfpJc=
|
||||
github.com/frankban/quicktest v1.9.0/go.mod h1:ui7WezCLWMWxVWr1GETZY3smRy0G4KWq9vcPtJmFl7Y=
|
||||
github.com/frankban/quicktest v1.14.4/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0=
|
||||
github.com/frankban/quicktest v1.14.6 h1:7Xjx+VpznH+oBnejlPUj8oUpdxnVs4f8XU8WnHkI4W8=
|
||||
github.com/frankban/quicktest v1.14.6/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0=
|
||||
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
|
||||
github.com/fsnotify/fsnotify v1.4.9 h1:hsms1Qyu0jgnwNXIxa+/V/PDsU6CfLf6CNO8H7IWoS4=
|
||||
github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ=
|
||||
github.com/fsnotify/fsnotify v1.5.4 h1:jRbGcIw6P2Meqdwuo0H1p6JVLbL5DHKAKlYndzMwVZI=
|
||||
github.com/fsnotify/fsnotify v1.5.4/go.mod h1:OVB6XrOHzAwXMpEM7uPOzcehqUV2UqJxmVXmkdnm1bU=
|
||||
github.com/gernest/wow v0.1.0/go.mod h1:dEPabJRi5BneI1Nev1VWo0ZlcTWibHWp43qxKms4elY=
|
||||
github.com/ghodss/yaml v0.0.0-20150909031657-73d445a93680/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
|
||||
github.com/ghodss/yaml v1.0.0 h1:wQHKEahhL6wmXdzwWG11gIVCkOv05bNOh+Rxn0yngAk=
|
||||
@@ -378,10 +421,11 @@ github.com/gin-contrib/sse v0.1.0/go.mod h1:RHrZQHXnP2xjPF+u1gW/2HnVO7nvIa9PG3Gm
|
||||
github.com/gin-gonic/gin v1.7.7 h1:3DoBmSbJbZAWqXJC3SLjAPfutPJJRN1U5pALB7EeTTs=
|
||||
github.com/gin-gonic/gin v1.7.7/go.mod h1:axIBovoeJpVj8S3BwE0uPMTeReE4+AfFtqpqaZ1qq1U=
|
||||
github.com/glycerine/go-unsnap-stream v0.0.0-20180323001048-9f0cb55181dd/go.mod h1:/20jfyN9Y5QPEAprSgKAUr+glWDY39ZiUEAYOEv5dsE=
|
||||
github.com/glycerine/go-unsnap-stream v0.0.0-20181221182339-f9677308dec2 h1:Ujru1hufTHVb++eG6OuNDKMxZnGIvF6o/u8q/8h2+I4=
|
||||
github.com/glycerine/go-unsnap-stream v0.0.0-20181221182339-f9677308dec2/go.mod h1:/20jfyN9Y5QPEAprSgKAUr+glWDY39ZiUEAYOEv5dsE=
|
||||
github.com/glycerine/goconvey v0.0.0-20180728074245-46e3a41ad493 h1:OTanQnFt0bi5iLFSdbEVA/idR6Q2WhCm+deb7ir2CcM=
|
||||
github.com/glycerine/go-unsnap-stream v0.0.0-20190901134440-81cf024a9e0a/go.mod h1:/20jfyN9Y5QPEAprSgKAUr+glWDY39ZiUEAYOEv5dsE=
|
||||
github.com/glycerine/goconvey v0.0.0-20180728074245-46e3a41ad493/go.mod h1:Ogl1Tioa0aV7gstGFO7KhffUsb9M4ydbEbbxpcEDc24=
|
||||
github.com/glycerine/goconvey v0.0.0-20190315024820-982ee783a72e/go.mod h1:Ogl1Tioa0aV7gstGFO7KhffUsb9M4ydbEbbxpcEDc24=
|
||||
github.com/glycerine/goconvey v0.0.0-20190410193231-58a59202ab31/go.mod h1:Ogl1Tioa0aV7gstGFO7KhffUsb9M4ydbEbbxpcEDc24=
|
||||
github.com/go-asn1-ber/asn1-ber v1.3.1/go.mod h1:hEBeB/ic+5LoWskz+yKT7vGhhPYkProFKoKdwZRWMe0=
|
||||
github.com/go-asn1-ber/asn1-ber v1.5.8-0.20250403174932-29230038a667 h1:BP4M0CvQ4S3TGls2FvczZtj5Re/2ZzkV9VwqPHH/3Bo=
|
||||
github.com/go-asn1-ber/asn1-ber v1.5.8-0.20250403174932-29230038a667/go.mod h1:hEBeB/ic+5LoWskz+yKT7vGhhPYkProFKoKdwZRWMe0=
|
||||
@@ -391,12 +435,18 @@ github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2
|
||||
github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=
|
||||
github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=
|
||||
github.com/go-kit/log v0.1.0/go.mod h1:zbhenjAZHb184qTLMA9ZjW7ThYL0H2mk7Q6pNt4vbaY=
|
||||
github.com/go-kit/log v0.2.0/go.mod h1:NwTd00d/i8cPZ3xOwwiv2PO5MOcx78fFErGNcVmBjv0=
|
||||
github.com/go-ldap/ldap/v3 v3.1.5 h1:5o1ik2It7MJoXwoS7JXWUebf18L7E1VWBBgYV/iVsN0=
|
||||
github.com/go-ldap/ldap/v3 v3.1.5/go.mod h1:5Zun81jBTabRaI8lzN7E1JjyEl1g6zI6u9pd8luAK4Q=
|
||||
github.com/go-llsqlite/adapter v0.0.0-20230927005056-7f5ce7f0c916 h1:OyQmpAN302wAopDgwVjgs2HkFawP9ahIEqkUYz7V7CA=
|
||||
github.com/go-llsqlite/adapter v0.0.0-20230927005056-7f5ce7f0c916/go.mod h1:DADrR88ONKPPeSGjFp5iEN55Arx3fi2qXZeKCYDpbmU=
|
||||
github.com/go-llsqlite/crawshaw v0.5.2-0.20240425034140-f30eb7704568 h1:3EpZo8LxIzF4q3BT+vttQQlRfA6uTtTb/cxVisWa5HM=
|
||||
github.com/go-llsqlite/crawshaw v0.5.2-0.20240425034140-f30eb7704568/go.mod h1:/YJdV7uBQaYDE0fwe4z3wwJIZBJxdYzd38ICggWqtaE=
|
||||
github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE=
|
||||
github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk=
|
||||
github.com/go-logfmt/logfmt v0.5.0 h1:TrB8swr/68K7m9CcGut2g3UOihhbcbiMAYiuTXdEih4=
|
||||
github.com/go-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG1KdI/P7A=
|
||||
github.com/go-logfmt/logfmt v0.5.1 h1:otpy5pqBCBZ1ng9RQ0dPu4PN7ba75Y/aA+UpowDyNVA=
|
||||
github.com/go-logfmt/logfmt v0.5.1/go.mod h1:WYhtIu8zTZfxdn5+rREduYbwxfcBr/Vr6KEVveWlfTs=
|
||||
github.com/go-logr/logr v0.1.0/go.mod h1:ixOQHD9gLJUVQQ2ZOR7zLEifBX6tGkNJF4QyIY7sIas=
|
||||
github.com/go-logr/logr v0.2.0/go.mod h1:z6/tIYblkpsD+a4lm/fGIIU9mZ+XfAiaFtq7xTgseGU=
|
||||
github.com/go-logr/logr v1.0.0/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
|
||||
@@ -424,6 +474,7 @@ github.com/go-sql-driver/mysql v1.4.0/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG
|
||||
github.com/go-sql-driver/mysql v1.6.0 h1:BCTh4TKNUYmOmMUcQ3IipzF5prigylS7XXjEkfCHuOE=
|
||||
github.com/go-sql-driver/mysql v1.6.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg=
|
||||
github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
|
||||
github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0/go.mod h1:fyg7847qk6SyHyPtNmDHnmrv/HOrqktSC+C9fM+CJOE=
|
||||
github.com/go-yaml/yaml v2.1.0+incompatible h1:RYi2hDdss1u4YE7GwixGzWwVo47T8UQwnTLB6vQiq+o=
|
||||
github.com/go-yaml/yaml v2.1.0+incompatible/go.mod h1:w2MrLa16VYP0jy6N7M5kHaCkaLENm+P+Tv+MfurjSw0=
|
||||
github.com/godbus/dbus/v5 v5.0.3/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
|
||||
@@ -432,6 +483,7 @@ github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5x
|
||||
github.com/gofrs/uuid v4.1.0+incompatible h1:sIa2eCvUTwgjbqXrPLfNwUf9S3i3mpH1O1atV+iL/Wk=
|
||||
github.com/gofrs/uuid v4.1.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM=
|
||||
github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
|
||||
github.com/gogo/protobuf v1.2.0/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
|
||||
github.com/gogo/protobuf v1.3.1/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o=
|
||||
github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q=
|
||||
github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q=
|
||||
@@ -481,8 +533,8 @@ github.com/golang/snappy v0.0.4/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEW
|
||||
github.com/google/btree v0.0.0-20180124185431-e89373fe6b4a/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
|
||||
github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
|
||||
github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
|
||||
github.com/google/btree v1.0.1 h1:gK4Kx5IaGY9CD5sPJ36FHiBJ6ZXl0kilRiiCj+jdYp4=
|
||||
github.com/google/btree v1.0.1/go.mod h1:xXMiIv4Fb/0kKde4SpL7qlzvu5cMJDRkFDxJfI9uaxA=
|
||||
github.com/google/btree v1.1.2 h1:xf4v41cLI2Z6FxbKm+8Bu+m8ifhj15JuZ9sa0jZCMUU=
|
||||
github.com/google/btree v1.1.2/go.mod h1:qOPhT0dTNdNzV6Z/lhRX0YXUafgPLFUh+gZMl761Gm4=
|
||||
github.com/google/cadvisor v0.38.5 h1:XOvqjL2+xMEuDORcLMv77NystZvQB7YgGxcKpRul/vE=
|
||||
github.com/google/cadvisor v0.38.5/go.mod h1:1OFB9sOOMkBdUBGCO/1SArawTnDscgMzTodacVDe8mA=
|
||||
github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
|
||||
@@ -539,15 +591,17 @@ github.com/googollee/go-engine.io v0.0.0-20180829091931-e2f255711dcb h1:n22Aukg/
|
||||
github.com/googollee/go-engine.io v0.0.0-20180829091931-e2f255711dcb/go.mod h1:MBpz1MS3P4HtRcBpQU4HcjvWXZ9q+JWacMEh2/BFYbg=
|
||||
github.com/googollee/go-socket.io v0.0.0-20181214084611-0ad7206c347a h1:NMY2a78Z98wdhMHJTJxTc9BFfnGGc5ZWfgY9a23zeck=
|
||||
github.com/googollee/go-socket.io v0.0.0-20181214084611-0ad7206c347a/go.mod h1:ftBGBMhSYToR5oV4ImIPKvAIsNaTkLC+tTvoNafqxlQ=
|
||||
github.com/gopherjs/gopherjs v0.0.0-20180628210949-0892b62f0d9f/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY=
|
||||
github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1 h1:EGx4pi6eqNxGaHF6qqu48+N2wcFQ5qg5FXgOdqsJ5d8=
|
||||
github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY=
|
||||
github.com/gopherjs/gopherjs v0.0.0-20181103185306-d547d1d9531e/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY=
|
||||
github.com/gopherjs/gopherjs v0.0.0-20190309154008-847fc94819f9/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY=
|
||||
github.com/gopherjs/gopherjs v0.0.0-20190910122728-9d188e94fb99 h1:twflg0XRTjwKpxb/jFExr4HGq6on2dEOmnL6FV+fgPw=
|
||||
github.com/gopherjs/gopherjs v0.0.0-20190910122728-9d188e94fb99/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY=
|
||||
github.com/gorilla/context v1.1.1/go.mod h1:kBGZzfjB9CEq2AlWe17Uuf7NDRt0dE0s8S51q0aT7Yg=
|
||||
github.com/gorilla/mux v1.6.2/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs=
|
||||
github.com/gorilla/mux v1.8.0 h1:i40aqfkR1h2SlN9hojwV5ZA91wcXFOvkdNIeFDP5koI=
|
||||
github.com/gorilla/mux v1.8.0/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So=
|
||||
github.com/gorilla/websocket v1.4.1 h1:q7AeDBpnBk8AogcD4DSag/Ukw/KV+YhzLj2bP5HvKCM=
|
||||
github.com/gorilla/websocket v1.4.1/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
|
||||
github.com/gosuri/uilive v0.0.0-20170323041506-ac356e6e42cd/go.mod h1:qkLSc0A5EXSP6B04TrN4oQoxqFI7A8XvoXSlJi8cwk8=
|
||||
github.com/gosuri/uiprogress v0.0.0-20170224063937-d0567a9d84a1/go.mod h1:C1RTYn4Sc7iEyf6j8ft5dyoZ4212h8G1ol9QQluh5+0=
|
||||
github.com/gorilla/websocket v1.5.0 h1:PPwGk2jz7EePpoHN/+ClbZu8SPxiqlu12wZP/3sWmnc=
|
||||
github.com/gorilla/websocket v1.5.0/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
|
||||
github.com/gosuri/uitable v0.0.0-20160404203958-36ee7e946282 h1:KFqmdzEPbU7Uck2tn50t+HQXZNVkxe8M9qRb/ZoSHaE=
|
||||
github.com/gosuri/uitable v0.0.0-20160404203958-36ee7e946282/go.mod h1:tKR86bXuXPZazfOTG1FIzvjIdXzd0mo4Vtn16vt0PJo=
|
||||
github.com/gregjones/httpcache v0.0.0-20180305231024-9cad4c3443a7/go.mod h1:FecbI9+v66THATjSRHfNgh1IVFe/9kFxbXtjV0ctIMA=
|
||||
@@ -559,10 +613,15 @@ github.com/hako/durafmt v0.0.0-20180520121703-7b7ae1e72ead h1:Y9WOGZY2nw5ksbEf5A
|
||||
github.com/hako/durafmt v0.0.0-20180520121703-7b7ae1e72ead/go.mod h1:5Scbynm8dF1XAPwIwkGPqzkM/shndPm79Jd1003hTjE=
|
||||
github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
|
||||
github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
|
||||
github.com/hexops/gotextdiff v1.0.3 h1:gitA9+qJrrTCsiCl7+kh75nPqQt1cx4ZkudSTLoUqJM=
|
||||
github.com/hexops/gotextdiff v1.0.3/go.mod h1:pSWU5MAI3yDq+fZBTazCSJysOMbxWL1BSow5/V2vxeg=
|
||||
github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
|
||||
github.com/huandu/xstrings v1.0.0/go.mod h1:4qWG/gcEcfX4z/mBDHJ++3ReCw9ibxbsNJbcucJdbSo=
|
||||
github.com/huandu/xstrings v1.2.0 h1:yPeWdRnmynF7p+lLYz0H2tthW9lqhMJrQV/U7yy4wX0=
|
||||
github.com/huandu/xstrings v1.2.0/go.mod h1:DvyZB1rfVYsBIigL8HwpZgxHwXozlTgGqn63UyNX5k4=
|
||||
github.com/huandu/xstrings v1.3.0/go.mod h1:y5/lhBue+AyNmUVz9RLU9xbLR0o4KIIExikq4ovT0aE=
|
||||
github.com/huandu/xstrings v1.3.1/go.mod h1:y5/lhBue+AyNmUVz9RLU9xbLR0o4KIIExikq4ovT0aE=
|
||||
github.com/huandu/xstrings v1.3.2 h1:L18LIDzqlW6xN2rEkpdV8+oL/IXWJ1APd+vsdYy4Wdw=
|
||||
github.com/huandu/xstrings v1.3.2/go.mod h1:y5/lhBue+AyNmUVz9RLU9xbLR0o4KIIExikq4ovT0aE=
|
||||
github.com/huaweicloud/huaweicloud-sdk-go v1.0.26 h1:aWTl4Ng9lZUW1DupYyqYiqkTwuTKMmqUZBKLmX0iWxo=
|
||||
github.com/huaweicloud/huaweicloud-sdk-go v1.0.26/go.mod h1:YHXxw/bm7AohI4jTY8Z43JYw+DPCDLqjxoLTqmcyja4=
|
||||
github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
|
||||
@@ -579,7 +638,6 @@ github.com/jaypipes/ghw v0.11.0 h1:i0pKvAM7eZk0KvLm9vzpcpDKTRnfR6AQ5pFkPVnYJXU=
|
||||
github.com/jaypipes/ghw v0.11.0/go.mod h1:jeJGbkRB2lL3/gxYzNYzEDETV1ZJ56OKr+CSeSEym+g=
|
||||
github.com/jdcloud-api/jdcloud-sdk-go v1.55.0 h1:mzVj8r6fluEwjn8ogqtGfYW2qSIVUaEq0JAsvjCav3A=
|
||||
github.com/jdcloud-api/jdcloud-sdk-go v1.55.0/go.mod h1:UrKjuULIWLjHFlG6aSPunArE5QX57LftMmStAZJBEX8=
|
||||
github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI=
|
||||
github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k=
|
||||
github.com/jmespath/go-jmespath v0.4.0 h1:BEgLn5cpjn8UN1mAw4NjwDrS35OdebyEtFe+9YPoQUg=
|
||||
github.com/jmespath/go-jmespath v0.4.0/go.mod h1:T8mJZnbsbmF+m6zOOFylbeCJqk5+pHWvzYPziyZiYoo=
|
||||
@@ -611,8 +669,10 @@ github.com/karrick/godirwalk v1.16.1/go.mod h1:j4mkqPuvaLI8mp1DroR3P6ad7cyYd4c1q
|
||||
github.com/kisielk/errcheck v1.2.0/go.mod h1:/BMXB+zMLi60iA8Vv6Ksmxu/1UDYcXs4uQLJ+jE2L00=
|
||||
github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8=
|
||||
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
|
||||
github.com/klauspost/cpuid/v2 v2.0.9 h1:lgaqFMSdTdQYdZ04uHyN2d/eKdOMyi2YLSvlQIBFYa4=
|
||||
github.com/klauspost/cpuid/v2 v2.0.4/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg=
|
||||
github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg=
|
||||
github.com/klauspost/cpuid/v2 v2.2.3 h1:sxCkb+qR91z4vsqw4vGGZlDgPz3G7gjaLyK3V8y70BU=
|
||||
github.com/klauspost/cpuid/v2 v2.2.3/go.mod h1:RVVoqg1df56z8g3pUjL/3lE5UfnlrJX8tyFgg4nqhuY=
|
||||
github.com/koding/websocketproxy v0.0.0-20181220232114-7ed82d81a28c h1:N7A4JCA2G+j5fuFxCsJqjFU/sZe0mj8H0sSoSwbaikw=
|
||||
github.com/koding/websocketproxy v0.0.0-20181220232114-7ed82d81a28c/go.mod h1:Nn5wlyECw3iJrzi0AhIWg+AJUb4PlRQVW4/3XHH1LZA=
|
||||
github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
|
||||
@@ -624,6 +684,7 @@ github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFB
|
||||
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
|
||||
github.com/kr/pretty v0.2.0/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
|
||||
github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
|
||||
github.com/kr/pretty v0.3.0/go.mod h1:640gp4NfQd8pI5XOwp5fnNeVWj67G7CFk/SaSQn7NBk=
|
||||
github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
|
||||
github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk=
|
||||
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
|
||||
@@ -647,8 +708,9 @@ github.com/lestrrat/go-pdebug v0.0.0-20180220043741-569c97477ae8/go.mod h1:VXFH1
|
||||
github.com/lib/pq v1.0.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo=
|
||||
github.com/libvirt/libvirt-go-xml v5.2.0+incompatible h1:ALyVpa0/lFfFaUpb5l0fNBohufmQG6jsOGRCl/nKEi8=
|
||||
github.com/libvirt/libvirt-go-xml v5.2.0+incompatible/go.mod h1:oBlgD3xOA01ihiK5stbhFzvieyW+jVS6kbbsMVF623A=
|
||||
github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0 h1:6E+4a0GO5zZEnZ81pIr0yLvtUWk2if982qA3F3QD6H4=
|
||||
github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0/go.mod h1:zJYVVT2jmtg6P3p1VtQj7WsuWi/y4VnjVBn7F8KPB3I=
|
||||
github.com/lufia/plan9stats v0.0.0-20220913051719-115f729f3c8c h1:VtwQ41oftZwlMnOEbMWQtSEUgU64U4s+GHk7hZK+jtY=
|
||||
github.com/lufia/plan9stats v0.0.0-20220913051719-115f729f3c8c/go.mod h1:JKx41uQRwqlTZabZc+kILPrO/3jlKnQ2Z8b7YiVw5cE=
|
||||
github.com/ma314smith/signedxml v0.0.0-20210628192057-abc5b481ae1c h1:UPJygtyk491bJJ/DnRJFuzcq9Dl9NSeFrJ7VdiRzMxc=
|
||||
github.com/ma314smith/signedxml v0.0.0-20210628192057-abc5b481ae1c/go.mod h1:KEgVcb43+f5KFUH/x6Vd3NROG0AIL2CuKMrIqYsmx6E=
|
||||
github.com/mailru/easyjson v0.0.0-20160728113105-d5b7844b561a/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
|
||||
@@ -664,14 +726,14 @@ github.com/mattn/go-colorable v0.1.9/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope
|
||||
github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4=
|
||||
github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s=
|
||||
github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU=
|
||||
github.com/mattn/go-isatty v0.0.14 h1:yVuAays6BHfxijgZPzw+3Zlu5yQgKGP2/hcQbHb7S9Y=
|
||||
github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94=
|
||||
github.com/mattn/go-isatty v0.0.16 h1:bq3VjFmv/sOjHtdEhmkEV4x1AJtvUvOJ2PFAZ5+peKQ=
|
||||
github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM=
|
||||
github.com/mattn/go-runewidth v0.0.3/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU=
|
||||
github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI=
|
||||
github.com/mattn/go-runewidth v0.0.12/go.mod h1:RAqKPSqVFrSLVXbA8x7dzmKdmGzieGRCM46jaSJTDAk=
|
||||
github.com/mattn/go-runewidth v0.0.13 h1:lTGmDsbAYt5DmK6OnoV7EuIF1wEIFAcxld6ypU4OSgU=
|
||||
github.com/mattn/go-runewidth v0.0.13/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w=
|
||||
github.com/mattn/go-sqlite3 v1.7.0/go.mod h1:FPy6KqzDD04eiIsT53CuJW3U88zkxoIYsOqkbpncsNc=
|
||||
github.com/mattn/go-sqlite3 v1.9.0/go.mod h1:FPy6KqzDD04eiIsT53CuJW3U88zkxoIYsOqkbpncsNc=
|
||||
github.com/mattn/go-sqlite3 v1.14.19 h1:fhGleo2h1p8tVChob4I9HpmVFIAkKGpiukdrgQbWfGI=
|
||||
github.com/mattn/go-sqlite3 v1.14.19/go.mod h1:2eHXhiwb8IkHr+BDWZGa96P6+rkvnG63S2DGjv9HUNg=
|
||||
@@ -706,6 +768,8 @@ github.com/minio/minio-go v6.0.14+incompatible h1:fnV+GD28LeqdN6vT2XdGKW8Qe/IfjJ
|
||||
github.com/minio/minio-go v6.0.14+incompatible/go.mod h1:7guKYtitv8dktvNUGrhzmNlA5wrAABTQXCoesZdFQO8=
|
||||
github.com/minio/minio-go/v6 v6.0.33 h1:CNThMAZ9bN6OEIP8DulqlYpaXKJ18rgG/Cqm14Q40xg=
|
||||
github.com/minio/minio-go/v6 v6.0.33/go.mod h1:vaNT59cWULS37E+E9zkuN/BVnKHyXtVGS+b04Boc66Y=
|
||||
github.com/minio/sha256-simd v1.0.0 h1:v1ta+49hkWZyvaKwrQB8elexRqm6Y0aMLjCNsrYxo6g=
|
||||
github.com/minio/sha256-simd v1.0.0/go.mod h1:OuYzVNI5vcoYIAmbIvHPl3N3jUzVedXbKy5RFepssQM=
|
||||
github.com/mistifyio/go-zfs v2.1.2-0.20190413222219-f784269be439+incompatible h1:aKW/4cBs+yK6gpqU3K/oIwk9Q/XICqd3zOX/UFuvqmk=
|
||||
github.com/mistifyio/go-zfs v2.1.2-0.20190413222219-f784269be439+incompatible/go.mod h1:8AuVvqP/mXw1px98n46wfvcGfQ4ci2FwoAjKYxuo3Z4=
|
||||
github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y=
|
||||
@@ -731,22 +795,37 @@ github.com/mozillazg/go-httpheader v0.2.1 h1:geV7TrjbL8KXSyvghnFm+NyTux/hxwueTSr
|
||||
github.com/mozillazg/go-httpheader v0.2.1/go.mod h1:jJ8xECTlalr6ValeXYdOF8fFUISeBAdw6E61aqQma60=
|
||||
github.com/mozillazg/go-pinyin v0.19.0 h1:p+J8/kjJ558KPvVGYLvqBhxf8jbZA2exSLCs2uUVN8c=
|
||||
github.com/mozillazg/go-pinyin v0.19.0/go.mod h1:iR4EnMMRXkfpFVV5FMi4FNB6wGq9NV6uDWbUuPhP4Yc=
|
||||
github.com/mr-tron/base58 v1.2.0 h1:T/HDJBh4ZCPbU39/+c3rRvE0uKBQlU27+QI8LJ4t64o=
|
||||
github.com/mr-tron/base58 v1.2.0/go.mod h1:BinMc/sQntlIE1frQmRFPUoPA1Zkr8VRgBdjWI2mNwc=
|
||||
github.com/mrunalp/fileutils v0.0.0-20200520151820-abd8a0e76976 h1:aZQToFSLH8ejFeSkTc3r3L4dPImcj7Ib/KgmkQqbGGg=
|
||||
github.com/mrunalp/fileutils v0.0.0-20200520151820-abd8a0e76976/go.mod h1:x8F1gnqOkIEiO4rqoeEEEqQbo7HjGMTvyoq3gej4iT0=
|
||||
github.com/mschoch/smat v0.0.0-20160514031455-90eadee771ae h1:VeRdUYdCw49yizlSbMEn2SZ+gT+3IUKx8BqxyQdz+BY=
|
||||
github.com/mschoch/smat v0.0.0-20160514031455-90eadee771ae/go.mod h1:qAyveg+e4CE+eKJXWVjKXM4ck2QobLqTDytGJbLLhJg=
|
||||
github.com/mschoch/smat v0.2.0 h1:8imxQsjDm8yFEAVBe7azKmKSgzSkZXDuKkSq9374khM=
|
||||
github.com/mschoch/smat v0.2.0/go.mod h1:kc9mz7DoBKqDyiRL7VZN8KvXQMWeTaVnttLRXOlotKw=
|
||||
github.com/multiformats/go-multihash v0.2.3 h1:7Lyc8XfX/IY2jWb/gI7JP+o7JEq9hOa7BFvVU9RSh+U=
|
||||
github.com/multiformats/go-multihash v0.2.3/go.mod h1:dXgKXCXjBzdscBLk9JkjINiEsCKRVch90MdaGiKsvSM=
|
||||
github.com/multiformats/go-varint v0.0.6 h1:gk85QWKxh3TazbLxED/NlDVv8+q+ReFJk7Y2W/KhfNY=
|
||||
github.com/multiformats/go-varint v0.0.6/go.mod h1:3Ls8CIEsrijN6+B7PbrXRPxHRPuXSrVKRY101jdMZYE=
|
||||
github.com/munnerz/goautoneg v0.0.0-20120707110453-a547fc61f48d/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ=
|
||||
github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
|
||||
github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
|
||||
github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f h1:y5//uYreIhSUg3J1GEMiLbxo1LJaP8RfCpH6pymGZus=
|
||||
github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f/go.mod h1:ZdcZmHo+o7JKHSa8/e818NopupXU1YMK5fe1lsApnBw=
|
||||
github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A=
|
||||
github.com/nxadm/tail v1.4.8/go.mod h1:+ncqLTQzXmGhMZNUePPaPqPvBxHAIsmXswZKocGu+AU=
|
||||
github.com/onsi/ginkgo v0.0.0-20170829012221-11459a886d9c/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
|
||||
github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
|
||||
github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
|
||||
github.com/onsi/ginkgo v1.11.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
|
||||
github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk=
|
||||
github.com/onsi/ginkgo v1.16.4/go.mod h1:dX+/inL/fNMqNlz0e9LfyB9TswhZpCVdJM/Z6Vvnwo0=
|
||||
github.com/onsi/ginkgo v1.16.5/go.mod h1:+E8gABHa3K6zRBolWtd+ROzc/U5bkGt0FwiG042wbpU=
|
||||
github.com/onsi/gomega v0.0.0-20170829124025-dcabb60a477c/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA=
|
||||
github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY=
|
||||
github.com/onsi/gomega v1.7.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY=
|
||||
github.com/op/go-logging v0.0.0-20160315200505-970db520ece7 h1:lDH9UUVJtmYCjyT0CI4q8xvlXPxeZ0gYCVvWbmPlp88=
|
||||
github.com/op/go-logging v0.0.0-20160315200505-970db520ece7/go.mod h1:HzydrMdWErDVzsI23lYNej1Htcns9BCg93Dk0bBINWk=
|
||||
github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY=
|
||||
github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo=
|
||||
github.com/onsi/gomega v1.17.0/go.mod h1:HnhC7FXeEQY45zxNK3PPoIUhzk/80Xly9PcubAlGdZY=
|
||||
github.com/opencontainers/go-digest v0.0.0-20180430190053-c9281466c8b2/go.mod h1:cMLVZDEM3+U2I4VmLI6N8jQYUd2OVphdqWwCJHrFt2s=
|
||||
github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U=
|
||||
github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM=
|
||||
@@ -764,6 +843,7 @@ github.com/opentracing-contrib/go-observer v0.0.0-20170622124052-a52f23424492 h1
|
||||
github.com/opentracing-contrib/go-observer v0.0.0-20170622124052-a52f23424492/go.mod h1:Ngi6UdF0k5OKD5t5wlmGhe/EDKPoUM3BXZSSfIuJbis=
|
||||
github.com/opentracing/opentracing-go v1.0.2 h1:3jA2P6O1F9UOrWVpwrIo17pu01KWvNWg4X946/Y5Zwg=
|
||||
github.com/opentracing/opentracing-go v1.0.2/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o=
|
||||
github.com/openzipkin/zipkin-go v0.1.6/go.mod h1:QgAqvLzwWbR/WpD4A3cGpPtJrZXNIiJc5AZX7/PBEpw=
|
||||
github.com/openzipkin/zipkin-go-opentracing v0.3.4 h1:x/pBv/5VJNWkcHF1G9xqhug8Iw7X1y1zOMzDmyuvP2g=
|
||||
github.com/openzipkin/zipkin-go-opentracing v0.3.4/go.mod h1:js2AbwmHW0YD9DwIw2JhQWmbfFi/UnWyYwdVhqbCDOE=
|
||||
github.com/oracle/oci-go-sdk v24.3.0+incompatible h1:x4mcfb4agelf1O4/1/auGlZ1lr97jXRSSN5MxTgG/zU=
|
||||
@@ -771,14 +851,57 @@ github.com/oracle/oci-go-sdk v24.3.0+incompatible/go.mod h1:VQb79nF8Z2cwLkLS35uk
|
||||
github.com/peterbourgon/diskv v2.0.1+incompatible/go.mod h1:uqqh8zWWbv1HBMNONnaR/tNboyR3/BZd58JJSHlUSCU=
|
||||
github.com/petermattis/goid v0.0.0-20250904145737-900bdf8bb490 h1:QTvNkZ5ylY0PGgA+Lih+GdboMLY/G9SEGLMEGVjTVA4=
|
||||
github.com/petermattis/goid v0.0.0-20250904145737-900bdf8bb490/go.mod h1:pxMtw7cyUw6B2bRH0ZBANSPg+AoSud1I1iyJHI69jH4=
|
||||
github.com/philhofer/fwd v1.0.0 h1:UbZqGr5Y38ApvM/V/jEljVxwocdweyH+vmYvRPBnbqQ=
|
||||
github.com/philhofer/fwd v1.0.0/go.mod h1:gk3iGcWd9+svBvR0sR+KPcfE+RNWozjowpeBVG3ZVNU=
|
||||
github.com/pierrec/lz4 v2.0.5+incompatible/go.mod h1:pdkljMzZIN41W+lC3N2tnIh5sFi+IEE17M5jbnwPHcY=
|
||||
github.com/pierrec/lz4 v2.6.1+incompatible h1:9UY3+iC23yxF0UfGaYrGplQ+79Rg+h/q9FV9ix19jjM=
|
||||
github.com/pierrec/lz4 v2.6.1+incompatible/go.mod h1:pdkljMzZIN41W+lC3N2tnIh5sFi+IEE17M5jbnwPHcY=
|
||||
github.com/pierrec/lz4/v4 v4.1.15 h1:MO0/ucJhngq7299dKLwIMtgTfbkoSPF6AoMYDd8Q4q0=
|
||||
github.com/pierrec/lz4/v4 v4.1.15/go.mod h1:gZWDp/Ze/IJXGXf23ltt2EXimqmTUXEy0GFuRQyBid4=
|
||||
github.com/pion/datachannel v1.5.2 h1:piB93s8LGmbECrpO84DnkIVWasRMk3IimbcXkTQLE6E=
|
||||
github.com/pion/datachannel v1.5.2/go.mod h1:FTGQWaHrdCwIJ1rw6xBIfZVkslikjShim5yr05XFuCQ=
|
||||
github.com/pion/dtls/v2 v2.1.3/go.mod h1:o6+WvyLDAlXF7YiPB/RlskRoeK+/JtuaZa5emwQcWus=
|
||||
github.com/pion/dtls/v2 v2.1.5/go.mod h1:BqCE7xPZbPSubGasRoDFJeTsyJtdD1FanJYL0JGheqY=
|
||||
github.com/pion/dtls/v2 v2.2.4 h1:YSfYwDQgrxMYXLBc/m7PFY5BVtWlNm/DN4qoU2CbcWg=
|
||||
github.com/pion/dtls/v2 v2.2.4/go.mod h1:WGKfxqhrddne4Kg3p11FUMJrynkOY4lb25zHNO49wuw=
|
||||
github.com/pion/ice/v2 v2.2.6 h1:R/vaLlI1J2gCx141L5PEwtuGAGcyS6e7E0hDeJFq5Ig=
|
||||
github.com/pion/ice/v2 v2.2.6/go.mod h1:SWuHiOGP17lGromHTFadUe1EuPgFh/oCU6FCMZHooVE=
|
||||
github.com/pion/interceptor v0.1.11 h1:00U6OlqxA3FFB50HSg25J/8cWi7P6FbSzw4eFn24Bvs=
|
||||
github.com/pion/interceptor v0.1.11/go.mod h1:tbtKjZY14awXd7Bq0mmWvgtHB5MDaRN7HV3OZ/uy7s8=
|
||||
github.com/pion/logging v0.2.2 h1:M9+AIj/+pxNsDfAT64+MAVgJO0rsyLnoJKCqf//DoeY=
|
||||
github.com/pion/logging v0.2.2/go.mod h1:k0/tDVsRCX2Mb2ZEmTqNa7CWsQPc+YYCB7Q+5pahoms=
|
||||
github.com/pion/mdns v0.0.5 h1:Q2oj/JB3NqfzY9xGZ1fPzZzK7sDSD8rZPOvcIQ10BCw=
|
||||
github.com/pion/mdns v0.0.5/go.mod h1:UgssrvdD3mxpi8tMxAXbsppL3vJ4Jipw1mTCW+al01g=
|
||||
github.com/pion/randutil v0.1.0 h1:CFG1UdESneORglEsnimhUjf33Rwjubwj6xfiOXBa3mA=
|
||||
github.com/pion/randutil v0.1.0/go.mod h1:XcJrSMMbbMRhASFVOlj/5hQial/Y8oH/HVo7TBZq+j8=
|
||||
github.com/pion/rtcp v1.2.9 h1:1ujStwg++IOLIEoOiIQ2s+qBuJ1VN81KW+9pMPsif+U=
|
||||
github.com/pion/rtcp v1.2.9/go.mod h1:qVPhiCzAm4D/rxb6XzKeyZiQK69yJpbUDJSF7TgrqNo=
|
||||
github.com/pion/rtp v1.7.13 h1:qcHwlmtiI50t1XivvoawdCGTP4Uiypzfrsap+bijcoA=
|
||||
github.com/pion/rtp v1.7.13/go.mod h1:bDb5n+BFZxXx0Ea7E5qe+klMuqiBrP+w8XSjiWtCUko=
|
||||
github.com/pion/sctp v1.8.0/go.mod h1:xFe9cLMZ5Vj6eOzpyiKjT9SwGM4KpK/8Jbw5//jc+0s=
|
||||
github.com/pion/sctp v1.8.2 h1:yBBCIrUMJ4yFICL3RIvR4eh/H2BTTvlligmSTy+3kiA=
|
||||
github.com/pion/sctp v1.8.2/go.mod h1:xFe9cLMZ5Vj6eOzpyiKjT9SwGM4KpK/8Jbw5//jc+0s=
|
||||
github.com/pion/sdp/v3 v3.0.5 h1:ouvI7IgGl+V4CrqskVtr3AaTrPvPisEOxwgpdktctkU=
|
||||
github.com/pion/sdp/v3 v3.0.5/go.mod h1:iiFWFpQO8Fy3S5ldclBkpXqmWy02ns78NOKoLLL0YQw=
|
||||
github.com/pion/srtp/v2 v2.0.9 h1:JJq3jClmDFBPX/F5roEb0U19jSU7eUhyDqR/NZ34EKQ=
|
||||
github.com/pion/srtp/v2 v2.0.9/go.mod h1:5TtM9yw6lsH0ppNCehB/EjEUli7VkUgKSPJqWVqbhQ4=
|
||||
github.com/pion/stun v0.3.5 h1:uLUCBCkQby4S1cf6CGuR9QrVOKcvUwFeemaC865QHDg=
|
||||
github.com/pion/stun v0.3.5/go.mod h1:gDMim+47EeEtfWogA37n6qXZS88L5V6LqFcf+DZA2UA=
|
||||
github.com/pion/transport v0.12.2/go.mod h1:N3+vZQD9HlDP5GWkZ85LohxNsDcNgofQmyL6ojX5d8Q=
|
||||
github.com/pion/transport v0.12.3/go.mod h1:OViWW9SP2peE/HbwBvARicmAVnesphkNkCVZIWJ6q9A=
|
||||
github.com/pion/transport v0.13.0/go.mod h1:yxm9uXpK9bpBBWkITk13cLo1y5/ur5VQpG22ny6EP7g=
|
||||
github.com/pion/transport v0.13.1 h1:/UH5yLeQtwm2VZIPjxwnNFxjS4DFhyLfS4GlfuKUzfA=
|
||||
github.com/pion/transport v0.13.1/go.mod h1:EBxbqzyv+ZrmDb82XswEE0BjfQFtuw1Nu6sjnjWCsGg=
|
||||
github.com/pion/transport/v2 v2.0.0 h1:bsMYyqHCbkvHwj+eNCFBuxtlKndKfyGI2vaQmM3fIE4=
|
||||
github.com/pion/transport/v2 v2.0.0/go.mod h1:HS2MEBJTwD+1ZI2eSXSvHJx/HnzQqRy2/LXxt6eVMHc=
|
||||
github.com/pion/turn/v2 v2.0.8 h1:KEstL92OUN3k5k8qxsXHpr7WWfrdp7iJZHx99ud8muw=
|
||||
github.com/pion/turn/v2 v2.0.8/go.mod h1:+y7xl719J8bAEVpSXBXvTxStjJv3hbz9YFflvkpcGPw=
|
||||
github.com/pion/udp v0.1.1/go.mod h1:6AFo+CMdKQm7UiA0eUPA8/eVCTx8jBIITLZHc9DWX5M=
|
||||
github.com/pion/udp v0.1.4 h1:OowsTmu1Od3sD6i3fQUJxJn2fEvJO6L1TidgadtbTI8=
|
||||
github.com/pion/udp v0.1.4/go.mod h1:G8LDo56HsFwC24LIcnT4YIDU5qcB6NepqqjP0keL2us=
|
||||
github.com/pion/webrtc/v3 v3.1.42 h1:wJEQFIXVanptnQcHOLTuIo4AtGB2+mG2x4OhIhnITOA=
|
||||
github.com/pion/webrtc/v3 v3.1.42/go.mod h1:ffD9DulDrPxyWvDPUIPAOSAWx9GUlOExiJPf7cCcMLA=
|
||||
github.com/pkg/diff v0.0.0-20200914180035-5b29258ca4f7/go.mod h1:zO8QMzTeZd5cpnIkz/Gn6iK0jDfGicM1nynOkkPIl28=
|
||||
github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA=
|
||||
github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
|
||||
@@ -789,38 +912,54 @@ github.com/pkg/term v1.0.0 h1:raTSNJjic7X4n89hhPyLOsgRYczmr3MyezRierWCTa8=
|
||||
github.com/pkg/term v1.0.0/go.mod h1:6rk0zrj6TXf8MR5fdVFsZMeGM2lxe3tUFLNBRlwX+dk=
|
||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c h1:ncq/mPwQF4JjgDlrVEn3C11VoGHZN7m8qihwgMEtzYw=
|
||||
github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c/go.mod h1:OmDBASR4679mdNQnz2pUhc2G8CO2JrUAVFDRBDP/hJE=
|
||||
github.com/power-devops/perfstat v0.0.0-20220216144756-c35f1ee13d7c h1:NRoLoZvkBTKvR5gQLgA3e0hqjkY9u1wm+iOL45VN/qI=
|
||||
github.com/power-devops/perfstat v0.0.0-20220216144756-c35f1ee13d7c/go.mod h1:OmDBASR4679mdNQnz2pUhc2G8CO2JrUAVFDRBDP/hJE=
|
||||
github.com/pquerna/otp v1.2.0 h1:/A3+Jn+cagqayeR3iHs/L62m5ue7710D35zl1zJ1kok=
|
||||
github.com/pquerna/otp v1.2.0/go.mod h1:dkJfzwRKNiegxyNb54X/3fLwhCynbMspSyWKnvi1AEg=
|
||||
github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw=
|
||||
github.com/prometheus/client_golang v0.9.3-0.20190127221311-3c4408c8b829/go.mod h1:p2iRAGwDERtqlqzRXnrOVns+ignqQo//hLXqYxZYVNs=
|
||||
github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo=
|
||||
github.com/prometheus/client_golang v1.5.1/go.mod h1:e9GMxYsXl05ICDXkRhurwBS4Q3OK1iX/F2sw+iXX5zU=
|
||||
github.com/prometheus/client_golang v1.7.1/go.mod h1:PY5Wy2awLA44sXw4AOSfFBetzPP4j5+D6mVACh+pe2M=
|
||||
github.com/prometheus/client_golang v1.11.0/go.mod h1:Z6t4BnS23TR94PD6BsDNk8yVqroYurpAkEiz0P2BEV0=
|
||||
github.com/prometheus/client_golang v1.12.1 h1:ZiaPsmm9uiBeaSMRznKsCDNtPCS0T3JVDGF+06gjBzk=
|
||||
github.com/prometheus/client_golang v1.12.1/go.mod h1:3Z9XVyYiZYEO+YQWt3RD2R3jrbd179Rt297l4aS6nDY=
|
||||
github.com/prometheus/client_golang v1.12.2 h1:51L9cDoUHVrXx4zWYlcLQIZ+d+VXHgqnYKkIuq4g/34=
|
||||
github.com/prometheus/client_golang v1.12.2/go.mod h1:3Z9XVyYiZYEO+YQWt3RD2R3jrbd179Rt297l4aS6nDY=
|
||||
github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo=
|
||||
github.com/prometheus/client_model v0.0.0-20190115171406-56726106282f/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo=
|
||||
github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
|
||||
github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
|
||||
github.com/prometheus/client_model v0.2.0 h1:uq5h0d+GuxiXLJLNABMgp2qUWDPiLvgCzz2dUR+/W/M=
|
||||
github.com/prometheus/client_model v0.2.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
|
||||
github.com/prometheus/common v0.2.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4=
|
||||
github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4=
|
||||
github.com/prometheus/common v0.6.0/go.mod h1:eBmuwkDJBwy6iBfxCBob6t6dR6ENT/y+J+Zk0j9GMYc=
|
||||
github.com/prometheus/common v0.9.1/go.mod h1:yhUN8i9wzaXS3w1O07YhxHEBxD+W35wd8bs7vj7HSQ4=
|
||||
github.com/prometheus/common v0.10.0/go.mod h1:Tlit/dnDKsSWFlCLTWaA1cyBgKHSMdTB80sz/V91rCo=
|
||||
github.com/prometheus/common v0.26.0/go.mod h1:M7rCNAaPfAosfx8veZJCuw84e35h3Cfd9VFqTh1DIvc=
|
||||
github.com/prometheus/common v0.32.1 h1:hWIdL3N2HoUx3B8j3YN9mWor0qhY/NlEKZEaXxuIRh4=
|
||||
github.com/prometheus/common v0.32.1/go.mod h1:vu+V0TpY+O6vW9J44gczi3Ap/oXXR10b+M/gUGO4Hls=
|
||||
github.com/prometheus/common v0.35.0 h1:Eyr+Pw2VymWejHqCugNaQXkAi6KayVNxaHeu6khmFBE=
|
||||
github.com/prometheus/common v0.35.0/go.mod h1:phzohg0JFMnBEFGxTDbfu3QyL5GI8gTQJFhYO5B3mfA=
|
||||
github.com/prometheus/procfs v0.0.0-20180125133057-cb4147076ac7/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
|
||||
github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
|
||||
github.com/prometheus/procfs v0.0.0-20190117184657-bf6a532e95b1/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
|
||||
github.com/prometheus/procfs v0.0.0-20190522114515-bc1a522cf7b1/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA=
|
||||
github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA=
|
||||
github.com/prometheus/procfs v0.0.8/go.mod h1:7Qr8sr6344vo1JqZ6HhLceV9o3AJ1Ff+GxbHq6oeK9A=
|
||||
github.com/prometheus/procfs v0.0.11/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU=
|
||||
github.com/prometheus/procfs v0.1.3/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU=
|
||||
github.com/prometheus/procfs v0.2.0/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU=
|
||||
github.com/prometheus/procfs v0.6.0/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA=
|
||||
github.com/prometheus/procfs v0.7.3 h1:4jVXhlkAyzOScmCkXBTOLRLTz8EeU+eyjrwB/EPq0VU=
|
||||
github.com/prometheus/procfs v0.7.3/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA=
|
||||
github.com/protolambda/ctxlock v0.1.0 h1:rCUY3+vRdcdZXqT07iXgyr744J2DU2LCBIXowYAjBCE=
|
||||
github.com/protolambda/ctxlock v0.1.0/go.mod h1:vefhX6rIZH8rsg5ZpOJfEDYQOppZi19SfPiGOFrNnwM=
|
||||
github.com/rcrowley/go-metrics v0.0.0-20181016184325-3113b8401b8a h1:9ZKAASQSHhDYGoxY8uLVpewe1GDZ2vu2Tr/vTdVAkFQ=
|
||||
github.com/rcrowley/go-metrics v0.0.0-20181016184325-3113b8401b8a/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4=
|
||||
github.com/remyoudompheng/bigfft v0.0.0-20200410134404-eec4a21b6bb0/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo=
|
||||
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec h1:W09IVJc94icq4NjY3clb7Lk8O1qJ8BdBEF8z0ibU0rE=
|
||||
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo=
|
||||
github.com/richardlehane/mscfb v1.0.4 h1:WULscsljNPConisD5hR0+OyZjwK46Pfyr6mPu5ZawpM=
|
||||
github.com/richardlehane/mscfb v1.0.4/go.mod h1:YzVpcZg9czvAuhk9T+a3avCpcFPMUWm7gK3DypaEsUk=
|
||||
github.com/richardlehane/msoleps v1.0.1/go.mod h1:BWev5JBpU9Ko2WAgmZEuiz4/u3ZYTKbjLycmwiWUfWg=
|
||||
@@ -831,13 +970,19 @@ github.com/rivo/uniseg v0.2.0 h1:S1pD9weZBuJdFmowNwbpi7BJ8TNftyUImj/0WQi72jY=
|
||||
github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc=
|
||||
github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ=
|
||||
github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
|
||||
github.com/rogpeppe/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc=
|
||||
github.com/rogpeppe/go-internal v1.8.0/go.mod h1:WmiCO8CzOY8rg0OYDC4/i/2WRWAB6poM+XZ2dLUbcbE=
|
||||
github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs=
|
||||
github.com/rogpeppe/go-internal v1.12.0 h1:exVL4IDcn6na9z1rAb56Vxr+CgyK3nn3O+epU5NdKM8=
|
||||
github.com/rogpeppe/go-internal v1.12.0/go.mod h1:E+RYuTGaKKdloAfM02xzb0FW3Paa99yedzYV+kq4uf4=
|
||||
github.com/rs/dnscache v0.0.0-20211102005908-e0241e321417 h1:Lt9DzQALzHoDwMBGJ6v8ObDPR0dzr2a6sXTB1Fq7IHs=
|
||||
github.com/rs/dnscache v0.0.0-20211102005908-e0241e321417/go.mod h1:qe5TWALJ8/a1Lqznoc5BDHpYX/8HU60Hm2AwRmqzxqA=
|
||||
github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
|
||||
github.com/ryszard/goskiplist v0.0.0-20150312221310-2dfbae5fcf46 h1:GHRpF1pTW19a8tTFrMLUcfWwyC0pnifVo2ClaLq+hP8=
|
||||
github.com/ryszard/goskiplist v0.0.0-20150312221310-2dfbae5fcf46/go.mod h1:uAQ5PCi+MFsC7HjREoAz1BU+Mq60+05gifQSsHSDG/8=
|
||||
github.com/satori/go.uuid v1.2.0 h1:0uYX9dsZ2yD7q2RtLRtPSdGDWzjeM3TbMJP9utgA0ww=
|
||||
github.com/satori/go.uuid v1.2.0/go.mod h1:dA0hQrYB0VpLJoorglMZABFdXlWrHn1NEOzdhQKdks0=
|
||||
github.com/sclevine/agouti v3.0.0+incompatible/go.mod h1:b4WX9W9L1sfQKXeJf1mUTLZKJ48R1S7H23Ji7oFO5Bw=
|
||||
github.com/seccomp/libseccomp-golang v0.9.1 h1:NJjM5DNFOs0s3kYE1WUOr6G8V97sdt46rlXTMfXGWBo=
|
||||
github.com/seccomp/libseccomp-golang v0.9.1/go.mod h1:GbW5+tmTXfcxTToHLXlScSlAvWlF4P2Ca7zGrPiEpWo=
|
||||
github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo=
|
||||
@@ -861,15 +1006,15 @@ github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ
|
||||
github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ=
|
||||
github.com/skip2/go-qrcode v0.0.0-20190110000554-dc11ecdae0a9 h1:lpEzuenPuO1XNTeikEmvqYFcU37GVLl8SRNblzyvGBE=
|
||||
github.com/skip2/go-qrcode v0.0.0-20190110000554-dc11ecdae0a9/go.mod h1:PLPIyL7ikehBD1OAjmKKiOEhbvWyHGaNDjquXMcYABo=
|
||||
github.com/smartystreets/assertions v0.0.0-20180607162144-eb5b59917fa2/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc=
|
||||
github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc=
|
||||
github.com/smartystreets/assertions v0.0.0-20190215210624-980c5ac6f3ac/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc=
|
||||
github.com/smartystreets/assertions v1.2.0 h1:42S6lae5dvLc7BrLu/0ugRtcFVjoJNMC/N3yZFZkDFs=
|
||||
github.com/smartystreets/assertions v1.2.0/go.mod h1:tcbTF8ujkAEcZ8TElKY+i30BzYlVhC/LOxJk7iOWnoo=
|
||||
github.com/smartystreets/goconvey v0.0.0-20180222194500-ef6db91d284a/go.mod h1:XDJAKZRPZ1CvBcN2aX5YOUTYGHki24fSF0Iv48Ibg0s=
|
||||
github.com/smartystreets/goconvey v0.0.0-20181108003508-044398e4856c/go.mod h1:XDJAKZRPZ1CvBcN2aX5YOUTYGHki24fSF0Iv48Ibg0s=
|
||||
github.com/smartystreets/goconvey v0.0.0-20190306220146-200a235640ff/go.mod h1:KSQcGKpxUMHk3nbYzs/tIBAM2iDooCn0BmttHOJEbLs=
|
||||
github.com/smartystreets/goconvey v0.0.0-20190330032615-68dc04aab96a/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA=
|
||||
github.com/smartystreets/goconvey v1.7.2 h1:9RBaZCeXEQ3UselpuwUQHltGVXvdwm6cv1hgR6gDIPg=
|
||||
github.com/smartystreets/goconvey v1.7.2/go.mod h1:Vw0tHAZW6lzCRk3xgdin6fKYcG+G3Pg9vgXWeJpQFMM=
|
||||
github.com/smartystreets/gunit v0.0.0-20180314194857-6f0d6275bdcd/go.mod h1:XUKj4gbqj2QvJk/OdLWzyZ3FYli0f+MdpngyryX0gcw=
|
||||
github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA=
|
||||
github.com/spaolacci/murmur3 v1.1.0 h1:7c1g84S4BPRrfL5Xrdp6fOJ206sU9y293DDHaoy0bLI=
|
||||
github.com/spaolacci/murmur3 v1.1.0/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA=
|
||||
@@ -897,7 +1042,6 @@ github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO
|
||||
github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
|
||||
github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg=
|
||||
github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
|
||||
github.com/syncthing/syncthing v0.14.48-rc.4/go.mod h1:nw3siZwHPA6M8iSfjDCWQ402eqvEIasMQOE8nFOxy7M=
|
||||
github.com/syndtr/gocapability v0.0.0-20180916011248-d98352740cb2 h1:b6uOv7YOFK0TYG7HtkIgExQo+2RdLuwRft63jn2HWj8=
|
||||
github.com/syndtr/gocapability v0.0.0-20180916011248-d98352740cb2/go.mod h1:hkRG7XYTFWNJGYcbNJQlaLq0fg1yr4J4t/NcTQtrfww=
|
||||
github.com/tailscale/depaware v0.0.0-20210622194025-720c4b409502/go.mod h1:p9lPsd+cx33L3H9nNoecRRxPssFKUwwI50I3pZ0yT+8=
|
||||
@@ -909,15 +1053,18 @@ github.com/tencentyun/cos-go-sdk-v5 v0.7.24 h1:ZsZij764lOaPsj7mEAlyxXvslGt6/m312
|
||||
github.com/tencentyun/cos-go-sdk-v5 v0.7.24/go.mod h1:wQBO5HdAkLjj2q6XQiIfDSP8DXDNrppDRw2Kp/1BODA=
|
||||
github.com/texttheater/golang-levenshtein v0.0.0-20180516184445-d188e65d659e h1:T5PdfK/M1xyrHwynxMIVMWLS7f/qHwfslZphxtGnw7s=
|
||||
github.com/texttheater/golang-levenshtein v0.0.0-20180516184445-d188e65d659e/go.mod h1:XDKHRm5ThF8YJjx001LtgelzsoaEcvnA7lVWz9EeX3g=
|
||||
github.com/tidwall/btree v1.6.0 h1:LDZfKfQIBHGHWSwckhXI0RPSXzlo+KYdjK7FWSqOzzg=
|
||||
github.com/tidwall/btree v1.6.0/go.mod h1:twD9XRA5jj9VUQGELzDO4HPQTNJsoWWfYEL+EUQ2cKY=
|
||||
github.com/tinylib/msgp v1.0.2/go.mod h1:+d+yLhGm8mzTaHzB+wgMYrodPfmZrzkirds8fDWklFE=
|
||||
github.com/tinylib/msgp v1.1.0 h1:9fQd+ICuRIu/ue4vxJZu6/LzxN0HwMds2nq/0cFvxHU=
|
||||
github.com/tinylib/msgp v1.1.0/go.mod h1:+d+yLhGm8mzTaHzB+wgMYrodPfmZrzkirds8fDWklFE=
|
||||
github.com/tinylib/msgp v1.1.2/go.mod h1:+d+yLhGm8mzTaHzB+wgMYrodPfmZrzkirds8fDWklFE=
|
||||
github.com/tjfoc/gmsm v1.4.1 h1:aMe1GlZb+0bLjn+cKTPEvvn9oUEBlJitaZiiBwsbgho=
|
||||
github.com/tjfoc/gmsm v1.4.1/go.mod h1:j4INPkHWMrhJb38G+J6W4Tw0AbuN8Thu3PbdVYhVcTE=
|
||||
github.com/tklauser/go-sysconf v0.3.10 h1:IJ1AZGZRWbY8T5Vfk04D9WOA5WSejdflXxP03OUqALw=
|
||||
github.com/tklauser/go-sysconf v0.3.10/go.mod h1:C8XykCvCb+Gn0oNCWPIlcb0RuglQTYaQ2hGm7jmxEFk=
|
||||
github.com/tklauser/numcpus v0.4.0 h1:E53Dm1HjH1/R2/aoCtXtPgzmElmn51aOkhCFSuZq//o=
|
||||
github.com/tklauser/numcpus v0.4.0/go.mod h1:1+UI3pD8NW14VMwdgJNJ1ESk2UnwhAnz5hMwiKKqXCQ=
|
||||
github.com/tklauser/numcpus v0.5.0 h1:ooe7gN0fg6myJ0EKoTAf5hebTZrH52px3New/D9iJ+A=
|
||||
github.com/tklauser/numcpus v0.5.0/go.mod h1:OGzpTxpcIMNGYQdit2BYL1pvk/dSOaJWjKoflh+RQjo=
|
||||
github.com/tredoe/osutil v1.5.0 h1:UGVxbbHRoZi8xXVmbNZ2vgG6XoJ15ndE4LniiQ3rJKg=
|
||||
github.com/tredoe/osutil v1.5.0/go.mod h1:TEzphzUUunysbdDRfdOgqkg10POQbnfIPV50ynqOfIg=
|
||||
github.com/ugorji/go v1.1.7/go.mod h1:kZn38zHttfInRq0xu/PH0az30d+z6vm202qpg1oXVMw=
|
||||
@@ -941,13 +1088,10 @@ github.com/volcengine/ve-tos-golang-sdk/v2 v2.6.2 h1:FZ7zrUf70YKVuES50mHO3z2VW0K
|
||||
github.com/volcengine/ve-tos-golang-sdk/v2 v2.6.2/go.mod h1:IrjK84IJJTuOZOTMv/P18Ydjy/x+ow7fF7q11jAxXLM=
|
||||
github.com/volcengine/volc-sdk-golang v1.0.23 h1:anOslb2Qp6ywnsbyq9jqR0ljuO63kg9PY+4OehIk5R8=
|
||||
github.com/volcengine/volc-sdk-golang v1.0.23/go.mod h1:AfG/PZRUkHJ9inETvbjNifTDgut25Wbkm2QoYBTbvyU=
|
||||
github.com/willf/bitset v1.1.3/go.mod h1:RjeCKbqT1RxIR/KWY6phxZiaY1IyutSBfGjNPySAYV4=
|
||||
github.com/willf/bitset v1.1.9/go.mod h1:RjeCKbqT1RxIR/KWY6phxZiaY1IyutSBfGjNPySAYV4=
|
||||
github.com/willf/bitset v1.1.10/go.mod h1:RjeCKbqT1RxIR/KWY6phxZiaY1IyutSBfGjNPySAYV4=
|
||||
github.com/willf/bitset v1.1.11-0.20200630133818-d5bec3311243 h1:R43TdZy32XXSXjJn7M/HhALJ9imq6ztLnChfYJpVDnM=
|
||||
github.com/willf/bitset v1.1.11-0.20200630133818-d5bec3311243/go.mod h1:RjeCKbqT1RxIR/KWY6phxZiaY1IyutSBfGjNPySAYV4=
|
||||
github.com/willf/bloom v0.0.0-20170505221640-54e3b963ee16/go.mod h1:MmAltL9pDMNTrvUkxdg0k0q5I0suxmuwp3KbyrZLOZ8=
|
||||
github.com/willf/bloom v2.0.3+incompatible h1:QDacWdqcAUI1MPOwIQZRy9kOR7yxfyEmxX8Wdm2/JPA=
|
||||
github.com/willf/bloom v2.0.3+incompatible/go.mod h1:MmAltL9pDMNTrvUkxdg0k0q5I0suxmuwp3KbyrZLOZ8=
|
||||
github.com/wk8/go-ordered-map/v2 v2.1.8 h1:5h/BUHu93oj4gIdvHHHGsScSTMijfx5PeYkE/fJgbpc=
|
||||
github.com/wk8/go-ordered-map/v2 v2.1.8/go.mod h1:5nJHM5DyteebpVlHnWMV0rPz6Zp7+xBAnxjb1X5vnTw=
|
||||
github.com/xuri/efp v0.0.0-20220603152613-6918739fd470 h1:6932x8ltq1w4utjmfMPVj09jdMlkY0aiA6+Skbtl3/c=
|
||||
@@ -963,6 +1107,7 @@ github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9de
|
||||
github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||
github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
|
||||
github.com/yuin/goldmark v1.4.1/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
|
||||
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
|
||||
github.com/yusufpapurcu/wmi v1.2.2 h1:KBNDSne4vP5mbSWnJbO+51IMOXJB67QiYCSBrubbPRg=
|
||||
github.com/yusufpapurcu/wmi v1.2.2/go.mod h1:SBZ9tNy3G9/m5Oi98Zks0QjeHVDvuK0qfxQmPyzfmi0=
|
||||
@@ -982,6 +1127,8 @@ go.etcd.io/etcd/client/pkg/v3 v3.5.0 h1:2aQv6F436YnN7I4VbI8PPYrBhu+SmrTaADcf8Mi/
|
||||
go.etcd.io/etcd/client/pkg/v3 v3.5.0/go.mod h1:IJHfcCEKxYu1Os13ZdwCwIUTUVGYTSAM3YSwc9/Ac1g=
|
||||
go.etcd.io/etcd/client/v3 v3.5.0 h1:62Eh0XOro+rDwkrypAGDfgmNh5Joq+z+W9HZdlXMzek=
|
||||
go.etcd.io/etcd/client/v3 v3.5.0/go.mod h1:AIKXXVX/DQXtfTEqBryiLTUXwON+GuvO6Z7lLS/oTh0=
|
||||
go.opencensus.io v0.20.1/go.mod h1:6WKK9ahsWS3RSO+PY9ZHZUfv2irvY6gN279GOPZjmmk=
|
||||
go.opencensus.io v0.20.2/go.mod h1:6WKK9ahsWS3RSO+PY9ZHZUfv2irvY6gN279GOPZjmmk=
|
||||
go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU=
|
||||
go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8=
|
||||
go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
|
||||
@@ -1001,10 +1148,12 @@ go.opentelemetry.io/otel/sdk v1.22.0 h1:6coWHw9xw7EfClIC/+O31R8IY3/+EiRFHevmHafB
|
||||
go.opentelemetry.io/otel/sdk v1.22.0/go.mod h1:iu7luyVGYovrRpe2fmj3CVKouQNdTOkxtLzPvPz1DOc=
|
||||
go.opentelemetry.io/otel/trace v1.23.0 h1:37Ik5Ib7xfYVb4V1UtnT97T1jI+AoIYkJyPkuL4iJgI=
|
||||
go.opentelemetry.io/otel/trace v1.23.0/go.mod h1:GSGTbIClEsuZrGIzoEHqsVfxgn5UkggkflQwDScNUsk=
|
||||
go.uber.org/atomic v1.7.0 h1:ADUqmZGgLDDfbSL9ZmPxKTybcoEYHgpYfELNoN+7hsw=
|
||||
go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc=
|
||||
go.uber.org/multierr v1.6.0 h1:y6IPFStTAIT5Ytl7/XYmHvzXQ7S3g/IeZW9hyZ5thw4=
|
||||
go.uber.org/atomic v1.10.0 h1:9qC72Qh0+3MqyJbAn8YU5xVq1frD8bn3JtD2oXtafVQ=
|
||||
go.uber.org/atomic v1.10.0/go.mod h1:LUxbIzbOniOlMKjJjyPfpl4v+PKK2cNJn91OQbhoJI0=
|
||||
go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9iU=
|
||||
go.uber.org/multierr v1.8.0 h1:dg6GjLku4EH+249NNmoIciG9N/jURbDG+pFlTkhzIC8=
|
||||
go.uber.org/multierr v1.8.0/go.mod h1:7EAYxJLBy9rStEaz58O2t4Uvip6FSURkq8/ppBp95ak=
|
||||
go.uber.org/zap v1.17.0 h1:MTjgFu6ZLKvY6Pvaqk97GlxNBuMpV4Hy/3P6tRGlI2U=
|
||||
go.uber.org/zap v1.17.0/go.mod h1:MXVU+bhUf/A7Xi2HNOnopQOrmycQ5Ih87HtOu4q5SSo=
|
||||
golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
|
||||
@@ -1020,7 +1169,11 @@ golang.org/x/crypto v0.0.0-20191206172530-e9b2fee46413/go.mod h1:LzIPMQfyMNhhGPh
|
||||
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||
golang.org/x/crypto v0.0.0-20201012173705-84dcc777aaee/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
||||
golang.org/x/crypto v0.0.0-20220131195533-30dcbda58838/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
|
||||
golang.org/x/crypto v0.0.0-20220427172511-eb4f295cb31f/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
|
||||
golang.org/x/crypto v0.0.0-20220516162934-403b01795ae8/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
|
||||
golang.org/x/crypto v0.1.0/go.mod h1:RecgLatLF4+eUMCP1PoPZQb+cVrJcOPbHkTkbkB9sbw=
|
||||
golang.org/x/crypto v0.5.0/go.mod h1:NK/OQwhpMQP3MwtdjgLlYHnH9ebylxKWv3e0fK+mkQU=
|
||||
golang.org/x/crypto v0.8.0/go.mod h1:mRqEX+O9/h5TFCrQhkgjo2yKi0yYA+9ecGkdQoHrywE=
|
||||
golang.org/x/crypto v0.21.0 h1:X31++rzVUdKhX5sWmSOFZxx8UW/ldWx55cbf08iNAMA=
|
||||
golang.org/x/crypto v0.21.0/go.mod h1:0BP7YvVV9gBbVKyeTG0Gyn+gZm94bibOW5BjDEYAOMs=
|
||||
@@ -1034,6 +1187,9 @@ golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u0
|
||||
golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4=
|
||||
golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM=
|
||||
golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU=
|
||||
golang.org/x/exp v0.0.0-20220428152302-39d4317da171/go.mod h1:lgLbSvA5ygNOMpwM/9anMpWVlVJ7Z+cHWq/eFuinpGE=
|
||||
golang.org/x/exp v0.0.0-20240506185415-9bf2ced13842 h1:vr/HnozRka3pE4EsMEg1lgkXJkTFJCVUX+S/ZT6wYzM=
|
||||
golang.org/x/exp v0.0.0-20240506185415-9bf2ced13842/go.mod h1:XtvwrStGgqGPLc4cjQfWqZHG1YFdYs6swckp8vpsjnc=
|
||||
golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js=
|
||||
golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
|
||||
golang.org/x/image v0.5.0 h1:5JMiNunQeQw++mMOz48/ISeNu3Iweh/JaZU8ZLqHRrI=
|
||||
@@ -1059,14 +1215,16 @@ golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||
golang.org/x/mod v0.4.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||
golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||
golang.org/x/mod v0.5.1/go.mod h1:5OXOZSfqPIIbmVBIIKWRFfZjPR0E5r58TLhUjH0a2Ro=
|
||||
golang.org/x/mod v0.6.0-dev.0.20211013180041-c96bc1413d57/go.mod h1:3p9vT2HGsQu2K1YbXdKPJLVgG5VJdoTa1poYQBtP1AY=
|
||||
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
|
||||
golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
|
||||
golang.org/x/net v0.0.0-20180524181706-dfa909b99c79/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20190125091013-d26f9f9a57f3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||
golang.org/x/net v0.0.0-20190313220215-9f648a60d977/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||
@@ -1092,6 +1250,7 @@ golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e/go.mod h1:qpuaurCH72eLCgpAm/
|
||||
golang.org/x/net v0.0.0-20200501053045-e0ff5e5a1de5/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
|
||||
golang.org/x/net v0.0.0-20200506145744-7e3656a0809f/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
|
||||
golang.org/x/net v0.0.0-20200513185701-a91f0712d120/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
|
||||
golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
|
||||
golang.org/x/net v0.0.0-20200520182314-0ba52f642ac2/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
|
||||
golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
|
||||
golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
|
||||
@@ -1099,12 +1258,25 @@ golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81R
|
||||
golang.org/x/net v0.0.0-20201010224723-4f7140c49acb/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
|
||||
golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
|
||||
golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
|
||||
golang.org/x/net v0.0.0-20201201195509-5d6afe98e0b7/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
|
||||
golang.org/x/net v0.0.0-20210119194325-5f4716e94777/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
||||
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
||||
golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM=
|
||||
golang.org/x/net v0.0.0-20210428140749-89ef3d95e781/go.mod h1:OJAsFXCWl8Ukc7SiCT/9KSuxbyM7479/AVlXFRxuMCk=
|
||||
golang.org/x/net v0.0.0-20210525063256-abc453219eb5/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||
golang.org/x/net v0.0.0-20211015210444-4f30a5c0130f/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||
golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||
golang.org/x/net v0.0.0-20211201190559-0a0e4e1bb54c/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||
golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk=
|
||||
golang.org/x/net v0.0.0-20220225172249-27dd8689420f/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk=
|
||||
golang.org/x/net v0.0.0-20220401154927-543a649e0bdd/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk=
|
||||
golang.org/x/net v0.0.0-20220425223048-2871e0cb64e4/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk=
|
||||
golang.org/x/net v0.0.0-20220531201128-c960675eff93/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
|
||||
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
|
||||
golang.org/x/net v0.1.0/go.mod h1:Cx3nUiGt4eDBEyega/BKRp+/AlGL8hYe7U9odMt2Cco=
|
||||
golang.org/x/net v0.5.0/go.mod h1:DivGGAXEgPSlEBzxGzZI+ZLohi+xUj054jfeKui00ws=
|
||||
golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
|
||||
golang.org/x/net v0.7.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
|
||||
golang.org/x/net v0.9.0/go.mod h1:d48xBJpPfHeWQsugry2m+kC02ZBRGRgulfHnEXEuWns=
|
||||
golang.org/x/net v0.23.0 h1:7EYJ93RZ9vYSZAIb2x3lnuvqO5zneoD6IvWjuhfxjTs=
|
||||
golang.org/x/net v0.23.0/go.mod h1:JKghWKKOSdJwpW2GEx0Ja7fmaKnMsbu+MWVZTokSYmg=
|
||||
@@ -1114,6 +1286,7 @@ golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4Iltr
|
||||
golang.org/x/oauth2 v0.0.0-20191202225959-858c2ad4c8b6/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
||||
golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
||||
golang.org/x/oauth2 v0.0.0-20210514164344-f6687ab2804c/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
|
||||
golang.org/x/oauth2 v0.0.0-20220223155221-ee480838109b/go.mod h1:DAh4E804XQdzx2j+YRIaUnCqCV2RuMz24cGBJ5QYIrc=
|
||||
golang.org/x/oauth2 v0.17.0 h1:6m3ZPmLEFdVxKKWnKq4VqZ60gutO35zm+zrAHVmHyDQ=
|
||||
golang.org/x/oauth2 v0.17.0/go.mod h1:OzPDGQiuQMguemayvdylqddI7qcD9lnSDb+1FiwQ5HA=
|
||||
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
@@ -1131,11 +1304,11 @@ golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJ
|
||||
golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.8.0 h1:3NFvSEYkUoMifnESzZl15y791HH1qU2xm6eCJU5ZPXQ=
|
||||
golang.org/x/sync v0.8.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
|
||||
golang.org/x/sys v0.0.0-20180724212812-e072cadbbdc8/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20181122145206-62eef0e2fa9b/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190116161447-11f53e031339/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
@@ -1151,6 +1324,7 @@ golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7w
|
||||
golang.org/x/sys v0.0.0-20190606203320-7fc4e5ec1444/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190904154756-749cb33beabd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190922100055-0a153f010e69/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190924154521-2837fb4f24fe/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
@@ -1174,6 +1348,7 @@ golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7w
|
||||
golang.org/x/sys v0.0.0-20200302150141-5c8b2ff67527/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200331124033-c3d80250170d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200413165638-669c56c373c4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200501052902-10377860bb8e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200511232937-7e40ca221e25/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200515095857-1151b9dac4a9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
@@ -1189,6 +1364,7 @@ golang.org/x/sys v0.0.0-20201110211018-35f3e6cf4a65/go.mod h1:h1NjWce9XRLGQEsW7w
|
||||
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20201201145000-ef89a241ccb3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20201204225414-ed752295db88/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210112080510-489259a85091/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210403161142-5e06dd20ab57/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
@@ -1198,12 +1374,21 @@ golang.org/x/sys v0.0.0-20210603081109-ebe580a85c40/go.mod h1:oPkhp1MJrh7nUepCBc
|
||||
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20210616094352-59db8d763f22/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20211019181941-9d821ace8654/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220114195835-da31bd327af9/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220128215802-99c3d69c2c27/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220412211240-33da011f77ad/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220503163025-988cb79eb6c6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220608164250-635b8c9b7f68/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220704084225-05e143d24a9e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.4.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.7.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.26.0 h1:KHjCJyddX0LoSTb3J+vWpupP9p0oznkqVk/IfjymZbo=
|
||||
@@ -1211,6 +1396,7 @@ golang.org/x/sys v0.26.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
|
||||
golang.org/x/term v0.1.0/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
|
||||
golang.org/x/term v0.4.0/go.mod h1:9P2UbLfCdcvo3p/nzKvsmas4TnlujnuoV9hGgYzW1lQ=
|
||||
golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k=
|
||||
golang.org/x/term v0.7.0/go.mod h1:P32HKFT3hSsZrRxla30E9HqToFYAQPCMs/zFMBUFqPY=
|
||||
golang.org/x/term v0.18.0 h1:FcHjZXDMxI8mM3nwhX9HlKop4C0YQvCVCdwYl2wOtE8=
|
||||
@@ -1226,17 +1412,18 @@ golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
|
||||
golang.org/x/text v0.3.8/go.mod h1:E6s5w1FMmriuDzIBO73fBruAKo1PCIq6d2Q6DHfQ8WQ=
|
||||
golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
|
||||
golang.org/x/text v0.6.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
|
||||
golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
|
||||
golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
|
||||
golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ=
|
||||
golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
|
||||
golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||
golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||
golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||
golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||
golang.org/x/time v0.0.0-20200630173020-3af7569d3a1e/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||
golang.org/x/time v0.5.0 h1:o7cqy6amK/52YcAKIPlM3a+Fpj35zvRj2TP+e1xFSfk=
|
||||
golang.org/x/time v0.5.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM=
|
||||
golang.org/x/tools v0.0.0-20180828015842-6cd1fcedba52/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20181011042414-1f849cf54d09/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20181030221726-6c7e314b6563/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
@@ -1284,8 +1471,10 @@ golang.org/x/tools v0.0.0-20200729194436-6467de6f59a7/go.mod h1:njjCfa9FT2d7l9Bc
|
||||
golang.org/x/tools v0.0.0-20200804011535-6c149bb5ef0d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA=
|
||||
golang.org/x/tools v0.0.0-20200825202427-b303f430e36d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA=
|
||||
golang.org/x/tools v0.0.0-20201211185031-d93e913c1a58/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
|
||||
golang.org/x/tools v0.0.0-20201224043029-2b0845dc783e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
|
||||
golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
|
||||
golang.org/x/tools v0.1.2/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
|
||||
golang.org/x/tools v0.1.8-0.20211029000441-d6a9af8af023/go.mod h1:nABZi5QlRsZVlzPpHl034qft6wpY4eDcsTt5AaioBiU=
|
||||
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
|
||||
golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU=
|
||||
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
@@ -1296,6 +1485,7 @@ golang.org/x/xerrors v0.0.0-20231012003039-104605ab7028 h1:+cNy6SZtPcJQH3LJVLOSm
|
||||
golang.org/x/xerrors v0.0.0-20231012003039-104605ab7028/go.mod h1:NDW/Ps6MPRej6fsCIbMTohpP40sJ/P/vI1MoTEGwX90=
|
||||
golang.zx2c4.com/wireguard/wgctrl v0.0.0-20230215201556-9c5414ab4bde h1:ybF7AMzIUikL9x4LgwEmzhXtzRpKNqngme1VGDWz+Nk=
|
||||
golang.zx2c4.com/wireguard/wgctrl v0.0.0-20230215201556-9c5414ab4bde/go.mod h1:mQqgjkW8GQQcJQsbBvK890TKqUK1DfKWkuBGbOkuMHQ=
|
||||
google.golang.org/api v0.3.1/go.mod h1:6wY9I6uQWHQ8EM57III9mq/AjF+i8G65rmVagqKMtkk=
|
||||
google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE=
|
||||
google.golang.org/api v0.7.0/go.mod h1:WtwebWUNSVBH/HAw79HIFXZNqEvBhG+Ra+ax0hx3E3M=
|
||||
google.golang.org/api v0.8.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg=
|
||||
@@ -1361,6 +1551,7 @@ google.golang.org/genproto/googleapis/api v0.0.0-20240304161311-37d4d3c04a78 h1:
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20240304161311-37d4d3c04a78/go.mod h1:O1cOfN1Cy6QEYr7VxtjOyP5AdAuR0aJ/MYZaaof623Y=
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20240228224816-df926f6c8641 h1:DKU1r6Tj5s1vlU/moGhuGz7E3xRfwjdAfDzbsaQJtEY=
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20240228224816-df926f6c8641/go.mod h1:UCOku4NytXMJuLQE5VuqA5lX3PcHCBo8pxNyvkf4xBs=
|
||||
google.golang.org/grpc v1.17.0/go.mod h1:6QZJwpn2B+Zp71q/5VxRsJ6NXXVCE5NRUHRo+f3cWCs=
|
||||
google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
|
||||
google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38=
|
||||
google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM=
|
||||
@@ -1434,6 +1625,7 @@ gotest.tools v2.2.0+incompatible h1:VsBPFP1AI068pPrMxtb/S8Zkgf9xEmTLJjfM+P5UIEo=
|
||||
gotest.tools v2.2.0+incompatible/go.mod h1:DsYFclhRJ6vuDpmuTbkuFWG+y2sxOXAzmJt81HFBacw=
|
||||
gotest.tools/v3 v3.5.1 h1:EENdUnS3pdur5nybKYIh2Vfgc8IUNBjxDPSjtiJcOzU=
|
||||
gotest.tools/v3 v3.5.1/go.mod h1:isy3WKz7GK6uNw/sbHzfKBLvlvXwUyV06n6brMxxopU=
|
||||
honnef.co/go/tools v0.0.0-20180728063816-88497007e858/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||
honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||
honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||
@@ -1460,6 +1652,16 @@ k8s.io/kube-openapi v0.0.0-20200805222855-6aeccd4b50c6/go.mod h1:UuqjUnNftUyPE5H
|
||||
k8s.io/utils v0.0.0-20200729134348-d5654de09c73/go.mod h1:jPW/WVKK9YHAvNhRxK0md/EJ228hCsBRufyofKtW8HA=
|
||||
k8s.io/utils v0.0.0-20201110183641-67b214c5f920 h1:CbnUZsM497iRC5QMVkHwyl8s2tB3g7yaSHkYPkpgelw=
|
||||
k8s.io/utils v0.0.0-20201110183641-67b214c5f920/go.mod h1:jPW/WVKK9YHAvNhRxK0md/EJ228hCsBRufyofKtW8HA=
|
||||
lukechampine.com/blake3 v1.1.6 h1:H3cROdztr7RCfoaTpGZFQsrqvweFLrqS73j7L7cmR5c=
|
||||
lukechampine.com/blake3 v1.1.6/go.mod h1:tkKEOtDkNtklkXtLNEOGNq5tcV90tJiA1vAA12R78LA=
|
||||
modernc.org/libc v1.22.3 h1:D/g6O5ftAfavceqlLOFwaZuA5KYafKwmr30A6iSqoyY=
|
||||
modernc.org/libc v1.22.3/go.mod h1:MQrloYP209xa2zHome2a8HLiLm6k0UT8CoHpV74tOFw=
|
||||
modernc.org/mathutil v1.5.0 h1:rV0Ko/6SfM+8G+yKiyI830l3Wuz1zRutdslNoQ0kfiQ=
|
||||
modernc.org/mathutil v1.5.0/go.mod h1:mZW8CKdRPY1v87qxC/wUdX5O1qDzXMP5TH3wjfpga6E=
|
||||
modernc.org/memory v1.5.0 h1:N+/8c5rE6EqugZwHii4IFsaJ7MUhoWX07J5tC/iI5Ds=
|
||||
modernc.org/memory v1.5.0/go.mod h1:PkUhL0Mugw21sHPeskwZW4D6VscE/GQJOnIpCnW6pSU=
|
||||
modernc.org/sqlite v1.21.1 h1:GyDFqNnESLOhwwDRaHGdp2jKLDzpyT/rNLglX3ZkMSU=
|
||||
modernc.org/sqlite v1.21.1/go.mod h1:XwQ0wZPIh1iKb5mkvCJ3szzbhk+tykC8ZWqTRTgYRwI=
|
||||
moul.io/http2curl/v2 v2.3.0 h1:9r3JfDzWPcbIklMOs2TnIFzDYvfAZvjeavG6EzP7jYs=
|
||||
moul.io/http2curl/v2 v2.3.0/go.mod h1:RW4hyBjTWSYDOxapodpNEtX0g5Eb16sxklBqmd2RHcE=
|
||||
rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8=
|
||||
@@ -1493,3 +1695,5 @@ yunion.io/x/sqlchemy v1.1.3-0.20250925091009-4ca0766fc8f0 h1:L4zE6kTD1PEki1jQnLL
|
||||
yunion.io/x/sqlchemy v1.1.3-0.20250925091009-4ca0766fc8f0/go.mod h1:vCIZpqhZ5Jzaq3tFyrti/vv8BijQKtkzSgNT/uH4H5A=
|
||||
yunion.io/x/structarg v0.0.0-20231017124457-df4d5009457c h1:QuLab2kSRECZRxo4Lo2KcYn6XjQFDGaZ1+x0pYDVVwQ=
|
||||
yunion.io/x/structarg v0.0.0-20231017124457-df4d5009457c/go.mod h1:EP6NSv2C0zzqBDTKumv8hPWLb3XvgMZDHQRfyuOrQng=
|
||||
zombiezen.com/go/sqlite v0.13.1 h1:qDzxyWWmMtSSEH5qxamqBFmqA2BLSSbtODi3ojaE02o=
|
||||
zombiezen.com/go/sqlite v0.13.1/go.mod h1:Ht/5Rg3Ae2hoyh1I7gbWtWAl89CNocfqeb/aAMTkJr4=
|
||||
|
||||
20
vendor/github.com/RoaringBitmap/roaring/.drone.yml
generated
vendored
Normal file
20
vendor/github.com/RoaringBitmap/roaring/.drone.yml
generated
vendored
Normal file
@@ -0,0 +1,20 @@
|
||||
kind: pipeline
|
||||
name: default
|
||||
|
||||
workspace:
|
||||
base: /go
|
||||
path: src/github.com/RoaringBitmap/roaring
|
||||
|
||||
steps:
|
||||
- name: test
|
||||
image: golang
|
||||
commands:
|
||||
- go get -t
|
||||
- go test
|
||||
- go test -race -run TestConcurrent*
|
||||
- go build -tags appengine
|
||||
- go test -tags appengine
|
||||
- GOARCH=386 go build
|
||||
- GOARCH=386 go test
|
||||
- GOARCH=arm go build
|
||||
- GOARCH=arm64 go build
|
||||
1
vendor/github.com/RoaringBitmap/roaring/.gitignore
generated
vendored
1
vendor/github.com/RoaringBitmap/roaring/.gitignore
generated
vendored
@@ -3,4 +3,3 @@ roaring-fuzz.zip
|
||||
workdir
|
||||
coverage.out
|
||||
testdata/all3.classic
|
||||
testdata/all3.msgp.snappy
|
||||
|
||||
30
vendor/github.com/RoaringBitmap/roaring/.travis.yml
generated
vendored
30
vendor/github.com/RoaringBitmap/roaring/.travis.yml
generated
vendored
@@ -1,30 +0,0 @@
|
||||
language: go
|
||||
sudo: false
|
||||
install:
|
||||
- go get -t github.com/RoaringBitmap/roaring
|
||||
- go get -t golang.org/x/tools/cmd/cover
|
||||
- go get -t github.com/mattn/goveralls
|
||||
- go get -t github.com/mschoch/smat
|
||||
notifications:
|
||||
email: false
|
||||
go:
|
||||
- "1.7.x"
|
||||
- "1.8.x"
|
||||
- "1.9.x"
|
||||
- "1.10.x"
|
||||
- tip
|
||||
|
||||
# whitelist
|
||||
branches:
|
||||
only:
|
||||
- master
|
||||
script:
|
||||
- goveralls -v -service travis-ci -ignore arraycontainer_gen.go,bitmapcontainer_gen.go,rle16_gen.go,rle_gen.go,roaringarray_gen.go,rle.go || go test
|
||||
- go test -race -run TestConcurrent*
|
||||
- GOARCH=arm64 go build
|
||||
- GOARCH=386 go build
|
||||
- GOARCH=386 go test
|
||||
- GOARCH=arm go build
|
||||
matrix:
|
||||
allow_failures:
|
||||
- go: tip
|
||||
6
vendor/github.com/RoaringBitmap/roaring/CONTRIBUTORS
generated
vendored
6
vendor/github.com/RoaringBitmap/roaring/CONTRIBUTORS
generated
vendored
@@ -11,4 +11,8 @@ Jason E. Aten (@glycerine),
|
||||
Vali Malinoiu (@0x4139),
|
||||
Forud Ghafouri (@fzerorubigd),
|
||||
Joe Nall (@joenall),
|
||||
(@fredim)
|
||||
(@fredim),
|
||||
Edd Robinson (@e-dard),
|
||||
Alexander Petrov (@alldroll),
|
||||
Guy Molinari (@guymolinari),
|
||||
Ling Jin (@JinLingChristopher)
|
||||
|
||||
33
vendor/github.com/RoaringBitmap/roaring/LICENSE
generated
vendored
33
vendor/github.com/RoaringBitmap/roaring/LICENSE
generated
vendored
@@ -200,3 +200,36 @@
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
|
||||
================================================================================
|
||||
|
||||
Portions of runcontainer.go are from the Go standard library, which is licensed
|
||||
under:
|
||||
|
||||
Copyright (c) 2009 The Go Authors. All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are
|
||||
met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above
|
||||
copyright notice, this list of conditions and the following disclaimer
|
||||
in the documentation and/or other materials provided with the
|
||||
distribution.
|
||||
* Neither the name of Google Inc. nor the names of its
|
||||
contributors may be used to endorse or promote products derived from
|
||||
this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
8
vendor/github.com/RoaringBitmap/roaring/Makefile
generated
vendored
8
vendor/github.com/RoaringBitmap/roaring/Makefile
generated
vendored
@@ -63,8 +63,8 @@ qa: fmtcheck test vet lint
|
||||
|
||||
# Get the dependencies
|
||||
deps:
|
||||
GOPATH=$(GOPATH) go get github.com/smartystreets/goconvey/convey
|
||||
GOPATH=$(GOPATH) go get github.com/willf/bitset
|
||||
GOPATH=$(GOPATH) go get github.com/stretchr/testify
|
||||
GOPATH=$(GOPATH) go get github.com/bits-and-blooms/bitset
|
||||
GOPATH=$(GOPATH) go get github.com/golang/lint/golint
|
||||
GOPATH=$(GOPATH) go get github.com/mschoch/smat
|
||||
GOPATH=$(GOPATH) go get github.com/dvyukov/go-fuzz/go-fuzz
|
||||
@@ -97,10 +97,6 @@ nuke:
|
||||
rm -rf ./target
|
||||
GOPATH=$(GOPATH) go clean -i ./...
|
||||
|
||||
|
||||
ser:
|
||||
go generate
|
||||
|
||||
cover:
|
||||
go test -coverprofile=coverage.out
|
||||
go tool cover -html=coverage.out
|
||||
|
||||
198
vendor/github.com/RoaringBitmap/roaring/README.md
generated
vendored
198
vendor/github.com/RoaringBitmap/roaring/README.md
generated
vendored
@@ -1,20 +1,22 @@
|
||||
roaring [](https://travis-ci.org/RoaringBitmap/roaring) [](https://coveralls.io/github/RoaringBitmap/roaring?branch=master) [](https://godoc.org/github.com/RoaringBitmap/roaring) [](https://goreportcard.com/report/github.com/RoaringBitmap/roaring)
|
||||
roaring [](https://godoc.org/github.com/RoaringBitmap/roaring/roaring64) [](https://goreportcard.com/report/github.com/RoaringBitmap/roaring)
|
||||
[](https://cloud.drone.io/RoaringBitmap/roaring)
|
||||

|
||||

|
||||

|
||||
=============
|
||||
|
||||
This is a go version of the Roaring bitmap data structure.
|
||||
|
||||
|
||||
|
||||
Roaring bitmaps are used by several major systems such as [Apache Lucene][lucene] and derivative systems such as [Solr][solr] and
|
||||
[Elasticsearch][elasticsearch], [Metamarkets' Druid][druid], [LinkedIn Pinot][pinot], [Netflix Atlas][atlas], [Apache Spark][spark], [OpenSearchServer][opensearchserver], [Cloud Torrent][cloudtorrent], [Whoosh][whoosh], [Pilosa][pilosa], [Microsoft Visual Studio Team Services (VSTS)][vsts], and eBay's [Apache Kylin][kylin].
|
||||
[Elasticsearch][elasticsearch], [Apache Druid (Incubating)][druid], [LinkedIn Pinot][pinot], [Netflix Atlas][atlas], [Apache Spark][spark], [OpenSearchServer][opensearchserver], [anacrolix/torrent][anacrolix/torrent], [Whoosh][whoosh], [Pilosa][pilosa], [Microsoft Visual Studio Team Services (VSTS)][vsts], and eBay's [Apache Kylin][kylin]. The YouTube SQL Engine, [Google Procella](https://research.google/pubs/pub48388/), uses Roaring bitmaps for indexing.
|
||||
|
||||
[lucene]: https://lucene.apache.org/
|
||||
[solr]: https://lucene.apache.org/solr/
|
||||
[elasticsearch]: https://www.elastic.co/products/elasticsearch
|
||||
[druid]: http://druid.io/
|
||||
[druid]: https://druid.apache.org/
|
||||
[spark]: https://spark.apache.org/
|
||||
[opensearchserver]: http://www.opensearchserver.com
|
||||
[cloudtorrent]: https://github.com/jpillora/cloud-torrent
|
||||
[anacrolix/torrent]: https://github.com/anacrolix/torrent
|
||||
[whoosh]: https://bitbucket.org/mchaput/whoosh/wiki/Home
|
||||
[pilosa]: https://www.pilosa.com/
|
||||
[kylin]: http://kylin.apache.org/
|
||||
@@ -28,11 +30,18 @@ Roaring bitmaps are found to work well in many important applications:
|
||||
|
||||
|
||||
The ``roaring`` Go library is used by
|
||||
* [Cloud Torrent](https://github.com/jpillora/cloud-torrent): a self-hosted remote torrent client
|
||||
* [runv](https://github.com/hyperhq/runv): an Hypervisor-based runtime for the Open Containers Initiative
|
||||
* [anacrolix/torrent]
|
||||
* [runv](https://github.com/hyperhq/runv)
|
||||
* [InfluxDB](https://www.influxdata.com)
|
||||
* [Pilosa](https://www.pilosa.com/)
|
||||
* [Bleve](http://www.blevesearch.com)
|
||||
* [lindb](https://github.com/lindb/lindb)
|
||||
* [Elasticell](https://github.com/deepfabric/elasticell)
|
||||
* [SourceGraph](https://github.com/sourcegraph/sourcegraph)
|
||||
* [M3](https://github.com/m3db/m3)
|
||||
* [trident](https://github.com/NetApp/trident)
|
||||
* [Husky](https://www.datadoghq.com/blog/engineering/introducing-husky/)
|
||||
|
||||
|
||||
This library is used in production in several systems, it is part of the [Awesome Go collection](https://awesome-go.com).
|
||||
|
||||
@@ -45,24 +54,108 @@ This code is licensed under Apache License, Version 2.0 (ASL2.0).
|
||||
|
||||
Copyright 2016-... by the authors.
|
||||
|
||||
When should you use a bitmap?
|
||||
===================================
|
||||
|
||||
|
||||
Sets are a fundamental abstraction in
|
||||
software. They can be implemented in various
|
||||
ways, as hash sets, as trees, and so forth.
|
||||
In databases and search engines, sets are often an integral
|
||||
part of indexes. For example, we may need to maintain a set
|
||||
of all documents or rows (represented by numerical identifier)
|
||||
that satisfy some property. Besides adding or removing
|
||||
elements from the set, we need fast functions
|
||||
to compute the intersection, the union, the difference between sets, and so on.
|
||||
|
||||
|
||||
To implement a set
|
||||
of integers, a particularly appealing strategy is the
|
||||
bitmap (also called bitset or bit vector). Using n bits,
|
||||
we can represent any set made of the integers from the range
|
||||
[0,n): the ith bit is set to one if integer i is present in the set.
|
||||
Commodity processors use words of W=32 or W=64 bits. By combining many such words, we can
|
||||
support large values of n. Intersections, unions and differences can then be implemented
|
||||
as bitwise AND, OR and ANDNOT operations.
|
||||
More complicated set functions can also be implemented as bitwise operations.
|
||||
|
||||
When the bitset approach is applicable, it can be orders of
|
||||
magnitude faster than other possible implementation of a set (e.g., as a hash set)
|
||||
while using several times less memory.
|
||||
|
||||
However, a bitset, even a compressed one is not always applicable. For example, if
|
||||
you have 1000 random-looking integers, then a simple array might be the best representation.
|
||||
We refer to this case as the "sparse" scenario.
|
||||
|
||||
When should you use compressed bitmaps?
|
||||
===================================
|
||||
|
||||
An uncompressed BitSet can use a lot of memory. For example, if you take a BitSet
|
||||
and set the bit at position 1,000,000 to true and you have just over 100kB. That is over 100kB
|
||||
to store the position of one bit. This is wasteful even if you do not care about memory:
|
||||
suppose that you need to compute the intersection between this BitSet and another one
|
||||
that has a bit at position 1,000,001 to true, then you need to go through all these zeroes,
|
||||
whether you like it or not. That can become very wasteful.
|
||||
|
||||
This being said, there are definitively cases where attempting to use compressed bitmaps is wasteful.
|
||||
For example, if you have a small universe size. E.g., your bitmaps represent sets of integers
|
||||
from [0,n) where n is small (e.g., n=64 or n=128). If you are able to uncompressed BitSet and
|
||||
it does not blow up your memory usage, then compressed bitmaps are probably not useful
|
||||
to you. In fact, if you do not need compression, then a BitSet offers remarkable speed.
|
||||
|
||||
The sparse scenario is another use case where compressed bitmaps should not be used.
|
||||
Keep in mind that random-looking data is usually not compressible. E.g., if you have a small set of
|
||||
32-bit random integers, it is not mathematically possible to use far less than 32 bits per integer,
|
||||
and attempts at compression can be counterproductive.
|
||||
|
||||
How does Roaring compares with the alternatives?
|
||||
==================================================
|
||||
|
||||
|
||||
Most alternatives to Roaring are part of a larger family of compressed bitmaps that are run-length-encoded
|
||||
bitmaps. They identify long runs of 1s or 0s and they represent them with a marker word.
|
||||
If you have a local mix of 1s and 0, you use an uncompressed word.
|
||||
|
||||
There are many formats in this family:
|
||||
|
||||
* Oracle's BBC is an obsolete format at this point: though it may provide good compression,
|
||||
it is likely much slower than more recent alternatives due to excessive branching.
|
||||
* WAH is a patented variation on BBC that provides better performance.
|
||||
* Concise is a variation on the patented WAH. It some specific instances, it can compress
|
||||
much better than WAH (up to 2x better), but it is generally slower.
|
||||
* EWAH is both free of patent, and it is faster than all the above. On the downside, it
|
||||
does not compress quite as well. It is faster because it allows some form of "skipping"
|
||||
over uncompressed words. So though none of these formats are great at random access, EWAH
|
||||
is better than the alternatives.
|
||||
|
||||
|
||||
|
||||
There is a big problem with these formats however that can hurt you badly in some cases: there is no random access. If you want to check whether a given value is present in the set, you have to start from the beginning and "uncompress" the whole thing. This means that if you want to intersect a big set with a large set, you still have to uncompress the whole big set in the worst case...
|
||||
|
||||
Roaring solves this problem. It works in the following manner. It divides the data into chunks of 2<sup>16</sup> integers
|
||||
(e.g., [0, 2<sup>16</sup>), [2<sup>16</sup>, 2 x 2<sup>16</sup>), ...). Within a chunk, it can use an uncompressed bitmap, a simple list of integers,
|
||||
or a list of runs. Whatever format it uses, they all allow you to check for the present of any one value quickly
|
||||
(e.g., with a binary search). The net result is that Roaring can compute many operations much faster than run-length-encoded
|
||||
formats like WAH, EWAH, Concise... Maybe surprisingly, Roaring also generally offers better compression ratios.
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
### References
|
||||
|
||||
- Daniel Lemire, Owen Kaser, Nathan Kurz, Luca Deri, Chris O'Hara, François Saint-Jacques, Gregory Ssi-Yan-Kai, Roaring Bitmaps: Implementation of an Optimized Software Library, Software: Practice and Experience 48 (4), 2018 [arXiv:1709.07821](https://arxiv.org/abs/1709.07821)
|
||||
- Samy Chambi, Daniel Lemire, Owen Kaser, Robert Godin,
|
||||
Better bitmap performance with Roaring bitmaps,
|
||||
Software: Practice and Experience 46 (5), 2016.
|
||||
http://arxiv.org/abs/1402.6407 This paper used data from http://lemire.me/data/realroaring2014.html
|
||||
- Daniel Lemire, Gregory Ssi-Yan-Kai, Owen Kaser, Consistently faster and smaller compressed bitmaps with Roaring, Software: Practice and Experience 46 (11), 2016. http://arxiv.org/abs/1603.06549
|
||||
|
||||
Software: Practice and Experience 46 (5), 2016.[arXiv:1402.6407](http://arxiv.org/abs/1402.6407) This paper used data from http://lemire.me/data/realroaring2014.html
|
||||
- Daniel Lemire, Gregory Ssi-Yan-Kai, Owen Kaser, Consistently faster and smaller compressed bitmaps with Roaring, Software: Practice and Experience 46 (11), 2016. [arXiv:1603.06549](http://arxiv.org/abs/1603.06549)
|
||||
|
||||
### Dependencies
|
||||
|
||||
Dependencies are fetched automatically by giving the `-t` flag to `go get`.
|
||||
|
||||
they include
|
||||
- github.com/smartystreets/goconvey/convey
|
||||
- github.com/willf/bitset
|
||||
- github.com/bits-and-blooms/bitset
|
||||
- github.com/mschoch/smat
|
||||
- github.com/glycerine/go-unsnap-stream
|
||||
- github.com/philhofer/fwd
|
||||
@@ -74,6 +167,15 @@ Note that the smat library requires Go 1.6 or better.
|
||||
|
||||
- go get -t github.com/RoaringBitmap/roaring
|
||||
|
||||
### Instructions for contributors
|
||||
|
||||
Using bash or other common shells:
|
||||
```
|
||||
$ git clone git@github.com:RoaringBitmap/roaring.git
|
||||
$ export GO111MODULE=on
|
||||
$ go mod tidy
|
||||
$ go test -v
|
||||
```
|
||||
|
||||
### Example
|
||||
|
||||
@@ -166,10 +268,70 @@ That is, given a fixed overhead for the universe size (x), Roaring
|
||||
bitmaps never use more than 2 bytes per integer. You can call
|
||||
``BoundSerializedSizeInBytes`` for a more precise estimate.
|
||||
|
||||
### 64-bit Roaring
|
||||
|
||||
By default, roaring is used to stored unsigned 32-bit integers. However, we also offer
|
||||
an extension dedicated to 64-bit integers. It supports roughly the same functions:
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/RoaringBitmap/roaring/roaring64"
|
||||
"bytes"
|
||||
)
|
||||
|
||||
|
||||
func main() {
|
||||
// example inspired by https://github.com/fzandona/goroar
|
||||
fmt.Println("==roaring64==")
|
||||
rb1 := roaring64.BitmapOf(1, 2, 3, 4, 5, 100, 1000)
|
||||
fmt.Println(rb1.String())
|
||||
|
||||
rb2 := roaring64.BitmapOf(3, 4, 1000)
|
||||
fmt.Println(rb2.String())
|
||||
|
||||
rb3 := roaring64.New()
|
||||
fmt.Println(rb3.String())
|
||||
|
||||
fmt.Println("Cardinality: ", rb1.GetCardinality())
|
||||
|
||||
fmt.Println("Contains 3? ", rb1.Contains(3))
|
||||
|
||||
rb1.And(rb2)
|
||||
|
||||
rb3.Add(1)
|
||||
rb3.Add(5)
|
||||
|
||||
rb3.Or(rb1)
|
||||
|
||||
|
||||
|
||||
// prints 1, 3, 4, 5, 1000
|
||||
i := rb3.Iterator()
|
||||
for i.HasNext() {
|
||||
fmt.Println(i.Next())
|
||||
}
|
||||
fmt.Println()
|
||||
|
||||
// next we include an example of serialization
|
||||
buf := new(bytes.Buffer)
|
||||
rb1.WriteTo(buf) // we omit error handling
|
||||
newrb:= roaring64.New()
|
||||
newrb.ReadFrom(buf)
|
||||
if rb1.Equals(newrb) {
|
||||
fmt.Println("I wrote the content to a byte stream and read it back.")
|
||||
}
|
||||
// you can iterate over bitmaps using ReverseIterator(), Iterator, ManyIterator()
|
||||
}
|
||||
```
|
||||
|
||||
Only the 32-bit roaring format is standard and cross-operable between Java, C++, C and Go. There is no guarantee that the 64-bit versions are compatible.
|
||||
|
||||
### Documentation
|
||||
|
||||
Current documentation is available at http://godoc.org/github.com/RoaringBitmap/roaring
|
||||
Current documentation is available at https://pkg.go.dev/github.com/RoaringBitmap/roaring and https://pkg.go.dev/github.com/RoaringBitmap/roaring/roaring64
|
||||
|
||||
### Goroutine safety
|
||||
|
||||
@@ -207,7 +369,7 @@ You can use roaring with gore:
|
||||
|
||||
- go get -u github.com/motemen/gore
|
||||
- Make sure that ``$GOPATH/bin`` is in your ``$PATH``.
|
||||
- go get github/RoaringBitmap/roaring
|
||||
- go get github.com/RoaringBitmap/roaring
|
||||
|
||||
```go
|
||||
$ gore
|
||||
@@ -228,12 +390,14 @@ You can help us test further the library with fuzzy testing:
|
||||
go get github.com/dvyukov/go-fuzz/go-fuzz-build
|
||||
go test -tags=gofuzz -run=TestGenerateSmatCorpus
|
||||
go-fuzz-build github.com/RoaringBitmap/roaring
|
||||
go-fuzz -bin=./roaring-fuzz.zip -workdir=workdir/ -timeout=200
|
||||
go-fuzz -bin=./roaring-fuzz.zip -workdir=workdir/ -timeout=200 -func FuzzSmat
|
||||
|
||||
Let it run, and if the # of crashers is > 0, check out the reports in
|
||||
the workdir where you should be able to find the panic goroutine stack
|
||||
traces.
|
||||
|
||||
You may also replace `-func FuzzSmat` by `-func FuzzSerializationBuffer` or `-func FuzzSerializationStream`.
|
||||
|
||||
### Alternative in Go
|
||||
|
||||
There is a Go version wrapping the C/C++ implementation https://github.com/RoaringBitmap/gocroaring
|
||||
|
||||
156
vendor/github.com/RoaringBitmap/roaring/arraycontainer.go
generated
vendored
156
vendor/github.com/RoaringBitmap/roaring/arraycontainer.go
generated
vendored
@@ -4,8 +4,6 @@ import (
|
||||
"fmt"
|
||||
)
|
||||
|
||||
//go:generate msgp -unexported
|
||||
|
||||
type arrayContainer struct {
|
||||
content []uint16
|
||||
}
|
||||
@@ -18,13 +16,26 @@ func (ac *arrayContainer) String() string {
|
||||
return s + "}"
|
||||
}
|
||||
|
||||
func (ac *arrayContainer) fillLeastSignificant16bits(x []uint32, i int, mask uint32) {
|
||||
func (ac *arrayContainer) fillLeastSignificant16bits(x []uint32, i int, mask uint32) int {
|
||||
for k := 0; k < len(ac.content); k++ {
|
||||
x[k+i] = uint32(ac.content[k]) | mask
|
||||
}
|
||||
return i + len(ac.content)
|
||||
}
|
||||
|
||||
func (ac *arrayContainer) getShortIterator() shortIterable {
|
||||
func (ac *arrayContainer) iterate(cb func(x uint16) bool) bool {
|
||||
iterator := shortIterator{ac.content, 0}
|
||||
|
||||
for iterator.hasNext() {
|
||||
if !cb(iterator.next()) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
func (ac *arrayContainer) getShortIterator() shortPeekable {
|
||||
return &shortIterator{ac.content, 0}
|
||||
}
|
||||
|
||||
@@ -33,7 +44,7 @@ func (ac *arrayContainer) getReverseIterator() shortIterable {
|
||||
}
|
||||
|
||||
func (ac *arrayContainer) getManyIterator() manyIterable {
|
||||
return &manyIterator{ac.content, 0}
|
||||
return &shortIterator{ac.content, 0}
|
||||
}
|
||||
|
||||
func (ac *arrayContainer) minimum() uint16 {
|
||||
@@ -347,28 +358,17 @@ func (ac *arrayContainer) iorArray(value2 *arrayContainer) container {
|
||||
len1 := value1.getCardinality()
|
||||
len2 := value2.getCardinality()
|
||||
maxPossibleCardinality := len1 + len2
|
||||
if maxPossibleCardinality > arrayDefaultMaxSize { // it could be a bitmap!
|
||||
bc := newBitmapContainer()
|
||||
for k := 0; k < len(value2.content); k++ {
|
||||
v := value2.content[k]
|
||||
i := uint(v) >> 6
|
||||
mask := uint64(1) << (v % 64)
|
||||
bc.bitmap[i] |= mask
|
||||
}
|
||||
for k := 0; k < len(ac.content); k++ {
|
||||
v := ac.content[k]
|
||||
i := uint(v) >> 6
|
||||
mask := uint64(1) << (v % 64)
|
||||
bc.bitmap[i] |= mask
|
||||
}
|
||||
bc.cardinality = int(popcntSlice(bc.bitmap))
|
||||
if bc.cardinality <= arrayDefaultMaxSize {
|
||||
return bc.toArrayContainer()
|
||||
}
|
||||
return bc
|
||||
}
|
||||
if maxPossibleCardinality > cap(value1.content) {
|
||||
newcontent := make([]uint16, 0, maxPossibleCardinality)
|
||||
// doubling the capacity reduces new slice allocations in the case of
|
||||
// repeated calls to iorArray().
|
||||
newSize := 2 * maxPossibleCardinality
|
||||
// the second check is to handle overly large array containers
|
||||
// and should not occur in normal usage,
|
||||
// as all array containers should be at most arrayDefaultMaxSize
|
||||
if newSize > 2*arrayDefaultMaxSize && maxPossibleCardinality <= 2*arrayDefaultMaxSize {
|
||||
newSize = 2 * arrayDefaultMaxSize
|
||||
}
|
||||
newcontent := make([]uint16, 0, newSize)
|
||||
copy(newcontent[len2:maxPossibleCardinality], ac.content[0:len1])
|
||||
ac.content = newcontent
|
||||
} else {
|
||||
@@ -376,6 +376,13 @@ func (ac *arrayContainer) iorArray(value2 *arrayContainer) container {
|
||||
}
|
||||
nl := union2by2(value1.content[len2:maxPossibleCardinality], value2.content, ac.content)
|
||||
ac.content = ac.content[:nl] // reslice to match actual used capacity
|
||||
|
||||
if nl > arrayDefaultMaxSize {
|
||||
// Only converting to a bitmap when arrayDefaultMaxSize
|
||||
// is actually exceeded minimizes conversions in the case of repeated
|
||||
// calls to iorArray().
|
||||
return ac.toBitmapContainer()
|
||||
}
|
||||
return ac
|
||||
}
|
||||
|
||||
@@ -388,11 +395,19 @@ func (ac *arrayContainer) iorBitmap(bc2 *bitmapContainer) container {
|
||||
}
|
||||
|
||||
func (ac *arrayContainer) iorRun16(rc *runContainer16) container {
|
||||
bc1 := ac.toBitmapContainer()
|
||||
bc2 := rc.toBitmapContainer()
|
||||
bc1.iorBitmap(bc2)
|
||||
*ac = *newArrayContainerFromBitmap(bc1)
|
||||
return ac
|
||||
runCardinality := rc.getCardinality()
|
||||
// heuristic for if the container should maybe be an
|
||||
// array container.
|
||||
if runCardinality < ac.getCardinality() &&
|
||||
runCardinality+ac.getCardinality() < arrayDefaultMaxSize {
|
||||
var result container
|
||||
result = ac
|
||||
for _, run := range rc.iv {
|
||||
result = result.iaddRange(int(run.start), int(run.start)+int(run.length)+1)
|
||||
}
|
||||
return result
|
||||
}
|
||||
return rc.orArray(ac)
|
||||
}
|
||||
|
||||
func (ac *arrayContainer) lazyIOR(a container) container {
|
||||
@@ -477,7 +492,7 @@ func (ac *arrayContainer) orArrayCardinality(value2 *arrayContainer) int {
|
||||
func (ac *arrayContainer) lazyorArray(value2 *arrayContainer) container {
|
||||
value1 := ac
|
||||
maxPossibleCardinality := value1.getCardinality() + value2.getCardinality()
|
||||
if maxPossibleCardinality > arrayLazyLowerBound { // it could be a bitmap!^M
|
||||
if maxPossibleCardinality > arrayLazyLowerBound { // it could be a bitmap!
|
||||
bc := newBitmapContainer()
|
||||
for k := 0; k < len(value2.content); k++ {
|
||||
v := value2.content[k]
|
||||
@@ -837,6 +852,10 @@ func (ac *arrayContainer) getCardinality() int {
|
||||
return len(ac.content)
|
||||
}
|
||||
|
||||
func (ac *arrayContainer) isEmpty() bool {
|
||||
return len(ac.content) == 0
|
||||
}
|
||||
|
||||
func (ac *arrayContainer) rank(x uint16) int {
|
||||
answer := binarySearch(ac.content, x)
|
||||
if answer >= 0 {
|
||||
@@ -864,6 +883,41 @@ func (ac *arrayContainer) loadData(bitmapContainer *bitmapContainer) {
|
||||
ac.content = make([]uint16, bitmapContainer.cardinality, bitmapContainer.cardinality)
|
||||
bitmapContainer.fillArray(ac.content)
|
||||
}
|
||||
|
||||
func (ac *arrayContainer) resetTo(a container) {
|
||||
switch x := a.(type) {
|
||||
case *arrayContainer:
|
||||
ac.realloc(len(x.content))
|
||||
copy(ac.content, x.content)
|
||||
|
||||
case *bitmapContainer:
|
||||
ac.realloc(x.cardinality)
|
||||
x.fillArray(ac.content)
|
||||
|
||||
case *runContainer16:
|
||||
card := int(x.getCardinality())
|
||||
ac.realloc(card)
|
||||
cur := 0
|
||||
for _, r := range x.iv {
|
||||
for val := r.start; val <= r.last(); val++ {
|
||||
ac.content[cur] = val
|
||||
cur++
|
||||
}
|
||||
}
|
||||
|
||||
default:
|
||||
panic("unsupported container type")
|
||||
}
|
||||
}
|
||||
|
||||
func (ac *arrayContainer) realloc(size int) {
|
||||
if cap(ac.content) < size {
|
||||
ac.content = make([]uint16, size)
|
||||
} else {
|
||||
ac.content = ac.content[:size]
|
||||
}
|
||||
}
|
||||
|
||||
func newArrayContainer() *arrayContainer {
|
||||
p := new(arrayContainer)
|
||||
return p
|
||||
@@ -915,10 +969,10 @@ func (ac *arrayContainer) numberOfRuns() (nr int) {
|
||||
runlen++
|
||||
} else {
|
||||
if cur < prev {
|
||||
panic("then fundamental arrayContainer assumption of sorted ac.content was broken")
|
||||
panic("the fundamental arrayContainer assumption of sorted ac.content was broken")
|
||||
}
|
||||
if cur == prev {
|
||||
panic("then fundamental arrayContainer assumption of deduplicated content was broken")
|
||||
panic("the fundamental arrayContainer assumption of deduplicated content was broken")
|
||||
} else {
|
||||
nr++
|
||||
runlen = 0
|
||||
@@ -953,16 +1007,42 @@ func (ac *arrayContainer) containerType() contype {
|
||||
return arrayContype
|
||||
}
|
||||
|
||||
func (ac *arrayContainer) addOffset(x uint16) []container {
|
||||
low := &arrayContainer{}
|
||||
high := &arrayContainer{}
|
||||
func (ac *arrayContainer) addOffset(x uint16) (container, container) {
|
||||
var low, high *arrayContainer
|
||||
|
||||
if len(ac.content) == 0 {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
if y := uint32(ac.content[0]) + uint32(x); highbits(y) == 0 {
|
||||
// Some elements will fall into low part, allocate a container.
|
||||
// Checking the first one is enough because they are ordered.
|
||||
low = &arrayContainer{}
|
||||
}
|
||||
if y := uint32(ac.content[len(ac.content)-1]) + uint32(x); highbits(y) > 0 {
|
||||
// Some elements will fall into high part, allocate a container.
|
||||
// Checking the last one is enough because they are ordered.
|
||||
high = &arrayContainer{}
|
||||
}
|
||||
|
||||
for _, val := range ac.content {
|
||||
y := uint32(val) + uint32(x)
|
||||
if highbits(y) > 0 {
|
||||
// OK, if high == nil then highbits(y) == 0 for all y.
|
||||
high.content = append(high.content, lowbits(y))
|
||||
} else {
|
||||
// OK, if low == nil then highbits(y) > 0 for all y.
|
||||
low.content = append(low.content, lowbits(y))
|
||||
}
|
||||
}
|
||||
return []container{low, high}
|
||||
|
||||
// Ensure proper nil interface.
|
||||
if low == nil {
|
||||
return nil, high
|
||||
}
|
||||
if high == nil {
|
||||
return low, nil
|
||||
}
|
||||
|
||||
return low, high
|
||||
}
|
||||
|
||||
134
vendor/github.com/RoaringBitmap/roaring/arraycontainer_gen.go
generated
vendored
134
vendor/github.com/RoaringBitmap/roaring/arraycontainer_gen.go
generated
vendored
@@ -1,134 +0,0 @@
|
||||
package roaring
|
||||
|
||||
// NOTE: THIS FILE WAS PRODUCED BY THE
|
||||
// MSGP CODE GENERATION TOOL (github.com/tinylib/msgp)
|
||||
// DO NOT EDIT
|
||||
|
||||
import "github.com/tinylib/msgp/msgp"
|
||||
|
||||
// Deprecated: DecodeMsg implements msgp.Decodable
|
||||
func (z *arrayContainer) DecodeMsg(dc *msgp.Reader) (err error) {
|
||||
var field []byte
|
||||
_ = field
|
||||
var zbzg uint32
|
||||
zbzg, err = dc.ReadMapHeader()
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
for zbzg > 0 {
|
||||
zbzg--
|
||||
field, err = dc.ReadMapKeyPtr()
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
switch msgp.UnsafeString(field) {
|
||||
case "content":
|
||||
var zbai uint32
|
||||
zbai, err = dc.ReadArrayHeader()
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
if cap(z.content) >= int(zbai) {
|
||||
z.content = (z.content)[:zbai]
|
||||
} else {
|
||||
z.content = make([]uint16, zbai)
|
||||
}
|
||||
for zxvk := range z.content {
|
||||
z.content[zxvk], err = dc.ReadUint16()
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
}
|
||||
default:
|
||||
err = dc.Skip()
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// Deprecated: EncodeMsg implements msgp.Encodable
|
||||
func (z *arrayContainer) EncodeMsg(en *msgp.Writer) (err error) {
|
||||
// map header, size 1
|
||||
// write "content"
|
||||
err = en.Append(0x81, 0xa7, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = en.WriteArrayHeader(uint32(len(z.content)))
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
for zxvk := range z.content {
|
||||
err = en.WriteUint16(z.content[zxvk])
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// Deprecated: MarshalMsg implements msgp.Marshaler
|
||||
func (z *arrayContainer) MarshalMsg(b []byte) (o []byte, err error) {
|
||||
o = msgp.Require(b, z.Msgsize())
|
||||
// map header, size 1
|
||||
// string "content"
|
||||
o = append(o, 0x81, 0xa7, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74)
|
||||
o = msgp.AppendArrayHeader(o, uint32(len(z.content)))
|
||||
for zxvk := range z.content {
|
||||
o = msgp.AppendUint16(o, z.content[zxvk])
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// Deprecated: UnmarshalMsg implements msgp.Unmarshaler
|
||||
func (z *arrayContainer) UnmarshalMsg(bts []byte) (o []byte, err error) {
|
||||
var field []byte
|
||||
_ = field
|
||||
var zcmr uint32
|
||||
zcmr, bts, err = msgp.ReadMapHeaderBytes(bts)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
for zcmr > 0 {
|
||||
zcmr--
|
||||
field, bts, err = msgp.ReadMapKeyZC(bts)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
switch msgp.UnsafeString(field) {
|
||||
case "content":
|
||||
var zajw uint32
|
||||
zajw, bts, err = msgp.ReadArrayHeaderBytes(bts)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
if cap(z.content) >= int(zajw) {
|
||||
z.content = (z.content)[:zajw]
|
||||
} else {
|
||||
z.content = make([]uint16, zajw)
|
||||
}
|
||||
for zxvk := range z.content {
|
||||
z.content[zxvk], bts, err = msgp.ReadUint16Bytes(bts)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
}
|
||||
default:
|
||||
bts, err = msgp.Skip(bts)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
o = bts
|
||||
return
|
||||
}
|
||||
|
||||
// Deprecated: Msgsize returns an upper bound estimate of the number of bytes occupied by the serialized message
|
||||
func (z *arrayContainer) Msgsize() (s int) {
|
||||
s = 1 + 8 + msgp.ArrayHeaderSize + (len(z.content) * (msgp.Uint16Size))
|
||||
return
|
||||
}
|
||||
177
vendor/github.com/RoaringBitmap/roaring/bitmapcontainer.go
generated
vendored
177
vendor/github.com/RoaringBitmap/roaring/bitmapcontainer.go
generated
vendored
@@ -5,8 +5,6 @@ import (
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
//go:generate msgp -unexported
|
||||
|
||||
type bitmapContainer struct {
|
||||
cardinality int
|
||||
bitmap []uint64
|
||||
@@ -96,6 +94,18 @@ func (bc *bitmapContainer) maximum() uint16 {
|
||||
return uint16(0)
|
||||
}
|
||||
|
||||
func (bc *bitmapContainer) iterate(cb func(x uint16) bool) bool {
|
||||
iterator := bitmapContainerShortIterator{bc, bc.NextSetBit(0)}
|
||||
|
||||
for iterator.hasNext() {
|
||||
if !cb(iterator.next()) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
type bitmapContainerShortIterator struct {
|
||||
ptr *bitmapContainer
|
||||
i int
|
||||
@@ -103,18 +113,28 @@ type bitmapContainerShortIterator struct {
|
||||
|
||||
func (bcsi *bitmapContainerShortIterator) next() uint16 {
|
||||
j := bcsi.i
|
||||
bcsi.i = bcsi.ptr.NextSetBit(bcsi.i + 1)
|
||||
bcsi.i = bcsi.ptr.NextSetBit(uint(bcsi.i) + 1)
|
||||
return uint16(j)
|
||||
}
|
||||
func (bcsi *bitmapContainerShortIterator) hasNext() bool {
|
||||
return bcsi.i >= 0
|
||||
}
|
||||
|
||||
func (bcsi *bitmapContainerShortIterator) peekNext() uint16 {
|
||||
return uint16(bcsi.i)
|
||||
}
|
||||
|
||||
func (bcsi *bitmapContainerShortIterator) advanceIfNeeded(minval uint16) {
|
||||
if bcsi.hasNext() && bcsi.peekNext() < minval {
|
||||
bcsi.i = bcsi.ptr.NextSetBit(uint(minval))
|
||||
}
|
||||
}
|
||||
|
||||
func newBitmapContainerShortIterator(a *bitmapContainer) *bitmapContainerShortIterator {
|
||||
return &bitmapContainerShortIterator{a, a.NextSetBit(0)}
|
||||
}
|
||||
|
||||
func (bc *bitmapContainer) getShortIterator() shortIterable {
|
||||
func (bc *bitmapContainer) getShortIterator() shortPeekable {
|
||||
return newBitmapContainerShortIterator(bc)
|
||||
}
|
||||
|
||||
@@ -181,6 +201,33 @@ func (bcmi *bitmapContainerManyIterator) nextMany(hs uint32, buf []uint32) int {
|
||||
return n
|
||||
}
|
||||
|
||||
func (bcmi *bitmapContainerManyIterator) nextMany64(hs uint64, buf []uint64) int {
|
||||
n := 0
|
||||
base := bcmi.base
|
||||
bitset := bcmi.bitset
|
||||
|
||||
for n < len(buf) {
|
||||
if bitset == 0 {
|
||||
base++
|
||||
if base >= len(bcmi.ptr.bitmap) {
|
||||
bcmi.base = base
|
||||
bcmi.bitset = bitset
|
||||
return n
|
||||
}
|
||||
bitset = bcmi.ptr.bitmap[base]
|
||||
continue
|
||||
}
|
||||
t := bitset & -bitset
|
||||
buf[n] = uint64(((base * 64) + int(popcount(t-1)))) | hs
|
||||
n = n + 1
|
||||
bitset ^= t
|
||||
}
|
||||
|
||||
bcmi.base = base
|
||||
bcmi.bitset = bitset
|
||||
return n
|
||||
}
|
||||
|
||||
func newBitmapContainerManyIterator(a *bitmapContainer) *bitmapContainerManyIterator {
|
||||
return &bitmapContainerManyIterator{a, -1, 0}
|
||||
}
|
||||
@@ -217,7 +264,7 @@ func bitmapEquals(a, b []uint64) bool {
|
||||
return true
|
||||
}
|
||||
|
||||
func (bc *bitmapContainer) fillLeastSignificant16bits(x []uint32, i int, mask uint32) {
|
||||
func (bc *bitmapContainer) fillLeastSignificant16bits(x []uint32, i int, mask uint32) int {
|
||||
// TODO: should be written as optimized assembly
|
||||
pos := i
|
||||
base := mask
|
||||
@@ -231,6 +278,7 @@ func (bc *bitmapContainer) fillLeastSignificant16bits(x []uint32, i int, mask ui
|
||||
}
|
||||
base += 64
|
||||
}
|
||||
return pos
|
||||
}
|
||||
|
||||
func (bc *bitmapContainer) equals(o container) bool {
|
||||
@@ -302,6 +350,10 @@ func (bc *bitmapContainer) getCardinality() int {
|
||||
return bc.cardinality
|
||||
}
|
||||
|
||||
func (bc *bitmapContainer) isEmpty() bool {
|
||||
return bc.cardinality == 0
|
||||
}
|
||||
|
||||
func (bc *bitmapContainer) clone() container {
|
||||
ptr := bitmapContainer{bc.cardinality, make([]uint64, len(bc.bitmap))}
|
||||
copy(ptr.bitmap, bc.bitmap[:])
|
||||
@@ -532,11 +584,31 @@ func (bc *bitmapContainer) iorBitmap(value2 *bitmapContainer) container {
|
||||
func (bc *bitmapContainer) lazyIORArray(value2 *arrayContainer) container {
|
||||
answer := bc
|
||||
c := value2.getCardinality()
|
||||
for k := 0; k < c; k++ {
|
||||
for k := 0; k+3 < c; k += 4 {
|
||||
content := (*[4]uint16)(unsafe.Pointer(&value2.content[k]))
|
||||
vc0 := content[0]
|
||||
i0 := uint(vc0) >> 6
|
||||
answer.bitmap[i0] = answer.bitmap[i0] | (uint64(1) << (vc0 % 64))
|
||||
|
||||
vc1 := content[1]
|
||||
i1 := uint(vc1) >> 6
|
||||
answer.bitmap[i1] = answer.bitmap[i1] | (uint64(1) << (vc1 % 64))
|
||||
|
||||
vc2 := content[2]
|
||||
i2 := uint(vc2) >> 6
|
||||
answer.bitmap[i2] = answer.bitmap[i2] | (uint64(1) << (vc2 % 64))
|
||||
|
||||
vc3 := content[3]
|
||||
i3 := uint(vc3) >> 6
|
||||
answer.bitmap[i3] = answer.bitmap[i3] | (uint64(1) << (vc3 % 64))
|
||||
}
|
||||
|
||||
for k := c &^ 3; k < c; k++ {
|
||||
vc := value2.content[k]
|
||||
i := uint(vc) >> 6
|
||||
answer.bitmap[i] = answer.bitmap[i] | (uint64(1) << (vc % 64))
|
||||
}
|
||||
|
||||
answer.cardinality = invalidCardinality
|
||||
return answer
|
||||
}
|
||||
@@ -892,6 +964,32 @@ func (bc *bitmapContainer) loadData(arrayContainer *arrayContainer) {
|
||||
}
|
||||
}
|
||||
|
||||
func (bc *bitmapContainer) resetTo(a container) {
|
||||
switch x := a.(type) {
|
||||
case *arrayContainer:
|
||||
fill(bc.bitmap, 0)
|
||||
bc.loadData(x)
|
||||
|
||||
case *bitmapContainer:
|
||||
bc.cardinality = x.cardinality
|
||||
copy(bc.bitmap, x.bitmap)
|
||||
|
||||
case *runContainer16:
|
||||
bc.cardinality = len(x.iv)
|
||||
lastEnd := 0
|
||||
for _, r := range x.iv {
|
||||
bc.cardinality += int(r.length)
|
||||
resetBitmapRange(bc.bitmap, lastEnd, int(r.start))
|
||||
lastEnd = int(r.start+r.length) + 1
|
||||
setBitmapRange(bc.bitmap, int(r.start), lastEnd)
|
||||
}
|
||||
resetBitmapRange(bc.bitmap, lastEnd, maxCapacity)
|
||||
|
||||
default:
|
||||
panic("unsupported container type")
|
||||
}
|
||||
}
|
||||
|
||||
func (bc *bitmapContainer) toArrayContainer() *arrayContainer {
|
||||
ac := &arrayContainer{}
|
||||
ac.loadData(bc)
|
||||
@@ -914,20 +1012,23 @@ func (bc *bitmapContainer) fillArray(container []uint16) {
|
||||
}
|
||||
}
|
||||
|
||||
func (bc *bitmapContainer) NextSetBit(i int) int {
|
||||
x := i / 64
|
||||
if x >= len(bc.bitmap) {
|
||||
func (bc *bitmapContainer) NextSetBit(i uint) int {
|
||||
var (
|
||||
x = i / 64
|
||||
length = uint(len(bc.bitmap))
|
||||
)
|
||||
if x >= length {
|
||||
return -1
|
||||
}
|
||||
w := bc.bitmap[x]
|
||||
w = w >> uint(i%64)
|
||||
if w != 0 {
|
||||
return i + countTrailingZeros(w)
|
||||
return int(i) + countTrailingZeros(w)
|
||||
}
|
||||
x++
|
||||
for ; x < len(bc.bitmap); x++ {
|
||||
for ; x < length; x++ {
|
||||
if bc.bitmap[x] != 0 {
|
||||
return (x * 64) + countTrailingZeros(bc.bitmap[x])
|
||||
return int(x*64) + countTrailingZeros(bc.bitmap[x])
|
||||
}
|
||||
}
|
||||
return -1
|
||||
@@ -948,7 +1049,7 @@ func (bc *bitmapContainer) PrevSetBit(i int) int {
|
||||
|
||||
w = w << uint(63-b)
|
||||
if w != 0 {
|
||||
return b - countLeadingZeros(w)
|
||||
return i - countLeadingZeros(w)
|
||||
}
|
||||
x--
|
||||
for ; x >= 0; x-- {
|
||||
@@ -1023,34 +1124,60 @@ func (bc *bitmapContainer) containerType() contype {
|
||||
return bitmapContype
|
||||
}
|
||||
|
||||
func (bc *bitmapContainer) addOffset(x uint16) []container {
|
||||
low := newBitmapContainer()
|
||||
high := newBitmapContainer()
|
||||
func (bc *bitmapContainer) addOffset(x uint16) (container, container) {
|
||||
var low, high *bitmapContainer
|
||||
|
||||
if bc.cardinality == 0 {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
b := uint32(x) >> 6
|
||||
i := uint32(x) % 64
|
||||
end := uint32(1024) - b
|
||||
|
||||
low = newBitmapContainer()
|
||||
if i == 0 {
|
||||
copy(low.bitmap[b:], bc.bitmap[:end])
|
||||
copy(high.bitmap[:b], bc.bitmap[end:])
|
||||
} else {
|
||||
low.bitmap[b] = bc.bitmap[0] << i
|
||||
for k := uint32(1); k < end; k++ {
|
||||
newval := bc.bitmap[k] << i
|
||||
if newval == 0 {
|
||||
newval = bc.bitmap[k-1] >> (64 - i)
|
||||
}
|
||||
newval |= bc.bitmap[k-1] >> (64 - i)
|
||||
low.bitmap[b+k] = newval
|
||||
}
|
||||
}
|
||||
low.computeCardinality()
|
||||
|
||||
if low.cardinality == bc.cardinality {
|
||||
// All elements from bc ended up in low, meaning high will be empty.
|
||||
return low, nil
|
||||
}
|
||||
|
||||
if low.cardinality == 0 {
|
||||
// low is empty, let's reuse the container for high.
|
||||
high = low
|
||||
low = nil
|
||||
} else {
|
||||
// None of the containers will be empty, so allocate both.
|
||||
high = newBitmapContainer()
|
||||
}
|
||||
|
||||
if i == 0 {
|
||||
copy(high.bitmap[:b], bc.bitmap[end:])
|
||||
} else {
|
||||
for k := end; k < 1024; k++ {
|
||||
newval := bc.bitmap[k] << i
|
||||
if newval == 0 {
|
||||
newval = bc.bitmap[k-1] >> (64 - i)
|
||||
}
|
||||
newval |= bc.bitmap[k-1] >> (64 - i)
|
||||
high.bitmap[k-end] = newval
|
||||
}
|
||||
high.bitmap[b] = bc.bitmap[1023] >> (64 - i)
|
||||
}
|
||||
low.computeCardinality()
|
||||
high.computeCardinality()
|
||||
return []container{low, high}
|
||||
|
||||
// Ensure proper nil interface.
|
||||
if low == nil {
|
||||
return nil, high
|
||||
}
|
||||
|
||||
return low, high
|
||||
}
|
||||
|
||||
415
vendor/github.com/RoaringBitmap/roaring/bitmapcontainer_gen.go
generated
vendored
415
vendor/github.com/RoaringBitmap/roaring/bitmapcontainer_gen.go
generated
vendored
@@ -1,415 +0,0 @@
|
||||
package roaring
|
||||
|
||||
// NOTE: THIS FILE WAS PRODUCED BY THE
|
||||
// MSGP CODE GENERATION TOOL (github.com/tinylib/msgp)
|
||||
// DO NOT EDIT
|
||||
|
||||
import "github.com/tinylib/msgp/msgp"
|
||||
|
||||
// Deprecated: DecodeMsg implements msgp.Decodable
|
||||
func (z *bitmapContainer) DecodeMsg(dc *msgp.Reader) (err error) {
|
||||
var field []byte
|
||||
_ = field
|
||||
var zbzg uint32
|
||||
zbzg, err = dc.ReadMapHeader()
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
for zbzg > 0 {
|
||||
zbzg--
|
||||
field, err = dc.ReadMapKeyPtr()
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
switch msgp.UnsafeString(field) {
|
||||
case "cardinality":
|
||||
z.cardinality, err = dc.ReadInt()
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
case "bitmap":
|
||||
var zbai uint32
|
||||
zbai, err = dc.ReadArrayHeader()
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
if cap(z.bitmap) >= int(zbai) {
|
||||
z.bitmap = (z.bitmap)[:zbai]
|
||||
} else {
|
||||
z.bitmap = make([]uint64, zbai)
|
||||
}
|
||||
for zxvk := range z.bitmap {
|
||||
z.bitmap[zxvk], err = dc.ReadUint64()
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
}
|
||||
default:
|
||||
err = dc.Skip()
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// Deprecated: EncodeMsg implements msgp.Encodable
|
||||
func (z *bitmapContainer) EncodeMsg(en *msgp.Writer) (err error) {
|
||||
// map header, size 2
|
||||
// write "cardinality"
|
||||
err = en.Append(0x82, 0xab, 0x63, 0x61, 0x72, 0x64, 0x69, 0x6e, 0x61, 0x6c, 0x69, 0x74, 0x79)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = en.WriteInt(z.cardinality)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
// write "bitmap"
|
||||
err = en.Append(0xa6, 0x62, 0x69, 0x74, 0x6d, 0x61, 0x70)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = en.WriteArrayHeader(uint32(len(z.bitmap)))
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
for zxvk := range z.bitmap {
|
||||
err = en.WriteUint64(z.bitmap[zxvk])
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// Deprecated: MarshalMsg implements msgp.Marshaler
|
||||
func (z *bitmapContainer) MarshalMsg(b []byte) (o []byte, err error) {
|
||||
o = msgp.Require(b, z.Msgsize())
|
||||
// map header, size 2
|
||||
// string "cardinality"
|
||||
o = append(o, 0x82, 0xab, 0x63, 0x61, 0x72, 0x64, 0x69, 0x6e, 0x61, 0x6c, 0x69, 0x74, 0x79)
|
||||
o = msgp.AppendInt(o, z.cardinality)
|
||||
// string "bitmap"
|
||||
o = append(o, 0xa6, 0x62, 0x69, 0x74, 0x6d, 0x61, 0x70)
|
||||
o = msgp.AppendArrayHeader(o, uint32(len(z.bitmap)))
|
||||
for zxvk := range z.bitmap {
|
||||
o = msgp.AppendUint64(o, z.bitmap[zxvk])
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// Deprecated: UnmarshalMsg implements msgp.Unmarshaler
|
||||
func (z *bitmapContainer) UnmarshalMsg(bts []byte) (o []byte, err error) {
|
||||
var field []byte
|
||||
_ = field
|
||||
var zcmr uint32
|
||||
zcmr, bts, err = msgp.ReadMapHeaderBytes(bts)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
for zcmr > 0 {
|
||||
zcmr--
|
||||
field, bts, err = msgp.ReadMapKeyZC(bts)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
switch msgp.UnsafeString(field) {
|
||||
case "cardinality":
|
||||
z.cardinality, bts, err = msgp.ReadIntBytes(bts)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
case "bitmap":
|
||||
var zajw uint32
|
||||
zajw, bts, err = msgp.ReadArrayHeaderBytes(bts)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
if cap(z.bitmap) >= int(zajw) {
|
||||
z.bitmap = (z.bitmap)[:zajw]
|
||||
} else {
|
||||
z.bitmap = make([]uint64, zajw)
|
||||
}
|
||||
for zxvk := range z.bitmap {
|
||||
z.bitmap[zxvk], bts, err = msgp.ReadUint64Bytes(bts)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
}
|
||||
default:
|
||||
bts, err = msgp.Skip(bts)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
o = bts
|
||||
return
|
||||
}
|
||||
|
||||
// Deprecated: Msgsize returns an upper bound estimate of the number of bytes occupied by the serialized message
|
||||
func (z *bitmapContainer) Msgsize() (s int) {
|
||||
s = 1 + 12 + msgp.IntSize + 7 + msgp.ArrayHeaderSize + (len(z.bitmap) * (msgp.Uint64Size))
|
||||
return
|
||||
}
|
||||
|
||||
// Deprecated: DecodeMsg implements msgp.Decodable
|
||||
func (z *bitmapContainerShortIterator) DecodeMsg(dc *msgp.Reader) (err error) {
|
||||
var field []byte
|
||||
_ = field
|
||||
var zhct uint32
|
||||
zhct, err = dc.ReadMapHeader()
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
for zhct > 0 {
|
||||
zhct--
|
||||
field, err = dc.ReadMapKeyPtr()
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
switch msgp.UnsafeString(field) {
|
||||
case "ptr":
|
||||
if dc.IsNil() {
|
||||
err = dc.ReadNil()
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
z.ptr = nil
|
||||
} else {
|
||||
if z.ptr == nil {
|
||||
z.ptr = new(bitmapContainer)
|
||||
}
|
||||
var zcua uint32
|
||||
zcua, err = dc.ReadMapHeader()
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
for zcua > 0 {
|
||||
zcua--
|
||||
field, err = dc.ReadMapKeyPtr()
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
switch msgp.UnsafeString(field) {
|
||||
case "cardinality":
|
||||
z.ptr.cardinality, err = dc.ReadInt()
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
case "bitmap":
|
||||
var zxhx uint32
|
||||
zxhx, err = dc.ReadArrayHeader()
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
if cap(z.ptr.bitmap) >= int(zxhx) {
|
||||
z.ptr.bitmap = (z.ptr.bitmap)[:zxhx]
|
||||
} else {
|
||||
z.ptr.bitmap = make([]uint64, zxhx)
|
||||
}
|
||||
for zwht := range z.ptr.bitmap {
|
||||
z.ptr.bitmap[zwht], err = dc.ReadUint64()
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
}
|
||||
default:
|
||||
err = dc.Skip()
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
case "i":
|
||||
z.i, err = dc.ReadInt()
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
default:
|
||||
err = dc.Skip()
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// Deprecated: EncodeMsg implements msgp.Encodable
|
||||
func (z *bitmapContainerShortIterator) EncodeMsg(en *msgp.Writer) (err error) {
|
||||
// map header, size 2
|
||||
// write "ptr"
|
||||
err = en.Append(0x82, 0xa3, 0x70, 0x74, 0x72)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if z.ptr == nil {
|
||||
err = en.WriteNil()
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
} else {
|
||||
// map header, size 2
|
||||
// write "cardinality"
|
||||
err = en.Append(0x82, 0xab, 0x63, 0x61, 0x72, 0x64, 0x69, 0x6e, 0x61, 0x6c, 0x69, 0x74, 0x79)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = en.WriteInt(z.ptr.cardinality)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
// write "bitmap"
|
||||
err = en.Append(0xa6, 0x62, 0x69, 0x74, 0x6d, 0x61, 0x70)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = en.WriteArrayHeader(uint32(len(z.ptr.bitmap)))
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
for zwht := range z.ptr.bitmap {
|
||||
err = en.WriteUint64(z.ptr.bitmap[zwht])
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
// write "i"
|
||||
err = en.Append(0xa1, 0x69)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = en.WriteInt(z.i)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// Deprecated: MarshalMsg implements msgp.Marshaler
|
||||
func (z *bitmapContainerShortIterator) MarshalMsg(b []byte) (o []byte, err error) {
|
||||
o = msgp.Require(b, z.Msgsize())
|
||||
// map header, size 2
|
||||
// string "ptr"
|
||||
o = append(o, 0x82, 0xa3, 0x70, 0x74, 0x72)
|
||||
if z.ptr == nil {
|
||||
o = msgp.AppendNil(o)
|
||||
} else {
|
||||
// map header, size 2
|
||||
// string "cardinality"
|
||||
o = append(o, 0x82, 0xab, 0x63, 0x61, 0x72, 0x64, 0x69, 0x6e, 0x61, 0x6c, 0x69, 0x74, 0x79)
|
||||
o = msgp.AppendInt(o, z.ptr.cardinality)
|
||||
// string "bitmap"
|
||||
o = append(o, 0xa6, 0x62, 0x69, 0x74, 0x6d, 0x61, 0x70)
|
||||
o = msgp.AppendArrayHeader(o, uint32(len(z.ptr.bitmap)))
|
||||
for zwht := range z.ptr.bitmap {
|
||||
o = msgp.AppendUint64(o, z.ptr.bitmap[zwht])
|
||||
}
|
||||
}
|
||||
// string "i"
|
||||
o = append(o, 0xa1, 0x69)
|
||||
o = msgp.AppendInt(o, z.i)
|
||||
return
|
||||
}
|
||||
|
||||
// Deprecated: UnmarshalMsg implements msgp.Unmarshaler
|
||||
func (z *bitmapContainerShortIterator) UnmarshalMsg(bts []byte) (o []byte, err error) {
|
||||
var field []byte
|
||||
_ = field
|
||||
var zlqf uint32
|
||||
zlqf, bts, err = msgp.ReadMapHeaderBytes(bts)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
for zlqf > 0 {
|
||||
zlqf--
|
||||
field, bts, err = msgp.ReadMapKeyZC(bts)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
switch msgp.UnsafeString(field) {
|
||||
case "ptr":
|
||||
if msgp.IsNil(bts) {
|
||||
bts, err = msgp.ReadNilBytes(bts)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
z.ptr = nil
|
||||
} else {
|
||||
if z.ptr == nil {
|
||||
z.ptr = new(bitmapContainer)
|
||||
}
|
||||
var zdaf uint32
|
||||
zdaf, bts, err = msgp.ReadMapHeaderBytes(bts)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
for zdaf > 0 {
|
||||
zdaf--
|
||||
field, bts, err = msgp.ReadMapKeyZC(bts)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
switch msgp.UnsafeString(field) {
|
||||
case "cardinality":
|
||||
z.ptr.cardinality, bts, err = msgp.ReadIntBytes(bts)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
case "bitmap":
|
||||
var zpks uint32
|
||||
zpks, bts, err = msgp.ReadArrayHeaderBytes(bts)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
if cap(z.ptr.bitmap) >= int(zpks) {
|
||||
z.ptr.bitmap = (z.ptr.bitmap)[:zpks]
|
||||
} else {
|
||||
z.ptr.bitmap = make([]uint64, zpks)
|
||||
}
|
||||
for zwht := range z.ptr.bitmap {
|
||||
z.ptr.bitmap[zwht], bts, err = msgp.ReadUint64Bytes(bts)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
}
|
||||
default:
|
||||
bts, err = msgp.Skip(bts)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
case "i":
|
||||
z.i, bts, err = msgp.ReadIntBytes(bts)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
default:
|
||||
bts, err = msgp.Skip(bts)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
o = bts
|
||||
return
|
||||
}
|
||||
|
||||
// Deprecated: Msgsize returns an upper bound estimate of the number of bytes occupied by the serialized message
|
||||
func (z *bitmapContainerShortIterator) Msgsize() (s int) {
|
||||
s = 1 + 4
|
||||
if z.ptr == nil {
|
||||
s += msgp.NilSize
|
||||
} else {
|
||||
s += 1 + 12 + msgp.IntSize + 7 + msgp.ArrayHeaderSize + (len(z.ptr.bitmap) * (msgp.Uint64Size))
|
||||
}
|
||||
s += 2 + msgp.IntSize
|
||||
return
|
||||
}
|
||||
2
vendor/github.com/RoaringBitmap/roaring/clz.go
generated
vendored
2
vendor/github.com/RoaringBitmap/roaring/clz.go
generated
vendored
@@ -1,4 +1,6 @@
|
||||
//go:build go1.9
|
||||
// +build go1.9
|
||||
|
||||
// "go1.9", from Go version 1.9 onward
|
||||
// See https://golang.org/pkg/go/build/#hdr-Build_Constraints
|
||||
|
||||
|
||||
1
vendor/github.com/RoaringBitmap/roaring/clz_compat.go
generated
vendored
1
vendor/github.com/RoaringBitmap/roaring/clz_compat.go
generated
vendored
@@ -1,3 +1,4 @@
|
||||
//go:build !go1.9
|
||||
// +build !go1.9
|
||||
|
||||
package roaring
|
||||
|
||||
2
vendor/github.com/RoaringBitmap/roaring/ctz.go
generated
vendored
2
vendor/github.com/RoaringBitmap/roaring/ctz.go
generated
vendored
@@ -1,4 +1,6 @@
|
||||
//go:build go1.9
|
||||
// +build go1.9
|
||||
|
||||
// "go1.9", from Go version 1.9 onward
|
||||
// See https://golang.org/pkg/go/build/#hdr-Build_Constraints
|
||||
|
||||
|
||||
1
vendor/github.com/RoaringBitmap/roaring/ctz_compat.go
generated
vendored
1
vendor/github.com/RoaringBitmap/roaring/ctz_compat.go
generated
vendored
@@ -1,3 +1,4 @@
|
||||
//go:build !go1.9
|
||||
// +build !go1.9
|
||||
|
||||
package roaring
|
||||
|
||||
140
vendor/github.com/RoaringBitmap/roaring/fastaggregation.go
generated
vendored
140
vendor/github.com/RoaringBitmap/roaring/fastaggregation.go
generated
vendored
@@ -33,15 +33,6 @@ main:
|
||||
s2 = x2.highlowcontainer.getKeyAtIndex(pos2)
|
||||
} else {
|
||||
c1 := x1.highlowcontainer.getContainerAtIndex(pos1)
|
||||
switch t := c1.(type) {
|
||||
case *arrayContainer:
|
||||
c1 = t.toBitmapContainer()
|
||||
case *runContainer16:
|
||||
if !t.isFull() {
|
||||
c1 = t.toBitmapContainer()
|
||||
}
|
||||
}
|
||||
|
||||
answer.highlowcontainer.appendContainer(s1, c1.lazyOR(x2.highlowcontainer.getContainerAtIndex(pos2)), false)
|
||||
pos1++
|
||||
pos2++
|
||||
@@ -89,18 +80,7 @@ main:
|
||||
}
|
||||
s2 = x2.highlowcontainer.getKeyAtIndex(pos2)
|
||||
} else {
|
||||
c1 := x1.highlowcontainer.getContainerAtIndex(pos1)
|
||||
switch t := c1.(type) {
|
||||
case *arrayContainer:
|
||||
c1 = t.toBitmapContainer()
|
||||
case *runContainer16:
|
||||
if !t.isFull() {
|
||||
c1 = t.toBitmapContainer()
|
||||
}
|
||||
case *bitmapContainer:
|
||||
c1 = x1.highlowcontainer.getWritableContainerAtIndex(pos1)
|
||||
}
|
||||
|
||||
c1 := x1.highlowcontainer.getWritableContainerAtIndex(pos1)
|
||||
x1.highlowcontainer.containers[pos1] = c1.lazyIOR(x2.highlowcontainer.getContainerAtIndex(pos2))
|
||||
x1.highlowcontainer.needCopyOnWrite[pos1] = false
|
||||
pos1++
|
||||
@@ -141,6 +121,10 @@ func (x1 *Bitmap) repairAfterLazy() {
|
||||
// FastAnd computes the intersection between many bitmaps quickly
|
||||
// Compared to the And function, it can take many bitmaps as input, thus saving the trouble
|
||||
// of manually calling "And" many times.
|
||||
//
|
||||
// Performance hints: if you have very large and tiny bitmaps,
|
||||
// it may be beneficial performance-wise to put a tiny bitmap
|
||||
// in first position.
|
||||
func FastAnd(bitmaps ...*Bitmap) *Bitmap {
|
||||
if len(bitmaps) == 0 {
|
||||
return NewBitmap()
|
||||
@@ -213,3 +197,117 @@ func HeapXor(bitmaps ...*Bitmap) *Bitmap {
|
||||
}
|
||||
return heap.Pop(&pq).(*item).value
|
||||
}
|
||||
|
||||
// AndAny provides a result equivalent to x1.And(FastOr(bitmaps)).
|
||||
// It's optimized to minimize allocations. It also might be faster than separate calls.
|
||||
func (x1 *Bitmap) AndAny(bitmaps ...*Bitmap) {
|
||||
if len(bitmaps) == 0 {
|
||||
return
|
||||
} else if len(bitmaps) == 1 {
|
||||
x1.And(bitmaps[0])
|
||||
return
|
||||
}
|
||||
|
||||
type withPos struct {
|
||||
bitmap *roaringArray
|
||||
pos int
|
||||
key uint16
|
||||
}
|
||||
filters := make([]withPos, 0, len(bitmaps))
|
||||
|
||||
for _, b := range bitmaps {
|
||||
if b.highlowcontainer.size() > 0 {
|
||||
filters = append(filters, withPos{
|
||||
bitmap: &b.highlowcontainer,
|
||||
pos: 0,
|
||||
key: b.highlowcontainer.getKeyAtIndex(0),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
basePos := 0
|
||||
intersections := 0
|
||||
keyContainers := make([]container, 0, len(filters))
|
||||
var (
|
||||
tmpArray *arrayContainer
|
||||
tmpBitmap *bitmapContainer
|
||||
minNextKey uint16
|
||||
)
|
||||
|
||||
for basePos < x1.highlowcontainer.size() && len(filters) > 0 {
|
||||
baseKey := x1.highlowcontainer.getKeyAtIndex(basePos)
|
||||
|
||||
// accumulate containers for current key, find next minimal key in filters
|
||||
// and exclude filters that do not have related values anymore
|
||||
i := 0
|
||||
maxPossibleOr := 0
|
||||
minNextKey = MaxUint16
|
||||
for _, f := range filters {
|
||||
if f.key < baseKey {
|
||||
f.pos = f.bitmap.advanceUntil(baseKey, f.pos)
|
||||
if f.pos == f.bitmap.size() {
|
||||
continue
|
||||
}
|
||||
f.key = f.bitmap.getKeyAtIndex(f.pos)
|
||||
}
|
||||
|
||||
if f.key == baseKey {
|
||||
cont := f.bitmap.getContainerAtIndex(f.pos)
|
||||
keyContainers = append(keyContainers, cont)
|
||||
maxPossibleOr += cont.getCardinality()
|
||||
|
||||
f.pos++
|
||||
if f.pos == f.bitmap.size() {
|
||||
continue
|
||||
}
|
||||
f.key = f.bitmap.getKeyAtIndex(f.pos)
|
||||
}
|
||||
|
||||
minNextKey = minOfUint16(minNextKey, f.key)
|
||||
filters[i] = f
|
||||
i++
|
||||
}
|
||||
filters = filters[:i]
|
||||
|
||||
if len(keyContainers) == 0 {
|
||||
basePos = x1.highlowcontainer.advanceUntil(minNextKey, basePos)
|
||||
continue
|
||||
}
|
||||
|
||||
var ored container
|
||||
|
||||
if len(keyContainers) == 1 {
|
||||
ored = keyContainers[0]
|
||||
} else {
|
||||
//TODO: special case for run containers?
|
||||
if maxPossibleOr > arrayDefaultMaxSize {
|
||||
if tmpBitmap == nil {
|
||||
tmpBitmap = newBitmapContainer()
|
||||
}
|
||||
tmpBitmap.resetTo(keyContainers[0])
|
||||
ored = tmpBitmap
|
||||
} else {
|
||||
if tmpArray == nil {
|
||||
tmpArray = newArrayContainerCapacity(maxPossibleOr)
|
||||
}
|
||||
tmpArray.realloc(maxPossibleOr)
|
||||
tmpArray.resetTo(keyContainers[0])
|
||||
ored = tmpArray
|
||||
}
|
||||
for _, c := range keyContainers[1:] {
|
||||
ored = ored.ior(c)
|
||||
}
|
||||
}
|
||||
|
||||
result := x1.highlowcontainer.getWritableContainerAtIndex(basePos).iand(ored)
|
||||
if !result.isEmpty() {
|
||||
x1.highlowcontainer.replaceKeyAndContainerAtIndex(intersections, baseKey, result, false)
|
||||
intersections++
|
||||
}
|
||||
|
||||
keyContainers = keyContainers[:0]
|
||||
basePos = x1.highlowcontainer.advanceUntil(minNextKey, basePos)
|
||||
}
|
||||
|
||||
x1.highlowcontainer.resize(intersections)
|
||||
}
|
||||
|
||||
166
vendor/github.com/RoaringBitmap/roaring/internal/byte_input.go
generated
vendored
Normal file
166
vendor/github.com/RoaringBitmap/roaring/internal/byte_input.go
generated
vendored
Normal file
@@ -0,0 +1,166 @@
|
||||
package internal
|
||||
|
||||
import (
|
||||
"encoding/binary"
|
||||
"io"
|
||||
)
|
||||
|
||||
// ByteInput typed interface around io.Reader or raw bytes
|
||||
type ByteInput interface {
|
||||
// Next returns a slice containing the next n bytes from the buffer,
|
||||
// advancing the buffer as if the bytes had been returned by Read.
|
||||
Next(n int) ([]byte, error)
|
||||
// ReadUInt32 reads uint32 with LittleEndian order
|
||||
ReadUInt32() (uint32, error)
|
||||
// ReadUInt16 reads uint16 with LittleEndian order
|
||||
ReadUInt16() (uint16, error)
|
||||
// GetReadBytes returns read bytes
|
||||
GetReadBytes() int64
|
||||
// SkipBytes skips exactly n bytes
|
||||
SkipBytes(n int) error
|
||||
}
|
||||
|
||||
// NewByteInputFromReader creates reader wrapper
|
||||
func NewByteInputFromReader(reader io.Reader) ByteInput {
|
||||
return &ByteInputAdapter{
|
||||
r: reader,
|
||||
readBytes: 0,
|
||||
}
|
||||
}
|
||||
|
||||
// NewByteInput creates raw bytes wrapper
|
||||
func NewByteInput(buf []byte) ByteInput {
|
||||
return &ByteBuffer{
|
||||
buf: buf,
|
||||
off: 0,
|
||||
}
|
||||
}
|
||||
|
||||
// ByteBuffer raw bytes wrapper
|
||||
type ByteBuffer struct {
|
||||
buf []byte
|
||||
off int
|
||||
}
|
||||
|
||||
// Next returns a slice containing the next n bytes from the reader
|
||||
// If there are fewer bytes than the given n, io.ErrUnexpectedEOF will be returned
|
||||
func (b *ByteBuffer) Next(n int) ([]byte, error) {
|
||||
m := len(b.buf) - b.off
|
||||
|
||||
if n > m {
|
||||
return nil, io.ErrUnexpectedEOF
|
||||
}
|
||||
|
||||
data := b.buf[b.off : b.off+n]
|
||||
b.off += n
|
||||
|
||||
return data, nil
|
||||
}
|
||||
|
||||
// ReadUInt32 reads uint32 with LittleEndian order
|
||||
func (b *ByteBuffer) ReadUInt32() (uint32, error) {
|
||||
if len(b.buf)-b.off < 4 {
|
||||
return 0, io.ErrUnexpectedEOF
|
||||
}
|
||||
|
||||
v := binary.LittleEndian.Uint32(b.buf[b.off:])
|
||||
b.off += 4
|
||||
|
||||
return v, nil
|
||||
}
|
||||
|
||||
// ReadUInt16 reads uint16 with LittleEndian order
|
||||
func (b *ByteBuffer) ReadUInt16() (uint16, error) {
|
||||
if len(b.buf)-b.off < 2 {
|
||||
return 0, io.ErrUnexpectedEOF
|
||||
}
|
||||
|
||||
v := binary.LittleEndian.Uint16(b.buf[b.off:])
|
||||
b.off += 2
|
||||
|
||||
return v, nil
|
||||
}
|
||||
|
||||
// GetReadBytes returns read bytes
|
||||
func (b *ByteBuffer) GetReadBytes() int64 {
|
||||
return int64(b.off)
|
||||
}
|
||||
|
||||
// SkipBytes skips exactly n bytes
|
||||
func (b *ByteBuffer) SkipBytes(n int) error {
|
||||
m := len(b.buf) - b.off
|
||||
|
||||
if n > m {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
|
||||
b.off += n
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// Reset resets the given buffer with a new byte slice
|
||||
func (b *ByteBuffer) Reset(buf []byte) {
|
||||
b.buf = buf
|
||||
b.off = 0
|
||||
}
|
||||
|
||||
// ByteInputAdapter reader wrapper
|
||||
type ByteInputAdapter struct {
|
||||
r io.Reader
|
||||
readBytes int
|
||||
}
|
||||
|
||||
// Next returns a slice containing the next n bytes from the buffer,
|
||||
// advancing the buffer as if the bytes had been returned by Read.
|
||||
func (b *ByteInputAdapter) Next(n int) ([]byte, error) {
|
||||
buf := make([]byte, n)
|
||||
m, err := io.ReadAtLeast(b.r, buf, n)
|
||||
b.readBytes += m
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return buf, nil
|
||||
}
|
||||
|
||||
// ReadUInt32 reads uint32 with LittleEndian order
|
||||
func (b *ByteInputAdapter) ReadUInt32() (uint32, error) {
|
||||
buf, err := b.Next(4)
|
||||
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
return binary.LittleEndian.Uint32(buf), nil
|
||||
}
|
||||
|
||||
// ReadUInt16 reads uint16 with LittleEndian order
|
||||
func (b *ByteInputAdapter) ReadUInt16() (uint16, error) {
|
||||
buf, err := b.Next(2)
|
||||
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
return binary.LittleEndian.Uint16(buf), nil
|
||||
}
|
||||
|
||||
// GetReadBytes returns read bytes
|
||||
func (b *ByteInputAdapter) GetReadBytes() int64 {
|
||||
return int64(b.readBytes)
|
||||
}
|
||||
|
||||
// SkipBytes skips exactly n bytes
|
||||
func (b *ByteInputAdapter) SkipBytes(n int) error {
|
||||
_, err := b.Next(n)
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
// Reset resets the given buffer with a new stream
|
||||
func (b *ByteInputAdapter) Reset(stream io.Reader) {
|
||||
b.r = stream
|
||||
b.readBytes = 0
|
||||
}
|
||||
21
vendor/github.com/RoaringBitmap/roaring/internal/pools.go
generated
vendored
Normal file
21
vendor/github.com/RoaringBitmap/roaring/internal/pools.go
generated
vendored
Normal file
@@ -0,0 +1,21 @@
|
||||
package internal
|
||||
|
||||
import (
|
||||
"sync"
|
||||
)
|
||||
|
||||
var (
|
||||
// ByteInputAdapterPool shared pool
|
||||
ByteInputAdapterPool = sync.Pool{
|
||||
New: func() interface{} {
|
||||
return &ByteInputAdapter{}
|
||||
},
|
||||
}
|
||||
|
||||
// ByteBufferPool shared pool
|
||||
ByteBufferPool = sync.Pool{
|
||||
New: func() interface{} {
|
||||
return &ByteBuffer{}
|
||||
},
|
||||
}
|
||||
)
|
||||
21
vendor/github.com/RoaringBitmap/roaring/manyiterator.go
generated
vendored
21
vendor/github.com/RoaringBitmap/roaring/manyiterator.go
generated
vendored
@@ -2,14 +2,10 @@ package roaring
|
||||
|
||||
type manyIterable interface {
|
||||
nextMany(hs uint32, buf []uint32) int
|
||||
nextMany64(hs uint64, buf []uint64) int
|
||||
}
|
||||
|
||||
type manyIterator struct {
|
||||
slice []uint16
|
||||
loc int
|
||||
}
|
||||
|
||||
func (si *manyIterator) nextMany(hs uint32, buf []uint32) int {
|
||||
func (si *shortIterator) nextMany(hs uint32, buf []uint32) int {
|
||||
n := 0
|
||||
l := si.loc
|
||||
s := si.slice
|
||||
@@ -21,3 +17,16 @@ func (si *manyIterator) nextMany(hs uint32, buf []uint32) int {
|
||||
si.loc = l
|
||||
return n
|
||||
}
|
||||
|
||||
func (si *shortIterator) nextMany64(hs uint64, buf []uint64) int {
|
||||
n := 0
|
||||
l := si.loc
|
||||
s := si.slice
|
||||
for n < len(buf) && l < len(s) {
|
||||
buf[n] = uint64(s[l]) | hs
|
||||
l++
|
||||
n++
|
||||
}
|
||||
si.loc = l
|
||||
return n
|
||||
}
|
||||
|
||||
9
vendor/github.com/RoaringBitmap/roaring/parallel.go
generated
vendored
9
vendor/github.com/RoaringBitmap/roaring/parallel.go
generated
vendored
@@ -166,7 +166,6 @@ func appenderRoutine(bitmapChan chan<- *Bitmap, resultChan <-chan keyedContainer
|
||||
make([]container, 0, expectedKeys),
|
||||
make([]bool, 0, expectedKeys),
|
||||
false,
|
||||
nil,
|
||||
},
|
||||
}
|
||||
for i := range keys {
|
||||
@@ -286,14 +285,14 @@ func ParAnd(parallelism int, bitmaps ...*Bitmap) *Bitmap {
|
||||
for input := range inputChan {
|
||||
c := input.containers[0].and(input.containers[1])
|
||||
for _, next := range input.containers[2:] {
|
||||
if c.getCardinality() == 0 {
|
||||
if c.isEmpty() {
|
||||
break
|
||||
}
|
||||
c = c.iand(next)
|
||||
}
|
||||
|
||||
// Send a nil explicitly if the result of the intersection is an empty container
|
||||
if c.getCardinality() == 0 {
|
||||
if c.isEmpty() {
|
||||
c = nil
|
||||
}
|
||||
|
||||
@@ -355,10 +354,10 @@ func ParOr(parallelism int, bitmaps ...*Bitmap) *Bitmap {
|
||||
if lKey == MaxUint16 && hKey == 0 {
|
||||
return New()
|
||||
} else if len(bitmaps) == 1 {
|
||||
return bitmaps[0]
|
||||
return bitmaps[0].Clone()
|
||||
}
|
||||
|
||||
keyRange := hKey - lKey + 1
|
||||
keyRange := int(hKey) - int(lKey) + 1
|
||||
if keyRange == 1 {
|
||||
// revert to FastOr. Since the key range is 0
|
||||
// no container-level aggregation parallelism is achievable
|
||||
|
||||
2
vendor/github.com/RoaringBitmap/roaring/popcnt.go
generated
vendored
2
vendor/github.com/RoaringBitmap/roaring/popcnt.go
generated
vendored
@@ -1,4 +1,6 @@
|
||||
//go:build go1.9
|
||||
// +build go1.9
|
||||
|
||||
// "go1.9", from Go version 1.9 onward
|
||||
// See https://golang.org/pkg/go/build/#hdr-Build_Constraints
|
||||
|
||||
|
||||
1
vendor/github.com/RoaringBitmap/roaring/popcnt_asm.go
generated
vendored
1
vendor/github.com/RoaringBitmap/roaring/popcnt_asm.go
generated
vendored
@@ -1,3 +1,4 @@
|
||||
//go:build amd64 && !appengine && !go1.9
|
||||
// +build amd64,!appengine,!go1.9
|
||||
|
||||
package roaring
|
||||
|
||||
1
vendor/github.com/RoaringBitmap/roaring/popcnt_compat.go
generated
vendored
1
vendor/github.com/RoaringBitmap/roaring/popcnt_compat.go
generated
vendored
@@ -1,3 +1,4 @@
|
||||
//go:build !go1.9
|
||||
// +build !go1.9
|
||||
|
||||
package roaring
|
||||
|
||||
1
vendor/github.com/RoaringBitmap/roaring/popcnt_generic.go
generated
vendored
1
vendor/github.com/RoaringBitmap/roaring/popcnt_generic.go
generated
vendored
@@ -1,3 +1,4 @@
|
||||
//go:build !amd64 || appengine || go1.9
|
||||
// +build !amd64 appengine go1.9
|
||||
|
||||
package roaring
|
||||
|
||||
500
vendor/github.com/RoaringBitmap/roaring/roaring.go
generated
vendored
500
vendor/github.com/RoaringBitmap/roaring/roaring.go
generated
vendored
@@ -6,12 +6,13 @@
|
||||
package roaring
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"bytes"
|
||||
"encoding/base64"
|
||||
"fmt"
|
||||
"io"
|
||||
"strconv"
|
||||
|
||||
"github.com/RoaringBitmap/roaring/internal"
|
||||
)
|
||||
|
||||
// Bitmap represents a compressed bitmap where you can add integers.
|
||||
@@ -52,23 +53,74 @@ func (rb *Bitmap) ToBytes() ([]byte, error) {
|
||||
return rb.highlowcontainer.toBytes()
|
||||
}
|
||||
|
||||
// Deprecated: WriteToMsgpack writes a msgpack2/snappy-streaming compressed serialized
|
||||
// version of this bitmap to stream. The format is not
|
||||
// compatible with the WriteTo() format, and is
|
||||
// experimental: it may produce smaller on disk
|
||||
// footprint and/or be faster to read, depending
|
||||
// on your content. Currently only the Go roaring
|
||||
// implementation supports this format.
|
||||
func (rb *Bitmap) WriteToMsgpack(stream io.Writer) (int64, error) {
|
||||
return 0, rb.highlowcontainer.writeToMsgpack(stream)
|
||||
// Checksum computes a hash (currently FNV-1a) for a bitmap that is suitable for
|
||||
// using bitmaps as elements in hash sets or as keys in hash maps, as well as
|
||||
// generally quicker comparisons.
|
||||
// The implementation is biased towards efficiency in little endian machines, so
|
||||
// expect some extra CPU cycles and memory to be used if your machine is big endian.
|
||||
// Likewise, don't use this to verify integrity unless you're certain you'll load
|
||||
// the bitmap on a machine with the same endianess used to create it.
|
||||
func (rb *Bitmap) Checksum() uint64 {
|
||||
const (
|
||||
offset = 14695981039346656037
|
||||
prime = 1099511628211
|
||||
)
|
||||
|
||||
var bytes []byte
|
||||
|
||||
hash := uint64(offset)
|
||||
|
||||
bytes = uint16SliceAsByteSlice(rb.highlowcontainer.keys)
|
||||
|
||||
for _, b := range bytes {
|
||||
hash ^= uint64(b)
|
||||
hash *= prime
|
||||
}
|
||||
|
||||
for _, c := range rb.highlowcontainer.containers {
|
||||
// 0 separator
|
||||
hash ^= 0
|
||||
hash *= prime
|
||||
|
||||
switch c := c.(type) {
|
||||
case *bitmapContainer:
|
||||
bytes = uint64SliceAsByteSlice(c.bitmap)
|
||||
case *arrayContainer:
|
||||
bytes = uint16SliceAsByteSlice(c.content)
|
||||
case *runContainer16:
|
||||
bytes = interval16SliceAsByteSlice(c.iv)
|
||||
default:
|
||||
panic("invalid container type")
|
||||
}
|
||||
|
||||
if len(bytes) == 0 {
|
||||
panic("empty containers are not supported")
|
||||
}
|
||||
|
||||
for _, b := range bytes {
|
||||
hash ^= uint64(b)
|
||||
hash *= prime
|
||||
}
|
||||
}
|
||||
|
||||
return hash
|
||||
}
|
||||
|
||||
// ReadFrom reads a serialized version of this bitmap from stream.
|
||||
// The format is compatible with other RoaringBitmap
|
||||
// implementations (Java, C) and is documented here:
|
||||
// https://github.com/RoaringBitmap/RoaringFormatSpec
|
||||
func (rb *Bitmap) ReadFrom(stream io.Reader) (int64, error) {
|
||||
return rb.highlowcontainer.readFrom(stream)
|
||||
// Since io.Reader is regarded as a stream and cannot be read twice.
|
||||
// So add cookieHeader to accept the 4-byte data that has been read in roaring64.ReadFrom.
|
||||
// It is not necessary to pass cookieHeader when call roaring.ReadFrom to read the roaring32 data directly.
|
||||
func (rb *Bitmap) ReadFrom(reader io.Reader, cookieHeader ...byte) (p int64, err error) {
|
||||
stream := internal.ByteInputAdapterPool.Get().(*internal.ByteInputAdapter)
|
||||
stream.Reset(reader)
|
||||
|
||||
p, err = rb.highlowcontainer.readFrom(stream, cookieHeader...)
|
||||
internal.ByteInputAdapterPool.Put(stream)
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// FromBuffer creates a bitmap from its serialized version stored in buffer
|
||||
@@ -87,8 +139,20 @@ func (rb *Bitmap) ReadFrom(stream io.Reader) (int64, error) {
|
||||
// You should *not* change the copy-on-write status of the resulting
|
||||
// bitmaps (SetCopyOnWrite).
|
||||
//
|
||||
func (rb *Bitmap) FromBuffer(buf []byte) (int64, error) {
|
||||
return rb.highlowcontainer.fromBuffer(buf)
|
||||
// If buf becomes unavailable, then a bitmap created with
|
||||
// FromBuffer would be effectively broken. Furthermore, any
|
||||
// bitmap derived from this bitmap (e.g., via Or, And) might
|
||||
// also be broken. Thus, before making buf unavailable, you should
|
||||
// call CloneCopyOnWriteContainers on all such bitmaps.
|
||||
//
|
||||
func (rb *Bitmap) FromBuffer(buf []byte) (p int64, err error) {
|
||||
stream := internal.ByteBufferPool.Get().(*internal.ByteBuffer)
|
||||
stream.Reset(buf)
|
||||
|
||||
p, err = rb.highlowcontainer.readFrom(stream)
|
||||
internal.ByteBufferPool.Put(stream)
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// RunOptimize attempts to further compress the runs of consecutive values found in the bitmap
|
||||
@@ -101,38 +165,16 @@ func (rb *Bitmap) HasRunCompression() bool {
|
||||
return rb.highlowcontainer.hasRunCompression()
|
||||
}
|
||||
|
||||
// Deprecated: ReadFromMsgpack reads a msgpack2/snappy-streaming serialized
|
||||
// version of this bitmap from stream. The format is
|
||||
// expected is that written by the WriteToMsgpack()
|
||||
// call; see additional notes there.
|
||||
func (rb *Bitmap) ReadFromMsgpack(stream io.Reader) (int64, error) {
|
||||
return 0, rb.highlowcontainer.readFromMsgpack(stream)
|
||||
}
|
||||
|
||||
// MarshalBinary implements the encoding.BinaryMarshaler interface for the bitmap
|
||||
// (same as ToBytes)
|
||||
func (rb *Bitmap) MarshalBinary() ([]byte, error) {
|
||||
var buf bytes.Buffer
|
||||
writer := bufio.NewWriter(&buf)
|
||||
_, err := rb.WriteTo(writer)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
err = writer.Flush()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return buf.Bytes(), nil
|
||||
return rb.ToBytes()
|
||||
}
|
||||
|
||||
// UnmarshalBinary implements the encoding.BinaryUnmarshaler interface for the bitmap
|
||||
func (rb *Bitmap) UnmarshalBinary(data []byte) error {
|
||||
var buf bytes.Buffer
|
||||
_, err := buf.Write(data)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
reader := bufio.NewReader(&buf)
|
||||
_, err = rb.ReadFrom(reader)
|
||||
r := bytes.NewReader(data)
|
||||
_, err := rb.ReadFrom(r)
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -162,8 +204,7 @@ func (rb *Bitmap) ToArray() []uint32 {
|
||||
hs := uint32(rb.highlowcontainer.getKeyAtIndex(pos)) << 16
|
||||
c := rb.highlowcontainer.getContainerAtIndex(pos)
|
||||
pos++
|
||||
c.fillLeastSignificant16bits(array, pos2, hs)
|
||||
pos2 += c.getCardinality()
|
||||
pos2 = c.fillLeastSignificant16bits(array, pos2, hs)
|
||||
}
|
||||
return array
|
||||
}
|
||||
@@ -215,11 +256,29 @@ type IntIterable interface {
|
||||
Next() uint32
|
||||
}
|
||||
|
||||
// IntPeekable allows you to look at the next value without advancing and
|
||||
// advance as long as the next value is smaller than minval
|
||||
type IntPeekable interface {
|
||||
IntIterable
|
||||
// PeekNext peeks the next value without advancing the iterator
|
||||
PeekNext() uint32
|
||||
// AdvanceIfNeeded advances as long as the next value is smaller than minval
|
||||
AdvanceIfNeeded(minval uint32)
|
||||
}
|
||||
|
||||
type intIterator struct {
|
||||
pos int
|
||||
hs uint32
|
||||
iter shortIterable
|
||||
iter shortPeekable
|
||||
highlowcontainer *roaringArray
|
||||
|
||||
// These embedded iterators per container type help reduce load in the GC.
|
||||
// This way, instead of making up-to 64k allocations per full iteration
|
||||
// we get a single allocation and simply reinitialize the appropriate
|
||||
// iterator and point to it in the generic `iter` member on each key bound.
|
||||
shortIter shortIterator
|
||||
runIter runIterator16
|
||||
bitmapIter bitmapContainerShortIterator
|
||||
}
|
||||
|
||||
// HasNext returns true if there are more integers to iterate over
|
||||
@@ -229,8 +288,19 @@ func (ii *intIterator) HasNext() bool {
|
||||
|
||||
func (ii *intIterator) init() {
|
||||
if ii.highlowcontainer.size() > ii.pos {
|
||||
ii.iter = ii.highlowcontainer.getContainerAtIndex(ii.pos).getShortIterator()
|
||||
ii.hs = uint32(ii.highlowcontainer.getKeyAtIndex(ii.pos)) << 16
|
||||
c := ii.highlowcontainer.getContainerAtIndex(ii.pos)
|
||||
switch t := c.(type) {
|
||||
case *arrayContainer:
|
||||
ii.shortIter = shortIterator{t.content, 0}
|
||||
ii.iter = &ii.shortIter
|
||||
case *runContainer16:
|
||||
ii.runIter = runIterator16{rc: t, curIndex: 0, curPosInIndex: 0}
|
||||
ii.iter = &ii.runIter
|
||||
case *bitmapContainer:
|
||||
ii.bitmapIter = bitmapContainerShortIterator{t, t.NextSetBit(0)}
|
||||
ii.iter = &ii.bitmapIter
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -244,12 +314,41 @@ func (ii *intIterator) Next() uint32 {
|
||||
return x
|
||||
}
|
||||
|
||||
func newIntIterator(a *Bitmap) *intIterator {
|
||||
p := new(intIterator)
|
||||
// PeekNext peeks the next value without advancing the iterator
|
||||
func (ii *intIterator) PeekNext() uint32 {
|
||||
return uint32(ii.iter.peekNext()&maxLowBit) | ii.hs
|
||||
}
|
||||
|
||||
// AdvanceIfNeeded advances as long as the next value is smaller than minval
|
||||
func (ii *intIterator) AdvanceIfNeeded(minval uint32) {
|
||||
to := minval & 0xffff0000
|
||||
|
||||
for ii.HasNext() && ii.hs < to {
|
||||
ii.pos++
|
||||
ii.init()
|
||||
}
|
||||
|
||||
if ii.HasNext() && ii.hs == to {
|
||||
ii.iter.advanceIfNeeded(lowbits(minval))
|
||||
|
||||
if !ii.iter.hasNext() {
|
||||
ii.pos++
|
||||
ii.init()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// IntIterator is meant to allow you to iterate through the values of a bitmap, see Initialize(a *Bitmap)
|
||||
type IntIterator = intIterator
|
||||
|
||||
|
||||
// Initialize configures the existing iterator so that it can iterate through the values of
|
||||
// the provided bitmap.
|
||||
// The iteration results are undefined if the bitmap is modified (e.g., with Add or Remove).
|
||||
func (p *intIterator) Initialize(a *Bitmap) {
|
||||
p.pos = 0
|
||||
p.highlowcontainer = &a.highlowcontainer
|
||||
p.init()
|
||||
return p
|
||||
}
|
||||
|
||||
type intReverseIterator struct {
|
||||
@@ -257,6 +356,10 @@ type intReverseIterator struct {
|
||||
hs uint32
|
||||
iter shortIterable
|
||||
highlowcontainer *roaringArray
|
||||
|
||||
shortIter reverseIterator
|
||||
runIter runReverseIterator16
|
||||
bitmapIter reverseBitmapContainerShortIterator
|
||||
}
|
||||
|
||||
// HasNext returns true if there are more integers to iterate over
|
||||
@@ -266,8 +369,30 @@ func (ii *intReverseIterator) HasNext() bool {
|
||||
|
||||
func (ii *intReverseIterator) init() {
|
||||
if ii.pos >= 0 {
|
||||
ii.iter = ii.highlowcontainer.getContainerAtIndex(ii.pos).getReverseIterator()
|
||||
ii.hs = uint32(ii.highlowcontainer.getKeyAtIndex(ii.pos)) << 16
|
||||
c := ii.highlowcontainer.getContainerAtIndex(ii.pos)
|
||||
switch t := c.(type) {
|
||||
case *arrayContainer:
|
||||
ii.shortIter = reverseIterator{t.content, len(t.content) - 1}
|
||||
ii.iter = &ii.shortIter
|
||||
case *runContainer16:
|
||||
index := int(len(t.iv)) - 1
|
||||
pos := uint16(0)
|
||||
|
||||
if index >= 0 {
|
||||
pos = t.iv[index].length
|
||||
}
|
||||
|
||||
ii.runIter = runReverseIterator16{rc: t, curIndex: index, curPosInIndex: pos}
|
||||
ii.iter = &ii.runIter
|
||||
case *bitmapContainer:
|
||||
pos := -1
|
||||
if t.cardinality > 0 {
|
||||
pos = int(t.maximum())
|
||||
}
|
||||
ii.bitmapIter = reverseBitmapContainerShortIterator{t, pos}
|
||||
ii.iter = &ii.bitmapIter
|
||||
}
|
||||
} else {
|
||||
ii.iter = nil
|
||||
}
|
||||
@@ -283,18 +408,24 @@ func (ii *intReverseIterator) Next() uint32 {
|
||||
return x
|
||||
}
|
||||
|
||||
func newIntReverseIterator(a *Bitmap) *intReverseIterator {
|
||||
p := new(intReverseIterator)
|
||||
// IntReverseIterator is meant to allow you to iterate through the values of a bitmap, see Initialize(a *Bitmap)
|
||||
type IntReverseIterator = intReverseIterator
|
||||
|
||||
// Initialize configures the existing iterator so that it can iterate through the values of
|
||||
// the provided bitmap.
|
||||
// The iteration results are undefined if the bitmap is modified (e.g., with Add or Remove).
|
||||
func (p *intReverseIterator) Initialize(a *Bitmap) {
|
||||
p.highlowcontainer = &a.highlowcontainer
|
||||
p.pos = a.highlowcontainer.size() - 1
|
||||
p.init()
|
||||
return p
|
||||
}
|
||||
|
||||
// ManyIntIterable allows you to iterate over the values in a Bitmap
|
||||
type ManyIntIterable interface {
|
||||
// pass in a buffer to fill up with values, returns how many values were returned
|
||||
NextMany([]uint32) int
|
||||
// NextMany fills buf up with values, returns how many values were returned
|
||||
NextMany(buf []uint32) int
|
||||
// NextMany64 fills up buf with 64 bit values, uses hs as a mask (OR), returns how many values were returned
|
||||
NextMany64(hs uint64, buf []uint64) int
|
||||
}
|
||||
|
||||
type manyIntIterator struct {
|
||||
@@ -302,12 +433,27 @@ type manyIntIterator struct {
|
||||
hs uint32
|
||||
iter manyIterable
|
||||
highlowcontainer *roaringArray
|
||||
|
||||
shortIter shortIterator
|
||||
runIter runIterator16
|
||||
bitmapIter bitmapContainerManyIterator
|
||||
}
|
||||
|
||||
func (ii *manyIntIterator) init() {
|
||||
if ii.highlowcontainer.size() > ii.pos {
|
||||
ii.iter = ii.highlowcontainer.getContainerAtIndex(ii.pos).getManyIterator()
|
||||
ii.hs = uint32(ii.highlowcontainer.getKeyAtIndex(ii.pos)) << 16
|
||||
c := ii.highlowcontainer.getContainerAtIndex(ii.pos)
|
||||
switch t := c.(type) {
|
||||
case *arrayContainer:
|
||||
ii.shortIter = shortIterator{t.content, 0}
|
||||
ii.iter = &ii.shortIter
|
||||
case *runContainer16:
|
||||
ii.runIter = runIterator16{rc: t, curIndex: 0, curPosInIndex: 0}
|
||||
ii.iter = &ii.runIter
|
||||
case *bitmapContainer:
|
||||
ii.bitmapIter = bitmapContainerManyIterator{t, -1, 0}
|
||||
ii.iter = &ii.bitmapIter
|
||||
}
|
||||
} else {
|
||||
ii.iter = nil
|
||||
}
|
||||
@@ -330,12 +476,36 @@ func (ii *manyIntIterator) NextMany(buf []uint32) int {
|
||||
return n
|
||||
}
|
||||
|
||||
func newManyIntIterator(a *Bitmap) *manyIntIterator {
|
||||
p := new(manyIntIterator)
|
||||
func (ii *manyIntIterator) NextMany64(hs64 uint64, buf []uint64) int {
|
||||
n := 0
|
||||
for n < len(buf) {
|
||||
if ii.iter == nil {
|
||||
break
|
||||
}
|
||||
|
||||
hs := uint64(ii.hs) | hs64
|
||||
moreN := ii.iter.nextMany64(hs, buf[n:])
|
||||
n += moreN
|
||||
if moreN == 0 {
|
||||
ii.pos = ii.pos + 1
|
||||
ii.init()
|
||||
}
|
||||
}
|
||||
|
||||
return n
|
||||
}
|
||||
|
||||
|
||||
// ManyIntIterator is meant to allow you to iterate through the values of a bitmap, see Initialize(a *Bitmap)
|
||||
type ManyIntIterator = manyIntIterator
|
||||
|
||||
// Initialize configures the existing iterator so that it can iterate through the values of
|
||||
// the provided bitmap.
|
||||
// The iteration results are undefined if the bitmap is modified (e.g., with Add or Remove).
|
||||
func (p *manyIntIterator) Initialize(a *Bitmap) {
|
||||
p.pos = 0
|
||||
p.highlowcontainer = &a.highlowcontainer
|
||||
p.init()
|
||||
return p
|
||||
}
|
||||
|
||||
// String creates a string representation of the Bitmap
|
||||
@@ -364,19 +534,60 @@ func (rb *Bitmap) String() string {
|
||||
return buffer.String()
|
||||
}
|
||||
|
||||
// Iterator creates a new IntIterable to iterate over the integers contained in the bitmap, in sorted order
|
||||
func (rb *Bitmap) Iterator() IntIterable {
|
||||
return newIntIterator(rb)
|
||||
// Iterate iterates over the bitmap, calling the given callback with each value in the bitmap. If the callback returns
|
||||
// false, the iteration is halted.
|
||||
// The iteration results are undefined if the bitmap is modified (e.g., with Add or Remove).
|
||||
// There is no guarantee as to what order the values will be iterated.
|
||||
func (rb *Bitmap) Iterate(cb func(x uint32) bool) {
|
||||
for i := 0; i < rb.highlowcontainer.size(); i++ {
|
||||
hs := uint32(rb.highlowcontainer.getKeyAtIndex(i)) << 16
|
||||
c := rb.highlowcontainer.getContainerAtIndex(i)
|
||||
|
||||
var shouldContinue bool
|
||||
// This is hacky but it avoids allocations from invoking an interface method with a closure
|
||||
switch t := c.(type) {
|
||||
case *arrayContainer:
|
||||
shouldContinue = t.iterate(func(x uint16) bool {
|
||||
return cb(uint32(x) | hs)
|
||||
})
|
||||
case *runContainer16:
|
||||
shouldContinue = t.iterate(func(x uint16) bool {
|
||||
return cb(uint32(x) | hs)
|
||||
})
|
||||
case *bitmapContainer:
|
||||
shouldContinue = t.iterate(func(x uint16) bool {
|
||||
return cb(uint32(x) | hs)
|
||||
})
|
||||
}
|
||||
|
||||
if !shouldContinue {
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ReverseIterator creates a new IntIterable to iterate over the integers contained in the bitmap, in sorted order
|
||||
// Iterator creates a new IntPeekable to iterate over the integers contained in the bitmap, in sorted order;
|
||||
// the iterator becomes invalid if the bitmap is modified (e.g., with Add or Remove).
|
||||
func (rb *Bitmap) Iterator() IntPeekable {
|
||||
p := new(intIterator)
|
||||
p.Initialize(rb)
|
||||
return p
|
||||
}
|
||||
|
||||
// ReverseIterator creates a new IntIterable to iterate over the integers contained in the bitmap, in sorted order;
|
||||
// the iterator becomes invalid if the bitmap is modified (e.g., with Add or Remove).
|
||||
func (rb *Bitmap) ReverseIterator() IntIterable {
|
||||
return newIntReverseIterator(rb)
|
||||
p := new(intReverseIterator)
|
||||
p.Initialize(rb)
|
||||
return p
|
||||
}
|
||||
|
||||
// ManyIterator creates a new ManyIntIterable to iterate over the integers contained in the bitmap, in sorted order
|
||||
// ManyIterator creates a new ManyIntIterable to iterate over the integers contained in the bitmap, in sorted order;
|
||||
// the iterator becomes invalid if the bitmap is modified (e.g., with Add or Remove).
|
||||
func (rb *Bitmap) ManyIterator() ManyIntIterable {
|
||||
return newManyIntIterator(rb)
|
||||
p := new(manyIntIterator)
|
||||
p.Initialize(rb)
|
||||
return p
|
||||
}
|
||||
|
||||
// Clone creates a copy of the Bitmap
|
||||
@@ -388,11 +599,17 @@ func (rb *Bitmap) Clone() *Bitmap {
|
||||
|
||||
// Minimum get the smallest value stored in this roaring bitmap, assumes that it is not empty
|
||||
func (rb *Bitmap) Minimum() uint32 {
|
||||
if len(rb.highlowcontainer.containers) == 0 {
|
||||
panic("Empty bitmap")
|
||||
}
|
||||
return uint32(rb.highlowcontainer.containers[0].minimum()) | (uint32(rb.highlowcontainer.keys[0]) << 16)
|
||||
}
|
||||
|
||||
// Maximum get the largest value stored in this roaring bitmap, assumes that it is not empty
|
||||
func (rb *Bitmap) Maximum() uint32 {
|
||||
if len(rb.highlowcontainer.containers) == 0 {
|
||||
panic("Empty bitmap")
|
||||
}
|
||||
lastindex := len(rb.highlowcontainer.containers) - 1
|
||||
return uint32(rb.highlowcontainer.containers[lastindex].maximum()) | (uint32(rb.highlowcontainer.keys[lastindex]) << 16)
|
||||
}
|
||||
@@ -418,42 +635,78 @@ func (rb *Bitmap) Equals(o interface{}) bool {
|
||||
return false
|
||||
}
|
||||
|
||||
// AddOffset adds the value 'offset' to each and every value in a bitmap, generating a new bitmap in the process
|
||||
func AddOffset(x *Bitmap, offset uint32) (answer *Bitmap) {
|
||||
containerOffset := highbits(offset)
|
||||
inOffset := lowbits(offset)
|
||||
return AddOffset64(x, int64(offset))
|
||||
}
|
||||
|
||||
// AddOffset64 adds the value 'offset' to each and every value in a bitmap, generating a new bitmap in the process
|
||||
// If offset + element is outside of the range [0,2^32), that the element will be dropped
|
||||
func AddOffset64(x *Bitmap, offset int64) (answer *Bitmap) {
|
||||
// we need "offset" to be a long because we want to support values
|
||||
// between -0xFFFFFFFF up to +-0xFFFFFFFF
|
||||
var containerOffset64 int64
|
||||
|
||||
if offset < 0 {
|
||||
containerOffset64 = (offset - (1 << 16) + 1) / (1 << 16)
|
||||
} else {
|
||||
containerOffset64 = offset >> 16
|
||||
}
|
||||
|
||||
answer = New()
|
||||
|
||||
if containerOffset64 >= (1<<16) || containerOffset64 < -(1<<16) {
|
||||
return answer
|
||||
}
|
||||
|
||||
containerOffset := int32(containerOffset64)
|
||||
inOffset := (uint16)(offset - containerOffset64*(1<<16))
|
||||
|
||||
if inOffset == 0 {
|
||||
answer = x.Clone()
|
||||
for pos := 0; pos < answer.highlowcontainer.size(); pos++ {
|
||||
key := answer.highlowcontainer.getKeyAtIndex(pos)
|
||||
for pos := 0; pos < x.highlowcontainer.size(); pos++ {
|
||||
key := int32(x.highlowcontainer.getKeyAtIndex(pos))
|
||||
key += containerOffset
|
||||
answer.highlowcontainer.keys[pos] = key
|
||||
|
||||
if key >= 0 && key <= MaxUint16 {
|
||||
c := x.highlowcontainer.getContainerAtIndex(pos).clone()
|
||||
answer.highlowcontainer.appendContainer(uint16(key), c, false)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
answer = New()
|
||||
for pos := 0; pos < x.highlowcontainer.size(); pos++ {
|
||||
key := x.highlowcontainer.getKeyAtIndex(pos)
|
||||
key := int32(x.highlowcontainer.getKeyAtIndex(pos))
|
||||
key += containerOffset
|
||||
|
||||
if key+1 < 0 || key > MaxUint16 {
|
||||
continue
|
||||
}
|
||||
|
||||
c := x.highlowcontainer.getContainerAtIndex(pos)
|
||||
offsetted := c.addOffset(inOffset)
|
||||
if offsetted[0].getCardinality() > 0 {
|
||||
lo, hi := c.addOffset(inOffset)
|
||||
|
||||
if lo != nil && key >= 0 {
|
||||
curSize := answer.highlowcontainer.size()
|
||||
lastkey := uint16(0)
|
||||
lastkey := int32(0)
|
||||
|
||||
if curSize > 0 {
|
||||
lastkey = answer.highlowcontainer.getKeyAtIndex(curSize - 1)
|
||||
lastkey = int32(answer.highlowcontainer.getKeyAtIndex(curSize - 1))
|
||||
}
|
||||
|
||||
if curSize > 0 && lastkey == key {
|
||||
prev := answer.highlowcontainer.getContainerAtIndex(curSize - 1)
|
||||
orrseult := prev.ior(offsetted[0])
|
||||
answer.highlowcontainer.setContainerAtIndex(curSize-1, orrseult)
|
||||
orresult := prev.ior(lo)
|
||||
answer.highlowcontainer.setContainerAtIndex(curSize-1, orresult)
|
||||
} else {
|
||||
answer.highlowcontainer.appendContainer(key, offsetted[0], false)
|
||||
answer.highlowcontainer.appendContainer(uint16(key), lo, false)
|
||||
}
|
||||
}
|
||||
if offsetted[1].getCardinality() > 0 {
|
||||
answer.highlowcontainer.appendContainer(key+1, offsetted[1], false)
|
||||
|
||||
if hi != nil && key+1 <= MaxUint16 {
|
||||
answer.highlowcontainer.appendContainer(uint16(key+1), hi, false)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return answer
|
||||
}
|
||||
|
||||
@@ -519,13 +772,13 @@ func (rb *Bitmap) Remove(x uint32) {
|
||||
if i >= 0 {
|
||||
c := rb.highlowcontainer.getWritableContainerAtIndex(i).iremoveReturnMinimized(lowbits(x))
|
||||
rb.highlowcontainer.setContainerAtIndex(i, c)
|
||||
if rb.highlowcontainer.getContainerAtIndex(i).getCardinality() == 0 {
|
||||
if rb.highlowcontainer.getContainerAtIndex(i).isEmpty() {
|
||||
rb.highlowcontainer.removeAtIndex(i)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// CheckedRemove removes the integer x from the bitmap and return true if the integer was effectively remove (and false if the integer was not present)
|
||||
// CheckedRemove removes the integer x from the bitmap and return true if the integer was effectively removed (and false if the integer was not present)
|
||||
func (rb *Bitmap) CheckedRemove(x uint32) bool {
|
||||
// TODO: add unit tests for this method
|
||||
hb := highbits(x)
|
||||
@@ -535,7 +788,7 @@ func (rb *Bitmap) CheckedRemove(x uint32) bool {
|
||||
oldcard := C.getCardinality()
|
||||
C = C.iremoveReturnMinimized(lowbits(x))
|
||||
rb.highlowcontainer.setContainerAtIndex(i, C)
|
||||
if rb.highlowcontainer.getContainerAtIndex(i).getCardinality() == 0 {
|
||||
if rb.highlowcontainer.getContainerAtIndex(i).isEmpty() {
|
||||
rb.highlowcontainer.removeAtIndex(i)
|
||||
return true
|
||||
}
|
||||
@@ -559,7 +812,10 @@ func (rb *Bitmap) GetCardinality() uint64 {
|
||||
return size
|
||||
}
|
||||
|
||||
// Rank returns the number of integers that are smaller or equal to x (Rank(infinity) would be GetCardinality())
|
||||
// Rank returns the number of integers that are smaller or equal to x (Rank(infinity) would be GetCardinality()).
|
||||
// If you pass the smallest value, you get the value 1. If you pass a value that is smaller than the smallest
|
||||
// value, you get 0. Note that this function differs in convention from the Select function since it
|
||||
// return 1 and not 0 on the smallest value.
|
||||
func (rb *Bitmap) Rank(x uint32) uint64 {
|
||||
size := uint64(0)
|
||||
for i := 0; i < rb.highlowcontainer.size(); i++ {
|
||||
@@ -576,17 +832,16 @@ func (rb *Bitmap) Rank(x uint32) uint64 {
|
||||
return size
|
||||
}
|
||||
|
||||
// Select returns the xth integer in the bitmap
|
||||
// Select returns the xth integer in the bitmap. If you pass 0, you get
|
||||
// the smallest element. Note that this function differs in convention from
|
||||
// the Rank function which returns 1 on the smallest value.
|
||||
func (rb *Bitmap) Select(x uint32) (uint32, error) {
|
||||
if rb.GetCardinality() <= uint64(x) {
|
||||
return 0, fmt.Errorf("can't find %dth integer in a bitmap with only %d items", x, rb.GetCardinality())
|
||||
}
|
||||
|
||||
remaining := x
|
||||
for i := 0; i < rb.highlowcontainer.size(); i++ {
|
||||
c := rb.highlowcontainer.getContainerAtIndex(i)
|
||||
if remaining >= uint32(c.getCardinality()) {
|
||||
remaining -= uint32(c.getCardinality())
|
||||
card := uint32(c.getCardinality())
|
||||
if remaining >= card {
|
||||
remaining -= card
|
||||
} else {
|
||||
key := rb.highlowcontainer.getKeyAtIndex(i)
|
||||
return uint32(key)<<16 + uint32(c.selectInt(uint16(remaining))), nil
|
||||
@@ -613,7 +868,7 @@ main:
|
||||
c1 := rb.highlowcontainer.getWritableContainerAtIndex(pos1)
|
||||
c2 := x2.highlowcontainer.getContainerAtIndex(pos2)
|
||||
diff := c1.iand(c2)
|
||||
if diff.getCardinality() > 0 {
|
||||
if !diff.isEmpty() {
|
||||
rb.highlowcontainer.replaceKeyAndContainerAtIndex(intersectionsize, s1, diff, false)
|
||||
intersectionsize++
|
||||
}
|
||||
@@ -744,6 +999,28 @@ main:
|
||||
return answer
|
||||
}
|
||||
|
||||
// IntersectsWithInterval checks whether a bitmap 'rb' and an open interval '[x,y)' intersect.
|
||||
func (rb *Bitmap) IntersectsWithInterval(x, y uint64) bool {
|
||||
if x >= y {
|
||||
return false
|
||||
}
|
||||
if x > MaxUint32 {
|
||||
return false
|
||||
}
|
||||
|
||||
it := intIterator{}
|
||||
it.Initialize(rb)
|
||||
it.AdvanceIfNeeded(uint32(x))
|
||||
if !it.HasNext() {
|
||||
return false
|
||||
}
|
||||
if uint64(it.Next()) >= y {
|
||||
return false
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
// Intersects checks whether two bitmap intersects, bitmaps are not modified
|
||||
func (rb *Bitmap) Intersects(x2 *Bitmap) bool {
|
||||
pos1 := 0
|
||||
@@ -815,7 +1092,7 @@ func (rb *Bitmap) Xor(x2 *Bitmap) {
|
||||
} else {
|
||||
// TODO: couple be computed in-place for reduced memory usage
|
||||
c := rb.highlowcontainer.getContainerAtIndex(pos1).xor(x2.highlowcontainer.getContainerAtIndex(pos2))
|
||||
if c.getCardinality() > 0 {
|
||||
if !c.isEmpty() {
|
||||
rb.highlowcontainer.setContainerAtIndex(pos1, c)
|
||||
pos1++
|
||||
} else {
|
||||
@@ -861,7 +1138,7 @@ main:
|
||||
}
|
||||
s2 = x2.highlowcontainer.getKeyAtIndex(pos2)
|
||||
} else {
|
||||
rb.highlowcontainer.replaceKeyAndContainerAtIndex(pos1, s1, rb.highlowcontainer.getWritableContainerAtIndex(pos1).ior(x2.highlowcontainer.getContainerAtIndex(pos2)), false)
|
||||
rb.highlowcontainer.replaceKeyAndContainerAtIndex(pos1, s1, rb.highlowcontainer.getUnionedWritableContainer(pos1, x2.highlowcontainer.getContainerAtIndex(pos2)), false)
|
||||
pos1++
|
||||
pos2++
|
||||
if (pos1 == length1) || (pos2 == length2) {
|
||||
@@ -895,7 +1172,7 @@ main:
|
||||
c1 := rb.highlowcontainer.getWritableContainerAtIndex(pos1)
|
||||
c2 := x2.highlowcontainer.getContainerAtIndex(pos2)
|
||||
diff := c1.iandNot(c2)
|
||||
if diff.getCardinality() > 0 {
|
||||
if !diff.isEmpty() {
|
||||
rb.highlowcontainer.replaceKeyAndContainerAtIndex(intersectionsize, s1, diff, false)
|
||||
intersectionsize++
|
||||
}
|
||||
@@ -1004,7 +1281,7 @@ main:
|
||||
C := x1.highlowcontainer.getContainerAtIndex(pos1)
|
||||
C = C.and(x2.highlowcontainer.getContainerAtIndex(pos2))
|
||||
|
||||
if C.getCardinality() > 0 {
|
||||
if !C.isEmpty() {
|
||||
answer.highlowcontainer.appendContainer(s1, C, false)
|
||||
}
|
||||
pos1++
|
||||
@@ -1051,7 +1328,7 @@ func Xor(x1, x2 *Bitmap) *Bitmap {
|
||||
pos2++
|
||||
} else {
|
||||
c := x1.highlowcontainer.getContainerAtIndex(pos1).xor(x2.highlowcontainer.getContainerAtIndex(pos2))
|
||||
if c.getCardinality() > 0 {
|
||||
if !c.isEmpty() {
|
||||
answer.highlowcontainer.appendContainer(s1, c, false)
|
||||
}
|
||||
pos1++
|
||||
@@ -1094,7 +1371,7 @@ main:
|
||||
c1 := x1.highlowcontainer.getContainerAtIndex(pos1)
|
||||
c2 := x2.highlowcontainer.getContainerAtIndex(pos2)
|
||||
diff := c1.andNot(c2)
|
||||
if diff.getCardinality() > 0 {
|
||||
if !diff.isEmpty() {
|
||||
answer.highlowcontainer.appendContainer(s1, diff, false)
|
||||
}
|
||||
pos1++
|
||||
@@ -1184,7 +1461,7 @@ func (rb *Bitmap) Flip(rangeStart, rangeEnd uint64) {
|
||||
|
||||
if i >= 0 {
|
||||
c := rb.highlowcontainer.getWritableContainerAtIndex(i).inot(int(containerStart), int(containerLast)+1)
|
||||
if c.getCardinality() > 0 {
|
||||
if !c.isEmpty() {
|
||||
rb.highlowcontainer.setContainerAtIndex(i, c)
|
||||
} else {
|
||||
rb.highlowcontainer.removeAtIndex(i)
|
||||
@@ -1265,7 +1542,7 @@ func (rb *Bitmap) RemoveRange(rangeStart, rangeEnd uint64) {
|
||||
return
|
||||
}
|
||||
c := rb.highlowcontainer.getWritableContainerAtIndex(i).iremoveRange(int(lbStart), int(lbLast+1))
|
||||
if c.getCardinality() > 0 {
|
||||
if !c.isEmpty() {
|
||||
rb.highlowcontainer.setContainerAtIndex(i, c)
|
||||
} else {
|
||||
rb.highlowcontainer.removeAtIndex(i)
|
||||
@@ -1278,7 +1555,7 @@ func (rb *Bitmap) RemoveRange(rangeStart, rangeEnd uint64) {
|
||||
if ifirst >= 0 {
|
||||
if lbStart != 0 {
|
||||
c := rb.highlowcontainer.getWritableContainerAtIndex(ifirst).iremoveRange(int(lbStart), int(max+1))
|
||||
if c.getCardinality() > 0 {
|
||||
if !c.isEmpty() {
|
||||
rb.highlowcontainer.setContainerAtIndex(ifirst, c)
|
||||
ifirst++
|
||||
}
|
||||
@@ -1289,7 +1566,7 @@ func (rb *Bitmap) RemoveRange(rangeStart, rangeEnd uint64) {
|
||||
if ilast >= 0 {
|
||||
if lbLast != max {
|
||||
c := rb.highlowcontainer.getWritableContainerAtIndex(ilast).iremoveRange(int(0), int(lbLast+1))
|
||||
if c.getCardinality() > 0 {
|
||||
if !c.isEmpty() {
|
||||
rb.highlowcontainer.setContainerAtIndex(ilast, c)
|
||||
} else {
|
||||
ilast++
|
||||
@@ -1345,7 +1622,7 @@ func Flip(bm *Bitmap, rangeStart, rangeEnd uint64) *Bitmap {
|
||||
|
||||
if i >= 0 {
|
||||
c := bm.highlowcontainer.getContainerAtIndex(i).not(int(containerStart), int(containerLast)+1)
|
||||
if c.getCardinality() > 0 {
|
||||
if !c.isEmpty() {
|
||||
answer.highlowcontainer.insertNewKeyValueAt(-j-1, uint16(hb), c)
|
||||
}
|
||||
|
||||
@@ -1374,6 +1651,21 @@ func (rb *Bitmap) GetCopyOnWrite() (val bool) {
|
||||
return rb.highlowcontainer.copyOnWrite
|
||||
}
|
||||
|
||||
// CloneCopyOnWriteContainers clones all containers which have
|
||||
// needCopyOnWrite set to true.
|
||||
// This can be used to make sure it is safe to munmap a []byte
|
||||
// that the roaring array may still have a reference to, after
|
||||
// calling FromBuffer.
|
||||
// More generally this function is useful if you call FromBuffer
|
||||
// to construct a bitmap with a backing array buf
|
||||
// and then later discard the buf array. Note that you should call
|
||||
// CloneCopyOnWriteContainers on all bitmaps that were derived
|
||||
// from the 'FromBuffer' bitmap since they map have dependencies
|
||||
// on the buf array as well.
|
||||
func (rb *Bitmap) CloneCopyOnWriteContainers() {
|
||||
rb.highlowcontainer.cloneCopyOnWriteContainers()
|
||||
}
|
||||
|
||||
// FlipInt calls Flip after casting the parameters (convenience method)
|
||||
func FlipInt(bm *Bitmap, rangeStart, rangeEnd int) *Bitmap {
|
||||
return Flip(bm, uint64(rangeStart), uint64(rangeEnd))
|
||||
|
||||
355
vendor/github.com/RoaringBitmap/roaring/roaringarray.go
generated
vendored
355
vendor/github.com/RoaringBitmap/roaring/roaringarray.go
generated
vendored
@@ -4,17 +4,15 @@ import (
|
||||
"bytes"
|
||||
"encoding/binary"
|
||||
"fmt"
|
||||
"github.com/RoaringBitmap/roaring/internal"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
|
||||
snappy "github.com/glycerine/go-unsnap-stream"
|
||||
"github.com/tinylib/msgp/msgp"
|
||||
)
|
||||
|
||||
//go:generate msgp -unexported
|
||||
|
||||
type container interface {
|
||||
addOffset(uint16) []container
|
||||
// addOffset returns the (low, high) parts of the shifted container.
|
||||
// Whenever one of them would be empty, nil will be returned instead to
|
||||
// avoid unnecessary allocations.
|
||||
addOffset(uint16) (container, container)
|
||||
|
||||
clone() container
|
||||
and(container) container
|
||||
@@ -22,6 +20,7 @@ type container interface {
|
||||
iand(container) container // i stands for inplace
|
||||
andNot(container) container
|
||||
iandNot(container) container // i stands for inplace
|
||||
isEmpty() bool
|
||||
getCardinality() int
|
||||
// rank returns the number of integers that are
|
||||
// smaller or equal to x. rank(infinity) would be getCardinality().
|
||||
@@ -39,7 +38,8 @@ type container interface {
|
||||
not(start, final int) container // range is [firstOfRange,lastOfRange)
|
||||
inot(firstOfRange, endx int) container // i stands for inplace, range is [firstOfRange,endx)
|
||||
xor(r container) container
|
||||
getShortIterator() shortIterable
|
||||
getShortIterator() shortPeekable
|
||||
iterate(cb func(x uint16) bool) bool
|
||||
getReverseIterator() shortIterable
|
||||
getManyIterator() manyIterable
|
||||
contains(i uint16) bool
|
||||
@@ -51,7 +51,7 @@ type container interface {
|
||||
// any of the implementations.
|
||||
equals(r container) bool
|
||||
|
||||
fillLeastSignificant16bits(array []uint32, i int, mask uint32)
|
||||
fillLeastSignificant16bits(array []uint32, i int, mask uint32) int
|
||||
or(r container) container
|
||||
orCardinality(r container) int
|
||||
isFull() bool
|
||||
@@ -64,7 +64,6 @@ type container interface {
|
||||
iremoveRange(start, final int) container // i stands for inplace, range is [firstOfRange,lastOfRange)
|
||||
selectInt(x uint16) int // selectInt returns the xth integer in the container
|
||||
serializedSizeInBytes() int
|
||||
readFrom(io.Reader) (int, error)
|
||||
writeTo(io.Writer) (int, error)
|
||||
|
||||
numberOfRuns() int
|
||||
@@ -104,18 +103,6 @@ type roaringArray struct {
|
||||
containers []container `msg:"-"` // don't try to serialize directly.
|
||||
needCopyOnWrite []bool
|
||||
copyOnWrite bool
|
||||
|
||||
// conserz is used at serialization time
|
||||
// to serialize containers. Otherwise empty.
|
||||
conserz []containerSerz
|
||||
}
|
||||
|
||||
// containerSerz facilitates serializing container (tricky to
|
||||
// serialize because it is an interface) by providing a
|
||||
// light wrapper with a type identifier.
|
||||
type containerSerz struct {
|
||||
t contype `msg:"t"` // type
|
||||
r msgp.Raw `msg:"r"` // Raw msgpack of the actual container type
|
||||
}
|
||||
|
||||
func newRoaringArray() *roaringArray {
|
||||
@@ -247,7 +234,6 @@ func (ra *roaringArray) resize(newsize int) {
|
||||
func (ra *roaringArray) clear() {
|
||||
ra.resize(0)
|
||||
ra.copyOnWrite = false
|
||||
ra.conserz = nil
|
||||
}
|
||||
|
||||
func (ra *roaringArray) clone() *roaringArray {
|
||||
@@ -283,6 +269,18 @@ func (ra *roaringArray) clone() *roaringArray {
|
||||
return &sa
|
||||
}
|
||||
|
||||
// clone all containers which have needCopyOnWrite set to true
|
||||
// This can be used to make sure it is safe to munmap a []byte
|
||||
// that the roaring array may still have a reference to.
|
||||
func (ra *roaringArray) cloneCopyOnWriteContainers() {
|
||||
for i, needCopyOnWrite := range ra.needCopyOnWrite {
|
||||
if needCopyOnWrite {
|
||||
ra.containers[i] = ra.containers[i].clone()
|
||||
ra.needCopyOnWrite[i] = false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// unused function:
|
||||
//func (ra *roaringArray) containsKey(x uint16) bool {
|
||||
// return (ra.binarySearch(0, int64(len(ra.keys)), x) >= 0)
|
||||
@@ -317,6 +315,17 @@ func (ra *roaringArray) getFastContainerAtIndex(i int, needsWriteable bool) cont
|
||||
return c
|
||||
}
|
||||
|
||||
// getUnionedWritableContainer switches behavior for in-place Or
|
||||
// depending on whether the container requires a copy on write.
|
||||
// If it does using the non-inplace or() method leads to fewer allocations.
|
||||
func (ra *roaringArray) getUnionedWritableContainer(pos int, other container) container {
|
||||
if ra.needCopyOnWrite[pos] {
|
||||
return ra.getContainerAtIndex(pos).or(other)
|
||||
}
|
||||
return ra.getContainerAtIndex(pos).ior(other)
|
||||
|
||||
}
|
||||
|
||||
func (ra *roaringArray) getWritableContainerAtIndex(i int) container {
|
||||
if ra.needCopyOnWrite[i] {
|
||||
ra.containers[i] = ra.containers[i].clone()
|
||||
@@ -479,20 +488,15 @@ func (ra *roaringArray) writeTo(w io.Writer) (n int64, err error) {
|
||||
nw += 2
|
||||
binary.LittleEndian.PutUint16(buf[2:], uint16(len(ra.keys)-1))
|
||||
nw += 2
|
||||
|
||||
// compute isRun bitmap
|
||||
var ir []byte
|
||||
|
||||
isRun := newBitmapContainer()
|
||||
// compute isRun bitmap without temporary allocation
|
||||
var runbitmapslice = buf[nw : nw+isRunSizeInBytes]
|
||||
for i, c := range ra.containers {
|
||||
switch c.(type) {
|
||||
case *runContainer16:
|
||||
isRun.iadd(uint16(i))
|
||||
runbitmapslice[i/8] |= 1 << (uint(i) % 8)
|
||||
}
|
||||
}
|
||||
// convert to little endian
|
||||
ir = isRun.asLittleEndianByteSlice()[:isRunSizeInBytes]
|
||||
nw += copy(buf[nw:], ir)
|
||||
nw += isRunSizeInBytes
|
||||
} else {
|
||||
binary.LittleEndian.PutUint32(buf[0:], uint32(serialCookieNoRunContainer))
|
||||
nw += 4
|
||||
@@ -549,50 +553,59 @@ func (ra *roaringArray) toBytes() ([]byte, error) {
|
||||
return buf.Bytes(), err
|
||||
}
|
||||
|
||||
func (ra *roaringArray) fromBuffer(buf []byte) (int64, error) {
|
||||
pos := 0
|
||||
if len(buf) < 8 {
|
||||
return 0, fmt.Errorf("buffer too small, expecting at least 8 bytes, was %d", len(buf))
|
||||
func (ra *roaringArray) readFrom(stream internal.ByteInput, cookieHeader ...byte) (int64, error) {
|
||||
var cookie uint32
|
||||
var err error
|
||||
if len(cookieHeader) > 0 && len(cookieHeader) != 4 {
|
||||
return int64(len(cookieHeader)), fmt.Errorf("error in roaringArray.readFrom: could not read initial cookie: incorrect size of cookie header")
|
||||
}
|
||||
if len(cookieHeader) == 4 {
|
||||
cookie = binary.LittleEndian.Uint32(cookieHeader)
|
||||
} else {
|
||||
cookie, err = stream.ReadUInt32()
|
||||
if err != nil {
|
||||
return stream.GetReadBytes(), fmt.Errorf("error in roaringArray.readFrom: could not read initial cookie: %s", err)
|
||||
}
|
||||
}
|
||||
|
||||
cookie := binary.LittleEndian.Uint32(buf)
|
||||
pos += 4
|
||||
var size uint32 // number of containers
|
||||
haveRunContainers := false
|
||||
var size uint32
|
||||
var isRunBitmap []byte
|
||||
|
||||
// cookie header
|
||||
if cookie&0x0000FFFF == serialCookie {
|
||||
haveRunContainers = true
|
||||
size = uint32(uint16(cookie>>16) + 1) // number of containers
|
||||
|
||||
size = uint32(cookie>>16 + 1)
|
||||
// create is-run-container bitmap
|
||||
isRunBitmapSize := (int(size) + 7) / 8
|
||||
if pos+isRunBitmapSize > len(buf) {
|
||||
return 0, fmt.Errorf("malformed bitmap, is-run bitmap overruns buffer at %d", pos+isRunBitmapSize)
|
||||
isRunBitmap, err = stream.Next(isRunBitmapSize)
|
||||
|
||||
if err != nil {
|
||||
return stream.GetReadBytes(), fmt.Errorf("malformed bitmap, failed to read is-run bitmap, got: %s", err)
|
||||
}
|
||||
|
||||
isRunBitmap = buf[pos : pos+isRunBitmapSize]
|
||||
pos += isRunBitmapSize
|
||||
} else if cookie == serialCookieNoRunContainer {
|
||||
size = binary.LittleEndian.Uint32(buf[pos:])
|
||||
pos += 4
|
||||
size, err = stream.ReadUInt32()
|
||||
if err != nil {
|
||||
return stream.GetReadBytes(), fmt.Errorf("malformed bitmap, failed to read a bitmap size: %s", err)
|
||||
}
|
||||
} else {
|
||||
return 0, fmt.Errorf("error in roaringArray.readFrom: did not find expected serialCookie in header")
|
||||
return stream.GetReadBytes(), fmt.Errorf("error in roaringArray.readFrom: did not find expected serialCookie in header")
|
||||
}
|
||||
if size > (1 << 16) {
|
||||
return 0, fmt.Errorf("It is logically impossible to have more than (1<<16) containers.")
|
||||
}
|
||||
// descriptive header
|
||||
// keycard - is {key, cardinality} tuple slice
|
||||
if pos+2*2*int(size) > len(buf) {
|
||||
return 0, fmt.Errorf("malfomred bitmap, key-cardinality slice overruns buffer at %d", pos+2*2*int(size))
|
||||
}
|
||||
keycard := byteSliceAsUint16Slice(buf[pos : pos+2*2*int(size)])
|
||||
pos += 2 * 2 * int(size)
|
||||
|
||||
if !haveRunContainers || size >= noOffsetThreshold {
|
||||
pos += 4 * int(size)
|
||||
if size > (1 << 16) {
|
||||
return stream.GetReadBytes(), fmt.Errorf("it is logically impossible to have more than (1<<16) containers")
|
||||
}
|
||||
|
||||
// descriptive header
|
||||
buf, err := stream.Next(2 * 2 * int(size))
|
||||
|
||||
if err != nil {
|
||||
return stream.GetReadBytes(), fmt.Errorf("failed to read descriptive header: %s", err)
|
||||
}
|
||||
|
||||
keycard := byteSliceAsUint16Slice(buf)
|
||||
|
||||
if isRunBitmap == nil || size >= noOffsetThreshold {
|
||||
if err := stream.SkipBytes(int(size) * 4); err != nil {
|
||||
return stream.GetReadBytes(), fmt.Errorf("failed to skip bytes: %s", err)
|
||||
}
|
||||
}
|
||||
|
||||
// Allocate slices upfront as number of containers is known
|
||||
@@ -601,11 +614,13 @@ func (ra *roaringArray) fromBuffer(buf []byte) (int64, error) {
|
||||
} else {
|
||||
ra.containers = make([]container, size)
|
||||
}
|
||||
|
||||
if cap(ra.keys) >= int(size) {
|
||||
ra.keys = ra.keys[:size]
|
||||
} else {
|
||||
ra.keys = make([]uint16, size)
|
||||
}
|
||||
|
||||
if cap(ra.needCopyOnWrite) >= int(size) {
|
||||
ra.needCopyOnWrite = ra.needCopyOnWrite[:size]
|
||||
} else {
|
||||
@@ -613,129 +628,61 @@ func (ra *roaringArray) fromBuffer(buf []byte) (int64, error) {
|
||||
}
|
||||
|
||||
for i := uint32(0); i < size; i++ {
|
||||
key := uint16(keycard[2*i])
|
||||
key := keycard[2*i]
|
||||
card := int(keycard[2*i+1]) + 1
|
||||
ra.keys[i] = key
|
||||
ra.needCopyOnWrite[i] = true
|
||||
|
||||
if haveRunContainers && isRunBitmap[i/8]&(1<<(i%8)) != 0 {
|
||||
if isRunBitmap != nil && isRunBitmap[i/8]&(1<<(i%8)) != 0 {
|
||||
// run container
|
||||
nr := binary.LittleEndian.Uint16(buf[pos:])
|
||||
pos += 2
|
||||
if pos+int(nr)*4 > len(buf) {
|
||||
return 0, fmt.Errorf("malformed bitmap, a run container overruns buffer at %d:%d", pos, pos+int(nr)*4)
|
||||
nr, err := stream.ReadUInt16()
|
||||
|
||||
if err != nil {
|
||||
return 0, fmt.Errorf("failed to read runtime container size: %s", err)
|
||||
}
|
||||
|
||||
buf, err := stream.Next(int(nr) * 4)
|
||||
|
||||
if err != nil {
|
||||
return stream.GetReadBytes(), fmt.Errorf("failed to read runtime container content: %s", err)
|
||||
}
|
||||
|
||||
nb := runContainer16{
|
||||
iv: byteSliceAsInterval16Slice(buf[pos : pos+int(nr)*4]),
|
||||
card: int64(card),
|
||||
iv: byteSliceAsInterval16Slice(buf),
|
||||
}
|
||||
pos += int(nr) * 4
|
||||
|
||||
ra.containers[i] = &nb
|
||||
} else if card > arrayDefaultMaxSize {
|
||||
// bitmap container
|
||||
buf, err := stream.Next(arrayDefaultMaxSize * 2)
|
||||
|
||||
if err != nil {
|
||||
return stream.GetReadBytes(), fmt.Errorf("failed to read bitmap container: %s", err)
|
||||
}
|
||||
|
||||
nb := bitmapContainer{
|
||||
cardinality: card,
|
||||
bitmap: byteSliceAsUint64Slice(buf[pos : pos+arrayDefaultMaxSize*2]),
|
||||
bitmap: byteSliceAsUint64Slice(buf),
|
||||
}
|
||||
pos += arrayDefaultMaxSize * 2
|
||||
|
||||
ra.containers[i] = &nb
|
||||
} else {
|
||||
// array container
|
||||
nb := arrayContainer{
|
||||
byteSliceAsUint16Slice(buf[pos : pos+card*2]),
|
||||
buf, err := stream.Next(card * 2)
|
||||
|
||||
if err != nil {
|
||||
return stream.GetReadBytes(), fmt.Errorf("failed to read array container: %s", err)
|
||||
}
|
||||
pos += card * 2
|
||||
|
||||
nb := arrayContainer{
|
||||
byteSliceAsUint16Slice(buf),
|
||||
}
|
||||
|
||||
ra.containers[i] = &nb
|
||||
}
|
||||
}
|
||||
|
||||
return int64(pos), nil
|
||||
}
|
||||
|
||||
func (ra *roaringArray) readFrom(stream io.Reader) (int64, error) {
|
||||
pos := 0
|
||||
var cookie uint32
|
||||
err := binary.Read(stream, binary.LittleEndian, &cookie)
|
||||
if err != nil {
|
||||
return 0, fmt.Errorf("error in roaringArray.readFrom: could not read initial cookie: %s", err)
|
||||
}
|
||||
pos += 4
|
||||
var size uint32
|
||||
haveRunContainers := false
|
||||
var isRun *bitmapContainer
|
||||
if cookie&0x0000FFFF == serialCookie {
|
||||
haveRunContainers = true
|
||||
size = uint32(uint16(cookie>>16) + 1)
|
||||
bytesToRead := (int(size) + 7) / 8
|
||||
numwords := (bytesToRead + 7) / 8
|
||||
by := make([]byte, bytesToRead, numwords*8)
|
||||
nr, err := io.ReadFull(stream, by)
|
||||
if err != nil {
|
||||
return 8 + int64(nr), fmt.Errorf("error in readFrom: could not read the "+
|
||||
"runContainer bit flags of length %v bytes: %v", bytesToRead, err)
|
||||
}
|
||||
pos += bytesToRead
|
||||
by = by[:cap(by)]
|
||||
isRun = newBitmapContainer()
|
||||
for i := 0; i < numwords; i++ {
|
||||
isRun.bitmap[i] = binary.LittleEndian.Uint64(by)
|
||||
by = by[8:]
|
||||
}
|
||||
} else if cookie == serialCookieNoRunContainer {
|
||||
err = binary.Read(stream, binary.LittleEndian, &size)
|
||||
if err != nil {
|
||||
return 0, fmt.Errorf("error in roaringArray.readFrom: when reading size, got: %s", err)
|
||||
}
|
||||
pos += 4
|
||||
} else {
|
||||
return 0, fmt.Errorf("error in roaringArray.readFrom: did not find expected serialCookie in header")
|
||||
}
|
||||
if size > (1 << 16) {
|
||||
return 0, fmt.Errorf("It is logically impossible to have more than (1<<16) containers.")
|
||||
}
|
||||
// descriptive header
|
||||
keycard := make([]uint16, 2*size, 2*size)
|
||||
err = binary.Read(stream, binary.LittleEndian, keycard)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
pos += 2 * 2 * int(size)
|
||||
// offset header
|
||||
if !haveRunContainers || size >= noOffsetThreshold {
|
||||
io.CopyN(ioutil.Discard, stream, 4*int64(size)) // we never skip ahead so this data can be ignored
|
||||
pos += 4 * int(size)
|
||||
}
|
||||
for i := uint32(0); i < size; i++ {
|
||||
key := int(keycard[2*i])
|
||||
card := int(keycard[2*i+1]) + 1
|
||||
if haveRunContainers && isRun.contains(uint16(i)) {
|
||||
nb := newRunContainer16()
|
||||
nr, err := nb.readFrom(stream)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
pos += nr
|
||||
ra.appendContainer(uint16(key), nb, false)
|
||||
} else if card > arrayDefaultMaxSize {
|
||||
nb := newBitmapContainer()
|
||||
nr, err := nb.readFrom(stream)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
nb.cardinality = card
|
||||
pos += nr
|
||||
ra.appendContainer(keycard[2*i], nb, false)
|
||||
} else {
|
||||
nb := newArrayContainerSize(card)
|
||||
nr, err := nb.readFrom(stream)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
pos += nr
|
||||
ra.appendContainer(keycard[2*i], nb, false)
|
||||
}
|
||||
}
|
||||
return int64(pos), nil
|
||||
return stream.GetReadBytes(), nil
|
||||
}
|
||||
|
||||
func (ra *roaringArray) hasRunCompression() bool {
|
||||
@@ -748,84 +695,6 @@ func (ra *roaringArray) hasRunCompression() bool {
|
||||
return false
|
||||
}
|
||||
|
||||
func (ra *roaringArray) writeToMsgpack(stream io.Writer) error {
|
||||
|
||||
ra.conserz = make([]containerSerz, len(ra.containers))
|
||||
for i, v := range ra.containers {
|
||||
switch cn := v.(type) {
|
||||
case *bitmapContainer:
|
||||
bts, err := cn.MarshalMsg(nil)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
ra.conserz[i].t = bitmapContype
|
||||
ra.conserz[i].r = bts
|
||||
case *arrayContainer:
|
||||
bts, err := cn.MarshalMsg(nil)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
ra.conserz[i].t = arrayContype
|
||||
ra.conserz[i].r = bts
|
||||
case *runContainer16:
|
||||
bts, err := cn.MarshalMsg(nil)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
ra.conserz[i].t = run16Contype
|
||||
ra.conserz[i].r = bts
|
||||
default:
|
||||
panic(fmt.Errorf("Unrecognized container implementation: %T", cn))
|
||||
}
|
||||
}
|
||||
w := snappy.NewWriter(stream)
|
||||
err := msgp.Encode(w, ra)
|
||||
ra.conserz = nil
|
||||
return err
|
||||
}
|
||||
|
||||
func (ra *roaringArray) readFromMsgpack(stream io.Reader) error {
|
||||
r := snappy.NewReader(stream)
|
||||
err := msgp.Decode(r, ra)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if len(ra.containers) != len(ra.keys) {
|
||||
ra.containers = make([]container, len(ra.keys))
|
||||
}
|
||||
|
||||
for i, v := range ra.conserz {
|
||||
switch v.t {
|
||||
case bitmapContype:
|
||||
c := &bitmapContainer{}
|
||||
_, err = c.UnmarshalMsg(v.r)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
ra.containers[i] = c
|
||||
case arrayContype:
|
||||
c := &arrayContainer{}
|
||||
_, err = c.UnmarshalMsg(v.r)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
ra.containers[i] = c
|
||||
case run16Contype:
|
||||
c := &runContainer16{}
|
||||
_, err = c.UnmarshalMsg(v.r)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
ra.containers[i] = c
|
||||
default:
|
||||
return fmt.Errorf("unrecognized contype serialization code: '%v'", v.t)
|
||||
}
|
||||
}
|
||||
ra.conserz = nil
|
||||
return nil
|
||||
}
|
||||
|
||||
func (ra *roaringArray) advanceUntil(min uint16, pos int) int {
|
||||
lower := pos + 1
|
||||
|
||||
|
||||
529
vendor/github.com/RoaringBitmap/roaring/roaringarray_gen.go
generated
vendored
529
vendor/github.com/RoaringBitmap/roaring/roaringarray_gen.go
generated
vendored
@@ -1,529 +0,0 @@
|
||||
package roaring
|
||||
|
||||
// NOTE: THIS FILE WAS PRODUCED BY THE
|
||||
// MSGP CODE GENERATION TOOL (github.com/tinylib/msgp)
|
||||
// DO NOT EDIT
|
||||
|
||||
import (
|
||||
"github.com/tinylib/msgp/msgp"
|
||||
)
|
||||
|
||||
// Deprecated: DecodeMsg implements msgp.Decodable
|
||||
func (z *containerSerz) DecodeMsg(dc *msgp.Reader) (err error) {
|
||||
var field []byte
|
||||
_ = field
|
||||
var zxvk uint32
|
||||
zxvk, err = dc.ReadMapHeader()
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
for zxvk > 0 {
|
||||
zxvk--
|
||||
field, err = dc.ReadMapKeyPtr()
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
switch msgp.UnsafeString(field) {
|
||||
case "t":
|
||||
{
|
||||
var zbzg uint8
|
||||
zbzg, err = dc.ReadUint8()
|
||||
z.t = contype(zbzg)
|
||||
}
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
case "r":
|
||||
err = z.r.DecodeMsg(dc)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
default:
|
||||
err = dc.Skip()
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// Deprecated: EncodeMsg implements msgp.Encodable
|
||||
func (z *containerSerz) EncodeMsg(en *msgp.Writer) (err error) {
|
||||
// map header, size 2
|
||||
// write "t"
|
||||
err = en.Append(0x82, 0xa1, 0x74)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = en.WriteUint8(uint8(z.t))
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
// write "r"
|
||||
err = en.Append(0xa1, 0x72)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = z.r.EncodeMsg(en)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// Deprecated: MarshalMsg implements msgp.Marshaler
|
||||
func (z *containerSerz) MarshalMsg(b []byte) (o []byte, err error) {
|
||||
o = msgp.Require(b, z.Msgsize())
|
||||
// map header, size 2
|
||||
// string "t"
|
||||
o = append(o, 0x82, 0xa1, 0x74)
|
||||
o = msgp.AppendUint8(o, uint8(z.t))
|
||||
// string "r"
|
||||
o = append(o, 0xa1, 0x72)
|
||||
o, err = z.r.MarshalMsg(o)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// Deprecated: UnmarshalMsg implements msgp.Unmarshaler
|
||||
func (z *containerSerz) UnmarshalMsg(bts []byte) (o []byte, err error) {
|
||||
var field []byte
|
||||
_ = field
|
||||
var zbai uint32
|
||||
zbai, bts, err = msgp.ReadMapHeaderBytes(bts)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
for zbai > 0 {
|
||||
zbai--
|
||||
field, bts, err = msgp.ReadMapKeyZC(bts)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
switch msgp.UnsafeString(field) {
|
||||
case "t":
|
||||
{
|
||||
var zcmr uint8
|
||||
zcmr, bts, err = msgp.ReadUint8Bytes(bts)
|
||||
z.t = contype(zcmr)
|
||||
}
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
case "r":
|
||||
bts, err = z.r.UnmarshalMsg(bts)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
default:
|
||||
bts, err = msgp.Skip(bts)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
o = bts
|
||||
return
|
||||
}
|
||||
|
||||
// Deprecated: Msgsize returns an upper bound estimate of the number of bytes occupied by the serialized message
|
||||
func (z *containerSerz) Msgsize() (s int) {
|
||||
s = 1 + 2 + msgp.Uint8Size + 2 + z.r.Msgsize()
|
||||
return
|
||||
}
|
||||
|
||||
// Deprecated: DecodeMsg implements msgp.Decodable
|
||||
func (z *contype) DecodeMsg(dc *msgp.Reader) (err error) {
|
||||
{
|
||||
var zajw uint8
|
||||
zajw, err = dc.ReadUint8()
|
||||
(*z) = contype(zajw)
|
||||
}
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// Deprecated: EncodeMsg implements msgp.Encodable
|
||||
func (z contype) EncodeMsg(en *msgp.Writer) (err error) {
|
||||
err = en.WriteUint8(uint8(z))
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// Deprecated: MarshalMsg implements msgp.Marshaler
|
||||
func (z contype) MarshalMsg(b []byte) (o []byte, err error) {
|
||||
o = msgp.Require(b, z.Msgsize())
|
||||
o = msgp.AppendUint8(o, uint8(z))
|
||||
return
|
||||
}
|
||||
|
||||
// Deprecated: UnmarshalMsg implements msgp.Unmarshaler
|
||||
func (z *contype) UnmarshalMsg(bts []byte) (o []byte, err error) {
|
||||
{
|
||||
var zwht uint8
|
||||
zwht, bts, err = msgp.ReadUint8Bytes(bts)
|
||||
(*z) = contype(zwht)
|
||||
}
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
o = bts
|
||||
return
|
||||
}
|
||||
|
||||
// Deprecated: Msgsize returns an upper bound estimate of the number of bytes occupied by the serialized message
|
||||
func (z contype) Msgsize() (s int) {
|
||||
s = msgp.Uint8Size
|
||||
return
|
||||
}
|
||||
|
||||
// Deprecated: DecodeMsg implements msgp.Decodable
|
||||
func (z *roaringArray) DecodeMsg(dc *msgp.Reader) (err error) {
|
||||
var field []byte
|
||||
_ = field
|
||||
var zlqf uint32
|
||||
zlqf, err = dc.ReadMapHeader()
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
for zlqf > 0 {
|
||||
zlqf--
|
||||
field, err = dc.ReadMapKeyPtr()
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
switch msgp.UnsafeString(field) {
|
||||
case "keys":
|
||||
var zdaf uint32
|
||||
zdaf, err = dc.ReadArrayHeader()
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
if cap(z.keys) >= int(zdaf) {
|
||||
z.keys = (z.keys)[:zdaf]
|
||||
} else {
|
||||
z.keys = make([]uint16, zdaf)
|
||||
}
|
||||
for zhct := range z.keys {
|
||||
z.keys[zhct], err = dc.ReadUint16()
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
}
|
||||
case "needCopyOnWrite":
|
||||
var zpks uint32
|
||||
zpks, err = dc.ReadArrayHeader()
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
if cap(z.needCopyOnWrite) >= int(zpks) {
|
||||
z.needCopyOnWrite = (z.needCopyOnWrite)[:zpks]
|
||||
} else {
|
||||
z.needCopyOnWrite = make([]bool, zpks)
|
||||
}
|
||||
for zcua := range z.needCopyOnWrite {
|
||||
z.needCopyOnWrite[zcua], err = dc.ReadBool()
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
}
|
||||
case "copyOnWrite":
|
||||
z.copyOnWrite, err = dc.ReadBool()
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
case "conserz":
|
||||
var zjfb uint32
|
||||
zjfb, err = dc.ReadArrayHeader()
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
if cap(z.conserz) >= int(zjfb) {
|
||||
z.conserz = (z.conserz)[:zjfb]
|
||||
} else {
|
||||
z.conserz = make([]containerSerz, zjfb)
|
||||
}
|
||||
for zxhx := range z.conserz {
|
||||
var zcxo uint32
|
||||
zcxo, err = dc.ReadMapHeader()
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
for zcxo > 0 {
|
||||
zcxo--
|
||||
field, err = dc.ReadMapKeyPtr()
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
switch msgp.UnsafeString(field) {
|
||||
case "t":
|
||||
{
|
||||
var zeff uint8
|
||||
zeff, err = dc.ReadUint8()
|
||||
z.conserz[zxhx].t = contype(zeff)
|
||||
}
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
case "r":
|
||||
err = z.conserz[zxhx].r.DecodeMsg(dc)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
default:
|
||||
err = dc.Skip()
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
default:
|
||||
err = dc.Skip()
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// Deprecated: EncodeMsg implements msgp.Encodable
|
||||
func (z *roaringArray) EncodeMsg(en *msgp.Writer) (err error) {
|
||||
// map header, size 4
|
||||
// write "keys"
|
||||
err = en.Append(0x84, 0xa4, 0x6b, 0x65, 0x79, 0x73)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = en.WriteArrayHeader(uint32(len(z.keys)))
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
for zhct := range z.keys {
|
||||
err = en.WriteUint16(z.keys[zhct])
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
}
|
||||
// write "needCopyOnWrite"
|
||||
err = en.Append(0xaf, 0x6e, 0x65, 0x65, 0x64, 0x43, 0x6f, 0x70, 0x79, 0x4f, 0x6e, 0x57, 0x72, 0x69, 0x74, 0x65)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = en.WriteArrayHeader(uint32(len(z.needCopyOnWrite)))
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
for zcua := range z.needCopyOnWrite {
|
||||
err = en.WriteBool(z.needCopyOnWrite[zcua])
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
}
|
||||
// write "copyOnWrite"
|
||||
err = en.Append(0xab, 0x63, 0x6f, 0x70, 0x79, 0x4f, 0x6e, 0x57, 0x72, 0x69, 0x74, 0x65)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = en.WriteBool(z.copyOnWrite)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
// write "conserz"
|
||||
err = en.Append(0xa7, 0x63, 0x6f, 0x6e, 0x73, 0x65, 0x72, 0x7a)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = en.WriteArrayHeader(uint32(len(z.conserz)))
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
for zxhx := range z.conserz {
|
||||
// map header, size 2
|
||||
// write "t"
|
||||
err = en.Append(0x82, 0xa1, 0x74)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = en.WriteUint8(uint8(z.conserz[zxhx].t))
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
// write "r"
|
||||
err = en.Append(0xa1, 0x72)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = z.conserz[zxhx].r.EncodeMsg(en)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// Deprecated: MarshalMsg implements msgp.Marshaler
|
||||
func (z *roaringArray) MarshalMsg(b []byte) (o []byte, err error) {
|
||||
o = msgp.Require(b, z.Msgsize())
|
||||
// map header, size 4
|
||||
// string "keys"
|
||||
o = append(o, 0x84, 0xa4, 0x6b, 0x65, 0x79, 0x73)
|
||||
o = msgp.AppendArrayHeader(o, uint32(len(z.keys)))
|
||||
for zhct := range z.keys {
|
||||
o = msgp.AppendUint16(o, z.keys[zhct])
|
||||
}
|
||||
// string "needCopyOnWrite"
|
||||
o = append(o, 0xaf, 0x6e, 0x65, 0x65, 0x64, 0x43, 0x6f, 0x70, 0x79, 0x4f, 0x6e, 0x57, 0x72, 0x69, 0x74, 0x65)
|
||||
o = msgp.AppendArrayHeader(o, uint32(len(z.needCopyOnWrite)))
|
||||
for zcua := range z.needCopyOnWrite {
|
||||
o = msgp.AppendBool(o, z.needCopyOnWrite[zcua])
|
||||
}
|
||||
// string "copyOnWrite"
|
||||
o = append(o, 0xab, 0x63, 0x6f, 0x70, 0x79, 0x4f, 0x6e, 0x57, 0x72, 0x69, 0x74, 0x65)
|
||||
o = msgp.AppendBool(o, z.copyOnWrite)
|
||||
// string "conserz"
|
||||
o = append(o, 0xa7, 0x63, 0x6f, 0x6e, 0x73, 0x65, 0x72, 0x7a)
|
||||
o = msgp.AppendArrayHeader(o, uint32(len(z.conserz)))
|
||||
for zxhx := range z.conserz {
|
||||
// map header, size 2
|
||||
// string "t"
|
||||
o = append(o, 0x82, 0xa1, 0x74)
|
||||
o = msgp.AppendUint8(o, uint8(z.conserz[zxhx].t))
|
||||
// string "r"
|
||||
o = append(o, 0xa1, 0x72)
|
||||
o, err = z.conserz[zxhx].r.MarshalMsg(o)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// Deprecated: UnmarshalMsg implements msgp.Unmarshaler
|
||||
func (z *roaringArray) UnmarshalMsg(bts []byte) (o []byte, err error) {
|
||||
var field []byte
|
||||
_ = field
|
||||
var zrsw uint32
|
||||
zrsw, bts, err = msgp.ReadMapHeaderBytes(bts)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
for zrsw > 0 {
|
||||
zrsw--
|
||||
field, bts, err = msgp.ReadMapKeyZC(bts)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
switch msgp.UnsafeString(field) {
|
||||
case "keys":
|
||||
var zxpk uint32
|
||||
zxpk, bts, err = msgp.ReadArrayHeaderBytes(bts)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
if cap(z.keys) >= int(zxpk) {
|
||||
z.keys = (z.keys)[:zxpk]
|
||||
} else {
|
||||
z.keys = make([]uint16, zxpk)
|
||||
}
|
||||
for zhct := range z.keys {
|
||||
z.keys[zhct], bts, err = msgp.ReadUint16Bytes(bts)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
}
|
||||
case "needCopyOnWrite":
|
||||
var zdnj uint32
|
||||
zdnj, bts, err = msgp.ReadArrayHeaderBytes(bts)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
if cap(z.needCopyOnWrite) >= int(zdnj) {
|
||||
z.needCopyOnWrite = (z.needCopyOnWrite)[:zdnj]
|
||||
} else {
|
||||
z.needCopyOnWrite = make([]bool, zdnj)
|
||||
}
|
||||
for zcua := range z.needCopyOnWrite {
|
||||
z.needCopyOnWrite[zcua], bts, err = msgp.ReadBoolBytes(bts)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
}
|
||||
case "copyOnWrite":
|
||||
z.copyOnWrite, bts, err = msgp.ReadBoolBytes(bts)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
case "conserz":
|
||||
var zobc uint32
|
||||
zobc, bts, err = msgp.ReadArrayHeaderBytes(bts)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
if cap(z.conserz) >= int(zobc) {
|
||||
z.conserz = (z.conserz)[:zobc]
|
||||
} else {
|
||||
z.conserz = make([]containerSerz, zobc)
|
||||
}
|
||||
for zxhx := range z.conserz {
|
||||
var zsnv uint32
|
||||
zsnv, bts, err = msgp.ReadMapHeaderBytes(bts)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
for zsnv > 0 {
|
||||
zsnv--
|
||||
field, bts, err = msgp.ReadMapKeyZC(bts)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
switch msgp.UnsafeString(field) {
|
||||
case "t":
|
||||
{
|
||||
var zkgt uint8
|
||||
zkgt, bts, err = msgp.ReadUint8Bytes(bts)
|
||||
z.conserz[zxhx].t = contype(zkgt)
|
||||
}
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
case "r":
|
||||
bts, err = z.conserz[zxhx].r.UnmarshalMsg(bts)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
default:
|
||||
bts, err = msgp.Skip(bts)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
default:
|
||||
bts, err = msgp.Skip(bts)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
o = bts
|
||||
return
|
||||
}
|
||||
|
||||
// Deprecated: Msgsize returns an upper bound estimate of the number of bytes occupied by the serialized message
|
||||
func (z *roaringArray) Msgsize() (s int) {
|
||||
s = 1 + 5 + msgp.ArrayHeaderSize + (len(z.keys) * (msgp.Uint16Size)) + 16 + msgp.ArrayHeaderSize + (len(z.needCopyOnWrite) * (msgp.BoolSize)) + 12 + msgp.BoolSize + 8 + msgp.ArrayHeaderSize
|
||||
for zxhx := range z.conserz {
|
||||
s += 1 + 2 + msgp.Uint8Size + 2 + z.conserz[zxhx].r.Msgsize()
|
||||
}
|
||||
return
|
||||
}
|
||||
1001
vendor/github.com/RoaringBitmap/roaring/runcontainer.go
generated
vendored
1001
vendor/github.com/RoaringBitmap/roaring/runcontainer.go
generated
vendored
File diff suppressed because it is too large
Load Diff
1126
vendor/github.com/RoaringBitmap/roaring/runcontainer_gen.go
generated
vendored
1126
vendor/github.com/RoaringBitmap/roaring/runcontainer_gen.go
generated
vendored
File diff suppressed because it is too large
Load Diff
51
vendor/github.com/RoaringBitmap/roaring/serialization.go
generated
vendored
51
vendor/github.com/RoaringBitmap/roaring/serialization.go
generated
vendored
@@ -2,11 +2,7 @@ package roaring
|
||||
|
||||
import (
|
||||
"encoding/binary"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
|
||||
"github.com/tinylib/msgp/msgp"
|
||||
)
|
||||
|
||||
// writeTo for runContainer16 follows this
|
||||
@@ -21,50 +17,3 @@ func (b *runContainer16) writeTo(stream io.Writer) (int, error) {
|
||||
}
|
||||
return stream.Write(buf)
|
||||
}
|
||||
|
||||
func (b *runContainer16) writeToMsgpack(stream io.Writer) (int, error) {
|
||||
bts, err := b.MarshalMsg(nil)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
return stream.Write(bts)
|
||||
}
|
||||
|
||||
func (b *runContainer16) readFromMsgpack(stream io.Reader) (int, error) {
|
||||
err := msgp.Decode(stream, b)
|
||||
return 0, err
|
||||
}
|
||||
|
||||
var errCorruptedStream = errors.New("insufficient/odd number of stored bytes, corrupted stream detected")
|
||||
|
||||
func (b *runContainer16) readFrom(stream io.Reader) (int, error) {
|
||||
b.iv = b.iv[:0]
|
||||
b.card = 0
|
||||
var numRuns uint16
|
||||
err := binary.Read(stream, binary.LittleEndian, &numRuns)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
nr := int(numRuns)
|
||||
encRun := make([]uint16, 2*nr)
|
||||
by := make([]byte, 4*nr)
|
||||
err = binary.Read(stream, binary.LittleEndian, &by)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
for i := range encRun {
|
||||
if len(by) < 2 {
|
||||
return 0, errCorruptedStream
|
||||
}
|
||||
encRun[i] = binary.LittleEndian.Uint16(by)
|
||||
by = by[2:]
|
||||
}
|
||||
for i := 0; i < nr; i++ {
|
||||
if i > 0 && b.iv[i-1].last() >= encRun[i*2] {
|
||||
return 0, fmt.Errorf("error: stored runContainer had runs that were not in sorted order!! (b.iv[i-1=%v].last = %v >= encRun[i=%v] = %v)", i-1, b.iv[i-1].last(), i, encRun[i*2])
|
||||
}
|
||||
b.iv = append(b.iv, interval16{start: encRun[i*2], length: encRun[i*2+1]})
|
||||
b.card += int64(encRun[i*2+1]) + 1
|
||||
}
|
||||
return 0, err
|
||||
}
|
||||
|
||||
24
vendor/github.com/RoaringBitmap/roaring/serialization_generic.go
generated
vendored
24
vendor/github.com/RoaringBitmap/roaring/serialization_generic.go
generated
vendored
@@ -1,4 +1,5 @@
|
||||
// +build !amd64,!386 appengine
|
||||
//go:build (!amd64 && !386 && !arm && !arm64 && !ppc64le && !mipsle && !mips64le && !mips64p32le && !wasm) || appengine
|
||||
// +build !amd64,!386,!arm,!arm64,!ppc64le,!mipsle,!mips64le,!mips64p32le,!wasm appengine
|
||||
|
||||
package roaring
|
||||
|
||||
@@ -74,6 +75,27 @@ func uint64SliceAsByteSlice(slice []uint64) []byte {
|
||||
return by
|
||||
}
|
||||
|
||||
func uint16SliceAsByteSlice(slice []uint16) []byte {
|
||||
by := make([]byte, len(slice)*2)
|
||||
|
||||
for i, v := range slice {
|
||||
binary.LittleEndian.PutUint16(by[i*2:], v)
|
||||
}
|
||||
|
||||
return by
|
||||
}
|
||||
|
||||
func interval16SliceAsByteSlice(slice []interval16) []byte {
|
||||
by := make([]byte, len(slice)*4)
|
||||
|
||||
for i, v := range slice {
|
||||
binary.LittleEndian.PutUint16(by[i*2:], v.start)
|
||||
binary.LittleEndian.PutUint16(by[i*2+2:], v.length)
|
||||
}
|
||||
|
||||
return by
|
||||
}
|
||||
|
||||
func byteSliceAsUint16Slice(slice []byte) []uint16 {
|
||||
if len(slice)%2 != 0 {
|
||||
panic("Slice size should be divisible by 2")
|
||||
|
||||
615
vendor/github.com/RoaringBitmap/roaring/serialization_littleendian.go
generated
vendored
615
vendor/github.com/RoaringBitmap/roaring/serialization_littleendian.go
generated
vendored
@@ -1,11 +1,14 @@
|
||||
// +build 386 amd64,!appengine
|
||||
//go:build (386 && !appengine) || (amd64 && !appengine) || (arm && !appengine) || (arm64 && !appengine) || (ppc64le && !appengine) || (mipsle && !appengine) || (mips64le && !appengine) || (mips64p32le && !appengine) || (wasm && !appengine)
|
||||
// +build 386,!appengine amd64,!appengine arm,!appengine arm64,!appengine ppc64le,!appengine mipsle,!appengine mips64le,!appengine mips64p32le,!appengine wasm,!appengine
|
||||
|
||||
package roaring
|
||||
|
||||
import (
|
||||
"encoding/binary"
|
||||
"errors"
|
||||
"io"
|
||||
"reflect"
|
||||
"runtime"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
@@ -22,22 +25,6 @@ func (bc *bitmapContainer) writeTo(stream io.Writer) (int, error) {
|
||||
return stream.Write(buf)
|
||||
}
|
||||
|
||||
// readFrom reads an arrayContainer from stream.
|
||||
// PRE-REQUISITE: you must size the arrayContainer correctly (allocate b.content)
|
||||
// *before* you call readFrom. We can't guess the size in the stream
|
||||
// by this point.
|
||||
func (ac *arrayContainer) readFrom(stream io.Reader) (int, error) {
|
||||
buf := uint16SliceAsByteSlice(ac.content)
|
||||
return io.ReadFull(stream, buf)
|
||||
}
|
||||
|
||||
func (bc *bitmapContainer) readFrom(stream io.Reader) (int, error) {
|
||||
buf := uint64SliceAsByteSlice(bc.bitmap)
|
||||
n, err := io.ReadFull(stream, buf)
|
||||
bc.computeCardinality()
|
||||
return n, err
|
||||
}
|
||||
|
||||
func uint64SliceAsByteSlice(slice []uint64) []byte {
|
||||
// make a new slice header
|
||||
header := *(*reflect.SliceHeader)(unsafe.Pointer(&slice))
|
||||
@@ -46,8 +33,12 @@ func uint64SliceAsByteSlice(slice []uint64) []byte {
|
||||
header.Len *= 8
|
||||
header.Cap *= 8
|
||||
|
||||
// instantiate result and use KeepAlive so data isn't unmapped.
|
||||
result := *(*[]byte)(unsafe.Pointer(&header))
|
||||
runtime.KeepAlive(&slice)
|
||||
|
||||
// return it
|
||||
return *(*[]byte)(unsafe.Pointer(&header))
|
||||
return result
|
||||
}
|
||||
|
||||
func uint16SliceAsByteSlice(slice []uint16) []byte {
|
||||
@@ -58,8 +49,28 @@ func uint16SliceAsByteSlice(slice []uint16) []byte {
|
||||
header.Len *= 2
|
||||
header.Cap *= 2
|
||||
|
||||
// instantiate result and use KeepAlive so data isn't unmapped.
|
||||
result := *(*[]byte)(unsafe.Pointer(&header))
|
||||
runtime.KeepAlive(&slice)
|
||||
|
||||
// return it
|
||||
return *(*[]byte)(unsafe.Pointer(&header))
|
||||
return result
|
||||
}
|
||||
|
||||
func interval16SliceAsByteSlice(slice []interval16) []byte {
|
||||
// make a new slice header
|
||||
header := *(*reflect.SliceHeader)(unsafe.Pointer(&slice))
|
||||
|
||||
// update its capacity and length
|
||||
header.Len *= 4
|
||||
header.Cap *= 4
|
||||
|
||||
// instantiate result and use KeepAlive so data isn't unmapped.
|
||||
result := *(*[]byte)(unsafe.Pointer(&header))
|
||||
runtime.KeepAlive(&slice)
|
||||
|
||||
// return it
|
||||
return result
|
||||
}
|
||||
|
||||
func (bc *bitmapContainer) asLittleEndianByteSlice() []byte {
|
||||
@@ -68,50 +79,574 @@ func (bc *bitmapContainer) asLittleEndianByteSlice() []byte {
|
||||
|
||||
// Deserialization code follows
|
||||
|
||||
func byteSliceAsUint16Slice(slice []byte) []uint16 {
|
||||
////
|
||||
// These methods (byteSliceAsUint16Slice,...) do not make copies,
|
||||
// they are pointer-based (unsafe). The caller is responsible to
|
||||
// ensure that the input slice does not get garbage collected, deleted
|
||||
// or modified while you hold the returned slince.
|
||||
////
|
||||
func byteSliceAsUint16Slice(slice []byte) (result []uint16) { // here we create a new slice holder
|
||||
if len(slice)%2 != 0 {
|
||||
panic("Slice size should be divisible by 2")
|
||||
}
|
||||
// reference: https://go101.org/article/unsafe.html
|
||||
|
||||
// make a new slice header
|
||||
header := *(*reflect.SliceHeader)(unsafe.Pointer(&slice))
|
||||
bHeader := (*reflect.SliceHeader)(unsafe.Pointer(&slice))
|
||||
rHeader := (*reflect.SliceHeader)(unsafe.Pointer(&result))
|
||||
|
||||
// update its capacity and length
|
||||
header.Len /= 2
|
||||
header.Cap /= 2
|
||||
// transfer the data from the given slice to a new variable (our result)
|
||||
rHeader.Data = bHeader.Data
|
||||
rHeader.Len = bHeader.Len / 2
|
||||
rHeader.Cap = bHeader.Cap / 2
|
||||
|
||||
// return it
|
||||
return *(*[]uint16)(unsafe.Pointer(&header))
|
||||
// instantiate result and use KeepAlive so data isn't unmapped.
|
||||
runtime.KeepAlive(&slice) // it is still crucial, GC can free it)
|
||||
|
||||
// return result
|
||||
return
|
||||
}
|
||||
|
||||
func byteSliceAsUint64Slice(slice []byte) []uint64 {
|
||||
func byteSliceAsUint64Slice(slice []byte) (result []uint64) {
|
||||
if len(slice)%8 != 0 {
|
||||
panic("Slice size should be divisible by 8")
|
||||
}
|
||||
// reference: https://go101.org/article/unsafe.html
|
||||
|
||||
// make a new slice header
|
||||
header := *(*reflect.SliceHeader)(unsafe.Pointer(&slice))
|
||||
bHeader := (*reflect.SliceHeader)(unsafe.Pointer(&slice))
|
||||
rHeader := (*reflect.SliceHeader)(unsafe.Pointer(&result))
|
||||
|
||||
// update its capacity and length
|
||||
header.Len /= 8
|
||||
header.Cap /= 8
|
||||
// transfer the data from the given slice to a new variable (our result)
|
||||
rHeader.Data = bHeader.Data
|
||||
rHeader.Len = bHeader.Len / 8
|
||||
rHeader.Cap = bHeader.Cap / 8
|
||||
|
||||
// return it
|
||||
return *(*[]uint64)(unsafe.Pointer(&header))
|
||||
// instantiate result and use KeepAlive so data isn't unmapped.
|
||||
runtime.KeepAlive(&slice) // it is still crucial, GC can free it)
|
||||
|
||||
// return result
|
||||
return
|
||||
}
|
||||
|
||||
func byteSliceAsInterval16Slice(slice []byte) []interval16 {
|
||||
func byteSliceAsInterval16Slice(slice []byte) (result []interval16) {
|
||||
if len(slice)%4 != 0 {
|
||||
panic("Slice size should be divisible by 4")
|
||||
}
|
||||
// reference: https://go101.org/article/unsafe.html
|
||||
|
||||
// make a new slice header
|
||||
header := *(*reflect.SliceHeader)(unsafe.Pointer(&slice))
|
||||
bHeader := (*reflect.SliceHeader)(unsafe.Pointer(&slice))
|
||||
rHeader := (*reflect.SliceHeader)(unsafe.Pointer(&result))
|
||||
|
||||
// update its capacity and length
|
||||
header.Len /= 4
|
||||
header.Cap /= 4
|
||||
// transfer the data from the given slice to a new variable (our result)
|
||||
rHeader.Data = bHeader.Data
|
||||
rHeader.Len = bHeader.Len / 4
|
||||
rHeader.Cap = bHeader.Cap / 4
|
||||
|
||||
// return it
|
||||
return *(*[]interval16)(unsafe.Pointer(&header))
|
||||
// instantiate result and use KeepAlive so data isn't unmapped.
|
||||
runtime.KeepAlive(&slice) // it is still crucial, GC can free it)
|
||||
|
||||
// return result
|
||||
return
|
||||
}
|
||||
|
||||
func byteSliceAsContainerSlice(slice []byte) (result []container) {
|
||||
var c container
|
||||
containerSize := int(unsafe.Sizeof(c))
|
||||
|
||||
if len(slice)%containerSize != 0 {
|
||||
panic("Slice size should be divisible by unsafe.Sizeof(container)")
|
||||
}
|
||||
// reference: https://go101.org/article/unsafe.html
|
||||
|
||||
// make a new slice header
|
||||
bHeader := (*reflect.SliceHeader)(unsafe.Pointer(&slice))
|
||||
rHeader := (*reflect.SliceHeader)(unsafe.Pointer(&result))
|
||||
|
||||
// transfer the data from the given slice to a new variable (our result)
|
||||
rHeader.Data = bHeader.Data
|
||||
rHeader.Len = bHeader.Len / containerSize
|
||||
rHeader.Cap = bHeader.Cap / containerSize
|
||||
|
||||
// instantiate result and use KeepAlive so data isn't unmapped.
|
||||
runtime.KeepAlive(&slice) // it is still crucial, GC can free it)
|
||||
|
||||
// return result
|
||||
return
|
||||
}
|
||||
|
||||
func byteSliceAsBitsetSlice(slice []byte) (result []bitmapContainer) {
|
||||
bitsetSize := int(unsafe.Sizeof(bitmapContainer{}))
|
||||
if len(slice)%bitsetSize != 0 {
|
||||
panic("Slice size should be divisible by unsafe.Sizeof(bitmapContainer)")
|
||||
}
|
||||
// reference: https://go101.org/article/unsafe.html
|
||||
|
||||
// make a new slice header
|
||||
bHeader := (*reflect.SliceHeader)(unsafe.Pointer(&slice))
|
||||
rHeader := (*reflect.SliceHeader)(unsafe.Pointer(&result))
|
||||
|
||||
// transfer the data from the given slice to a new variable (our result)
|
||||
rHeader.Data = bHeader.Data
|
||||
rHeader.Len = bHeader.Len / bitsetSize
|
||||
rHeader.Cap = bHeader.Cap / bitsetSize
|
||||
|
||||
// instantiate result and use KeepAlive so data isn't unmapped.
|
||||
runtime.KeepAlive(&slice) // it is still crucial, GC can free it)
|
||||
|
||||
// return result
|
||||
return
|
||||
}
|
||||
|
||||
func byteSliceAsArraySlice(slice []byte) (result []arrayContainer) {
|
||||
arraySize := int(unsafe.Sizeof(arrayContainer{}))
|
||||
if len(slice)%arraySize != 0 {
|
||||
panic("Slice size should be divisible by unsafe.Sizeof(arrayContainer)")
|
||||
}
|
||||
// reference: https://go101.org/article/unsafe.html
|
||||
|
||||
// make a new slice header
|
||||
bHeader := (*reflect.SliceHeader)(unsafe.Pointer(&slice))
|
||||
rHeader := (*reflect.SliceHeader)(unsafe.Pointer(&result))
|
||||
|
||||
// transfer the data from the given slice to a new variable (our result)
|
||||
rHeader.Data = bHeader.Data
|
||||
rHeader.Len = bHeader.Len / arraySize
|
||||
rHeader.Cap = bHeader.Cap / arraySize
|
||||
|
||||
// instantiate result and use KeepAlive so data isn't unmapped.
|
||||
runtime.KeepAlive(&slice) // it is still crucial, GC can free it)
|
||||
|
||||
// return result
|
||||
return
|
||||
}
|
||||
|
||||
func byteSliceAsRun16Slice(slice []byte) (result []runContainer16) {
|
||||
run16Size := int(unsafe.Sizeof(runContainer16{}))
|
||||
if len(slice)%run16Size != 0 {
|
||||
panic("Slice size should be divisible by unsafe.Sizeof(runContainer16)")
|
||||
}
|
||||
// reference: https://go101.org/article/unsafe.html
|
||||
|
||||
// make a new slice header
|
||||
bHeader := (*reflect.SliceHeader)(unsafe.Pointer(&slice))
|
||||
rHeader := (*reflect.SliceHeader)(unsafe.Pointer(&result))
|
||||
|
||||
// transfer the data from the given slice to a new variable (our result)
|
||||
rHeader.Data = bHeader.Data
|
||||
rHeader.Len = bHeader.Len / run16Size
|
||||
rHeader.Cap = bHeader.Cap / run16Size
|
||||
|
||||
// instantiate result and use KeepAlive so data isn't unmapped.
|
||||
runtime.KeepAlive(&slice) // it is still crucial, GC can free it)
|
||||
|
||||
// return result
|
||||
return
|
||||
}
|
||||
|
||||
func byteSliceAsBoolSlice(slice []byte) (result []bool) {
|
||||
boolSize := int(unsafe.Sizeof(true))
|
||||
if len(slice)%boolSize != 0 {
|
||||
panic("Slice size should be divisible by unsafe.Sizeof(bool)")
|
||||
}
|
||||
// reference: https://go101.org/article/unsafe.html
|
||||
|
||||
// make a new slice header
|
||||
bHeader := (*reflect.SliceHeader)(unsafe.Pointer(&slice))
|
||||
rHeader := (*reflect.SliceHeader)(unsafe.Pointer(&result))
|
||||
|
||||
// transfer the data from the given slice to a new variable (our result)
|
||||
rHeader.Data = bHeader.Data
|
||||
rHeader.Len = bHeader.Len / boolSize
|
||||
rHeader.Cap = bHeader.Cap / boolSize
|
||||
|
||||
// instantiate result and use KeepAlive so data isn't unmapped.
|
||||
runtime.KeepAlive(&slice) // it is still crucial, GC can free it)
|
||||
|
||||
// return result
|
||||
return
|
||||
}
|
||||
|
||||
// FrozenView creates a static view of a serialized bitmap stored in buf.
|
||||
// It uses CRoaring's frozen bitmap format.
|
||||
//
|
||||
// The format specification is available here:
|
||||
// https://github.com/RoaringBitmap/CRoaring/blob/2c867e9f9c9e2a3a7032791f94c4c7ae3013f6e0/src/roaring.c#L2756-L2783
|
||||
//
|
||||
// The provided byte array (buf) is expected to be a constant.
|
||||
// The function makes the best effort attempt not to copy data.
|
||||
// Only little endian is supported. The function will err if it detects a big
|
||||
// endian serialized file.
|
||||
// You should take care not to modify buff as it will likely result in
|
||||
// unexpected program behavior.
|
||||
// If said buffer comes from a memory map, it's advisable to give it read
|
||||
// only permissions, either at creation or by calling Mprotect from the
|
||||
// golang.org/x/sys/unix package.
|
||||
//
|
||||
// Resulting bitmaps are effectively immutable in the following sense:
|
||||
// a copy-on-write marker is used so that when you modify the resulting
|
||||
// bitmap, copies of selected data (containers) are made.
|
||||
// You should *not* change the copy-on-write status of the resulting
|
||||
// bitmaps (SetCopyOnWrite).
|
||||
//
|
||||
// If buf becomes unavailable, then a bitmap created with
|
||||
// FromBuffer would be effectively broken. Furthermore, any
|
||||
// bitmap derived from this bitmap (e.g., via Or, And) might
|
||||
// also be broken. Thus, before making buf unavailable, you should
|
||||
// call CloneCopyOnWriteContainers on all such bitmaps.
|
||||
//
|
||||
func (rb *Bitmap) FrozenView(buf []byte) error {
|
||||
return rb.highlowcontainer.frozenView(buf)
|
||||
}
|
||||
|
||||
/* Verbatim specification from CRoaring.
|
||||
*
|
||||
* FROZEN SERIALIZATION FORMAT DESCRIPTION
|
||||
*
|
||||
* -- (beginning must be aligned by 32 bytes) --
|
||||
* <bitset_data> uint64_t[BITSET_CONTAINER_SIZE_IN_WORDS * num_bitset_containers]
|
||||
* <run_data> rle16_t[total number of rle elements in all run containers]
|
||||
* <array_data> uint16_t[total number of array elements in all array containers]
|
||||
* <keys> uint16_t[num_containers]
|
||||
* <counts> uint16_t[num_containers]
|
||||
* <typecodes> uint8_t[num_containers]
|
||||
* <header> uint32_t
|
||||
*
|
||||
* <header> is a 4-byte value which is a bit union of FROZEN_COOKIE (15 bits)
|
||||
* and the number of containers (17 bits).
|
||||
*
|
||||
* <counts> stores number of elements for every container.
|
||||
* Its meaning depends on container type.
|
||||
* For array and bitset containers, this value is the container cardinality minus one.
|
||||
* For run container, it is the number of rle_t elements (n_runs).
|
||||
*
|
||||
* <bitset_data>,<array_data>,<run_data> are flat arrays of elements of
|
||||
* all containers of respective type.
|
||||
*
|
||||
* <*_data> and <keys> are kept close together because they are not accessed
|
||||
* during deserilization. This may reduce IO in case of large mmaped bitmaps.
|
||||
* All members have their native alignments during deserilization except <header>,
|
||||
* which is not guaranteed to be aligned by 4 bytes.
|
||||
*/
|
||||
const FROZEN_COOKIE = 13766
|
||||
|
||||
var (
|
||||
FrozenBitmapInvalidCookie = errors.New("header does not contain the FROZEN_COOKIE")
|
||||
FrozenBitmapBigEndian = errors.New("loading big endian frozen bitmaps is not supported")
|
||||
FrozenBitmapIncomplete = errors.New("input buffer too small to contain a frozen bitmap")
|
||||
FrozenBitmapOverpopulated = errors.New("too many containers")
|
||||
FrozenBitmapUnexpectedData = errors.New("spurious data in input")
|
||||
FrozenBitmapInvalidTypecode = errors.New("unrecognized typecode")
|
||||
FrozenBitmapBufferTooSmall = errors.New("buffer too small")
|
||||
)
|
||||
|
||||
func (ra *roaringArray) frozenView(buf []byte) error {
|
||||
if len(buf) < 4 {
|
||||
return FrozenBitmapIncomplete
|
||||
}
|
||||
|
||||
headerBE := binary.BigEndian.Uint32(buf[len(buf)-4:])
|
||||
if headerBE&0x7fff == FROZEN_COOKIE {
|
||||
return FrozenBitmapBigEndian
|
||||
}
|
||||
|
||||
header := binary.LittleEndian.Uint32(buf[len(buf)-4:])
|
||||
buf = buf[:len(buf)-4]
|
||||
|
||||
if header&0x7fff != FROZEN_COOKIE {
|
||||
return FrozenBitmapInvalidCookie
|
||||
}
|
||||
|
||||
nCont := int(header >> 15)
|
||||
if nCont > (1 << 16) {
|
||||
return FrozenBitmapOverpopulated
|
||||
}
|
||||
|
||||
// 1 byte per type, 2 bytes per key, 2 bytes per count.
|
||||
if len(buf) < 5*nCont {
|
||||
return FrozenBitmapIncomplete
|
||||
}
|
||||
|
||||
types := buf[len(buf)-nCont:]
|
||||
buf = buf[:len(buf)-nCont]
|
||||
|
||||
counts := byteSliceAsUint16Slice(buf[len(buf)-2*nCont:])
|
||||
buf = buf[:len(buf)-2*nCont]
|
||||
|
||||
keys := byteSliceAsUint16Slice(buf[len(buf)-2*nCont:])
|
||||
buf = buf[:len(buf)-2*nCont]
|
||||
|
||||
nBitmap, nArray, nRun := 0, 0, 0
|
||||
nArrayEl, nRunEl := 0, 0
|
||||
for i, t := range types {
|
||||
switch t {
|
||||
case 1:
|
||||
nBitmap++
|
||||
case 2:
|
||||
nArray++
|
||||
nArrayEl += int(counts[i]) + 1
|
||||
case 3:
|
||||
nRun++
|
||||
nRunEl += int(counts[i])
|
||||
default:
|
||||
return FrozenBitmapInvalidTypecode
|
||||
}
|
||||
}
|
||||
|
||||
if len(buf) < (1<<13)*nBitmap+4*nRunEl+2*nArrayEl {
|
||||
return FrozenBitmapIncomplete
|
||||
}
|
||||
|
||||
bitsetsArena := byteSliceAsUint64Slice(buf[:(1<<13)*nBitmap])
|
||||
buf = buf[(1<<13)*nBitmap:]
|
||||
|
||||
runsArena := byteSliceAsInterval16Slice(buf[:4*nRunEl])
|
||||
buf = buf[4*nRunEl:]
|
||||
|
||||
arraysArena := byteSliceAsUint16Slice(buf[:2*nArrayEl])
|
||||
buf = buf[2*nArrayEl:]
|
||||
|
||||
if len(buf) != 0 {
|
||||
return FrozenBitmapUnexpectedData
|
||||
}
|
||||
|
||||
var c container
|
||||
containersSz := int(unsafe.Sizeof(c))*nCont
|
||||
bitsetsSz := int(unsafe.Sizeof(bitmapContainer{}))*nBitmap
|
||||
arraysSz := int(unsafe.Sizeof(arrayContainer{}))*nArray
|
||||
runsSz := int(unsafe.Sizeof(runContainer16{}))*nRun
|
||||
needCOWSz := int(unsafe.Sizeof(true))*nCont
|
||||
|
||||
bitmapArenaSz := containersSz + bitsetsSz + arraysSz + runsSz + needCOWSz
|
||||
bitmapArena := make([]byte, bitmapArenaSz)
|
||||
|
||||
containers := byteSliceAsContainerSlice(bitmapArena[:containersSz])
|
||||
bitmapArena = bitmapArena[containersSz:]
|
||||
|
||||
bitsets := byteSliceAsBitsetSlice(bitmapArena[:bitsetsSz])
|
||||
bitmapArena = bitmapArena[bitsetsSz:]
|
||||
|
||||
arrays := byteSliceAsArraySlice(bitmapArena[:arraysSz])
|
||||
bitmapArena = bitmapArena[arraysSz:]
|
||||
|
||||
runs := byteSliceAsRun16Slice(bitmapArena[:runsSz])
|
||||
bitmapArena = bitmapArena[runsSz:]
|
||||
|
||||
needCOW := byteSliceAsBoolSlice(bitmapArena)
|
||||
|
||||
iBitset, iArray, iRun := 0, 0, 0
|
||||
for i, t := range types {
|
||||
needCOW[i] = true
|
||||
|
||||
switch t {
|
||||
case 1:
|
||||
containers[i] = &bitsets[iBitset]
|
||||
bitsets[iBitset].cardinality = int(counts[i]) + 1
|
||||
bitsets[iBitset].bitmap = bitsetsArena[:1024]
|
||||
bitsetsArena = bitsetsArena[1024:]
|
||||
iBitset++
|
||||
case 2:
|
||||
containers[i] = &arrays[iArray]
|
||||
sz := int(counts[i]) + 1
|
||||
arrays[iArray].content = arraysArena[:sz]
|
||||
arraysArena = arraysArena[sz:]
|
||||
iArray++
|
||||
case 3:
|
||||
containers[i] = &runs[iRun]
|
||||
runs[iRun].iv = runsArena[:counts[i]]
|
||||
runsArena = runsArena[counts[i]:]
|
||||
iRun++
|
||||
}
|
||||
}
|
||||
|
||||
// Not consuming the full input is a bug.
|
||||
if iBitset != nBitmap || len(bitsetsArena) != 0 ||
|
||||
iArray != nArray || len(arraysArena) != 0 ||
|
||||
iRun != nRun || len(runsArena) != 0 {
|
||||
panic("we missed something")
|
||||
}
|
||||
|
||||
ra.keys = keys
|
||||
ra.containers = containers
|
||||
ra.needCopyOnWrite = needCOW
|
||||
ra.copyOnWrite = true
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (bm *Bitmap) GetFrozenSizeInBytes() uint64 {
|
||||
nBits, nArrayEl, nRunEl := uint64(0), uint64(0), uint64(0)
|
||||
for _, c := range bm.highlowcontainer.containers {
|
||||
switch v := c.(type) {
|
||||
case *bitmapContainer:
|
||||
nBits++
|
||||
case *arrayContainer:
|
||||
nArrayEl += uint64(len(v.content))
|
||||
case *runContainer16:
|
||||
nRunEl += uint64(len(v.iv))
|
||||
}
|
||||
}
|
||||
return 4 + 5*uint64(len(bm.highlowcontainer.containers)) +
|
||||
(nBits << 13) + 2*nArrayEl + 4*nRunEl
|
||||
}
|
||||
|
||||
func (bm *Bitmap) Freeze() ([]byte, error) {
|
||||
sz := bm.GetFrozenSizeInBytes()
|
||||
buf := make([]byte, sz)
|
||||
_, err := bm.FreezeTo(buf)
|
||||
return buf, err
|
||||
}
|
||||
|
||||
func (bm *Bitmap) FreezeTo(buf []byte) (int, error) {
|
||||
containers := bm.highlowcontainer.containers
|
||||
nCont := len(containers)
|
||||
|
||||
nBits, nArrayEl, nRunEl := 0, 0, 0
|
||||
for _, c := range containers {
|
||||
switch v := c.(type) {
|
||||
case *bitmapContainer:
|
||||
nBits++
|
||||
case *arrayContainer:
|
||||
nArrayEl += len(v.content)
|
||||
case *runContainer16:
|
||||
nRunEl += len(v.iv)
|
||||
}
|
||||
}
|
||||
|
||||
serialSize := 4 + 5*nCont + (1<<13)*nBits + 4*nRunEl + 2*nArrayEl
|
||||
if len(buf) < serialSize {
|
||||
return 0, FrozenBitmapBufferTooSmall
|
||||
}
|
||||
|
||||
bitsArena := byteSliceAsUint64Slice(buf[:(1<<13)*nBits])
|
||||
buf = buf[(1<<13)*nBits:]
|
||||
|
||||
runsArena := byteSliceAsInterval16Slice(buf[:4*nRunEl])
|
||||
buf = buf[4*nRunEl:]
|
||||
|
||||
arraysArena := byteSliceAsUint16Slice(buf[:2*nArrayEl])
|
||||
buf = buf[2*nArrayEl:]
|
||||
|
||||
keys := byteSliceAsUint16Slice(buf[:2*nCont])
|
||||
buf = buf[2*nCont:]
|
||||
|
||||
counts := byteSliceAsUint16Slice(buf[:2*nCont])
|
||||
buf = buf[2*nCont:]
|
||||
|
||||
types := buf[:nCont]
|
||||
buf = buf[nCont:]
|
||||
|
||||
header := uint32(FROZEN_COOKIE | (nCont << 15))
|
||||
binary.LittleEndian.PutUint32(buf[:4], header)
|
||||
|
||||
copy(keys, bm.highlowcontainer.keys[:])
|
||||
|
||||
for i, c := range containers {
|
||||
switch v := c.(type) {
|
||||
case *bitmapContainer:
|
||||
copy(bitsArena, v.bitmap)
|
||||
bitsArena = bitsArena[1024:]
|
||||
counts[i] = uint16(v.cardinality - 1)
|
||||
types[i] = 1
|
||||
case *arrayContainer:
|
||||
copy(arraysArena, v.content)
|
||||
arraysArena = arraysArena[len(v.content):]
|
||||
elems := len(v.content)
|
||||
counts[i] = uint16(elems - 1)
|
||||
types[i] = 2
|
||||
case *runContainer16:
|
||||
copy(runsArena, v.iv)
|
||||
runs := len(v.iv)
|
||||
runsArena = runsArena[runs:]
|
||||
counts[i] = uint16(runs)
|
||||
types[i] = 3
|
||||
}
|
||||
}
|
||||
|
||||
return serialSize, nil
|
||||
}
|
||||
|
||||
func (bm *Bitmap) WriteFrozenTo(wr io.Writer) (int, error) {
|
||||
// FIXME: this is a naive version that iterates 4 times through the
|
||||
// containers and allocates 3*len(containers) bytes; it's quite likely
|
||||
// it can be done more efficiently.
|
||||
containers := bm.highlowcontainer.containers
|
||||
written := 0
|
||||
|
||||
for _, c := range containers {
|
||||
c, ok := c.(*bitmapContainer)
|
||||
if !ok {
|
||||
continue
|
||||
}
|
||||
n, err := wr.Write(uint64SliceAsByteSlice(c.bitmap))
|
||||
written += n
|
||||
if err != nil {
|
||||
return written, err
|
||||
}
|
||||
}
|
||||
|
||||
for _, c := range containers {
|
||||
c, ok := c.(*runContainer16)
|
||||
if !ok {
|
||||
continue
|
||||
}
|
||||
n, err := wr.Write(interval16SliceAsByteSlice(c.iv))
|
||||
written += n
|
||||
if err != nil {
|
||||
return written, err
|
||||
}
|
||||
}
|
||||
|
||||
for _, c := range containers {
|
||||
c, ok := c.(*arrayContainer)
|
||||
if !ok {
|
||||
continue
|
||||
}
|
||||
n, err := wr.Write(uint16SliceAsByteSlice(c.content))
|
||||
written += n
|
||||
if err != nil {
|
||||
return written, err
|
||||
}
|
||||
}
|
||||
|
||||
n, err := wr.Write(uint16SliceAsByteSlice(bm.highlowcontainer.keys))
|
||||
written += n
|
||||
if err != nil {
|
||||
return written, err
|
||||
}
|
||||
|
||||
countTypeBuf := make([]byte, 3*len(containers))
|
||||
counts := byteSliceAsUint16Slice(countTypeBuf[:2*len(containers)])
|
||||
types := countTypeBuf[2*len(containers):]
|
||||
|
||||
for i, c := range containers {
|
||||
switch c := c.(type) {
|
||||
case *bitmapContainer:
|
||||
counts[i] = uint16(c.cardinality - 1)
|
||||
types[i] = 1
|
||||
case *arrayContainer:
|
||||
elems := len(c.content)
|
||||
counts[i] = uint16(elems - 1)
|
||||
types[i] = 2
|
||||
case *runContainer16:
|
||||
runs := len(c.iv)
|
||||
counts[i] = uint16(runs)
|
||||
types[i] = 3
|
||||
}
|
||||
}
|
||||
|
||||
n, err = wr.Write(countTypeBuf)
|
||||
written += n
|
||||
if err != nil {
|
||||
return written, err
|
||||
}
|
||||
|
||||
header := uint32(FROZEN_COOKIE | (len(containers) << 15))
|
||||
if err := binary.Write(wr, binary.LittleEndian, header); err != nil {
|
||||
return written, err
|
||||
}
|
||||
written += 4
|
||||
|
||||
return written, nil
|
||||
}
|
||||
|
||||
1
vendor/github.com/RoaringBitmap/roaring/serializationfuzz.go
generated
vendored
1
vendor/github.com/RoaringBitmap/roaring/serializationfuzz.go
generated
vendored
@@ -1,3 +1,4 @@
|
||||
//go:build gofuzz
|
||||
// +build gofuzz
|
||||
|
||||
package roaring
|
||||
|
||||
61
vendor/github.com/RoaringBitmap/roaring/setutil.go
generated
vendored
61
vendor/github.com/RoaringBitmap/roaring/setutil.go
generated
vendored
@@ -14,6 +14,7 @@ func equal(a, b []uint16) bool {
|
||||
|
||||
func difference(set1 []uint16, set2 []uint16, buffer []uint16) int {
|
||||
if 0 == len(set2) {
|
||||
buffer = buffer[:len(set1)]
|
||||
for k := 0; k < len(set1); k++ {
|
||||
buffer[k] = set1[k]
|
||||
}
|
||||
@@ -134,66 +135,6 @@ func exclusiveUnion2by2(set1 []uint16, set2 []uint16, buffer []uint16) int {
|
||||
return pos
|
||||
}
|
||||
|
||||
func union2by2(set1 []uint16, set2 []uint16, buffer []uint16) int {
|
||||
pos := 0
|
||||
k1 := 0
|
||||
k2 := 0
|
||||
if 0 == len(set2) {
|
||||
buffer = buffer[:len(set1)]
|
||||
copy(buffer, set1[:])
|
||||
return len(set1)
|
||||
}
|
||||
if 0 == len(set1) {
|
||||
buffer = buffer[:len(set2)]
|
||||
copy(buffer, set2[:])
|
||||
return len(set2)
|
||||
}
|
||||
s1 := set1[k1]
|
||||
s2 := set2[k2]
|
||||
buffer = buffer[:cap(buffer)]
|
||||
for {
|
||||
if s1 < s2 {
|
||||
buffer[pos] = s1
|
||||
pos++
|
||||
k1++
|
||||
if k1 >= len(set1) {
|
||||
copy(buffer[pos:], set2[k2:])
|
||||
pos += len(set2) - k2
|
||||
break
|
||||
}
|
||||
s1 = set1[k1]
|
||||
} else if s1 == s2 {
|
||||
buffer[pos] = s1
|
||||
pos++
|
||||
k1++
|
||||
k2++
|
||||
if k1 >= len(set1) {
|
||||
copy(buffer[pos:], set2[k2:])
|
||||
pos += len(set2) - k2
|
||||
break
|
||||
}
|
||||
if k2 >= len(set2) {
|
||||
copy(buffer[pos:], set1[k1:])
|
||||
pos += len(set1) - k1
|
||||
break
|
||||
}
|
||||
s1 = set1[k1]
|
||||
s2 = set2[k2]
|
||||
} else { // if (set1[k1]>set2[k2])
|
||||
buffer[pos] = s2
|
||||
pos++
|
||||
k2++
|
||||
if k2 >= len(set2) {
|
||||
copy(buffer[pos:], set1[k1:])
|
||||
pos += len(set1) - k1
|
||||
break
|
||||
}
|
||||
s2 = set2[k2]
|
||||
}
|
||||
}
|
||||
return pos
|
||||
}
|
||||
|
||||
func union2by2Cardinality(set1 []uint16, set2 []uint16) int {
|
||||
pos := 0
|
||||
k1 := 0
|
||||
|
||||
7
vendor/github.com/RoaringBitmap/roaring/setutil_arm64.go
generated
vendored
Normal file
7
vendor/github.com/RoaringBitmap/roaring/setutil_arm64.go
generated
vendored
Normal file
@@ -0,0 +1,7 @@
|
||||
//go:build arm64 && !gccgo && !appengine
|
||||
// +build arm64,!gccgo,!appengine
|
||||
|
||||
package roaring
|
||||
|
||||
//go:noescape
|
||||
func union2by2(set1 []uint16, set2 []uint16, buffer []uint16) (size int)
|
||||
132
vendor/github.com/RoaringBitmap/roaring/setutil_arm64.s
generated
vendored
Normal file
132
vendor/github.com/RoaringBitmap/roaring/setutil_arm64.s
generated
vendored
Normal file
@@ -0,0 +1,132 @@
|
||||
// +build arm64,!gccgo,!appengine
|
||||
|
||||
#include "textflag.h"
|
||||
|
||||
|
||||
// This implements union2by2 using golang's version of arm64 assembly
|
||||
// The algorithm is very similar to the generic one,
|
||||
// but makes better use of arm64 features so is notably faster.
|
||||
// The basic algorithm structure is as follows:
|
||||
// 1. If either set is empty, copy the other set into the buffer and return the length
|
||||
// 2. Otherwise, load the first element of each set into a variable (s1 and s2).
|
||||
// 3. a. Compare the values of s1 and s2.
|
||||
// b. add the smaller one to the buffer.
|
||||
// c. perform a bounds check before incrementing.
|
||||
// If one set is finished, copy the rest of the other set over.
|
||||
// d. update s1 and or s2 to the next value, continue loop.
|
||||
//
|
||||
// Past the fact of the algorithm, this code makes use of several arm64 features
|
||||
// Condition Codes:
|
||||
// arm64's CMP operation sets 4 bits that can be used for branching,
|
||||
// rather than just true or false.
|
||||
// As a consequence, a single comparison gives enough information to distinguish the three cases
|
||||
//
|
||||
// Post-increment pointers after load/store:
|
||||
// Instructions like `MOVHU.P 2(R0), R6`
|
||||
// increment the register by a specified amount, in this example 2.
|
||||
// Because uint16's are exactly 2 bytes and the length of the slices
|
||||
// is part of the slice header,
|
||||
// there is no need to separately track the index into the slice.
|
||||
// Instead, the code can calculate the final read value and compare against that,
|
||||
// using the post-increment reads to move the pointers along.
|
||||
//
|
||||
// TODO: CALL out to memmove once the list is exhausted.
|
||||
// Right now it moves the necessary shorts so that the remaining count
|
||||
// is a multiple of 4 and then copies 64 bits at a time.
|
||||
|
||||
TEXT ·union2by2(SB), NOSPLIT, $0-80
|
||||
// R0, R1, and R2 for the pointers to the three slices
|
||||
MOVD set1+0(FP), R0
|
||||
MOVD set2+24(FP), R1
|
||||
MOVD buffer+48(FP), R2
|
||||
|
||||
//R3 and R4 will be the values at which we will have finished reading set1 and set2.
|
||||
// R3 should be R0 + 2 * set1_len+8(FP)
|
||||
MOVD set1_len+8(FP), R3
|
||||
MOVD set2_len+32(FP), R4
|
||||
|
||||
ADD R3<<1, R0, R3
|
||||
ADD R4<<1, R1, R4
|
||||
|
||||
|
||||
//Rather than counting the number of elements added separately
|
||||
//Save the starting register of buffer.
|
||||
MOVD buffer+48(FP), R5
|
||||
|
||||
// set1 is empty, just flush set2
|
||||
CMP R0, R3
|
||||
BEQ flush_right
|
||||
|
||||
// set2 is empty, just flush set1
|
||||
CMP R1, R4
|
||||
BEQ flush_left
|
||||
|
||||
// R6, R7 are the working space for s1 and s2
|
||||
MOVD ZR, R6
|
||||
MOVD ZR, R7
|
||||
|
||||
MOVHU.P 2(R0), R6
|
||||
MOVHU.P 2(R1), R7
|
||||
loop:
|
||||
|
||||
CMP R6, R7
|
||||
BEQ pop_both // R6 == R7
|
||||
BLS pop_right // R6 > R7
|
||||
//pop_left: // R6 < R7
|
||||
MOVHU.P R6, 2(R2)
|
||||
CMP R0, R3
|
||||
BEQ pop_then_flush_right
|
||||
MOVHU.P 2(R0), R6
|
||||
JMP loop
|
||||
pop_both:
|
||||
MOVHU.P R6, 2(R2) //could also use R7, since they are equal
|
||||
CMP R0, R3
|
||||
BEQ flush_right
|
||||
CMP R1, R4
|
||||
BEQ flush_left
|
||||
MOVHU.P 2(R0), R6
|
||||
MOVHU.P 2(R1), R7
|
||||
JMP loop
|
||||
pop_right:
|
||||
MOVHU.P R7, 2(R2)
|
||||
CMP R1, R4
|
||||
BEQ pop_then_flush_left
|
||||
MOVHU.P 2(R1), R7
|
||||
JMP loop
|
||||
|
||||
pop_then_flush_right:
|
||||
MOVHU.P R7, 2(R2)
|
||||
flush_right:
|
||||
MOVD R1, R0
|
||||
MOVD R4, R3
|
||||
JMP flush_left
|
||||
pop_then_flush_left:
|
||||
MOVHU.P R6, 2(R2)
|
||||
flush_left:
|
||||
CMP R0, R3
|
||||
BEQ return
|
||||
//figure out how many bytes to slough off. Must be a multiple of two
|
||||
SUB R0, R3, R4
|
||||
ANDS $6, R4
|
||||
BEQ long_flush //handles the 0 mod 8 case
|
||||
SUBS $4, R4, R4 // since possible values are 2, 4, 6, this splits evenly
|
||||
BLT pop_single // exactly the 2 case
|
||||
MOVW.P 4(R0), R6
|
||||
MOVW.P R6, 4(R2)
|
||||
BEQ long_flush // we're now aligned by 64 bits, as R4==4, otherwise 2 more
|
||||
pop_single:
|
||||
MOVHU.P 2(R0), R6
|
||||
MOVHU.P R6, 2(R2)
|
||||
long_flush:
|
||||
// at this point we know R3 - R0 is a multiple of 8.
|
||||
CMP R0, R3
|
||||
BEQ return
|
||||
MOVD.P 8(R0), R6
|
||||
MOVD.P R6, 8(R2)
|
||||
JMP long_flush
|
||||
return:
|
||||
// number of shorts written is (R5 - R2) >> 1
|
||||
SUB R5, R2
|
||||
LSR $1, R2, R2
|
||||
MOVD R2, size+72(FP)
|
||||
RET
|
||||
64
vendor/github.com/RoaringBitmap/roaring/setutil_generic.go
generated
vendored
Normal file
64
vendor/github.com/RoaringBitmap/roaring/setutil_generic.go
generated
vendored
Normal file
@@ -0,0 +1,64 @@
|
||||
//go:build !arm64 || gccgo || appengine
|
||||
// +build !arm64 gccgo appengine
|
||||
|
||||
package roaring
|
||||
|
||||
func union2by2(set1 []uint16, set2 []uint16, buffer []uint16) int {
|
||||
pos := 0
|
||||
k1 := 0
|
||||
k2 := 0
|
||||
if 0 == len(set2) {
|
||||
buffer = buffer[:len(set1)]
|
||||
copy(buffer, set1[:])
|
||||
return len(set1)
|
||||
}
|
||||
if 0 == len(set1) {
|
||||
buffer = buffer[:len(set2)]
|
||||
copy(buffer, set2[:])
|
||||
return len(set2)
|
||||
}
|
||||
s1 := set1[k1]
|
||||
s2 := set2[k2]
|
||||
buffer = buffer[:cap(buffer)]
|
||||
for {
|
||||
if s1 < s2 {
|
||||
buffer[pos] = s1
|
||||
pos++
|
||||
k1++
|
||||
if k1 >= len(set1) {
|
||||
copy(buffer[pos:], set2[k2:])
|
||||
pos += len(set2) - k2
|
||||
break
|
||||
}
|
||||
s1 = set1[k1]
|
||||
} else if s1 == s2 {
|
||||
buffer[pos] = s1
|
||||
pos++
|
||||
k1++
|
||||
k2++
|
||||
if k1 >= len(set1) {
|
||||
copy(buffer[pos:], set2[k2:])
|
||||
pos += len(set2) - k2
|
||||
break
|
||||
}
|
||||
if k2 >= len(set2) {
|
||||
copy(buffer[pos:], set1[k1:])
|
||||
pos += len(set1) - k1
|
||||
break
|
||||
}
|
||||
s1 = set1[k1]
|
||||
s2 = set2[k2]
|
||||
} else { // if (set1[k1]>set2[k2])
|
||||
buffer[pos] = s2
|
||||
pos++
|
||||
k2++
|
||||
if k2 >= len(set2) {
|
||||
copy(buffer[pos:], set1[k1:])
|
||||
pos += len(set1) - k1
|
||||
break
|
||||
}
|
||||
s2 = set2[k2]
|
||||
}
|
||||
}
|
||||
return pos
|
||||
}
|
||||
16
vendor/github.com/RoaringBitmap/roaring/shortiterator.go
generated
vendored
16
vendor/github.com/RoaringBitmap/roaring/shortiterator.go
generated
vendored
@@ -5,6 +5,12 @@ type shortIterable interface {
|
||||
next() uint16
|
||||
}
|
||||
|
||||
type shortPeekable interface {
|
||||
shortIterable
|
||||
peekNext() uint16
|
||||
advanceIfNeeded(minval uint16)
|
||||
}
|
||||
|
||||
type shortIterator struct {
|
||||
slice []uint16
|
||||
loc int
|
||||
@@ -20,6 +26,16 @@ func (si *shortIterator) next() uint16 {
|
||||
return a
|
||||
}
|
||||
|
||||
func (si *shortIterator) peekNext() uint16 {
|
||||
return si.slice[si.loc]
|
||||
}
|
||||
|
||||
func (si *shortIterator) advanceIfNeeded(minval uint16) {
|
||||
if si.hasNext() && si.peekNext() < minval {
|
||||
si.loc = advanceUntil(si.slice, si.loc, len(si.slice), minval)
|
||||
}
|
||||
}
|
||||
|
||||
type reverseIterator struct {
|
||||
slice []uint16
|
||||
loc int
|
||||
|
||||
3
vendor/github.com/RoaringBitmap/roaring/smat.go
generated
vendored
3
vendor/github.com/RoaringBitmap/roaring/smat.go
generated
vendored
@@ -1,3 +1,4 @@
|
||||
//go:build gofuzz
|
||||
// +build gofuzz
|
||||
|
||||
/*
|
||||
@@ -62,8 +63,8 @@ import (
|
||||
"fmt"
|
||||
"sort"
|
||||
|
||||
"github.com/bits-and-blooms/bitset"
|
||||
"github.com/mschoch/smat"
|
||||
"github.com/willf/bitset"
|
||||
)
|
||||
|
||||
// fuzz test using state machine driven by byte stream.
|
||||
|
||||
28
vendor/github.com/RoaringBitmap/roaring/util.go
generated
vendored
28
vendor/github.com/RoaringBitmap/roaring/util.go
generated
vendored
@@ -1,6 +1,7 @@
|
||||
package roaring
|
||||
|
||||
import (
|
||||
"math"
|
||||
"math/rand"
|
||||
"sort"
|
||||
)
|
||||
@@ -15,7 +16,7 @@ const (
|
||||
noOffsetThreshold = 4
|
||||
|
||||
// MaxUint32 is the largest uint32 value.
|
||||
MaxUint32 = 4294967295
|
||||
MaxUint32 = math.MaxUint32
|
||||
|
||||
// MaxRange is One more than the maximum allowed bitmap bit index. For use as an upper
|
||||
// bound for ranges.
|
||||
@@ -23,7 +24,7 @@ const (
|
||||
|
||||
// MaxUint16 is the largest 16 bit unsigned int.
|
||||
// This is the largest value an interval16 can store.
|
||||
MaxUint16 = 65535
|
||||
MaxUint16 = math.MaxUint16
|
||||
|
||||
// Compute wordSizeInBytes, the size of a word in bytes.
|
||||
_m = ^uint64(0)
|
||||
@@ -112,7 +113,7 @@ func highbits(x uint32) uint16 {
|
||||
return uint16(x >> 16)
|
||||
}
|
||||
func lowbits(x uint32) uint16 {
|
||||
return uint16(x & 0xFFFF)
|
||||
return uint16(x & maxLowBit)
|
||||
}
|
||||
|
||||
const maxLowBit = 0xFFFF
|
||||
@@ -302,24 +303,3 @@ func minOfUint16(a, b uint16) uint16 {
|
||||
}
|
||||
return b
|
||||
}
|
||||
|
||||
func maxInt(a, b int) int {
|
||||
if a > b {
|
||||
return a
|
||||
}
|
||||
return b
|
||||
}
|
||||
|
||||
func maxUint16(a, b uint16) uint16 {
|
||||
if a > b {
|
||||
return a
|
||||
}
|
||||
return b
|
||||
}
|
||||
|
||||
func minUint16(a, b uint16) uint16 {
|
||||
if a < b {
|
||||
return a
|
||||
}
|
||||
return b
|
||||
}
|
||||
|
||||
201
vendor/github.com/ajwerner/btree/LICENSE
generated
vendored
Normal file
201
vendor/github.com/ajwerner/btree/LICENSE
generated
vendored
Normal file
@@ -0,0 +1,201 @@
|
||||
Apache License
|
||||
Version 2.0, January 2004
|
||||
http://www.apache.org/licenses/
|
||||
|
||||
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||
|
||||
1. Definitions.
|
||||
|
||||
"License" shall mean the terms and conditions for use, reproduction,
|
||||
and distribution as defined by Sections 1 through 9 of this document.
|
||||
|
||||
"Licensor" shall mean the copyright owner or entity authorized by
|
||||
the copyright owner that is granting the License.
|
||||
|
||||
"Legal Entity" shall mean the union of the acting entity and all
|
||||
other entities that control, are controlled by, or are under common
|
||||
control with that entity. For the purposes of this definition,
|
||||
"control" means (i) the power, direct or indirect, to cause the
|
||||
direction or management of such entity, whether by contract or
|
||||
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||
|
||||
"You" (or "Your") shall mean an individual or Legal Entity
|
||||
exercising permissions granted by this License.
|
||||
|
||||
"Source" form shall mean the preferred form for making modifications,
|
||||
including but not limited to software source code, documentation
|
||||
source, and configuration files.
|
||||
|
||||
"Object" form shall mean any form resulting from mechanical
|
||||
transformation or translation of a Source form, including but
|
||||
not limited to compiled object code, generated documentation,
|
||||
and conversions to other media types.
|
||||
|
||||
"Work" shall mean the work of authorship, whether in Source or
|
||||
Object form, made available under the License, as indicated by a
|
||||
copyright notice that is included in or attached to the work
|
||||
(an example is provided in the Appendix below).
|
||||
|
||||
"Derivative Works" shall mean any work, whether in Source or Object
|
||||
form, that is based on (or derived from) the Work and for which the
|
||||
editorial revisions, annotations, elaborations, or other modifications
|
||||
represent, as a whole, an original work of authorship. For the purposes
|
||||
of this License, Derivative Works shall not include works that remain
|
||||
separable from, or merely link (or bind by name) to the interfaces of,
|
||||
the Work and Derivative Works thereof.
|
||||
|
||||
"Contribution" shall mean any work of authorship, including
|
||||
the original version of the Work and any modifications or additions
|
||||
to that Work or Derivative Works thereof, that is intentionally
|
||||
submitted to Licensor for inclusion in the Work by the copyright owner
|
||||
or by an individual or Legal Entity authorized to submit on behalf of
|
||||
the copyright owner. For the purposes of this definition, "submitted"
|
||||
means any form of electronic, verbal, or written communication sent
|
||||
to the Licensor or its representatives, including but not limited to
|
||||
communication on electronic mailing lists, source code control systems,
|
||||
and issue tracking systems that are managed by, or on behalf of, the
|
||||
Licensor for the purpose of discussing and improving the Work, but
|
||||
excluding communication that is conspicuously marked or otherwise
|
||||
designated in writing by the copyright owner as "Not a Contribution."
|
||||
|
||||
"Contributor" shall mean Licensor and any individual or Legal Entity
|
||||
on behalf of whom a Contribution has been received by Licensor and
|
||||
subsequently incorporated within the Work.
|
||||
|
||||
2. Grant of Copyright License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
copyright license to reproduce, prepare Derivative Works of,
|
||||
publicly display, publicly perform, sublicense, and distribute the
|
||||
Work and such Derivative Works in Source or Object form.
|
||||
|
||||
3. Grant of Patent License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
(except as stated in this section) patent license to make, have made,
|
||||
use, offer to sell, sell, import, and otherwise transfer the Work,
|
||||
where such license applies only to those patent claims licensable
|
||||
by such Contributor that are necessarily infringed by their
|
||||
Contribution(s) alone or by combination of their Contribution(s)
|
||||
with the Work to which such Contribution(s) was submitted. If You
|
||||
institute patent litigation against any entity (including a
|
||||
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
||||
or a Contribution incorporated within the Work constitutes direct
|
||||
or contributory patent infringement, then any patent licenses
|
||||
granted to You under this License for that Work shall terminate
|
||||
as of the date such litigation is filed.
|
||||
|
||||
4. Redistribution. You may reproduce and distribute copies of the
|
||||
Work or Derivative Works thereof in any medium, with or without
|
||||
modifications, and in Source or Object form, provided that You
|
||||
meet the following conditions:
|
||||
|
||||
(a) You must give any other recipients of the Work or
|
||||
Derivative Works a copy of this License; and
|
||||
|
||||
(b) You must cause any modified files to carry prominent notices
|
||||
stating that You changed the files; and
|
||||
|
||||
(c) You must retain, in the Source form of any Derivative Works
|
||||
that You distribute, all copyright, patent, trademark, and
|
||||
attribution notices from the Source form of the Work,
|
||||
excluding those notices that do not pertain to any part of
|
||||
the Derivative Works; and
|
||||
|
||||
(d) If the Work includes a "NOTICE" text file as part of its
|
||||
distribution, then any Derivative Works that You distribute must
|
||||
include a readable copy of the attribution notices contained
|
||||
within such NOTICE file, excluding those notices that do not
|
||||
pertain to any part of the Derivative Works, in at least one
|
||||
of the following places: within a NOTICE text file distributed
|
||||
as part of the Derivative Works; within the Source form or
|
||||
documentation, if provided along with the Derivative Works; or,
|
||||
within a display generated by the Derivative Works, if and
|
||||
wherever such third-party notices normally appear. The contents
|
||||
of the NOTICE file are for informational purposes only and
|
||||
do not modify the License. You may add Your own attribution
|
||||
notices within Derivative Works that You distribute, alongside
|
||||
or as an addendum to the NOTICE text from the Work, provided
|
||||
that such additional attribution notices cannot be construed
|
||||
as modifying the License.
|
||||
|
||||
You may add Your own copyright statement to Your modifications and
|
||||
may provide additional or different license terms and conditions
|
||||
for use, reproduction, or distribution of Your modifications, or
|
||||
for any such Derivative Works as a whole, provided Your use,
|
||||
reproduction, and distribution of the Work otherwise complies with
|
||||
the conditions stated in this License.
|
||||
|
||||
5. Submission of Contributions. Unless You explicitly state otherwise,
|
||||
any Contribution intentionally submitted for inclusion in the Work
|
||||
by You to the Licensor shall be under the terms and conditions of
|
||||
this License, without any additional terms or conditions.
|
||||
Notwithstanding the above, nothing herein shall supersede or modify
|
||||
the terms of any separate license agreement you may have executed
|
||||
with Licensor regarding such Contributions.
|
||||
|
||||
6. Trademarks. This License does not grant permission to use the trade
|
||||
names, trademarks, service marks, or product names of the Licensor,
|
||||
except as required for reasonable and customary use in describing the
|
||||
origin of the Work and reproducing the content of the NOTICE file.
|
||||
|
||||
7. Disclaimer of Warranty. Unless required by applicable law or
|
||||
agreed to in writing, Licensor provides the Work (and each
|
||||
Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
implied, including, without limitation, any warranties or conditions
|
||||
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
||||
PARTICULAR PURPOSE. You are solely responsible for determining the
|
||||
appropriateness of using or redistributing the Work and assume any
|
||||
risks associated with Your exercise of permissions under this License.
|
||||
|
||||
8. Limitation of Liability. In no event and under no legal theory,
|
||||
whether in tort (including negligence), contract, or otherwise,
|
||||
unless required by applicable law (such as deliberate and grossly
|
||||
negligent acts) or agreed to in writing, shall any Contributor be
|
||||
liable to You for damages, including any direct, indirect, special,
|
||||
incidental, or consequential damages of any character arising as a
|
||||
result of this License or out of the use or inability to use the
|
||||
Work (including but not limited to damages for loss of goodwill,
|
||||
work stoppage, computer failure or malfunction, or any and all
|
||||
other commercial damages or losses), even if such Contributor
|
||||
has been advised of the possibility of such damages.
|
||||
|
||||
9. Accepting Warranty or Additional Liability. While redistributing
|
||||
the Work or Derivative Works thereof, You may choose to offer,
|
||||
and charge a fee for, acceptance of support, warranty, indemnity,
|
||||
or other liability obligations and/or rights consistent with this
|
||||
License. However, in accepting such obligations, You may act only
|
||||
on Your own behalf and on Your sole responsibility, not on behalf
|
||||
of any other Contributor, and only if You agree to indemnify,
|
||||
defend, and hold each Contributor harmless for any liability
|
||||
incurred by, or claims asserted against, such Contributor by reason
|
||||
of your accepting any such warranty or additional liability.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
APPENDIX: How to apply the Apache License to your work.
|
||||
|
||||
To apply the Apache License to your work, attach the following
|
||||
boilerplate notice, with the fields enclosed by brackets "[]"
|
||||
replaced with your own identifying information. (Don't include
|
||||
the brackets!) The text should be enclosed in the appropriate
|
||||
comment syntax for the file format. We also recommend that a
|
||||
file or class name and description of purpose be included on the
|
||||
same "printed page" as the copyright notice for easier
|
||||
identification within third-party archives.
|
||||
|
||||
Copyright [yyyy] [name of copyright owner]
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
7
vendor/github.com/ajwerner/btree/README.md
generated
vendored
Normal file
7
vendor/github.com/ajwerner/btree/README.md
generated
vendored
Normal file
@@ -0,0 +1,7 @@
|
||||
# btree
|
||||
|
||||
go 1.18 generics experiment in building generic augmented btree data structures.
|
||||
|
||||
Don't use this in production, go 1.18 isn't even out yet!
|
||||
|
||||
Read more about this in the introductory [blog post](./blog/blog.md).
|
||||
61
vendor/github.com/ajwerner/btree/btree.go
generated
vendored
Normal file
61
vendor/github.com/ajwerner/btree/btree.go
generated
vendored
Normal file
@@ -0,0 +1,61 @@
|
||||
// Copyright 2021 Andrew Werner.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
// implied. See the License for the specific language governing
|
||||
// permissions and limitations under the License.
|
||||
|
||||
package btree
|
||||
|
||||
import "github.com/ajwerner/btree/internal/abstract"
|
||||
|
||||
// Map is a ordered map from K to V.
|
||||
type Map[K, V any] struct {
|
||||
abstract.Map[K, V, struct{}]
|
||||
}
|
||||
|
||||
// MakeMap constructs a new Map with the provided comparison function.
|
||||
func MakeMap[K, V any](cmp func(K, K) int) Map[K, V] {
|
||||
return Map[K, V]{
|
||||
Map: abstract.MakeMap[K, V, struct{}](cmp, nil),
|
||||
}
|
||||
}
|
||||
|
||||
// Clone clones the Map, lazily. It does so in constant time.
|
||||
func (m *Map[K, V]) Clone() Map[K, V] {
|
||||
return Map[K, V]{Map: m.Map.Clone()}
|
||||
}
|
||||
|
||||
// Set is an ordered set of items of type T.
|
||||
type Set[T any] Map[T, struct{}]
|
||||
|
||||
// MakeSet constructs a new Set with the provided comparison function.
|
||||
func MakeSet[T any](cmp func(T, T) int) Set[T] {
|
||||
return (Set[T])(MakeMap[T, struct{}](cmp))
|
||||
}
|
||||
|
||||
// Clone clones the Set, lazily. It does so in constant time.
|
||||
func (t *Set[T]) Clone() Set[T] {
|
||||
return (Set[T])((*Map[T, struct{}])(t).Clone())
|
||||
}
|
||||
|
||||
// Upsert inserts or updates the provided item. It returns
|
||||
// the overwritten item if a previous value existed for the key.
|
||||
func (t *Set[T]) Upsert(item T) (replaced T, overwrote bool) {
|
||||
replaced, _, overwrote = t.Map.Upsert(item, struct{}{})
|
||||
return replaced, overwrote
|
||||
}
|
||||
|
||||
// Delete removes the value with the provided key. It returns true if the
|
||||
// item existed in the set.
|
||||
func (t *Set[K]) Delete(item K) (removed bool) {
|
||||
_, _, removed = t.Map.Delete(item)
|
||||
return removed
|
||||
}
|
||||
181
vendor/github.com/ajwerner/btree/internal/abstract/aug_btree.go
generated
vendored
Normal file
181
vendor/github.com/ajwerner/btree/internal/abstract/aug_btree.go
generated
vendored
Normal file
@@ -0,0 +1,181 @@
|
||||
// Copyright 2018 The Cockroach Authors.
|
||||
// Copyright 2021 Andrew Werner.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
// implied. See the License for the specific language governing
|
||||
// permissions and limitations under the License.
|
||||
|
||||
package abstract
|
||||
|
||||
import (
|
||||
"strings"
|
||||
)
|
||||
|
||||
// TODO(ajwerner): It'd be amazing to find a way to make this not a single
|
||||
// compile-time constant.
|
||||
|
||||
const (
|
||||
Degree = 64
|
||||
MaxEntries = 2*Degree - 1
|
||||
MinEntries = Degree - 1
|
||||
)
|
||||
|
||||
// TODO(ajwerner): Probably we want comparison to occur on pointers to the
|
||||
// objects rather than the objects themselves, at least in some cases. For very
|
||||
// large objects, probably it's better to just store the objects as pointers
|
||||
// in the abstract itself and to use a sync.Pool to pool allocations. For very
|
||||
// small objects, directly calling less on the object is probably ideal. The
|
||||
// question is mid-sized objects.
|
||||
|
||||
// Map is an implementation of an augmented B-Tree.
|
||||
//
|
||||
// Write operations are not safe for concurrent mutation by multiple
|
||||
// goroutines, but Read operations are.
|
||||
type Map[K, V, A any] struct {
|
||||
root *Node[K, V, A]
|
||||
length int
|
||||
cfg config[K, V, A]
|
||||
}
|
||||
|
||||
// MakeMap constructs a new Map.
|
||||
func MakeMap[K, V, A any](cmp func(K, K) int, up Updater[K, V, A]) Map[K, V, A] {
|
||||
return Map[K, V, A]{
|
||||
cfg: makeConfig(cmp, up),
|
||||
}
|
||||
}
|
||||
|
||||
// Reset removes all items from the AugBTree. In doing so, it allows memory
|
||||
// held by the AugBTree to be recycled. Failure to call this method before
|
||||
// letting a AugBTree be GCed is safe in that it won't cause a memory leak,
|
||||
// but it will prevent AugBTree nodes from being efficiently re-used.
|
||||
func (t *Map[K, V, A]) Reset() {
|
||||
if t.root != nil {
|
||||
t.root.decRef(t.cfg.np, true /* recursive */)
|
||||
t.root = nil
|
||||
}
|
||||
t.length = 0
|
||||
}
|
||||
|
||||
// Clone clones the AugBTree, lazily. It does so in constant time.
|
||||
func (t *Map[K, V, A]) Clone() Map[K, V, A] {
|
||||
if t.root != nil {
|
||||
// Incrementing the reference count on the root node is sufficient to
|
||||
// ensure that no node in the cloned tree can be mutated by an actor
|
||||
// holding a reference to the original tree and vice versa. This
|
||||
// property is upheld because the root node in the receiver AugBTree and
|
||||
// the returned AugBTree will both necessarily have a reference count of at
|
||||
// least 2 when this method returns. All tree mutations recursively
|
||||
// acquire mutable node references (see mut) as they traverse down the
|
||||
// tree. The act of acquiring a mutable node reference performs a clone
|
||||
// if a node's reference count is greater than one. Cloning a node (see
|
||||
// clone) increases the reference count on each of its children,
|
||||
// ensuring that they have a reference count of at least 2. This, in
|
||||
// turn, ensures that any of the child nodes that are modified will also
|
||||
// be copied-on-write, recursively ensuring the immutability property
|
||||
// over the entire tree.
|
||||
t.root.incRef()
|
||||
}
|
||||
return *t
|
||||
}
|
||||
|
||||
// Delete removes an item equal to the passed in item from the tree.
|
||||
func (t *Map[K, V, A]) Delete(k K) (removedK K, v V, found bool) {
|
||||
if t.root == nil || t.root.count == 0 {
|
||||
return removedK, v, false
|
||||
}
|
||||
if removedK, v, found, _ = mut(t.cfg.np, &t.root).remove(&t.cfg, k); found {
|
||||
t.length--
|
||||
}
|
||||
if t.root.count == 0 {
|
||||
old := t.root
|
||||
if t.root.IsLeaf() {
|
||||
t.root = nil
|
||||
} else {
|
||||
t.root = t.root.children[0]
|
||||
}
|
||||
old.decRef(t.cfg.np, false /* recursive */)
|
||||
}
|
||||
return removedK, v, found
|
||||
}
|
||||
|
||||
// Upsert adds the given item to the tree. If an item in the tree already equals
|
||||
// the given one, it is replaced with the new item.
|
||||
func (t *Map[K, V, A]) Upsert(item K, value V) (replacedK K, replacedV V, replaced bool) {
|
||||
if t.root == nil {
|
||||
t.root = t.cfg.np.getLeafNode()
|
||||
} else if t.root.count >= MaxEntries {
|
||||
splitLaK, splitLaV, splitNode := mut(t.cfg.np, &t.root).
|
||||
split(&t.cfg, MaxEntries/2)
|
||||
newRoot := t.cfg.np.getInteriorNode()
|
||||
newRoot.count = 1
|
||||
newRoot.keys[0] = splitLaK
|
||||
newRoot.values[0] = splitLaV
|
||||
newRoot.children[0] = t.root
|
||||
newRoot.children[1] = splitNode
|
||||
newRoot.update(&t.cfg.Config)
|
||||
t.root = newRoot
|
||||
}
|
||||
replacedK, replacedV, replaced, _ = mut(t.cfg.np, &t.root).
|
||||
insert(&t.cfg, item, value)
|
||||
if !replaced {
|
||||
t.length++
|
||||
}
|
||||
return replacedK, replacedV, replaced
|
||||
}
|
||||
|
||||
// MakeIter returns a new Iterator object. It is not safe to continue using an
|
||||
// Iterator after modifications are made to the tree. If modifications are made,
|
||||
// create a new Iterator.
|
||||
func (t *Map[K, V, A]) Iterator() Iterator[K, V, A] {
|
||||
it := Iterator[K, V, A]{r: t}
|
||||
it.Reset()
|
||||
return it
|
||||
}
|
||||
|
||||
// Height returns the height of the tree.
|
||||
func (t *Map[K, V, A]) Height() int {
|
||||
if t.root == nil {
|
||||
return 0
|
||||
}
|
||||
h := 1
|
||||
n := t.root
|
||||
for !n.IsLeaf() {
|
||||
n = n.children[0]
|
||||
h++
|
||||
}
|
||||
return h
|
||||
}
|
||||
|
||||
// Len returns the number of items currently in the tree.
|
||||
func (t *Map[K, V, A]) Len() int {
|
||||
return t.length
|
||||
}
|
||||
|
||||
// Get returns the value associated with the requested key, if it exists.
|
||||
func (t *Map[K, V, A]) Get(k K) (v V, ok bool) {
|
||||
it := t.Iterator()
|
||||
it.SeekGE(k)
|
||||
if it.Valid() && it.Compare(it.Cur(), k) == 0 {
|
||||
return it.Value(), true
|
||||
}
|
||||
return v, false
|
||||
}
|
||||
|
||||
// String returns a string description of the tree. The format is
|
||||
// similar to the https://en.wikipedia.org/wiki/Newick_format.
|
||||
func (t *Map[K, V, A]) String() string {
|
||||
if t.length == 0 {
|
||||
return ";"
|
||||
}
|
||||
var b strings.Builder
|
||||
t.root.writeString(&b)
|
||||
return b.String()
|
||||
}
|
||||
98
vendor/github.com/ajwerner/btree/internal/abstract/config.go
generated
vendored
Normal file
98
vendor/github.com/ajwerner/btree/internal/abstract/config.go
generated
vendored
Normal file
@@ -0,0 +1,98 @@
|
||||
// Copyright 2021 Andrew Werner.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
// implied. See the License for the specific language governing
|
||||
// permissions and limitations under the License.
|
||||
|
||||
package abstract
|
||||
|
||||
// Config is used to configure the tree. It consists of a comparison function
|
||||
// for keys and any auxiliary data provided by the instantiator. It is provided
|
||||
// on the iterator and passed to the augmentation's Update method.
|
||||
type Config[K, V, A any] struct {
|
||||
|
||||
// Updater is used to update the augmentations to the tree.
|
||||
Updater Updater[K, V, A]
|
||||
|
||||
cmp func(K, K) int
|
||||
}
|
||||
|
||||
// Updater is used to update the augmentation of the node when the subtree
|
||||
// changes.
|
||||
type Updater[K, V, A any] interface {
|
||||
|
||||
// Update should update the augmentation of the passed node, optionally
|
||||
// using the data in the UpdataMeta to optimize the update. If the
|
||||
// augmentation changed, and thus, changes should occur in the ancestors
|
||||
// of the subtree rooted at this node, return true.
|
||||
Update(*Node[K, V, A], UpdateInfo[K, A]) (changed bool)
|
||||
}
|
||||
|
||||
// UpdateInfo is used to describe the update operation.
|
||||
type UpdateInfo[K, A any] struct {
|
||||
|
||||
// Action indicates the semantics of the below fields. If Default, no
|
||||
// fields will be populated.
|
||||
Action Action
|
||||
|
||||
// ModifiedOther is the augmentation of a node which was either a previous
|
||||
// child (Removal), new child (Insertion), or represents the new
|
||||
// right-hand-side after a split.
|
||||
ModifiedOther *A
|
||||
|
||||
// RelevantKey will be populated in all non-Default events.
|
||||
RelevantKey K
|
||||
}
|
||||
|
||||
// Action is used to classify the type of Update in order to permit various
|
||||
// optimizations when updated the augmented state.
|
||||
type Action int
|
||||
|
||||
const (
|
||||
|
||||
// Default implies that no assumptions may be made with regards to the
|
||||
// change in state of the node and thus the augmented state should be
|
||||
// recalculated in full.
|
||||
Default Action = iota
|
||||
|
||||
// Split indicates that this node is the left-hand side of a split.
|
||||
// The ModifiedOther will correspond to the updated state of the
|
||||
// augmentation for the right-hand side and the RelevantKey is the split
|
||||
// key to be moved into the parent.
|
||||
Split
|
||||
|
||||
// Removal indicates that this is a removal event. If the RelevantNode is
|
||||
// populated, it indicates a rebalance which caused the node rooted
|
||||
// at that subtree to also be removed.
|
||||
Removal
|
||||
|
||||
// Insertion indicates that this is a insertion event. If the RelevantNode is
|
||||
// populated, it indicates a rebalance which caused the node rooted
|
||||
// at that subtree to also be added.
|
||||
Insertion
|
||||
)
|
||||
|
||||
// Compare compares two values using the same comparison function as the Map.
|
||||
func (c *Config[K, V, A]) Compare(a, b K) int { return c.cmp(a, b) }
|
||||
|
||||
type config[K, V, A any] struct {
|
||||
Config[K, V, A]
|
||||
np *nodePool[K, V, A]
|
||||
}
|
||||
|
||||
func makeConfig[K, V, A any](
|
||||
cmp func(K, K) int, up Updater[K, V, A],
|
||||
) (c config[K, V, A]) {
|
||||
c.Updater = up
|
||||
c.cmp = cmp
|
||||
c.np = getNodePool[K, V, A]()
|
||||
return c
|
||||
}
|
||||
73
vendor/github.com/ajwerner/btree/internal/abstract/iter_stack.go
generated
vendored
Normal file
73
vendor/github.com/ajwerner/btree/internal/abstract/iter_stack.go
generated
vendored
Normal file
@@ -0,0 +1,73 @@
|
||||
// Copyright 2018 The Cockroach Authors.
|
||||
// Copyright 2021 Andrew Werner.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
// implied. See the License for the specific language governing
|
||||
// permissions and limitations under the License.
|
||||
|
||||
package abstract
|
||||
|
||||
// iterStack represents a stack of (node, pos) tuples, which captures
|
||||
// iteration state as an Iterator descends a AugBTree.
|
||||
type iterStack[K, V, A any] struct {
|
||||
a iterStackArr[K, V, A]
|
||||
aLen int16 // -1 when using s
|
||||
s []iterFrame[K, V, A]
|
||||
}
|
||||
|
||||
const iterStackDepth = 10
|
||||
|
||||
// Used to avoid allocations for stacks below a certain size.
|
||||
type iterStackArr[K, V, A any] [iterStackDepth]iterFrame[K, V, A]
|
||||
|
||||
type iterFrame[K, V, A any] struct {
|
||||
node *Node[K, V, A]
|
||||
pos int16
|
||||
}
|
||||
|
||||
func (is *iterStack[K, V, A]) push(f iterFrame[K, V, A]) {
|
||||
if is.aLen == -1 {
|
||||
is.s = append(is.s, f)
|
||||
} else if int(is.aLen) == len(is.a) {
|
||||
is.s = make([](iterFrame[K, V, A]), int(is.aLen)+1, 2*int(is.aLen))
|
||||
copy(is.s, is.a[:])
|
||||
is.s[int(is.aLen)] = f
|
||||
is.aLen = -1
|
||||
} else {
|
||||
is.a[is.aLen] = f
|
||||
is.aLen++
|
||||
}
|
||||
}
|
||||
|
||||
func (is *iterStack[K, V, A]) pop() iterFrame[K, V, A] {
|
||||
if is.aLen == -1 {
|
||||
f := is.s[len(is.s)-1]
|
||||
is.s = is.s[:len(is.s)-1]
|
||||
return f
|
||||
}
|
||||
is.aLen--
|
||||
return is.a[is.aLen]
|
||||
}
|
||||
|
||||
func (is *iterStack[K, V, A]) len() int {
|
||||
if is.aLen == -1 {
|
||||
return len(is.s)
|
||||
}
|
||||
return int(is.aLen)
|
||||
}
|
||||
|
||||
func (is *iterStack[K, V, A]) reset() {
|
||||
if is.aLen == -1 {
|
||||
is.s = is.s[:0]
|
||||
} else {
|
||||
is.aLen = 0
|
||||
}
|
||||
}
|
||||
179
vendor/github.com/ajwerner/btree/internal/abstract/iterator.go
generated
vendored
Normal file
179
vendor/github.com/ajwerner/btree/internal/abstract/iterator.go
generated
vendored
Normal file
@@ -0,0 +1,179 @@
|
||||
// Copyright 2018 The Cockroach Authors.
|
||||
// Copyright 2021 Andrew Werner.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
// implied. See the License for the specific language governing
|
||||
// permissions and limitations under the License.
|
||||
|
||||
package abstract
|
||||
|
||||
// Iterator is responsible for search and traversal within a AugBTree.
|
||||
type Iterator[K, V, A any] struct {
|
||||
r *Map[K, V, A]
|
||||
iterFrame[K, V, A]
|
||||
s iterStack[K, V, A]
|
||||
}
|
||||
|
||||
func (i *Iterator[K, V, A]) lowLevel() *LowLevelIterator[K, V, A] {
|
||||
return (*LowLevelIterator[K, V, A])(i)
|
||||
}
|
||||
|
||||
// Compare compares two keys using the same comparison function as the map.
|
||||
func (i *Iterator[K, V, A]) Compare(a, b K) int {
|
||||
return i.r.cfg.cmp(a, b)
|
||||
}
|
||||
|
||||
// Reset marks the iterator as invalid and clears any state.
|
||||
func (i *Iterator[K, V, A]) Reset() {
|
||||
i.node = i.r.root
|
||||
i.pos = -1
|
||||
i.s.reset()
|
||||
}
|
||||
|
||||
// SeekGE seeks to the first key greater-than or equal to the provided
|
||||
// key.
|
||||
func (i *Iterator[K, V, A]) SeekGE(key K) {
|
||||
i.Reset()
|
||||
if i.node == nil {
|
||||
return
|
||||
}
|
||||
ll := i.lowLevel()
|
||||
for {
|
||||
pos, found := i.node.find(i.r.cfg.cmp, key)
|
||||
i.pos = int16(pos)
|
||||
if found {
|
||||
return
|
||||
}
|
||||
if i.node.IsLeaf() {
|
||||
if i.pos == i.node.count {
|
||||
i.Next()
|
||||
}
|
||||
return
|
||||
}
|
||||
ll.Descend()
|
||||
}
|
||||
}
|
||||
|
||||
// SeekLT seeks to the first key less-than the provided key.
|
||||
func (i *Iterator[K, V, A]) SeekLT(key K) {
|
||||
i.Reset()
|
||||
if i.node == nil {
|
||||
return
|
||||
}
|
||||
ll := i.lowLevel()
|
||||
for {
|
||||
pos, found := i.node.find(i.r.cfg.cmp, key)
|
||||
i.pos = int16(pos)
|
||||
if found || i.node.IsLeaf() {
|
||||
i.Prev()
|
||||
return
|
||||
}
|
||||
ll.Descend()
|
||||
}
|
||||
}
|
||||
|
||||
// First seeks to the first key in the AugBTree.
|
||||
func (i *Iterator[K, V, A]) First() {
|
||||
i.Reset()
|
||||
i.pos = 0
|
||||
if i.node == nil {
|
||||
return
|
||||
}
|
||||
ll := i.lowLevel()
|
||||
for !i.node.IsLeaf() {
|
||||
ll.Descend()
|
||||
}
|
||||
i.pos = 0
|
||||
}
|
||||
|
||||
// Last seeks to the last key in the AugBTree.
|
||||
func (i *Iterator[K, V, A]) Last() {
|
||||
i.Reset()
|
||||
if i.node == nil {
|
||||
return
|
||||
}
|
||||
ll := i.lowLevel()
|
||||
for !i.node.IsLeaf() {
|
||||
i.pos = i.node.count
|
||||
ll.Descend()
|
||||
}
|
||||
i.pos = i.node.count - 1
|
||||
}
|
||||
|
||||
// Next positions the Iterator to the key immediately following
|
||||
// its current position.
|
||||
func (i *Iterator[K, V, A]) Next() {
|
||||
if i.node == nil {
|
||||
return
|
||||
}
|
||||
ll := i.lowLevel()
|
||||
if i.node.IsLeaf() {
|
||||
i.pos++
|
||||
if i.pos < i.node.count {
|
||||
return
|
||||
}
|
||||
for i.s.len() > 0 && i.pos >= i.node.count {
|
||||
ll.Ascend()
|
||||
}
|
||||
return
|
||||
}
|
||||
i.pos++
|
||||
ll.Descend()
|
||||
for !i.node.IsLeaf() {
|
||||
i.pos = 0
|
||||
ll.Descend()
|
||||
}
|
||||
i.pos = 0
|
||||
}
|
||||
|
||||
// Prev positions the Iterator to the key immediately preceding
|
||||
// its current position.
|
||||
func (i *Iterator[K, V, A]) Prev() {
|
||||
if i.node == nil {
|
||||
return
|
||||
}
|
||||
ll := i.lowLevel()
|
||||
if i.node.IsLeaf() {
|
||||
i.pos--
|
||||
if i.pos >= 0 {
|
||||
return
|
||||
}
|
||||
for i.s.len() > 0 && i.pos < 0 {
|
||||
ll.Ascend()
|
||||
i.pos--
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
ll.Descend()
|
||||
for !i.node.IsLeaf() {
|
||||
i.pos = i.node.count
|
||||
ll.Descend()
|
||||
}
|
||||
i.pos = i.node.count - 1
|
||||
}
|
||||
|
||||
// Valid returns whether the Iterator is positioned at a valid position.
|
||||
func (i *Iterator[K, V, A]) Valid() bool {
|
||||
return i.node != nil && i.pos >= 0 && i.pos < i.node.count
|
||||
}
|
||||
|
||||
// Cur returns the key at the Iterator's current position. It is illegal
|
||||
// to call Key if the Iterator is not valid.
|
||||
func (i *Iterator[K, V, A]) Cur() K {
|
||||
return i.node.keys[i.pos]
|
||||
}
|
||||
|
||||
// Value returns the value at the Iterator's current position. It is illegal
|
||||
// to call Value if the Iterator is not valid.
|
||||
func (i *Iterator[K, V, A]) Value() V {
|
||||
return i.node.values[i.pos]
|
||||
}
|
||||
81
vendor/github.com/ajwerner/btree/internal/abstract/low_level.go
generated
vendored
Normal file
81
vendor/github.com/ajwerner/btree/internal/abstract/low_level.go
generated
vendored
Normal file
@@ -0,0 +1,81 @@
|
||||
package abstract
|
||||
|
||||
// LowLevelIterator is exposed to developers within this module for use
|
||||
// implemented augmented search functionality.
|
||||
type LowLevelIterator[K, V, A any] Iterator[K, V, A]
|
||||
|
||||
// LowLevel converts an iterator to a LowLevelIterator. Given this package
|
||||
// is internal, callers outside of this module cannot construct a
|
||||
// LowLevelIterator.
|
||||
func LowLevel[K, V, A any](
|
||||
it *Iterator[K, V, A],
|
||||
) *LowLevelIterator[K, V, A] {
|
||||
return it.lowLevel()
|
||||
}
|
||||
|
||||
// Config returns the Map's config.
|
||||
func (i *LowLevelIterator[K, V, A]) Config() *Config[K, V, A] {
|
||||
return &i.r.cfg.Config
|
||||
}
|
||||
|
||||
// IncrementPos increments the iterator's position within the current node.
|
||||
func (i *LowLevelIterator[K, V, A]) IncrementPos() {
|
||||
i.SetPos(i.pos + 1)
|
||||
}
|
||||
|
||||
// SetPos sets the iterator's position within the current node.
|
||||
func (i *LowLevelIterator[K, V, A]) SetPos(pos int16) {
|
||||
i.pos = pos
|
||||
}
|
||||
|
||||
// Node returns the current Node.
|
||||
func (i *LowLevelIterator[K, V, A]) Node() *Node[K, V, A] {
|
||||
return i.node
|
||||
}
|
||||
|
||||
// IsLeaf returns true if the current node is a leaf.
|
||||
func (i *LowLevelIterator[K, V, A]) IsLeaf() bool {
|
||||
return i.node.IsLeaf()
|
||||
}
|
||||
|
||||
// Pos returns the current position within the current node.
|
||||
func (i *LowLevelIterator[K, V, A]) Pos() int16 {
|
||||
return i.pos
|
||||
}
|
||||
|
||||
// Depth returns the number of nodes above the current node in the stack.
|
||||
// It is illegal to call Ascend if this function returns 0.
|
||||
func (i *LowLevelIterator[K, V, A]) Depth() int {
|
||||
return i.s.len()
|
||||
}
|
||||
|
||||
// Child returns the augmentation of the child node at the current position.
|
||||
// It is illegal to call if this is a leaf node or there is no child
|
||||
// node at the current position.
|
||||
func (i *LowLevelIterator[K, V, A]) Child() *A {
|
||||
return &i.node.children[i.pos].aug
|
||||
}
|
||||
|
||||
// Descend pushes the current position into the iterators stack and
|
||||
// descends into the child node currently pointed to by the iterator.
|
||||
// It is illegal to call if there is no such child. The position in the
|
||||
// new node will be 0.
|
||||
func (i *LowLevelIterator[K, V, A]) Descend() {
|
||||
i.s.push(i.iterFrame)
|
||||
i.iterFrame = i.makeFrame(i.node.children[i.pos], 0)
|
||||
}
|
||||
|
||||
// Ascend ascends up to the current node's parent and resets the position
|
||||
// to the one previously set for this parent node.
|
||||
func (i *LowLevelIterator[K, V, A]) Ascend() {
|
||||
i.iterFrame = i.s.pop()
|
||||
}
|
||||
|
||||
func (i *LowLevelIterator[K, V, A]) makeFrame(
|
||||
n *Node[K, V, A], pos int16,
|
||||
) iterFrame[K, V, A] {
|
||||
return iterFrame[K, V, A]{
|
||||
node: n,
|
||||
pos: pos,
|
||||
}
|
||||
}
|
||||
589
vendor/github.com/ajwerner/btree/internal/abstract/node.go
generated
vendored
Normal file
589
vendor/github.com/ajwerner/btree/internal/abstract/node.go
generated
vendored
Normal file
@@ -0,0 +1,589 @@
|
||||
// Copyright 2018 The Cockroach Authors.
|
||||
// Copyright 2021 Andrew Werner.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
// implied. See the License for the specific language governing
|
||||
// permissions and limitations under the License.
|
||||
|
||||
package abstract
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
"sync/atomic"
|
||||
)
|
||||
|
||||
// Node represents a node in the tree.
|
||||
type Node[K, V, A any] struct {
|
||||
ref int32
|
||||
count int16
|
||||
aug A
|
||||
keys [MaxEntries]K
|
||||
values [MaxEntries]V
|
||||
children *[MaxEntries + 1]*Node[K, V, A]
|
||||
}
|
||||
|
||||
type interiorNode[K, V, A any] struct {
|
||||
Node[K, V, A]
|
||||
children [MaxEntries + 1]*Node[K, V, A]
|
||||
}
|
||||
|
||||
func (n *Node[K, V, A]) GetA() *A {
|
||||
return &n.aug
|
||||
}
|
||||
|
||||
func (n *Node[K, V, A]) IsLeaf() bool {
|
||||
return n.children == nil
|
||||
}
|
||||
|
||||
func (n *Node[K, V, A]) Count() int16 {
|
||||
return n.count
|
||||
}
|
||||
|
||||
func (n *Node[K, V, A]) GetKey(i int16) K {
|
||||
return n.keys[i]
|
||||
}
|
||||
|
||||
func (n *Node[K, V, A]) GetChild(i int16) *A {
|
||||
if !n.IsLeaf() && n.children[i] != nil {
|
||||
return &n.children[i].aug
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// mut creates and returns a mutable node reference. If the node is not shared
|
||||
// with any other trees then it can be modified in place. Otherwise, it must be
|
||||
// cloned to ensure unique ownership. In this way, we enforce a copy-on-write
|
||||
// policy which transparently incorporates the idea of local mutations, like
|
||||
// Clojure's transients or Haskell's ST monad, where nodes are only copied
|
||||
// during the first time that they are modified between Clone operations.
|
||||
//
|
||||
// When a node is cloned, the provided pointer will be redirected to the new
|
||||
// mutable node.
|
||||
func mut[K, V, A any](
|
||||
np *nodePool[K, V, A],
|
||||
n **Node[K, V, A],
|
||||
) *Node[K, V, A] {
|
||||
if atomic.LoadInt32(&(*n).ref) == 1 {
|
||||
// Exclusive ownership. Can mutate in place.
|
||||
return *n
|
||||
}
|
||||
// If we do not have unique ownership over the node then we
|
||||
// clone it to gain unique ownership. After doing so, we can
|
||||
// release our reference to the old node. We pass recursive
|
||||
// as true because even though we just observed the node's
|
||||
// reference count to be greater than 1, we might be racing
|
||||
// with another call to decRef on this node.
|
||||
c := (*n).clone(np)
|
||||
(*n).decRef(np, true /* recursive */)
|
||||
*n = c
|
||||
return *n
|
||||
}
|
||||
|
||||
// incRef acquires a reference to the node.
|
||||
func (n *Node[K, V, A]) incRef() {
|
||||
atomic.AddInt32(&n.ref, 1)
|
||||
}
|
||||
|
||||
// decRef releases a reference to the node. If requested, the method
|
||||
// will recurse into child nodes and decrease their refcounts as well.
|
||||
func (n *Node[K, V, A]) decRef(
|
||||
np *nodePool[K, V, A], recursive bool,
|
||||
) {
|
||||
if atomic.AddInt32(&n.ref, -1) > 0 {
|
||||
// Other references remain. Can't free.
|
||||
return
|
||||
}
|
||||
// Clear and release node into memory pool.
|
||||
if n.IsLeaf() {
|
||||
np.putLeafNode(n)
|
||||
} else {
|
||||
// Release child references first, if requested.
|
||||
if recursive {
|
||||
for i := int16(0); i <= n.count; i++ {
|
||||
n.children[i].decRef(np, true /* recursive */)
|
||||
}
|
||||
}
|
||||
np.putInteriorNode(n)
|
||||
}
|
||||
}
|
||||
|
||||
// clone creates a clone of the receiver with a single reference count.
|
||||
func (n *Node[K, V, A]) clone(
|
||||
np *nodePool[K, V, A],
|
||||
) *Node[K, V, A] {
|
||||
var c *Node[K, V, A]
|
||||
if n.IsLeaf() {
|
||||
c = np.getLeafNode()
|
||||
} else {
|
||||
c = np.getInteriorNode()
|
||||
}
|
||||
// NB: copy field-by-field without touching N.N.ref to avoid
|
||||
// triggering the race detector and looking like a data race.
|
||||
c.count = n.count
|
||||
n.aug = c.aug
|
||||
c.keys = n.keys
|
||||
if !c.IsLeaf() {
|
||||
// Copy children and increase each refcount.
|
||||
*c.children = *n.children
|
||||
for i := int16(0); i <= c.count; i++ {
|
||||
c.children[i].incRef()
|
||||
}
|
||||
}
|
||||
return c
|
||||
}
|
||||
|
||||
func (n *Node[K, V, A]) insertAt(index int, item K, value V, nd *Node[K, V, A]) {
|
||||
if index < int(n.count) {
|
||||
copy(n.keys[index+1:n.count+1], n.keys[index:n.count])
|
||||
copy(n.values[index+1:n.count+1], n.values[index:n.count])
|
||||
if !n.IsLeaf() {
|
||||
copy(n.children[index+2:n.count+2], n.children[index+1:n.count+1])
|
||||
}
|
||||
}
|
||||
n.keys[index] = item
|
||||
n.values[index] = value
|
||||
if !n.IsLeaf() {
|
||||
n.children[index+1] = nd
|
||||
}
|
||||
n.count++
|
||||
}
|
||||
|
||||
func (n *Node[K, V, A]) pushBack(item K, value V, nd *Node[K, V, A]) {
|
||||
n.keys[n.count] = item
|
||||
n.values[n.count] = value
|
||||
if !n.IsLeaf() {
|
||||
n.children[n.count+1] = nd
|
||||
}
|
||||
n.count++
|
||||
}
|
||||
|
||||
func (n *Node[K, V, A]) pushFront(item K, value V, nd *Node[K, V, A]) {
|
||||
if !n.IsLeaf() {
|
||||
copy(n.children[1:n.count+2], n.children[:n.count+1])
|
||||
n.children[0] = nd
|
||||
}
|
||||
copy(n.keys[1:n.count+1], n.keys[:n.count])
|
||||
copy(n.values[1:n.count+1], n.values[:n.count])
|
||||
n.keys[0] = item
|
||||
n.values[0] = value
|
||||
n.count++
|
||||
}
|
||||
|
||||
// removeAt removes a value at a given index, pulling all subsequent values
|
||||
// back.
|
||||
func (n *Node[K, V, A]) removeAt(index int) (K, V, *Node[K, V, A]) {
|
||||
var child *Node[K, V, A]
|
||||
if !n.IsLeaf() {
|
||||
child = n.children[index+1]
|
||||
copy(n.children[index+1:n.count], n.children[index+2:n.count+1])
|
||||
n.children[n.count] = nil
|
||||
}
|
||||
n.count--
|
||||
outK := n.keys[index]
|
||||
outV := n.values[index]
|
||||
copy(n.keys[index:n.count], n.keys[index+1:n.count+1])
|
||||
copy(n.values[index:n.count], n.values[index+1:n.count+1])
|
||||
var rk K
|
||||
var rv V
|
||||
n.keys[n.count] = rk
|
||||
n.values[n.count] = rv
|
||||
return outK, outV, child
|
||||
}
|
||||
|
||||
// popBack removes and returns the last element in the list.
|
||||
func (n *Node[K, V, A]) popBack() (K, V, *Node[K, V, A]) {
|
||||
n.count--
|
||||
outK := n.keys[n.count]
|
||||
outV := n.values[n.count]
|
||||
var rK K
|
||||
var rV V
|
||||
n.keys[n.count] = rK
|
||||
n.values[n.count] = rV
|
||||
if n.IsLeaf() {
|
||||
return outK, outV, nil
|
||||
}
|
||||
child := n.children[n.count+1]
|
||||
n.children[n.count+1] = nil
|
||||
return outK, outV, child
|
||||
}
|
||||
|
||||
// popFront removes and returns the first element in the list.
|
||||
func (n *Node[K, V, A]) popFront() (K, V, *Node[K, V, A]) {
|
||||
n.count--
|
||||
var child *Node[K, V, A]
|
||||
if !n.IsLeaf() {
|
||||
child = n.children[0]
|
||||
copy(n.children[:n.count+1], n.children[1:n.count+2])
|
||||
n.children[n.count+1] = nil
|
||||
}
|
||||
outK := n.keys[0]
|
||||
outV := n.values[0]
|
||||
copy(n.keys[:n.count], n.keys[1:n.count+1])
|
||||
copy(n.values[:n.count], n.values[1:n.count+1])
|
||||
var rK K
|
||||
var rV V
|
||||
n.keys[n.count] = rK
|
||||
n.values[n.count] = rV
|
||||
return outK, outV, child
|
||||
}
|
||||
|
||||
// find returns the index where the given item should be inserted into this
|
||||
// list. 'found' is true if the item already exists in the list at the given
|
||||
// index.
|
||||
func (n *Node[K, V, A]) find(cmp func(K, K) int, item K) (index int, found bool) {
|
||||
// Logic copied from sort.Search. Inlining this gave
|
||||
// an 11% speedup on BenchmarkBTreeDeleteInsert.
|
||||
i, j := 0, int(n.count)
|
||||
for i < j {
|
||||
h := int(uint(i+j) >> 1) // avoid overflow when computing h
|
||||
// i ≤ h < j
|
||||
c := cmp(item, n.keys[h])
|
||||
if c < 0 {
|
||||
j = h
|
||||
} else if c > 0 {
|
||||
i = h + 1
|
||||
} else {
|
||||
return h, true
|
||||
}
|
||||
}
|
||||
return i, false
|
||||
}
|
||||
|
||||
// split splits the given node at the given index. The current node shrinks,
|
||||
// and this function returns the item that existed at that index and a new
|
||||
// node containing all keys/children after it.
|
||||
//
|
||||
// Before:
|
||||
//
|
||||
// +-----------+
|
||||
// | x y z |
|
||||
// +--/-/-\-\--+
|
||||
//
|
||||
// After:
|
||||
//
|
||||
// +-----------+
|
||||
// | y |
|
||||
// +----/-\----+
|
||||
// / \
|
||||
// v v
|
||||
// +-----------+ +-----------+
|
||||
// | x | | z |
|
||||
// +-----------+ +-----------+
|
||||
//
|
||||
func (n *Node[K, V, A]) split(cfg *config[K, V, A], i int) (K, V, *Node[K, V, A]) {
|
||||
outK := n.keys[i]
|
||||
outV := n.values[i]
|
||||
var next *Node[K, V, A]
|
||||
if n.IsLeaf() {
|
||||
next = cfg.np.getLeafNode()
|
||||
} else {
|
||||
next = cfg.np.getInteriorNode()
|
||||
}
|
||||
next.count = n.count - int16(i+1)
|
||||
copy(next.keys[:], n.keys[i+1:n.count])
|
||||
copy(next.values[:], n.values[i+1:n.count])
|
||||
var rK K
|
||||
var rV V
|
||||
for j := int16(i); j < n.count; j++ {
|
||||
n.keys[j] = rK
|
||||
n.values[j] = rV
|
||||
}
|
||||
if !n.IsLeaf() {
|
||||
copy(next.children[:], n.children[i+1:n.count+1])
|
||||
for j := int16(i + 1); j <= n.count; j++ {
|
||||
n.children[j] = nil
|
||||
}
|
||||
}
|
||||
n.count = int16(i)
|
||||
next.update(&cfg.Config)
|
||||
n.updateOn(&cfg.Config, Split, outK, next)
|
||||
return outK, outV, next
|
||||
}
|
||||
|
||||
func (n *Node[K, V, A]) update(cfg *Config[K, V, A]) bool {
|
||||
return n.updateWithMeta(cfg, UpdateInfo[K, A]{})
|
||||
}
|
||||
|
||||
func (n *Node[K, V, A]) updateWithMeta(cfg *Config[K, V, A], md UpdateInfo[K, A]) bool {
|
||||
if cfg.Updater == nil {
|
||||
return false
|
||||
}
|
||||
return cfg.Updater.Update(n, md)
|
||||
}
|
||||
|
||||
func (n *Node[K, V, A]) updateOn(cfg *Config[K, V, A], action Action, k K, affected *Node[K, V, A]) bool {
|
||||
if cfg.Updater == nil {
|
||||
return false
|
||||
}
|
||||
var a *A
|
||||
if affected != nil {
|
||||
a = &affected.aug
|
||||
}
|
||||
return n.updateWithMeta(cfg, UpdateInfo[K, A]{
|
||||
Action: action,
|
||||
RelevantKey: k,
|
||||
ModifiedOther: a,
|
||||
})
|
||||
}
|
||||
|
||||
// insert inserts an item into the suAugBTree rooted at this node, making sure no
|
||||
// nodes in the suAugBTree exceed MaxEntries keys. Returns true if an existing item
|
||||
// was replaced and false if an item was inserted. Also returns whether the
|
||||
// node's upper bound changes.
|
||||
func (n *Node[K, V, A]) insert(cfg *config[K, V, A], item K, value V) (replacedK K, replacedV V, replaced, newBound bool) {
|
||||
i, found := n.find(cfg.cmp, item)
|
||||
if found {
|
||||
replacedV = n.values[i]
|
||||
replacedK = n.keys[i]
|
||||
n.keys[i] = item
|
||||
n.values[i] = value
|
||||
return replacedK, replacedV, true, false
|
||||
}
|
||||
if n.IsLeaf() {
|
||||
n.insertAt(i, item, value, nil)
|
||||
return replacedK, replacedV, false, n.updateOn(&cfg.Config, Insertion, item, nil)
|
||||
}
|
||||
if n.children[i].count >= MaxEntries {
|
||||
splitLK, splitLV, splitNode := mut(cfg.np, &n.children[i]).
|
||||
split(cfg, MaxEntries/2)
|
||||
n.insertAt(i, splitLK, splitLV, splitNode)
|
||||
if c := cfg.cmp(item, n.keys[i]); c < 0 {
|
||||
// no change, we want first split node
|
||||
} else if c > 0 {
|
||||
i++ // we want second split node
|
||||
} else {
|
||||
// TODO(ajwerner): add something to the augmentation api to
|
||||
// deal with replacement.
|
||||
replacedV = n.values[i]
|
||||
replacedK = n.keys[i]
|
||||
n.keys[i] = item
|
||||
n.values[i] = value
|
||||
return replacedK, replacedV, true, false
|
||||
}
|
||||
}
|
||||
replacedK, replacedV, replaced, newBound =
|
||||
mut(cfg.np, &n.children[i]).insert(cfg, item, value)
|
||||
if newBound {
|
||||
newBound = n.updateOn(&cfg.Config, Insertion, item, nil)
|
||||
}
|
||||
return replacedK, replacedV, replaced, newBound
|
||||
}
|
||||
|
||||
// removeMax removes and returns the maximum item from the suAugBTree rooted at
|
||||
// this node.
|
||||
func (n *Node[K, V, A]) removeMax(cfg *config[K, V, A]) (K, V) {
|
||||
if n.IsLeaf() {
|
||||
n.count--
|
||||
outK := n.keys[n.count]
|
||||
outV := n.values[n.count]
|
||||
var rK K
|
||||
var rV V
|
||||
n.keys[n.count] = rK
|
||||
n.values[n.count] = rV
|
||||
n.updateOn(&cfg.Config, Removal, outK, nil)
|
||||
return outK, outV
|
||||
}
|
||||
// Recurse into max child.
|
||||
i := int(n.count)
|
||||
if n.children[i].count <= MinEntries {
|
||||
// Child not large enough to remove from.
|
||||
n.rebalanceOrMerge(cfg, i)
|
||||
return n.removeMax(cfg) // redo
|
||||
}
|
||||
child := mut(cfg.np, &n.children[i])
|
||||
outK, outV := child.removeMax(cfg)
|
||||
n.updateOn(&cfg.Config, Removal, outK, nil)
|
||||
return outK, outV
|
||||
}
|
||||
|
||||
// rebalanceOrMerge grows child 'i' to ensure it has sufficient room to remove
|
||||
// an item from it while keeping it at or above MinItems.
|
||||
func (n *Node[K, V, A]) rebalanceOrMerge(
|
||||
cfg *config[K, V, A], i int,
|
||||
) {
|
||||
switch {
|
||||
case i > 0 && n.children[i-1].count > MinEntries:
|
||||
// Rebalance from left sibling.
|
||||
//
|
||||
// +-----------+
|
||||
// | y |
|
||||
// +----/-\----+
|
||||
// / \
|
||||
// v v
|
||||
// +-----------+ +-----------+
|
||||
// | x | | |
|
||||
// +----------\+ +-----------+
|
||||
// \
|
||||
// v
|
||||
// a
|
||||
//
|
||||
// After:
|
||||
//
|
||||
// +-----------+
|
||||
// | x |
|
||||
// +----/-\----+
|
||||
// / \
|
||||
// v v
|
||||
// +-----------+ +-----------+
|
||||
// | | | y |
|
||||
// +-----------+ +/----------+
|
||||
// /
|
||||
// v
|
||||
// a
|
||||
//
|
||||
left := mut(cfg.np, &n.children[i-1])
|
||||
child := mut(cfg.np, &n.children[i])
|
||||
xLaK, xLaV, grandChild := left.popBack()
|
||||
yLaK, yLaV := n.keys[i-1], n.values[i-1]
|
||||
child.pushFront(yLaK, yLaV, grandChild)
|
||||
n.keys[i-1], n.values[i-1] = xLaK, xLaV
|
||||
left.updateOn(&cfg.Config, Removal, xLaK, grandChild)
|
||||
child.updateOn(&cfg.Config, Insertion, yLaK, grandChild)
|
||||
|
||||
case i < int(n.count) && n.children[i+1].count > MinEntries:
|
||||
// Rebalance from right sibling.
|
||||
//
|
||||
// +-----------+
|
||||
// | y |
|
||||
// +----/-\----+
|
||||
// / \
|
||||
// v v
|
||||
// +-----------+ +-----------+
|
||||
// | | | x |
|
||||
// +-----------+ +/----------+
|
||||
// /
|
||||
// v
|
||||
// a
|
||||
//
|
||||
// After:
|
||||
//
|
||||
// +-----------+
|
||||
// | x |
|
||||
// +----/-\----+
|
||||
// / \
|
||||
// v v
|
||||
// +-----------+ +-----------+
|
||||
// | y | | |
|
||||
// +----------\+ +-----------+
|
||||
// \
|
||||
// v
|
||||
// a
|
||||
//
|
||||
right := mut(cfg.np, &n.children[i+1])
|
||||
child := mut(cfg.np, &n.children[i])
|
||||
xLaK, xLaV, grandChild := right.popFront()
|
||||
yLaK, yLaV := n.keys[i], n.values[i]
|
||||
child.pushBack(yLaK, yLaV, grandChild)
|
||||
n.keys[i], n.values[i] = xLaK, xLaV
|
||||
right.updateOn(&cfg.Config, Removal, xLaK, grandChild)
|
||||
child.updateOn(&cfg.Config, Insertion, yLaK, grandChild)
|
||||
|
||||
default:
|
||||
// Merge with either the left or right sibling.
|
||||
//
|
||||
// +-----------+
|
||||
// | u y v |
|
||||
// +----/-\----+
|
||||
// / \
|
||||
// v v
|
||||
// +-----------+ +-----------+
|
||||
// | x | | z |
|
||||
// +-----------+ +-----------+
|
||||
//
|
||||
// After:
|
||||
//
|
||||
// +-----------+
|
||||
// | u v |
|
||||
// +-----|-----+
|
||||
// |
|
||||
// v
|
||||
// +-----------+
|
||||
// | x y z |
|
||||
// +-----------+
|
||||
//
|
||||
if i >= int(n.count) {
|
||||
i = int(n.count - 1)
|
||||
}
|
||||
child := mut(cfg.np, &n.children[i])
|
||||
// Make mergeChild mutable, bumping the refcounts on its children if necessary.
|
||||
_ = mut(cfg.np, &n.children[i+1])
|
||||
mergeLaK, mergeLaV, mergeChild := n.removeAt(i)
|
||||
child.keys[child.count] = mergeLaK
|
||||
child.values[child.count] = mergeLaV
|
||||
copy(child.keys[child.count+1:], mergeChild.keys[:mergeChild.count])
|
||||
copy(child.values[child.count+1:], mergeChild.values[:mergeChild.count])
|
||||
if !child.IsLeaf() {
|
||||
copy(child.children[child.count+1:], mergeChild.children[:mergeChild.count+1])
|
||||
}
|
||||
child.count += mergeChild.count + 1
|
||||
|
||||
child.updateOn(&cfg.Config, Insertion, mergeLaK, mergeChild)
|
||||
mergeChild.decRef(cfg.np, false /* recursive */)
|
||||
}
|
||||
}
|
||||
|
||||
// remove removes an item from the suAugBTree rooted at this node. Returns the item
|
||||
// that was removed or nil if no matching item was found. Also returns whether
|
||||
// the node's upper bound changes.
|
||||
func (n *Node[K, V, A]) remove(
|
||||
cfg *config[K, V, A], item K,
|
||||
) (outK K, outV V, found, newBound bool) {
|
||||
i, found := n.find(cfg.cmp, item)
|
||||
if n.IsLeaf() {
|
||||
if found {
|
||||
outK, outV, _ = n.removeAt(i)
|
||||
return outK, outV, true, n.updateOn(&cfg.Config, Removal, outK, nil)
|
||||
}
|
||||
var rK K
|
||||
var rV V
|
||||
return rK, rV, false, false
|
||||
}
|
||||
if n.children[i].count <= MinEntries {
|
||||
// Child not large enough to remove from.
|
||||
n.rebalanceOrMerge(cfg, i)
|
||||
return n.remove(cfg, item) // redo
|
||||
}
|
||||
child := mut(cfg.np, &n.children[i])
|
||||
if found {
|
||||
// Replace the item being removed with the max item in our left child.
|
||||
outK = n.keys[i]
|
||||
outV = n.values[i]
|
||||
n.keys[i], n.values[i] = child.removeMax(cfg)
|
||||
return outK, outV, true, n.updateOn(&cfg.Config, Removal, outK, nil)
|
||||
}
|
||||
// Latch is not in this node and child is large enough to remove from.
|
||||
outK, outV, found, newBound = child.remove(cfg, item)
|
||||
if newBound {
|
||||
newBound = n.updateOn(&cfg.Config, Removal, outK, nil)
|
||||
}
|
||||
return outK, outV, found, newBound
|
||||
}
|
||||
|
||||
func (n *Node[K, V, A]) writeString(b *strings.Builder) {
|
||||
if n.IsLeaf() {
|
||||
for i := int16(0); i < n.count; i++ {
|
||||
if i != 0 {
|
||||
b.WriteString(",")
|
||||
}
|
||||
fmt.Fprintf(b, "%v:%v", n.keys[i], n.values[i])
|
||||
}
|
||||
return
|
||||
}
|
||||
for i := int16(0); i <= n.count; i++ {
|
||||
b.WriteString("(")
|
||||
n.children[i].writeString(b)
|
||||
b.WriteString(")")
|
||||
if i < n.count {
|
||||
fmt.Fprintf(b, "%v:%v", n.keys[i], n.values[i])
|
||||
}
|
||||
}
|
||||
}
|
||||
75
vendor/github.com/ajwerner/btree/internal/abstract/node_pool.go
generated
vendored
Normal file
75
vendor/github.com/ajwerner/btree/internal/abstract/node_pool.go
generated
vendored
Normal file
@@ -0,0 +1,75 @@
|
||||
// Copyright 2021 Andrew Werner.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
// implied. See the License for the specific language governing
|
||||
// permissions and limitations under the License.
|
||||
|
||||
package abstract
|
||||
|
||||
import "sync"
|
||||
|
||||
type nodePool[K, V, A any] struct {
|
||||
interiorNodePool, leafNodePool sync.Pool
|
||||
}
|
||||
|
||||
var syncPoolMap sync.Map
|
||||
|
||||
func getNodePool[K, V, A any]() *nodePool[K, V, A] {
|
||||
var nilNode *Node[K, V, A]
|
||||
v, ok := syncPoolMap.Load(nilNode)
|
||||
if !ok {
|
||||
v, _ = syncPoolMap.LoadOrStore(nilNode, newNodePool[K, V, A]())
|
||||
}
|
||||
return v.(*nodePool[K, V, A])
|
||||
|
||||
}
|
||||
|
||||
func newNodePool[K, V, A any]() *nodePool[K, V, A] {
|
||||
np := nodePool[K, V, A]{}
|
||||
np.leafNodePool = sync.Pool{
|
||||
New: func() interface{} {
|
||||
return new(Node[K, V, A])
|
||||
},
|
||||
}
|
||||
np.interiorNodePool = sync.Pool{
|
||||
New: func() interface{} {
|
||||
n := new(interiorNode[K, V, A])
|
||||
n.Node.children = &n.children
|
||||
return &n.Node
|
||||
},
|
||||
}
|
||||
return &np
|
||||
}
|
||||
|
||||
func (np *nodePool[K, V, A]) getInteriorNode() *Node[K, V, A] {
|
||||
n := np.interiorNodePool.Get().(*Node[K, V, A])
|
||||
n.ref = 1
|
||||
return n
|
||||
}
|
||||
|
||||
func (np *nodePool[K, V, A]) getLeafNode() *Node[K, V, A] {
|
||||
n := np.leafNodePool.Get().(*Node[K, V, A])
|
||||
n.ref = 1
|
||||
return n
|
||||
}
|
||||
|
||||
func (np *nodePool[K, V, A]) putInteriorNode(n *Node[K, V, A]) {
|
||||
children := n.children
|
||||
*children = [MaxEntries + 1]*Node[K, V, A]{}
|
||||
*n = Node[K, V, A]{}
|
||||
n.children = children
|
||||
np.interiorNodePool.Put(n)
|
||||
}
|
||||
|
||||
func (np *nodePool[K, V, A]) putLeafNode(n *Node[K, V, A]) {
|
||||
*n = Node[K, V, A]{}
|
||||
np.leafNodePool.Put(n)
|
||||
}
|
||||
19
vendor/github.com/alecthomas/atomic/COPYING
generated
vendored
Normal file
19
vendor/github.com/alecthomas/atomic/COPYING
generated
vendored
Normal file
@@ -0,0 +1,19 @@
|
||||
Copyright (C) 2018 Alec Thomas
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
this software and associated documentation files (the "Software"), to deal in
|
||||
the Software without restriction, including without limitation the rights to
|
||||
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
of the Software, and to permit persons to whom the Software is furnished to do
|
||||
so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
52
vendor/github.com/alecthomas/atomic/README.md
generated
vendored
Normal file
52
vendor/github.com/alecthomas/atomic/README.md
generated
vendored
Normal file
@@ -0,0 +1,52 @@
|
||||
# Type-safe atomic values for Go
|
||||
|
||||
One issue with Go's sync/atomic package is that there is no guarantee from the
|
||||
type system that operations on an integer value will be applied through the
|
||||
sync/atomic functions. This package solves that and introduces two type-safe
|
||||
interfaces for use with integer and non-integer atomic values.
|
||||
|
||||
The first interface is for any value:
|
||||
|
||||
```go
|
||||
// Value represents a value that can be atomically loaded or replaced.
|
||||
type Value[T any] interface {
|
||||
// Load value atomically.
|
||||
Load() T
|
||||
// Store value atomically.
|
||||
Store(value T)
|
||||
// Swap the previous value with the new value atomically.
|
||||
Swap(new T) (old T)
|
||||
// CompareAndSwap the previous value with new if its value is "old".
|
||||
CompareAndSwap(old, new T) (swapped bool)
|
||||
}
|
||||
```
|
||||
|
||||
The second interface is a `Value[T]` constrained to the 32 and 64 bit integer
|
||||
types and adds a single `Add()` method:
|
||||
|
||||
```go
|
||||
// Int expresses atomic operations on signed or unsigned integer values.
|
||||
type Int[T atomicint] interface {
|
||||
Value[T]
|
||||
// Add a value and return the new result.
|
||||
Add(delta T) (new T)
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
## Performance
|
||||
|
||||
```
|
||||
BenchmarkInt64Add
|
||||
BenchmarkInt64Add-8 174217112 6.887 ns/op
|
||||
BenchmarkIntInterfaceAdd
|
||||
BenchmarkIntInterfaceAdd-8 174129980 6.889 ns/op
|
||||
BenchmarkStdlibInt64Add
|
||||
BenchmarkStdlibInt64Add-8 174152660 6.887 ns/op
|
||||
BenchmarkInterfaceStore
|
||||
BenchmarkInterfaceStore-8 16015668 76.17 ns/op
|
||||
BenchmarkValueStore
|
||||
BenchmarkValueStore-8 16155405 75.03 ns/op
|
||||
BenchmarkStdlibValueStore
|
||||
BenchmarkStdlibValueStore-8 16391035 74.85 ns/op
|
||||
```
|
||||
149
vendor/github.com/alecthomas/atomic/atomic.go
generated
vendored
Normal file
149
vendor/github.com/alecthomas/atomic/atomic.go
generated
vendored
Normal file
@@ -0,0 +1,149 @@
|
||||
// Package atomic contains type-safe atomic types.
|
||||
//
|
||||
// The zero value for the numeric types cannot be used. Use New*. The
|
||||
// rationale for this behaviour is that copying an atomic integer is not
|
||||
// reliable. Copying can be prevented by embedding sync.Mutex, but that bloats
|
||||
// the type.
|
||||
package atomic
|
||||
|
||||
import "sync/atomic"
|
||||
|
||||
// Interface represents atomic operations on a value.
|
||||
type Interface[T any] interface {
|
||||
// Load value atomically.
|
||||
Load() T
|
||||
// Store value atomically.
|
||||
Store(value T)
|
||||
// Swap the previous value with the new value atomically.
|
||||
Swap(new T) (old T)
|
||||
// CompareAndSwap the previous value with new if its value is "old".
|
||||
CompareAndSwap(old, new T) (swapped bool)
|
||||
}
|
||||
|
||||
var _ Interface[bool] = &Value[bool]{}
|
||||
|
||||
// Value wraps any generic value in atomic load and store operations.
|
||||
type Value[T any] struct {
|
||||
value atomic.Value
|
||||
}
|
||||
|
||||
// New atomic Value.
|
||||
func New[T any](seed T) *Value[T] {
|
||||
v := &Value[T]{}
|
||||
v.value.Store(seed)
|
||||
return v
|
||||
}
|
||||
|
||||
func (v *Value[T]) Load() (out T) {
|
||||
value := v.value.Load()
|
||||
if value == nil {
|
||||
return out
|
||||
}
|
||||
return value.(T)
|
||||
}
|
||||
func (v *Value[T]) Store(value T) { v.value.Store(value) }
|
||||
func (v *Value[T]) Swap(new T) (old T) { return v.value.Swap(new).(T) }
|
||||
func (v *Value[T]) CompareAndSwap(old, new T) (swapped bool) { return v.value.CompareAndSwap(old, new) }
|
||||
|
||||
// atomicint defines the types that atomic integer operations are supported on.
|
||||
type atomicint interface {
|
||||
int32 | uint32 | int64 | uint64
|
||||
}
|
||||
|
||||
// Int expresses atomic operations on signed or unsigned integer values.
|
||||
type Int[T atomicint] interface {
|
||||
Interface[T]
|
||||
// Add a value and return the new result.
|
||||
Add(delta T) (new T)
|
||||
}
|
||||
|
||||
// Currently not supported by Go's generic type system:
|
||||
//
|
||||
// ./atomic.go:48:9: cannot use type switch on type parameter value v (variable of type T constrained by atomicint)
|
||||
//
|
||||
// // ForInt infers and creates an atomic Int[T] type for a value.
|
||||
// func ForInt[T atomicint](v T) Int[T] {
|
||||
// switch v.(type) {
|
||||
// case int32:
|
||||
// return NewInt32(v)
|
||||
// case uint32:
|
||||
// return NewUint32(v)
|
||||
// case int64:
|
||||
// return NewInt64(v)
|
||||
// case uint64:
|
||||
// return NewUint64(v)
|
||||
// }
|
||||
// panic("can't happen")
|
||||
// }
|
||||
|
||||
// Int32 atomic value.
|
||||
//
|
||||
// Copying creates an alias. The zero value is not usable, use NewInt32.
|
||||
type Int32 struct{ value *int32 }
|
||||
|
||||
// NewInt32 creates a new atomic integer with an initial value.
|
||||
func NewInt32(value int32) Int32 { return Int32{value: &value} }
|
||||
|
||||
var _ Int[int32] = &Int32{}
|
||||
|
||||
func (i Int32) Add(delta int32) (new int32) { return atomic.AddInt32(i.value, delta) }
|
||||
func (i Int32) Load() (val int32) { return atomic.LoadInt32(i.value) }
|
||||
func (i Int32) Store(val int32) { atomic.StoreInt32(i.value, val) }
|
||||
func (i Int32) Swap(new int32) (old int32) { return atomic.SwapInt32(i.value, new) }
|
||||
func (i Int32) CompareAndSwap(old, new int32) (swapped bool) {
|
||||
return atomic.CompareAndSwapInt32(i.value, old, new)
|
||||
}
|
||||
|
||||
// Uint32 atomic value.
|
||||
//
|
||||
// Copying creates an alias.
|
||||
type Uint32 struct{ value *uint32 }
|
||||
|
||||
var _ Int[uint32] = Uint32{}
|
||||
|
||||
// NewUint32 creates a new atomic integer with an initial value.
|
||||
func NewUint32(value uint32) Uint32 { return Uint32{value: &value} }
|
||||
|
||||
func (i Uint32) Add(delta uint32) (new uint32) { return atomic.AddUint32(i.value, delta) }
|
||||
func (i Uint32) Load() (val uint32) { return atomic.LoadUint32(i.value) }
|
||||
func (i Uint32) Store(val uint32) { atomic.StoreUint32(i.value, val) }
|
||||
func (i Uint32) Swap(new uint32) (old uint32) { return atomic.SwapUint32(i.value, new) }
|
||||
func (i Uint32) CompareAndSwap(old, new uint32) (swapped bool) {
|
||||
return atomic.CompareAndSwapUint32(i.value, old, new)
|
||||
}
|
||||
|
||||
// Int64 atomic value.
|
||||
//
|
||||
// Copying creates an alias.
|
||||
type Int64 struct{ value *int64 }
|
||||
|
||||
var _ Int[int64] = Int64{}
|
||||
|
||||
// NewInt64 creates a new atomic integer with an initial value.
|
||||
func NewInt64(value int64) Int64 { return Int64{value: &value} }
|
||||
|
||||
func (i Int64) Add(delta int64) (new int64) { return atomic.AddInt64(i.value, delta) }
|
||||
func (i Int64) Load() (val int64) { return atomic.LoadInt64(i.value) }
|
||||
func (i Int64) Store(val int64) { atomic.StoreInt64(i.value, val) }
|
||||
func (i Int64) Swap(new int64) (old int64) { return atomic.SwapInt64(i.value, new) }
|
||||
func (i Int64) CompareAndSwap(old, new int64) (swapped bool) {
|
||||
return atomic.CompareAndSwapInt64(i.value, old, new)
|
||||
}
|
||||
|
||||
// Uint64 atomic value.
|
||||
//
|
||||
// Copying creates an alias.
|
||||
type Uint64 struct{ value *uint64 }
|
||||
|
||||
var _ Int[uint64] = Uint64{}
|
||||
|
||||
// NewUint64 creates a new atomic integer with an initial value.
|
||||
func NewUint64(value uint64) Uint64 { return Uint64{value: &value} }
|
||||
|
||||
func (i Uint64) Add(delta uint64) (new uint64) { return atomic.AddUint64(i.value, delta) }
|
||||
func (i Uint64) Load() (val uint64) { return atomic.LoadUint64(i.value) }
|
||||
func (i Uint64) Store(val uint64) { atomic.StoreUint64(i.value, val) }
|
||||
func (i Uint64) Swap(new uint64) (old uint64) { return atomic.SwapUint64(i.value, new) }
|
||||
func (i Uint64) CompareAndSwap(old, new uint64) (swapped bool) {
|
||||
return atomic.CompareAndSwapUint64(i.value, old, new)
|
||||
}
|
||||
21
vendor/github.com/anacrolix/chansync/LICENSE
generated
vendored
Normal file
21
vendor/github.com/anacrolix/chansync/LICENSE
generated
vendored
Normal file
@@ -0,0 +1,21 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2021 Matt Joiner
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
34
vendor/github.com/anacrolix/chansync/broadcast-cond.go.go
generated
vendored
Normal file
34
vendor/github.com/anacrolix/chansync/broadcast-cond.go.go
generated
vendored
Normal file
@@ -0,0 +1,34 @@
|
||||
package chansync
|
||||
|
||||
import (
|
||||
"github.com/anacrolix/chansync/events"
|
||||
"github.com/anacrolix/sync"
|
||||
)
|
||||
|
||||
// Can be used as zero-value. Due to the caller needing to bring their own synchronization, an
|
||||
// equivalent to "sync".Cond.Signal is not provided. BroadcastCond is intended to be selected on
|
||||
// with other channels.
|
||||
type BroadcastCond struct {
|
||||
mu sync.Mutex
|
||||
ch chan struct{}
|
||||
}
|
||||
|
||||
func (me *BroadcastCond) Broadcast() {
|
||||
me.mu.Lock()
|
||||
defer me.mu.Unlock()
|
||||
if me.ch != nil {
|
||||
close(me.ch)
|
||||
me.ch = nil
|
||||
}
|
||||
}
|
||||
|
||||
// Should be called before releasing locks on resources that might trigger subsequent Broadcasts.
|
||||
// The channel is closed when the condition changes.
|
||||
func (me *BroadcastCond) Signaled() events.Signaled {
|
||||
me.mu.Lock()
|
||||
defer me.mu.Unlock()
|
||||
if me.ch == nil {
|
||||
me.ch = make(chan struct{})
|
||||
}
|
||||
return me.ch
|
||||
}
|
||||
12
vendor/github.com/anacrolix/chansync/events/events.go
generated
vendored
Normal file
12
vendor/github.com/anacrolix/chansync/events/events.go
generated
vendored
Normal file
@@ -0,0 +1,12 @@
|
||||
package events
|
||||
|
||||
// Here we'll strongly-type channels to assist correct usage, if possible.
|
||||
|
||||
type (
|
||||
Signaled <-chan struct{}
|
||||
Done <-chan struct{}
|
||||
Active <-chan struct{}
|
||||
Signal chan<- struct{}
|
||||
Acquire chan<- struct{}
|
||||
Release <-chan struct{}
|
||||
)
|
||||
85
vendor/github.com/anacrolix/chansync/flag.go
generated
vendored
Normal file
85
vendor/github.com/anacrolix/chansync/flag.go
generated
vendored
Normal file
@@ -0,0 +1,85 @@
|
||||
package chansync
|
||||
|
||||
import (
|
||||
"sync"
|
||||
|
||||
"github.com/anacrolix/chansync/events"
|
||||
)
|
||||
|
||||
type ReadOnlyFlag interface {
|
||||
Bool() bool
|
||||
On() events.Active
|
||||
Off() events.Active
|
||||
}
|
||||
|
||||
// Flag wraps a boolean value that starts as false (off). You can wait for it to be on or off, and
|
||||
// set the value as needed.
|
||||
type Flag struct {
|
||||
mu sync.Mutex
|
||||
on chan struct{}
|
||||
off chan struct{}
|
||||
state bool
|
||||
inited bool
|
||||
}
|
||||
|
||||
func (me *Flag) Bool() bool {
|
||||
me.mu.Lock()
|
||||
defer me.mu.Unlock()
|
||||
return me.state
|
||||
}
|
||||
|
||||
func (me *Flag) On() events.Active {
|
||||
me.mu.Lock()
|
||||
defer me.mu.Unlock()
|
||||
me.init()
|
||||
return me.on
|
||||
}
|
||||
|
||||
func (me *Flag) Off() events.Active {
|
||||
me.mu.Lock()
|
||||
defer me.mu.Unlock()
|
||||
me.init()
|
||||
return me.off
|
||||
}
|
||||
|
||||
func (me *Flag) init() {
|
||||
if me.inited {
|
||||
return
|
||||
}
|
||||
me.on = make(chan struct{})
|
||||
me.off = make(chan struct{})
|
||||
close(me.off)
|
||||
me.inited = true
|
||||
}
|
||||
|
||||
func (me *Flag) SetBool(b bool) {
|
||||
if b {
|
||||
me.Set()
|
||||
} else {
|
||||
me.Clear()
|
||||
}
|
||||
}
|
||||
|
||||
func (me *Flag) Set() {
|
||||
me.mu.Lock()
|
||||
defer me.mu.Unlock()
|
||||
me.init()
|
||||
if me.state {
|
||||
return
|
||||
}
|
||||
me.state = true
|
||||
close(me.on)
|
||||
me.off = make(chan struct{})
|
||||
}
|
||||
|
||||
func (me *Flag) Clear() {
|
||||
me.mu.Lock()
|
||||
defer me.mu.Unlock()
|
||||
me.init()
|
||||
if !me.state {
|
||||
return
|
||||
}
|
||||
me.state = false
|
||||
close(me.off)
|
||||
me.on = make(chan struct{})
|
||||
}
|
||||
28
vendor/github.com/anacrolix/chansync/level.go
generated
vendored
Normal file
28
vendor/github.com/anacrolix/chansync/level.go
generated
vendored
Normal file
@@ -0,0 +1,28 @@
|
||||
package chansync
|
||||
|
||||
import (
|
||||
"sync"
|
||||
|
||||
"github.com/anacrolix/chansync/events"
|
||||
)
|
||||
|
||||
type LevelTrigger struct {
|
||||
ch chan struct{}
|
||||
initOnce sync.Once
|
||||
}
|
||||
|
||||
func (me *LevelTrigger) Signal() events.Signal {
|
||||
me.init()
|
||||
return me.ch
|
||||
}
|
||||
|
||||
func (me *LevelTrigger) Active() events.Active {
|
||||
me.init()
|
||||
return me.ch
|
||||
}
|
||||
|
||||
func (me *LevelTrigger) init() {
|
||||
me.initOnce.Do(func() {
|
||||
me.ch = make(chan struct{})
|
||||
})
|
||||
}
|
||||
31
vendor/github.com/anacrolix/chansync/semaphore.go
generated
vendored
Normal file
31
vendor/github.com/anacrolix/chansync/semaphore.go
generated
vendored
Normal file
@@ -0,0 +1,31 @@
|
||||
package chansync
|
||||
|
||||
import (
|
||||
"github.com/anacrolix/chansync/events"
|
||||
)
|
||||
|
||||
// Channel semaphore, as is popular for controlling access to limited resources. Should not be used
|
||||
// zero-initialized.
|
||||
type Semaphore struct {
|
||||
ch chan struct{}
|
||||
}
|
||||
|
||||
// Returns an initialized semaphore with n slots.
|
||||
func NewSemaphore(n int) Semaphore {
|
||||
return Semaphore{ch: make(chan struct{}, n)}
|
||||
}
|
||||
|
||||
// Returns a channel for acquiring a slot.
|
||||
func (me Semaphore) Acquire() events.Acquire {
|
||||
return me.ch
|
||||
}
|
||||
|
||||
// Returns a channel for releasing a slot.
|
||||
func (me Semaphore) Release() events.Release {
|
||||
return me.ch
|
||||
}
|
||||
|
||||
// Returns the current number of acquired values.
|
||||
func (me Semaphore) Value() int {
|
||||
return len(me.ch)
|
||||
}
|
||||
44
vendor/github.com/anacrolix/chansync/set-once.go
generated
vendored
Normal file
44
vendor/github.com/anacrolix/chansync/set-once.go
generated
vendored
Normal file
@@ -0,0 +1,44 @@
|
||||
package chansync
|
||||
|
||||
import (
|
||||
"sync"
|
||||
"sync/atomic"
|
||||
|
||||
"github.com/anacrolix/chansync/events"
|
||||
)
|
||||
|
||||
// SetOnce is a boolean value that can only be flipped from false to true.
|
||||
type SetOnce struct {
|
||||
ch chan struct{}
|
||||
// Could be faster than trying to receive from ch
|
||||
closed uint32
|
||||
initOnce sync.Once
|
||||
closeOnce sync.Once
|
||||
}
|
||||
|
||||
// Returns a channel that is closed when the event is flagged.
|
||||
func (me *SetOnce) Done() events.Done {
|
||||
me.init()
|
||||
return me.ch
|
||||
}
|
||||
|
||||
func (me *SetOnce) init() {
|
||||
me.initOnce.Do(func() {
|
||||
me.ch = make(chan struct{})
|
||||
})
|
||||
}
|
||||
|
||||
// Set only returns true the first time it is called.
|
||||
func (me *SetOnce) Set() (first bool) {
|
||||
me.closeOnce.Do(func() {
|
||||
me.init()
|
||||
first = true
|
||||
atomic.StoreUint32(&me.closed, 1)
|
||||
close(me.ch)
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
func (me *SetOnce) IsSet() bool {
|
||||
return atomic.LoadUint32(&me.closed) != 0
|
||||
}
|
||||
25
vendor/github.com/anacrolix/dht/README.md
generated
vendored
25
vendor/github.com/anacrolix/dht/README.md
generated
vendored
@@ -1,25 +0,0 @@
|
||||
# dht
|
||||
|
||||
[](https://circleci.com/gh/anacrolix/dht)
|
||||
[](https://godoc.org/github.com/anacrolix/dht)
|
||||
[](https://gitter.im/anacrolix/torrent?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
|
||||
|
||||
## Installation
|
||||
|
||||
Install the library package with `go get github.com/anacrolix/dht`, or the provided cmds with `go get github.com/anacrolix/dht/cmd/...`.
|
||||
|
||||
## Commands
|
||||
|
||||
Here I'll describe what some of the provided commands in `./cmd` do.
|
||||
|
||||
Note that the [`godo`](https://github.com/anacrolix/godo) command which is invoked in the following examples builds and executes a Go import path, like `go run`. It's easier to use this convention than to spell out the install/invoke cycle for every single example.
|
||||
|
||||
### dht-ping
|
||||
|
||||
Pings DHT nodes with the given network addresses.
|
||||
|
||||
$ godo ./cmd/dht-ping router.bittorrent.com:6881 router.utorrent.com:6881
|
||||
2015/04/01 17:21:23 main.go:33: dht server on [::]:60058
|
||||
32f54e697351ff4aec29cdbaabf2fbe3467cc267 (router.bittorrent.com:6881): 648.218621ms
|
||||
ebff36697351ff4aec29cdbaabf2fbe3467cc267 (router.utorrent.com:6881): 873.864706ms
|
||||
2/2 responses (100.000000%)
|
||||
263
vendor/github.com/anacrolix/dht/announce.go
generated
vendored
263
vendor/github.com/anacrolix/dht/announce.go
generated
vendored
@@ -1,263 +0,0 @@
|
||||
package dht
|
||||
|
||||
// get_peers and announce_peers.
|
||||
|
||||
import (
|
||||
"container/heap"
|
||||
"context"
|
||||
|
||||
"github.com/anacrolix/dht/krpc"
|
||||
"github.com/anacrolix/sync"
|
||||
"github.com/willf/bloom"
|
||||
"golang.org/x/time/rate"
|
||||
)
|
||||
|
||||
// Maintains state for an ongoing Announce operation. An Announce is started
|
||||
// by calling Server.Announce.
|
||||
type Announce struct {
|
||||
mu sync.Mutex
|
||||
Peers chan PeersValues
|
||||
// Inner chan is set to nil when on close.
|
||||
values chan PeersValues
|
||||
stop chan struct{}
|
||||
triedAddrs *bloom.BloomFilter
|
||||
// True when contact with all starting addrs has been initiated. This
|
||||
// prevents a race where the first transaction finishes before the rest
|
||||
// have been opened, sees no other transactions are pending and ends the
|
||||
// announce.
|
||||
contactedStartAddrs bool
|
||||
// How many transactions are still ongoing.
|
||||
pending int
|
||||
server *Server
|
||||
infoHash int160
|
||||
// Count of (probably) distinct addresses we've sent get_peers requests
|
||||
// to.
|
||||
numContacted int
|
||||
// The torrent port that we're announcing.
|
||||
announcePort int
|
||||
// The torrent port should be determined by the receiver in case we're
|
||||
// being NATed.
|
||||
announcePortImplied bool
|
||||
|
||||
nodesPendingContact nodesByDistance
|
||||
nodeContactorCond sync.Cond
|
||||
contactRateLimiter *rate.Limiter
|
||||
}
|
||||
|
||||
// Returns the number of distinct remote addresses the announce has queried.
|
||||
func (a *Announce) NumContacted() int {
|
||||
a.mu.Lock()
|
||||
defer a.mu.Unlock()
|
||||
return a.numContacted
|
||||
}
|
||||
|
||||
func newBloomFilterForTraversal() *bloom.BloomFilter {
|
||||
return bloom.NewWithEstimates(10000, 0.5)
|
||||
}
|
||||
|
||||
// This is kind of the main thing you want to do with DHT. It traverses the
|
||||
// graph toward nodes that store peers for the infohash, streaming them to the
|
||||
// caller, and announcing the local node to each node if allowed and
|
||||
// specified.
|
||||
func (s *Server) Announce(infoHash [20]byte, port int, impliedPort bool) (*Announce, error) {
|
||||
startAddrs, err := s.traversalStartingAddrs()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
a := &Announce{
|
||||
Peers: make(chan PeersValues, 100),
|
||||
stop: make(chan struct{}),
|
||||
values: make(chan PeersValues),
|
||||
triedAddrs: newBloomFilterForTraversal(),
|
||||
server: s,
|
||||
infoHash: int160FromByteArray(infoHash),
|
||||
announcePort: port,
|
||||
announcePortImplied: impliedPort,
|
||||
contactRateLimiter: s.announceContactRateLimiter,
|
||||
}
|
||||
a.nodesPendingContact.target = int160FromByteArray(infoHash)
|
||||
a.nodeContactorCond.L = &a.mu
|
||||
// Function ferries from values to Values until discovery is halted.
|
||||
go func() {
|
||||
defer close(a.Peers)
|
||||
for {
|
||||
select {
|
||||
case psv := <-a.values:
|
||||
select {
|
||||
case a.Peers <- psv:
|
||||
case <-a.stop:
|
||||
return
|
||||
}
|
||||
case <-a.stop:
|
||||
return
|
||||
}
|
||||
}
|
||||
}()
|
||||
go func() {
|
||||
a.mu.Lock()
|
||||
defer a.mu.Unlock()
|
||||
for _, addr := range startAddrs {
|
||||
if !a.reserveContact(addr) {
|
||||
continue
|
||||
}
|
||||
a.mu.Unlock()
|
||||
a.contactRateLimiter.Wait(context.TODO())
|
||||
a.mu.Lock()
|
||||
a.contact(addr)
|
||||
}
|
||||
a.contactedStartAddrs = true
|
||||
// If we failed to contact any of the starting addrs, no transactions
|
||||
// will complete triggering a check that there are no pending
|
||||
// responses.
|
||||
a.maybeClose()
|
||||
}()
|
||||
go a.nodeContactor()
|
||||
return a, nil
|
||||
}
|
||||
|
||||
func validNodeAddr(addr Addr) bool {
|
||||
ua := addr.UDPAddr()
|
||||
if ua.Port == 0 {
|
||||
return false
|
||||
}
|
||||
if ip4 := ua.IP.To4(); ip4 != nil && ip4[0] == 0 {
|
||||
// Why?
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
func (a *Announce) reserveContact(addr Addr) bool {
|
||||
if !validNodeAddr(addr) {
|
||||
return false
|
||||
}
|
||||
if a.triedAddrs.Test([]byte(addr.String())) {
|
||||
return false
|
||||
}
|
||||
if a.server.ipBlocked(addr.UDPAddr().IP) {
|
||||
return false
|
||||
}
|
||||
a.pending++
|
||||
a.triedAddrs.Add([]byte(addr.String()))
|
||||
return true
|
||||
}
|
||||
|
||||
func (a *Announce) completeContact() {
|
||||
a.pending--
|
||||
a.maybeClose()
|
||||
}
|
||||
|
||||
func (a *Announce) contact(addr Addr) {
|
||||
a.numContacted++
|
||||
go func() {
|
||||
if a.getPeers(addr) != nil {
|
||||
a.mu.Lock()
|
||||
a.completeContact()
|
||||
a.mu.Unlock()
|
||||
}
|
||||
}()
|
||||
}
|
||||
|
||||
func (a *Announce) maybeClose() {
|
||||
if a.contactedStartAddrs && a.pending == 0 {
|
||||
a.close()
|
||||
}
|
||||
}
|
||||
|
||||
func (a *Announce) responseNode(node krpc.NodeInfo) {
|
||||
a.pendContact(node)
|
||||
}
|
||||
|
||||
// Announce to a peer, if appropriate.
|
||||
func (a *Announce) maybeAnnouncePeer(to Addr, token string, peerId *krpc.ID) {
|
||||
if !a.server.config.NoSecurity && (peerId == nil || !NodeIdSecure(*peerId, to.UDPAddr().IP)) {
|
||||
return
|
||||
}
|
||||
a.server.mu.Lock()
|
||||
defer a.server.mu.Unlock()
|
||||
a.server.announcePeer(to, a.infoHash, a.announcePort, token, a.announcePortImplied, nil)
|
||||
}
|
||||
|
||||
func (a *Announce) getPeers(addr Addr) error {
|
||||
a.server.mu.Lock()
|
||||
defer a.server.mu.Unlock()
|
||||
return a.server.getPeers(addr, a.infoHash, func(m krpc.Msg, err error) {
|
||||
// Register suggested nodes closer to the target info-hash.
|
||||
if m.R != nil && m.SenderID() != nil {
|
||||
expvars.Add("announce get_peers response nodes values", int64(len(m.R.Nodes)))
|
||||
expvars.Add("announce get_peers response nodes6 values", int64(len(m.R.Nodes6)))
|
||||
a.mu.Lock()
|
||||
m.R.ForAllNodes(a.responseNode)
|
||||
a.mu.Unlock()
|
||||
select {
|
||||
case a.values <- PeersValues{
|
||||
Peers: m.R.Values,
|
||||
NodeInfo: krpc.NodeInfo{
|
||||
Addr: addr.KRPC(),
|
||||
ID: *m.SenderID(),
|
||||
},
|
||||
}:
|
||||
case <-a.stop:
|
||||
}
|
||||
a.maybeAnnouncePeer(addr, m.R.Token, m.SenderID())
|
||||
}
|
||||
a.mu.Lock()
|
||||
a.completeContact()
|
||||
a.mu.Unlock()
|
||||
})
|
||||
}
|
||||
|
||||
// Corresponds to the "values" key in a get_peers KRPC response. A list of
|
||||
// peers that a node has reported as being in the swarm for a queried info
|
||||
// hash.
|
||||
type PeersValues struct {
|
||||
Peers []Peer // Peers given in get_peers response.
|
||||
krpc.NodeInfo // The node that gave the response.
|
||||
}
|
||||
|
||||
// Stop the announce.
|
||||
func (a *Announce) Close() {
|
||||
a.mu.Lock()
|
||||
defer a.mu.Unlock()
|
||||
a.close()
|
||||
}
|
||||
|
||||
func (a *Announce) close() {
|
||||
select {
|
||||
case <-a.stop:
|
||||
default:
|
||||
close(a.stop)
|
||||
a.nodeContactorCond.Broadcast()
|
||||
}
|
||||
}
|
||||
|
||||
func (a *Announce) pendContact(node krpc.NodeInfo) {
|
||||
if !a.reserveContact(NewAddr(node.Addr.UDP())) {
|
||||
return
|
||||
}
|
||||
heap.Push(&a.nodesPendingContact, node)
|
||||
a.nodeContactorCond.Signal()
|
||||
}
|
||||
|
||||
func (a *Announce) nodeContactor() {
|
||||
a.mu.Lock()
|
||||
defer a.mu.Unlock()
|
||||
for {
|
||||
for {
|
||||
select {
|
||||
case <-a.stop:
|
||||
return
|
||||
default:
|
||||
}
|
||||
if a.nodesPendingContact.Len() > 0 {
|
||||
break
|
||||
}
|
||||
a.nodeContactorCond.Wait()
|
||||
}
|
||||
a.mu.Unlock()
|
||||
a.contactRateLimiter.Wait(context.TODO())
|
||||
a.mu.Lock()
|
||||
ni := heap.Pop(&a.nodesPendingContact).(krpc.NodeInfo)
|
||||
a.contact(NewAddr(ni.Addr.UDP()))
|
||||
}
|
||||
}
|
||||
87
vendor/github.com/anacrolix/dht/int160.go
generated
vendored
87
vendor/github.com/anacrolix/dht/int160.go
generated
vendored
@@ -1,87 +0,0 @@
|
||||
package dht
|
||||
|
||||
import (
|
||||
"math"
|
||||
"math/big"
|
||||
)
|
||||
|
||||
type int160 struct {
|
||||
bits [20]uint8
|
||||
}
|
||||
|
||||
func (me *int160) AsByteArray() [20]byte {
|
||||
return me.bits
|
||||
}
|
||||
|
||||
func (me *int160) ByteString() string {
|
||||
return string(me.bits[:])
|
||||
}
|
||||
|
||||
func (me *int160) BitLen() int {
|
||||
var a big.Int
|
||||
a.SetBytes(me.bits[:])
|
||||
return a.BitLen()
|
||||
}
|
||||
|
||||
func (me *int160) SetBytes(b []byte) {
|
||||
n := copy(me.bits[:], b)
|
||||
if n != 20 {
|
||||
panic(n)
|
||||
}
|
||||
}
|
||||
|
||||
func (me int160) Bytes() []byte {
|
||||
return me.bits[:]
|
||||
}
|
||||
|
||||
func (l int160) Cmp(r int160) int {
|
||||
for i := range l.bits {
|
||||
if l.bits[i] < r.bits[i] {
|
||||
return -1
|
||||
} else if l.bits[i] > r.bits[i] {
|
||||
return 1
|
||||
}
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func (me *int160) SetMax() {
|
||||
for i := range me.bits {
|
||||
me.bits[i] = math.MaxUint8
|
||||
}
|
||||
}
|
||||
|
||||
func (me *int160) Xor(a, b *int160) {
|
||||
for i := range me.bits {
|
||||
me.bits[i] = a.bits[i] ^ b.bits[i]
|
||||
}
|
||||
}
|
||||
|
||||
func (me *int160) IsZero() bool {
|
||||
for _, b := range me.bits {
|
||||
if b != 0 {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
func int160FromBytes(b []byte) (ret int160) {
|
||||
ret.SetBytes(b)
|
||||
return
|
||||
}
|
||||
|
||||
func int160FromByteArray(b [20]byte) (ret int160) {
|
||||
ret.SetBytes(b[:])
|
||||
return
|
||||
}
|
||||
|
||||
func int160FromByteString(s string) (ret int160) {
|
||||
ret.SetBytes([]byte(s))
|
||||
return
|
||||
}
|
||||
|
||||
func distance(a, b int160) (ret int160) {
|
||||
ret.Xor(&a, &b)
|
||||
return
|
||||
}
|
||||
36
vendor/github.com/anacrolix/dht/krpc/id.go
generated
vendored
36
vendor/github.com/anacrolix/dht/krpc/id.go
generated
vendored
@@ -1,36 +0,0 @@
|
||||
package krpc
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/anacrolix/torrent/bencode"
|
||||
)
|
||||
|
||||
type ID [20]byte
|
||||
|
||||
var _ interface {
|
||||
bencode.Marshaler
|
||||
bencode.Unmarshaler
|
||||
} = (*ID)(nil)
|
||||
|
||||
func IdFromString(s string) (id ID) {
|
||||
if n := copy(id[:], s); n != 20 {
|
||||
panic(n)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func (id *ID) MarshalBencode() ([]byte, error) {
|
||||
return []byte("20:" + string(id[:])), nil
|
||||
}
|
||||
|
||||
func (id *ID) UnmarshalBencode(b []byte) error {
|
||||
var s string
|
||||
if err := bencode.Unmarshal(b, &s); err != nil {
|
||||
return err
|
||||
}
|
||||
if n := copy(id[:], s); n != 20 {
|
||||
return fmt.Errorf("string has wrong length: %d", n)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
94
vendor/github.com/anacrolix/dht/krpc/msg.go
generated
vendored
94
vendor/github.com/anacrolix/dht/krpc/msg.go
generated
vendored
@@ -1,94 +0,0 @@
|
||||
package krpc
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
)
|
||||
|
||||
// Msg represents messages that nodes in the network send to each other as specified by the protocol.
|
||||
// They are also refered to as the KRPC messages.
|
||||
// There are three types of messages: QUERY, RESPONSE, ERROR
|
||||
// The message is a dictonary that is then
|
||||
// "bencoded" (serialization & compression format adopted by the BitTorrent)
|
||||
// and sent via the UDP connection to peers.
|
||||
//
|
||||
// A KRPC message is a single dictionary with two keys common to every message and additional keys depending on the type of message.
|
||||
// Every message has a key "t" with a string value representing a transaction ID.
|
||||
// This transaction ID is generated by the querying node and is echoed in the response, so responses
|
||||
// may be correlated with multiple queries to the same node. The transaction ID should be encoded as a short string of binary numbers, typically 2 characters are enough as they cover 2^16 outstanding queries. The other key contained in every KRPC message is "y" with a single character value describing the type of message. The value of the "y" key is one of "q" for query, "r" for response, or "e" for error.
|
||||
// 3 message types: QUERY, RESPONSE, ERROR
|
||||
type Msg struct {
|
||||
Q string `bencode:"q,omitempty"` // Query method (one of 4: "ping", "find_node", "get_peers", "announce_peer")
|
||||
A *MsgArgs `bencode:"a,omitempty"` // named arguments sent with a query
|
||||
T string `bencode:"t"` // required: transaction ID
|
||||
Y string `bencode:"y"` // required: type of the message: q for QUERY, r for RESPONSE, e for ERROR
|
||||
R *Return `bencode:"r,omitempty"` // RESPONSE type only
|
||||
E *Error `bencode:"e,omitempty"` // ERROR type only
|
||||
IP NodeAddr `bencode:"ip,omitempty"`
|
||||
ReadOnly bool `bencode:"ro,omitempty"`
|
||||
}
|
||||
|
||||
type MsgArgs struct {
|
||||
ID ID `bencode:"id"` // ID of the querying Node
|
||||
InfoHash ID `bencode:"info_hash,omitempty"` // InfoHash of the torrent
|
||||
Target ID `bencode:"target,omitempty"` // ID of the node sought
|
||||
Token string `bencode:"token,omitempty"` // Token received from an earlier get_peers query
|
||||
Port int `bencode:"port,omitempty"` // Senders torrent port
|
||||
ImpliedPort bool `bencode:"implied_port,omitempty"` // Use senders apparent DHT port
|
||||
Want []Want `bencode:"want,omitempty"` // Contains strings like "n4" and "n6" from BEP 32.
|
||||
}
|
||||
|
||||
type Want string
|
||||
|
||||
const (
|
||||
WantNodes Want = "n4"
|
||||
WantNodes6 Want = "n6"
|
||||
)
|
||||
|
||||
type Return struct {
|
||||
ID ID `bencode:"id"` // ID of the querying node
|
||||
Nodes CompactIPv4NodeInfo `bencode:"nodes,omitempty"` // K closest nodes to the requested target
|
||||
Nodes6 CompactIPv6NodeInfo `bencode:"nodes6,omitempty"` // K closest nodes to the requested target
|
||||
Token string `bencode:"token,omitempty"` // Token for future announce_peer
|
||||
Values []NodeAddr `bencode:"values,omitempty"` // Torrent peers
|
||||
}
|
||||
|
||||
func (r Return) ForAllNodes(f func(NodeInfo)) {
|
||||
for _, n := range r.Nodes {
|
||||
f(n)
|
||||
}
|
||||
for _, n := range r.Nodes6 {
|
||||
f(n)
|
||||
}
|
||||
}
|
||||
|
||||
var _ fmt.Stringer = Msg{}
|
||||
|
||||
func (m Msg) String() string {
|
||||
return fmt.Sprintf("%#v", m)
|
||||
}
|
||||
|
||||
// The node ID of the source of this Msg. Returns nil if it isn't present.
|
||||
// TODO: Can we verify Msgs more aggressively so this is guaranteed to return
|
||||
// a valid ID for a checked Msg?
|
||||
func (m Msg) SenderID() *ID {
|
||||
switch m.Y {
|
||||
case "q":
|
||||
if m.A == nil {
|
||||
return nil
|
||||
}
|
||||
return &m.A.ID
|
||||
case "r":
|
||||
if m.R == nil {
|
||||
return nil
|
||||
}
|
||||
return &m.R.ID
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m Msg) Error() *Error {
|
||||
if m.Y != "e" {
|
||||
return nil
|
||||
}
|
||||
return m.E
|
||||
}
|
||||
43
vendor/github.com/anacrolix/dht/misc.go
generated
vendored
43
vendor/github.com/anacrolix/dht/misc.go
generated
vendored
@@ -1,43 +0,0 @@
|
||||
package dht
|
||||
|
||||
import (
|
||||
"net"
|
||||
|
||||
"github.com/anacrolix/dht/krpc"
|
||||
)
|
||||
|
||||
func mustListen(addr string) net.PacketConn {
|
||||
ret, err := net.ListenPacket("udp", addr)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return ret
|
||||
}
|
||||
|
||||
func addrResolver(addr string) func() ([]Addr, error) {
|
||||
return func() ([]Addr, error) {
|
||||
ua, err := net.ResolveUDPAddr("udp", addr)
|
||||
return []Addr{NewAddr(ua)}, err
|
||||
}
|
||||
}
|
||||
|
||||
type nodesByDistance struct {
|
||||
nis []krpc.NodeInfo
|
||||
target int160
|
||||
}
|
||||
|
||||
func (me nodesByDistance) Len() int { return len(me.nis) }
|
||||
func (me nodesByDistance) Less(i, j int) bool {
|
||||
return distance(int160FromByteArray(me.nis[i].ID), me.target).Cmp(distance(int160FromByteArray(me.nis[j].ID), me.target)) < 0
|
||||
}
|
||||
func (me *nodesByDistance) Pop() interface{} {
|
||||
ret := me.nis[len(me.nis)-1]
|
||||
me.nis = me.nis[:len(me.nis)-1]
|
||||
return ret
|
||||
}
|
||||
func (me *nodesByDistance) Push(x interface{}) {
|
||||
me.nis = append(me.nis, x.(krpc.NodeInfo))
|
||||
}
|
||||
func (me nodesByDistance) Swap(i, j int) {
|
||||
me.nis[i], me.nis[j] = me.nis[j], me.nis[i]
|
||||
}
|
||||
57
vendor/github.com/anacrolix/dht/node.go
generated
vendored
57
vendor/github.com/anacrolix/dht/node.go
generated
vendored
@@ -1,57 +0,0 @@
|
||||
package dht
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"github.com/anacrolix/dht/krpc"
|
||||
)
|
||||
|
||||
type nodeKey struct {
|
||||
addr Addr
|
||||
id int160
|
||||
}
|
||||
|
||||
type node struct {
|
||||
nodeKey
|
||||
announceToken string
|
||||
readOnly bool
|
||||
|
||||
lastGotQuery time.Time
|
||||
lastGotResponse time.Time
|
||||
|
||||
consecutiveFailures int
|
||||
}
|
||||
|
||||
func (n *node) hasAddrAndID(addr Addr, id int160) bool {
|
||||
return id == n.id && n.addr.String() == addr.String()
|
||||
}
|
||||
|
||||
func (n *node) IsSecure() bool {
|
||||
return NodeIdSecure(n.id.AsByteArray(), n.addr.UDPAddr().IP)
|
||||
}
|
||||
|
||||
func (n *node) idString() string {
|
||||
return n.id.ByteString()
|
||||
}
|
||||
|
||||
func (n *node) NodeInfo() (ret krpc.NodeInfo) {
|
||||
ret.Addr = n.addr.KRPC()
|
||||
if n := copy(ret.ID[:], n.idString()); n != 20 {
|
||||
panic(n)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// Per the spec in BEP 5.
|
||||
func (n *node) IsGood() bool {
|
||||
if n.id.IsZero() {
|
||||
return false
|
||||
}
|
||||
if time.Since(n.lastGotResponse) < 15*time.Minute {
|
||||
return true
|
||||
}
|
||||
if !n.lastGotResponse.IsZero() && time.Since(n.lastGotQuery) < 15*time.Minute {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
832
vendor/github.com/anacrolix/dht/server.go
generated
vendored
832
vendor/github.com/anacrolix/dht/server.go
generated
vendored
@@ -1,832 +0,0 @@
|
||||
package dht
|
||||
|
||||
import (
|
||||
"crypto/rand"
|
||||
"encoding/binary"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"log"
|
||||
"net"
|
||||
"sync"
|
||||
"text/tabwriter"
|
||||
"time"
|
||||
|
||||
"github.com/anacrolix/dht/krpc"
|
||||
"github.com/anacrolix/missinggo"
|
||||
"github.com/anacrolix/missinggo/conntrack"
|
||||
"github.com/anacrolix/torrent/bencode"
|
||||
"github.com/anacrolix/torrent/iplist"
|
||||
"github.com/anacrolix/torrent/logonce"
|
||||
"github.com/anacrolix/torrent/metainfo"
|
||||
"golang.org/x/time/rate"
|
||||
)
|
||||
|
||||
// A Server defines parameters for a DHT node server that is able to send
|
||||
// queries, and respond to the ones from the network. Each node has a globally
|
||||
// unique identifier known as the "node ID." Node IDs are chosen at random
|
||||
// from the same 160-bit space as BitTorrent infohashes and define the
|
||||
// behaviour of the node. Zero valued Server does not have a valid ID and thus
|
||||
// is unable to function properly. Use `NewServer(nil)` to initialize a
|
||||
// default node.
|
||||
type Server struct {
|
||||
id int160
|
||||
socket net.PacketConn
|
||||
|
||||
mu sync.RWMutex
|
||||
transactions map[transactionKey]*Transaction
|
||||
nextT uint64 // unique "t" field for outbound queries
|
||||
table table
|
||||
closed missinggo.Event
|
||||
ipBlockList iplist.Ranger
|
||||
tokenServer tokenServer // Manages tokens we issue to our queriers.
|
||||
config ServerConfig
|
||||
stats ServerStats
|
||||
|
||||
announceContactRateLimiter *rate.Limiter
|
||||
}
|
||||
|
||||
func (s *Server) numGoodNodes() (num int) {
|
||||
s.table.forNodes(func(n *node) bool {
|
||||
if n.IsGood() {
|
||||
num++
|
||||
}
|
||||
return true
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
func prettySince(t time.Time) string {
|
||||
if t.IsZero() {
|
||||
return "never"
|
||||
}
|
||||
d := time.Since(t)
|
||||
d /= time.Second
|
||||
d *= time.Second
|
||||
return fmt.Sprintf("%s ago", d)
|
||||
}
|
||||
|
||||
func (s *Server) WriteStatus(w io.Writer) {
|
||||
fmt.Fprintf(w, "Listening on %s\n", s.Addr())
|
||||
s.mu.Lock()
|
||||
defer s.mu.Unlock()
|
||||
fmt.Fprintf(w, "Nodes in table: %d good, %d total\n", s.numGoodNodes(), s.numNodes())
|
||||
fmt.Fprintf(w, "Ongoing transactions: %d\n", len(s.transactions))
|
||||
fmt.Fprintf(w, "Server node ID: %x\n", s.id.Bytes())
|
||||
fmt.Fprintln(w)
|
||||
tw := tabwriter.NewWriter(w, 0, 0, 1, ' ', 0)
|
||||
fmt.Fprintf(tw, "b#\tnode id\taddr\tanntok\tlast query\tlast response\tcf\n")
|
||||
for i, b := range s.table.buckets {
|
||||
b.EachNode(func(n *node) bool {
|
||||
fmt.Fprintf(tw, "%d\t%x\t%s\t%v\t%s\t%s\t%d\n",
|
||||
i,
|
||||
n.id.Bytes(),
|
||||
n.addr,
|
||||
len(n.announceToken),
|
||||
prettySince(n.lastGotQuery),
|
||||
prettySince(n.lastGotResponse),
|
||||
n.consecutiveFailures,
|
||||
)
|
||||
return true
|
||||
})
|
||||
}
|
||||
tw.Flush()
|
||||
fmt.Fprintln(w)
|
||||
}
|
||||
|
||||
func (s *Server) numNodes() (num int) {
|
||||
s.table.forNodes(func(n *node) bool {
|
||||
num++
|
||||
return true
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
// Stats returns statistics for the server.
|
||||
func (s *Server) Stats() ServerStats {
|
||||
s.mu.Lock()
|
||||
defer s.mu.Unlock()
|
||||
ss := s.stats
|
||||
ss.GoodNodes = s.numGoodNodes()
|
||||
ss.Nodes = s.numNodes()
|
||||
ss.OutstandingTransactions = len(s.transactions)
|
||||
return ss
|
||||
}
|
||||
|
||||
// Addr returns the listen address for the server. Packets arriving to this address
|
||||
// are processed by the server (unless aliens are involved).
|
||||
func (s *Server) Addr() net.Addr {
|
||||
return s.socket.LocalAddr()
|
||||
}
|
||||
|
||||
// NewServer initializes a new DHT node server.
|
||||
func NewServer(c *ServerConfig) (s *Server, err error) {
|
||||
if c == nil {
|
||||
c = &ServerConfig{
|
||||
Conn: mustListen(":0"),
|
||||
NoSecurity: true,
|
||||
StartingNodes: GlobalBootstrapAddrs,
|
||||
ConnectionTracking: conntrack.NewInstance(),
|
||||
}
|
||||
}
|
||||
if missinggo.IsZeroValue(c.NodeId) {
|
||||
c.NodeId = RandomNodeID()
|
||||
if !c.NoSecurity && c.PublicIP != nil {
|
||||
SecureNodeId(&c.NodeId, c.PublicIP)
|
||||
}
|
||||
}
|
||||
s = &Server{
|
||||
config: *c,
|
||||
ipBlockList: c.IPBlocklist,
|
||||
tokenServer: tokenServer{
|
||||
maxIntervalDelta: 2,
|
||||
interval: 5 * time.Minute,
|
||||
secret: make([]byte, 20),
|
||||
},
|
||||
transactions: make(map[transactionKey]*Transaction),
|
||||
table: table{
|
||||
k: 8,
|
||||
},
|
||||
announceContactRateLimiter: rate.NewLimiter(10, 10),
|
||||
}
|
||||
if s.config.ConnectionTracking == nil {
|
||||
s.config.ConnectionTracking = conntrack.NewInstance()
|
||||
}
|
||||
rand.Read(s.tokenServer.secret)
|
||||
s.socket = c.Conn
|
||||
s.id = int160FromByteArray(c.NodeId)
|
||||
s.table.rootID = s.id
|
||||
go func() {
|
||||
err := s.serve()
|
||||
s.mu.Lock()
|
||||
defer s.mu.Unlock()
|
||||
if s.closed.IsSet() {
|
||||
return
|
||||
}
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}()
|
||||
return
|
||||
}
|
||||
|
||||
// Returns a description of the Server. Python repr-style.
|
||||
func (s *Server) String() string {
|
||||
return fmt.Sprintf("dht server on %s", s.socket.LocalAddr())
|
||||
}
|
||||
|
||||
// Packets to and from any address matching a range in the list are dropped.
|
||||
func (s *Server) SetIPBlockList(list iplist.Ranger) {
|
||||
s.mu.Lock()
|
||||
defer s.mu.Unlock()
|
||||
s.ipBlockList = list
|
||||
}
|
||||
|
||||
func (s *Server) IPBlocklist() iplist.Ranger {
|
||||
return s.ipBlockList
|
||||
}
|
||||
|
||||
func (s *Server) processPacket(b []byte, addr Addr) {
|
||||
if len(b) < 2 || b[0] != 'd' || b[len(b)-1] != 'e' {
|
||||
// KRPC messages are bencoded dicts.
|
||||
readNotKRPCDict.Add(1)
|
||||
return
|
||||
}
|
||||
var d krpc.Msg
|
||||
err := bencode.Unmarshal(b, &d)
|
||||
if err != nil {
|
||||
readUnmarshalError.Add(1)
|
||||
func() {
|
||||
if se, ok := err.(*bencode.SyntaxError); ok {
|
||||
// The message was truncated.
|
||||
if int(se.Offset) == len(b) {
|
||||
return
|
||||
}
|
||||
// Some messages seem to drop to nul chars abrubtly.
|
||||
if int(se.Offset) < len(b) && b[se.Offset] == 0 {
|
||||
return
|
||||
}
|
||||
// The message isn't bencode from the first.
|
||||
if se.Offset == 0 {
|
||||
return
|
||||
}
|
||||
}
|
||||
// if missinggo.CryHeard() {
|
||||
// log.Printf("%s: received bad krpc message from %s: %s: %+q", s, addr, err, b)
|
||||
// }
|
||||
}()
|
||||
return
|
||||
}
|
||||
s.mu.Lock()
|
||||
defer s.mu.Unlock()
|
||||
if s.closed.IsSet() {
|
||||
return
|
||||
}
|
||||
var n *node
|
||||
if sid := d.SenderID(); sid != nil {
|
||||
n, _ = s.getNode(addr, int160FromByteArray(*sid), !d.ReadOnly)
|
||||
if n != nil && d.ReadOnly {
|
||||
n.readOnly = true
|
||||
}
|
||||
}
|
||||
if d.Y == "q" {
|
||||
readQuery.Add(1)
|
||||
s.handleQuery(addr, d)
|
||||
return
|
||||
}
|
||||
t := s.findResponseTransaction(d.T, addr)
|
||||
if t == nil {
|
||||
return
|
||||
}
|
||||
go t.handleResponse(d)
|
||||
if n != nil {
|
||||
n.lastGotResponse = time.Now()
|
||||
n.consecutiveFailures = 0
|
||||
}
|
||||
s.deleteTransaction(t)
|
||||
}
|
||||
|
||||
func (s *Server) serve() error {
|
||||
var b [0x10000]byte
|
||||
for {
|
||||
n, addr, err := s.socket.ReadFrom(b[:])
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
read.Add(1)
|
||||
if n == len(b) {
|
||||
logonce.Stderr.Printf("received dht packet exceeds buffer size")
|
||||
continue
|
||||
}
|
||||
if missinggo.AddrPort(addr) == 0 {
|
||||
readZeroPort.Add(1)
|
||||
continue
|
||||
}
|
||||
s.mu.Lock()
|
||||
blocked := s.ipBlocked(missinggo.AddrIP(addr))
|
||||
s.mu.Unlock()
|
||||
if blocked {
|
||||
readBlocked.Add(1)
|
||||
continue
|
||||
}
|
||||
s.processPacket(b[:n], NewAddr(addr.(*net.UDPAddr)))
|
||||
}
|
||||
}
|
||||
|
||||
func (s *Server) ipBlocked(ip net.IP) (blocked bool) {
|
||||
if s.ipBlockList == nil {
|
||||
return
|
||||
}
|
||||
_, blocked = s.ipBlockList.Lookup(ip)
|
||||
return
|
||||
}
|
||||
|
||||
// Adds directly to the node table.
|
||||
func (s *Server) AddNode(ni krpc.NodeInfo) error {
|
||||
id := int160FromByteArray(ni.ID)
|
||||
if id.IsZero() {
|
||||
return s.Ping(ni.Addr.UDP(), nil)
|
||||
}
|
||||
_, err := s.getNode(NewAddr(ni.Addr.UDP()), int160FromByteArray(ni.ID), true)
|
||||
return err
|
||||
}
|
||||
|
||||
func wantsContain(ws []krpc.Want, w krpc.Want) bool {
|
||||
for _, _w := range ws {
|
||||
if _w == w {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func shouldReturnNodes(queryWants []krpc.Want, querySource net.IP) bool {
|
||||
if len(queryWants) != 0 {
|
||||
return wantsContain(queryWants, krpc.WantNodes)
|
||||
}
|
||||
return querySource.To4() != nil
|
||||
}
|
||||
|
||||
func shouldReturnNodes6(queryWants []krpc.Want, querySource net.IP) bool {
|
||||
if len(queryWants) != 0 {
|
||||
return wantsContain(queryWants, krpc.WantNodes6)
|
||||
}
|
||||
return querySource.To4() == nil
|
||||
}
|
||||
|
||||
func (s *Server) makeReturnNodes(target int160, filter func(krpc.NodeAddr) bool) []krpc.NodeInfo {
|
||||
return s.closestGoodNodeInfos(8, target, filter)
|
||||
}
|
||||
|
||||
func (s *Server) setReturnNodes(r *krpc.Return, queryMsg krpc.Msg, querySource Addr) {
|
||||
target := int160FromByteArray(queryMsg.A.InfoHash)
|
||||
if shouldReturnNodes(queryMsg.A.Want, querySource.UDPAddr().IP) {
|
||||
r.Nodes = s.makeReturnNodes(target, func(na krpc.NodeAddr) bool { return na.IP.To4() != nil })
|
||||
}
|
||||
if shouldReturnNodes6(queryMsg.A.Want, querySource.UDPAddr().IP) {
|
||||
r.Nodes6 = s.makeReturnNodes(target, func(krpc.NodeAddr) bool { return true })
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: Probably should write error messages back to senders if something is
|
||||
// wrong.
|
||||
func (s *Server) handleQuery(source Addr, m krpc.Msg) {
|
||||
if m.SenderID() != nil {
|
||||
if n, _ := s.getNode(source, int160FromByteArray(*m.SenderID()), !m.ReadOnly); n != nil {
|
||||
n.lastGotQuery = time.Now()
|
||||
}
|
||||
}
|
||||
if s.config.OnQuery != nil {
|
||||
propagate := s.config.OnQuery(&m, source.UDPAddr())
|
||||
if !propagate {
|
||||
return
|
||||
}
|
||||
}
|
||||
// Don't respond.
|
||||
if s.config.Passive {
|
||||
return
|
||||
}
|
||||
// TODO: Should we disallow replying to ourself?
|
||||
args := m.A
|
||||
switch m.Q {
|
||||
case "ping":
|
||||
s.reply(source, m.T, krpc.Return{})
|
||||
case "get_peers":
|
||||
var r krpc.Return
|
||||
// TODO: Return nodes.
|
||||
s.setReturnNodes(&r, m, source)
|
||||
r.Token = s.createToken(source)
|
||||
s.reply(source, m.T, r)
|
||||
case "find_node":
|
||||
var r krpc.Return
|
||||
s.setReturnNodes(&r, m, source)
|
||||
s.reply(source, m.T, r)
|
||||
case "announce_peer":
|
||||
readAnnouncePeer.Add(1)
|
||||
if !s.validToken(args.Token, source) {
|
||||
expvars.Add("received announce_peer with invalid token", 1)
|
||||
return
|
||||
}
|
||||
expvars.Add("received announce_peer with valid token", 1)
|
||||
if h := s.config.OnAnnouncePeer; h != nil {
|
||||
p := Peer{
|
||||
IP: source.UDPAddr().IP,
|
||||
Port: args.Port,
|
||||
}
|
||||
if args.ImpliedPort {
|
||||
p.Port = source.UDPAddr().Port
|
||||
}
|
||||
go h(metainfo.Hash(args.InfoHash), p)
|
||||
}
|
||||
s.reply(source, m.T, krpc.Return{})
|
||||
default:
|
||||
s.sendError(source, m.T, krpc.ErrorMethodUnknown)
|
||||
}
|
||||
}
|
||||
|
||||
func (s *Server) sendError(addr Addr, t string, e krpc.Error) {
|
||||
m := krpc.Msg{
|
||||
T: t,
|
||||
Y: "e",
|
||||
E: &e,
|
||||
}
|
||||
b, err := bencode.Marshal(m)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
_, err = s.writeToNode(b, addr)
|
||||
if err != nil {
|
||||
log.Printf("error replying to %s: %s", addr, err)
|
||||
}
|
||||
}
|
||||
|
||||
func (s *Server) reply(addr Addr, t string, r krpc.Return) {
|
||||
expvars.Add("replied to peer", 1)
|
||||
r.ID = s.id.AsByteArray()
|
||||
m := krpc.Msg{
|
||||
T: t,
|
||||
Y: "r",
|
||||
R: &r,
|
||||
IP: addr.KRPC(),
|
||||
}
|
||||
b, err := bencode.Marshal(m)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
_, err = s.writeToNode(b, addr)
|
||||
if err != nil {
|
||||
log.Printf("error replying to %s: %s", addr, err)
|
||||
}
|
||||
}
|
||||
|
||||
// Returns the node if it's in the routing table, adding it if appropriate.
|
||||
func (s *Server) getNode(addr Addr, id int160, tryAdd bool) (*node, error) {
|
||||
if n := s.table.getNode(addr, id); n != nil {
|
||||
return n, nil
|
||||
}
|
||||
n := &node{nodeKey: nodeKey{
|
||||
id: id,
|
||||
addr: addr,
|
||||
}}
|
||||
// Check that the node would be good to begin with. (It might have a bad
|
||||
// ID or banned address, or we fucked up the initial node field
|
||||
// invariant.)
|
||||
if err := s.nodeErr(n); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if !tryAdd {
|
||||
return nil, errors.New("node not present and add flag false")
|
||||
}
|
||||
b := s.table.bucketForID(id)
|
||||
if b.Len() >= s.table.k {
|
||||
if b.EachNode(func(n *node) bool {
|
||||
if s.nodeIsBad(n) {
|
||||
s.table.dropNode(n)
|
||||
}
|
||||
return b.Len() >= s.table.k
|
||||
}) {
|
||||
return nil, errors.New("no room in bucket")
|
||||
}
|
||||
}
|
||||
if err := s.table.addNode(n); err != nil {
|
||||
panic(fmt.Sprintf("expected to add node: %s", err))
|
||||
}
|
||||
return n, nil
|
||||
}
|
||||
|
||||
func (s *Server) nodeIsBad(n *node) bool {
|
||||
return s.nodeErr(n) != nil
|
||||
}
|
||||
|
||||
func (s *Server) nodeErr(n *node) error {
|
||||
if n.id == s.id {
|
||||
return errors.New("is self")
|
||||
}
|
||||
if n.id.IsZero() {
|
||||
return errors.New("has zero id")
|
||||
}
|
||||
if !s.config.NoSecurity && !n.IsSecure() {
|
||||
return errors.New("not secure")
|
||||
}
|
||||
if n.IsGood() {
|
||||
return nil
|
||||
}
|
||||
if n.consecutiveFailures >= 3 {
|
||||
return fmt.Errorf("has %d consecutive failures", n.consecutiveFailures)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *Server) writeToNode(b []byte, node Addr) (wrote bool, err error) {
|
||||
if list := s.ipBlockList; list != nil {
|
||||
if r, ok := list.Lookup(missinggo.AddrIP(node.UDPAddr())); ok {
|
||||
err = fmt.Errorf("write to %s blocked: %s", node, r.Description)
|
||||
return
|
||||
}
|
||||
}
|
||||
// log.Printf("writing to %s: %q", node.UDPAddr(), b)
|
||||
n, err := s.socket.WriteTo(b, node.UDPAddr())
|
||||
writes.Add(1)
|
||||
if err != nil {
|
||||
writeErrors.Add(1)
|
||||
err = fmt.Errorf("error writing %d bytes to %s: %s", len(b), node, err)
|
||||
return
|
||||
}
|
||||
wrote = true
|
||||
if n != len(b) {
|
||||
err = io.ErrShortWrite
|
||||
return
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func (s *Server) findResponseTransaction(transactionID string, sourceNode Addr) *Transaction {
|
||||
return s.transactions[transactionKey{
|
||||
sourceNode.String(),
|
||||
transactionID}]
|
||||
}
|
||||
|
||||
func (s *Server) nextTransactionID() string {
|
||||
var b [binary.MaxVarintLen64]byte
|
||||
n := binary.PutUvarint(b[:], s.nextT)
|
||||
s.nextT++
|
||||
return string(b[:n])
|
||||
}
|
||||
|
||||
func (s *Server) deleteTransaction(t *Transaction) {
|
||||
delete(s.transactions, t.key())
|
||||
}
|
||||
|
||||
func (s *Server) deleteTransactionUnlocked(t *Transaction) {
|
||||
s.mu.Lock()
|
||||
defer s.mu.Unlock()
|
||||
s.deleteTransaction(t)
|
||||
}
|
||||
|
||||
func (s *Server) addTransaction(t *Transaction) {
|
||||
if _, ok := s.transactions[t.key()]; ok {
|
||||
panic("transaction not unique")
|
||||
}
|
||||
s.transactions[t.key()] = t
|
||||
}
|
||||
|
||||
// ID returns the 20-byte server ID. This is the ID used to communicate with the
|
||||
// DHT network.
|
||||
func (s *Server) ID() [20]byte {
|
||||
return s.id.AsByteArray()
|
||||
}
|
||||
|
||||
func (s *Server) createToken(addr Addr) string {
|
||||
return s.tokenServer.CreateToken(addr)
|
||||
}
|
||||
|
||||
func (s *Server) validToken(token string, addr Addr) bool {
|
||||
return s.tokenServer.ValidToken(token, addr)
|
||||
}
|
||||
|
||||
func (s *Server) connTrackEntryForAddr(a Addr) conntrack.Entry {
|
||||
return conntrack.Entry{
|
||||
s.socket.LocalAddr().Network(),
|
||||
s.socket.LocalAddr().String(),
|
||||
a.String(),
|
||||
}
|
||||
}
|
||||
|
||||
func (s *Server) query(addr Addr, q string, a *krpc.MsgArgs, callback func(krpc.Msg, error)) error {
|
||||
tid := s.nextTransactionID()
|
||||
if a == nil {
|
||||
a = &krpc.MsgArgs{}
|
||||
}
|
||||
if callback == nil {
|
||||
callback = func(krpc.Msg, error) {}
|
||||
}
|
||||
a.ID = s.ID()
|
||||
m := krpc.Msg{
|
||||
T: tid,
|
||||
Y: "q",
|
||||
Q: q,
|
||||
A: a,
|
||||
}
|
||||
// BEP 43. Outgoing queries from passive nodes should contain "ro":1 in
|
||||
// the top level dictionary.
|
||||
if s.config.Passive {
|
||||
m.ReadOnly = true
|
||||
}
|
||||
b, err := bencode.Marshal(m)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
var t *Transaction
|
||||
t = &Transaction{
|
||||
remoteAddr: addr,
|
||||
t: tid,
|
||||
querySender: func() error {
|
||||
cteh := s.config.ConnectionTracking.Wait(s.connTrackEntryForAddr(addr), "send dht query", -1)
|
||||
wrote, err := s.writeToNode(b, addr)
|
||||
if wrote {
|
||||
cteh.Done()
|
||||
} else {
|
||||
cteh.Forget()
|
||||
}
|
||||
return err
|
||||
},
|
||||
onResponse: func(m krpc.Msg) {
|
||||
go callback(m, nil)
|
||||
go s.deleteTransactionUnlocked(t)
|
||||
},
|
||||
onTimeout: func() {
|
||||
go callback(krpc.Msg{}, errors.New("query timed out"))
|
||||
s.mu.Lock()
|
||||
defer s.mu.Unlock()
|
||||
s.deleteTransaction(t)
|
||||
for _, n := range s.table.addrNodes(addr) {
|
||||
n.consecutiveFailures++
|
||||
}
|
||||
},
|
||||
onSendError: func(err error) {
|
||||
go callback(krpc.Msg{}, fmt.Errorf("error resending query: %s", err))
|
||||
s.mu.Lock()
|
||||
defer s.mu.Unlock()
|
||||
s.deleteTransaction(t)
|
||||
for _, n := range s.table.addrNodes(addr) {
|
||||
n.consecutiveFailures++
|
||||
}
|
||||
},
|
||||
queryResendDelay: func() time.Duration {
|
||||
if s.config.QueryResendDelay != nil {
|
||||
return s.config.QueryResendDelay()
|
||||
}
|
||||
return defaultQueryResendDelay()
|
||||
},
|
||||
}
|
||||
s.stats.OutboundQueriesAttempted++
|
||||
t.mu.Lock()
|
||||
t.startResendTimer()
|
||||
t.mu.Unlock()
|
||||
s.addTransaction(t)
|
||||
return nil
|
||||
}
|
||||
|
||||
// Sends a ping query to the address given.
|
||||
func (s *Server) Ping(node *net.UDPAddr, callback func(krpc.Msg, error)) error {
|
||||
s.mu.Lock()
|
||||
defer s.mu.Unlock()
|
||||
return s.ping(node, callback)
|
||||
}
|
||||
|
||||
func (s *Server) ping(node *net.UDPAddr, callback func(krpc.Msg, error)) error {
|
||||
return s.query(NewAddr(node), "ping", nil, callback)
|
||||
}
|
||||
|
||||
func (s *Server) announcePeer(node Addr, infoHash int160, port int, token string, impliedPort bool, callback func(krpc.Msg, error)) error {
|
||||
if port == 0 && !impliedPort {
|
||||
return errors.New("nothing to announce")
|
||||
}
|
||||
return s.query(node, "announce_peer", &krpc.MsgArgs{
|
||||
ImpliedPort: impliedPort,
|
||||
InfoHash: infoHash.AsByteArray(),
|
||||
Port: port,
|
||||
Token: token,
|
||||
}, func(m krpc.Msg, err error) {
|
||||
if callback != nil {
|
||||
go callback(m, err)
|
||||
}
|
||||
if err := m.Error(); err != nil {
|
||||
announceErrors.Add(1)
|
||||
return
|
||||
}
|
||||
s.mu.Lock()
|
||||
defer s.mu.Unlock()
|
||||
s.stats.SuccessfulOutboundAnnouncePeerQueries++
|
||||
})
|
||||
}
|
||||
|
||||
// Add response nodes to node table.
|
||||
func (s *Server) addResponseNodes(d krpc.Msg) {
|
||||
if d.R == nil {
|
||||
return
|
||||
}
|
||||
d.R.ForAllNodes(func(ni krpc.NodeInfo) {
|
||||
s.getNode(NewAddr(ni.Addr.UDP()), int160FromByteArray(ni.ID), true)
|
||||
})
|
||||
}
|
||||
|
||||
// Sends a find_node query to addr. targetID is the node we're looking for.
|
||||
func (s *Server) findNode(addr Addr, targetID int160, callback func(krpc.Msg, error)) (err error) {
|
||||
return s.query(addr, "find_node", &krpc.MsgArgs{
|
||||
Target: targetID.AsByteArray(),
|
||||
Want: []krpc.Want{krpc.WantNodes, krpc.WantNodes6},
|
||||
}, func(m krpc.Msg, err error) {
|
||||
// Scrape peers from the response to put in the server's table before
|
||||
// handing the response back to the caller.
|
||||
s.mu.Lock()
|
||||
s.addResponseNodes(m)
|
||||
s.mu.Unlock()
|
||||
callback(m, err)
|
||||
})
|
||||
}
|
||||
|
||||
type TraversalStats struct {
|
||||
NumAddrsTried int
|
||||
NumResponses int
|
||||
}
|
||||
|
||||
// Populates the node table.
|
||||
func (s *Server) Bootstrap() (ts TraversalStats, err error) {
|
||||
initialAddrs, err := s.traversalStartingAddrs()
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
var outstanding sync.WaitGroup
|
||||
triedAddrs := newBloomFilterForTraversal()
|
||||
var onAddr func(addr Addr)
|
||||
onAddr = func(addr Addr) {
|
||||
if triedAddrs.Test([]byte(addr.String())) {
|
||||
return
|
||||
}
|
||||
ts.NumAddrsTried++
|
||||
outstanding.Add(1)
|
||||
triedAddrs.AddString(addr.String())
|
||||
s.findNode(addr, s.id, func(m krpc.Msg, err error) {
|
||||
defer outstanding.Done()
|
||||
s.mu.Lock()
|
||||
defer s.mu.Unlock()
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
ts.NumResponses++
|
||||
if r := m.R; r != nil {
|
||||
r.ForAllNodes(func(ni krpc.NodeInfo) {
|
||||
onAddr(NewAddr(ni.Addr.UDP()))
|
||||
})
|
||||
}
|
||||
})
|
||||
}
|
||||
s.mu.Lock()
|
||||
for _, addr := range initialAddrs {
|
||||
onAddr(addr)
|
||||
}
|
||||
s.mu.Unlock()
|
||||
outstanding.Wait()
|
||||
return
|
||||
}
|
||||
|
||||
// Returns how many nodes are in the node table.
|
||||
func (s *Server) NumNodes() int {
|
||||
s.mu.Lock()
|
||||
defer s.mu.Unlock()
|
||||
return s.numNodes()
|
||||
}
|
||||
|
||||
// Exports the current node table.
|
||||
func (s *Server) Nodes() (nis []krpc.NodeInfo) {
|
||||
s.mu.Lock()
|
||||
defer s.mu.Unlock()
|
||||
s.table.forNodes(func(n *node) bool {
|
||||
nis = append(nis, krpc.NodeInfo{
|
||||
Addr: n.addr.KRPC(),
|
||||
ID: n.id.AsByteArray(),
|
||||
})
|
||||
return true
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
// Stops the server network activity. This is all that's required to clean-up a Server.
|
||||
func (s *Server) Close() {
|
||||
s.mu.Lock()
|
||||
defer s.mu.Unlock()
|
||||
s.closed.Set()
|
||||
s.socket.Close()
|
||||
}
|
||||
|
||||
func (s *Server) getPeers(addr Addr, infoHash int160, callback func(krpc.Msg, error)) (err error) {
|
||||
return s.query(addr, "get_peers", &krpc.MsgArgs{
|
||||
InfoHash: infoHash.AsByteArray(),
|
||||
Want: []krpc.Want{krpc.WantNodes, krpc.WantNodes6},
|
||||
}, func(m krpc.Msg, err error) {
|
||||
go callback(m, err)
|
||||
s.mu.Lock()
|
||||
defer s.mu.Unlock()
|
||||
s.addResponseNodes(m)
|
||||
if m.R != nil && m.R.Token != "" && m.SenderID() != nil {
|
||||
if n, _ := s.getNode(addr, int160FromByteArray(*m.SenderID()), false); n != nil {
|
||||
n.announceToken = m.R.Token
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
func (s *Server) closestGoodNodeInfos(
|
||||
k int,
|
||||
targetID int160,
|
||||
filter func(krpc.NodeAddr) bool,
|
||||
) (
|
||||
ret []krpc.NodeInfo,
|
||||
) {
|
||||
for _, n := range s.closestNodes(k, targetID, func(n *node) bool {
|
||||
return n.IsGood() && filter(n.NodeInfo().Addr)
|
||||
}) {
|
||||
ret = append(ret, n.NodeInfo())
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func (s *Server) closestNodes(k int, target int160, filter func(*node) bool) []*node {
|
||||
return s.table.closestNodes(k, target, filter)
|
||||
}
|
||||
|
||||
func (s *Server) traversalStartingAddrs() (addrs []Addr, err error) {
|
||||
s.mu.RLock()
|
||||
s.table.forNodes(func(n *node) bool {
|
||||
addrs = append(addrs, n.addr)
|
||||
return true
|
||||
})
|
||||
s.mu.RUnlock()
|
||||
if len(addrs) > 0 {
|
||||
return
|
||||
}
|
||||
if s.config.StartingNodes != nil {
|
||||
addrs, err = s.config.StartingNodes()
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
}
|
||||
if len(addrs) == 0 {
|
||||
err = errors.New("no initial nodes")
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func (s *Server) AddNodesFromFile(fileName string) (added int, err error) {
|
||||
ns, err := ReadNodesFromFile(fileName)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
for _, n := range ns {
|
||||
if s.AddNode(n) == nil {
|
||||
added++
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
72
vendor/github.com/anacrolix/dht/transaction.go
generated
vendored
72
vendor/github.com/anacrolix/dht/transaction.go
generated
vendored
@@ -1,72 +0,0 @@
|
||||
package dht
|
||||
|
||||
import (
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/anacrolix/dht/krpc"
|
||||
)
|
||||
|
||||
// Transaction keeps track of a message exchange between nodes, such as a
|
||||
// query message and a response message.
|
||||
type Transaction struct {
|
||||
remoteAddr Addr
|
||||
t string
|
||||
onResponse func(krpc.Msg)
|
||||
onTimeout func()
|
||||
onSendError func(error)
|
||||
querySender func() error
|
||||
queryResendDelay func() time.Duration
|
||||
|
||||
mu sync.Mutex
|
||||
gotResponse bool
|
||||
timer *time.Timer
|
||||
retries int
|
||||
lastSend time.Time
|
||||
}
|
||||
|
||||
func (t *Transaction) handleResponse(m krpc.Msg) {
|
||||
t.mu.Lock()
|
||||
t.gotResponse = true
|
||||
t.mu.Unlock()
|
||||
t.onResponse(m)
|
||||
}
|
||||
|
||||
func (t *Transaction) key() transactionKey {
|
||||
return transactionKey{
|
||||
t.remoteAddr.String(),
|
||||
t.t,
|
||||
}
|
||||
}
|
||||
|
||||
func (t *Transaction) startResendTimer() {
|
||||
t.timer = time.AfterFunc(0, t.resendCallback)
|
||||
}
|
||||
|
||||
func (t *Transaction) resendCallback() {
|
||||
t.mu.Lock()
|
||||
defer t.mu.Unlock()
|
||||
if t.gotResponse {
|
||||
return
|
||||
}
|
||||
if t.retries == 3 {
|
||||
go t.onTimeout()
|
||||
return
|
||||
}
|
||||
t.retries++
|
||||
if err := t.sendQuery(); err != nil {
|
||||
go t.onSendError(err)
|
||||
return
|
||||
}
|
||||
if t.timer.Reset(t.queryResendDelay()) {
|
||||
panic("timer should have fired to get here")
|
||||
}
|
||||
}
|
||||
|
||||
func (t *Transaction) sendQuery() error {
|
||||
if err := t.querySender(); err != nil {
|
||||
return err
|
||||
}
|
||||
t.lastSend = time.Now()
|
||||
return nil
|
||||
}
|
||||
0
vendor/github.com/anacrolix/dht/LICENSE → vendor/github.com/anacrolix/dht/v2/LICENSE
generated
vendored
0
vendor/github.com/anacrolix/dht/LICENSE → vendor/github.com/anacrolix/dht/v2/LICENSE
generated
vendored
21
vendor/github.com/anacrolix/dht/v2/README.md
generated
vendored
Normal file
21
vendor/github.com/anacrolix/dht/v2/README.md
generated
vendored
Normal file
@@ -0,0 +1,21 @@
|
||||
# dht
|
||||
|
||||
[](https://pkg.go.dev/github.com/anacrolix/dht/v2)
|
||||
|
||||
## Installation
|
||||
|
||||
Get the library package with `go get github.com/anacrolix/dht/v2`, or the provided cmds with `go install github.com/anacrolix/dht/v2/cmd/...@latest`.
|
||||
|
||||
## Commands
|
||||
|
||||
Here I'll describe what some of the provided commands in `./cmd` do.
|
||||
|
||||
### dht-ping
|
||||
|
||||
Pings DHT nodes with the given network addresses.
|
||||
|
||||
$ go run ./cmd/dht-ping router.bittorrent.com:6881 router.utorrent.com:6881
|
||||
2015/04/01 17:21:23 main.go:33: dht server on [::]:60058
|
||||
32f54e697351ff4aec29cdbaabf2fbe3467cc267 (router.bittorrent.com:6881): 648.218621ms
|
||||
ebff36697351ff4aec29cdbaabf2fbe3467cc267 (router.utorrent.com:6881): 873.864706ms
|
||||
2/2 responses (100.000000%)
|
||||
42
vendor/github.com/anacrolix/dht/addr.go → vendor/github.com/anacrolix/dht/v2/addr.go
generated
vendored
42
vendor/github.com/anacrolix/dht/addr.go → vendor/github.com/anacrolix/dht/v2/addr.go
generated
vendored
@@ -3,7 +3,9 @@ package dht
|
||||
import (
|
||||
"net"
|
||||
|
||||
"github.com/anacrolix/dht/krpc"
|
||||
"github.com/anacrolix/missinggo/v2"
|
||||
|
||||
"github.com/anacrolix/dht/v2/krpc"
|
||||
)
|
||||
|
||||
// Used internally to refer to node network addresses. String() is called a
|
||||
@@ -11,35 +13,49 @@ import (
|
||||
// interface does not satisfy net.Addr, as the underlying type must be passed
|
||||
// to any OS-level function that take net.Addr.
|
||||
type Addr interface {
|
||||
UDPAddr() *net.UDPAddr
|
||||
Raw() net.Addr
|
||||
Port() int
|
||||
IP() net.IP
|
||||
String() string
|
||||
KRPC() krpc.NodeAddr
|
||||
}
|
||||
|
||||
// Speeds up some of the commonly called Addr methods.
|
||||
type cachedAddr struct {
|
||||
ua net.UDPAddr
|
||||
s string
|
||||
raw net.Addr
|
||||
port int
|
||||
ip net.IP
|
||||
s string
|
||||
}
|
||||
|
||||
func (ca cachedAddr) String() string {
|
||||
return ca.s
|
||||
}
|
||||
|
||||
func (ca cachedAddr) UDPAddr() *net.UDPAddr {
|
||||
return &ca.ua
|
||||
}
|
||||
|
||||
func (ca cachedAddr) KRPC() krpc.NodeAddr {
|
||||
return krpc.NodeAddr{
|
||||
IP: ca.ua.IP,
|
||||
Port: ca.ua.Port,
|
||||
IP: ca.ip,
|
||||
Port: ca.port,
|
||||
}
|
||||
}
|
||||
|
||||
func NewAddr(ua *net.UDPAddr) Addr {
|
||||
func (ca cachedAddr) IP() net.IP {
|
||||
return ca.ip
|
||||
}
|
||||
|
||||
func (ca cachedAddr) Port() int {
|
||||
return ca.port
|
||||
}
|
||||
|
||||
func (ca cachedAddr) Raw() net.Addr {
|
||||
return ca.raw
|
||||
}
|
||||
|
||||
func NewAddr(raw net.Addr) Addr {
|
||||
return cachedAddr{
|
||||
ua: *ua,
|
||||
s: ua.String(),
|
||||
raw: raw,
|
||||
s: raw.String(),
|
||||
ip: missinggo.AddrIP(raw),
|
||||
port: missinggo.AddrPort(raw),
|
||||
}
|
||||
}
|
||||
219
vendor/github.com/anacrolix/dht/v2/announce.go
generated
vendored
Normal file
219
vendor/github.com/anacrolix/dht/v2/announce.go
generated
vendored
Normal file
@@ -0,0 +1,219 @@
|
||||
package dht
|
||||
|
||||
// get_peers and announce_peers.
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"sync"
|
||||
"sync/atomic"
|
||||
|
||||
"github.com/anacrolix/chansync"
|
||||
"github.com/anacrolix/chansync/events"
|
||||
"github.com/anacrolix/log"
|
||||
|
||||
"github.com/anacrolix/dht/v2/int160"
|
||||
dhtutil "github.com/anacrolix/dht/v2/k-nearest-nodes"
|
||||
"github.com/anacrolix/dht/v2/krpc"
|
||||
"github.com/anacrolix/dht/v2/traversal"
|
||||
)
|
||||
|
||||
// Maintains state for an ongoing Announce operation. An Announce is started by calling
|
||||
// Server.Announce.
|
||||
type Announce struct {
|
||||
Peers chan PeersValues
|
||||
|
||||
server *Server
|
||||
infoHash int160.T // Target
|
||||
|
||||
announcePeerOpts *AnnouncePeerOpts
|
||||
scrape bool
|
||||
peerAnnounced chansync.SetOnce
|
||||
|
||||
traversal *traversal.Operation
|
||||
|
||||
closed chansync.SetOnce
|
||||
}
|
||||
|
||||
func (a *Announce) String() string {
|
||||
return fmt.Sprintf("%[1]T %[1]p of %v on %v", a, a.infoHash, a.server)
|
||||
}
|
||||
|
||||
// Returns the number of distinct remote addresses the announce has queried.
|
||||
func (a *Announce) NumContacted() uint32 {
|
||||
return atomic.LoadUint32(&a.traversal.Stats().NumAddrsTried)
|
||||
}
|
||||
|
||||
func (a *Announce) TraversalStats() TraversalStats {
|
||||
return *a.traversal.Stats()
|
||||
}
|
||||
|
||||
// Server.Announce option
|
||||
type AnnounceOpt func(a *Announce)
|
||||
|
||||
// Scrape BEP 33 bloom filters in queries.
|
||||
func Scrape() AnnounceOpt {
|
||||
return func(a *Announce) {
|
||||
a.scrape = true
|
||||
}
|
||||
}
|
||||
|
||||
// Arguments for announce_peer from a Server.Announce.
|
||||
type AnnouncePeerOpts struct {
|
||||
// The peer port that we're announcing.
|
||||
Port int
|
||||
// The peer port should be determined by the receiver to be the source port of the query packet.
|
||||
ImpliedPort bool
|
||||
}
|
||||
|
||||
// Finish an Announce get_peers traversal with an announce of a local peer.
|
||||
func AnnouncePeer(opts AnnouncePeerOpts) AnnounceOpt {
|
||||
return func(a *Announce) {
|
||||
a.announcePeerOpts = &opts
|
||||
}
|
||||
}
|
||||
|
||||
// Deprecated: Use Server.AnnounceTraversal.
|
||||
// Traverses the DHT graph toward nodes that store peers for the infohash, streaming them to the
|
||||
// caller, and announcing the local node to each responding node if port is non-zero or impliedPort
|
||||
// is true.
|
||||
func (s *Server) Announce(infoHash [20]byte, port int, impliedPort bool, opts ...AnnounceOpt) (_ *Announce, err error) {
|
||||
if port != 0 || impliedPort {
|
||||
opts = append([]AnnounceOpt{AnnouncePeer(AnnouncePeerOpts{
|
||||
Port: port,
|
||||
ImpliedPort: impliedPort,
|
||||
})}, opts...)
|
||||
}
|
||||
return s.AnnounceTraversal(infoHash, opts...)
|
||||
}
|
||||
|
||||
// Traverses the DHT graph toward nodes that store peers for the infohash, streaming them to the
|
||||
// caller.
|
||||
func (s *Server) AnnounceTraversal(infoHash [20]byte, opts ...AnnounceOpt) (_ *Announce, err error) {
|
||||
infoHashInt160 := int160.FromByteArray(infoHash)
|
||||
a := &Announce{
|
||||
Peers: make(chan PeersValues),
|
||||
server: s,
|
||||
infoHash: infoHashInt160,
|
||||
}
|
||||
for _, opt := range opts {
|
||||
opt(a)
|
||||
}
|
||||
a.traversal = traversal.Start(traversal.OperationInput{
|
||||
Target: infoHash,
|
||||
DoQuery: a.getPeers,
|
||||
NodeFilter: s.TraversalNodeFilter,
|
||||
})
|
||||
nodes, err := s.TraversalStartingNodes()
|
||||
if err != nil {
|
||||
a.traversal.Stop()
|
||||
return
|
||||
}
|
||||
a.traversal.AddNodes(nodes)
|
||||
go func() {
|
||||
<-a.traversal.Stalled()
|
||||
a.traversal.Stop()
|
||||
<-a.traversal.Stopped()
|
||||
if a.announcePeerOpts != nil {
|
||||
a.announceClosest()
|
||||
}
|
||||
a.peerAnnounced.Set()
|
||||
close(a.Peers)
|
||||
}()
|
||||
return a, nil
|
||||
}
|
||||
|
||||
func (a *Announce) announceClosest() {
|
||||
var wg sync.WaitGroup
|
||||
a.traversal.Closest().Range(func(elem dhtutil.Elem) {
|
||||
wg.Add(1)
|
||||
go func() {
|
||||
a.logger().Levelf(log.Debug,
|
||||
"announce_peer to %v: %v",
|
||||
elem, a.announcePeer(elem),
|
||||
)
|
||||
wg.Done()
|
||||
}()
|
||||
})
|
||||
wg.Wait()
|
||||
}
|
||||
|
||||
func (a *Announce) announcePeer(peer dhtutil.Elem) error {
|
||||
ctx, cancel := context.WithCancel(context.Background())
|
||||
defer cancel()
|
||||
go func() {
|
||||
select {
|
||||
case <-a.closed.Done():
|
||||
cancel()
|
||||
case <-ctx.Done():
|
||||
}
|
||||
}()
|
||||
return a.server.announcePeer(
|
||||
ctx,
|
||||
NewAddr(peer.Addr.UDP()),
|
||||
a.infoHash,
|
||||
a.announcePeerOpts.Port,
|
||||
peer.Data.(string),
|
||||
a.announcePeerOpts.ImpliedPort,
|
||||
QueryRateLimiting{},
|
||||
).Err
|
||||
}
|
||||
|
||||
func (a *Announce) getPeers(ctx context.Context, addr krpc.NodeAddr) (tqr traversal.QueryResult) {
|
||||
res := a.server.GetPeers(ctx, NewAddr(addr.UDP()), a.infoHash, a.scrape, QueryRateLimiting{})
|
||||
if r := res.Reply.R; r != nil {
|
||||
peersValues := PeersValues{
|
||||
Peers: r.Values,
|
||||
NodeInfo: krpc.NodeInfo{
|
||||
Addr: addr,
|
||||
ID: r.ID,
|
||||
},
|
||||
Return: *r,
|
||||
}
|
||||
select {
|
||||
case a.Peers <- peersValues:
|
||||
case <-a.traversal.Stopped():
|
||||
}
|
||||
if r.Token != nil {
|
||||
tqr.ClosestData = *r.Token
|
||||
tqr.ResponseFrom = &krpc.NodeInfo{
|
||||
ID: r.ID,
|
||||
Addr: addr,
|
||||
}
|
||||
}
|
||||
tqr.Nodes = r.Nodes
|
||||
tqr.Nodes6 = r.Nodes6
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// Corresponds to the "values" key in a get_peers KRPC response. A list of
|
||||
// peers that a node has reported as being in the swarm for a queried info
|
||||
// hash.
|
||||
type PeersValues struct {
|
||||
Peers []Peer // Peers given in get_peers response.
|
||||
krpc.NodeInfo // The node that gave the response.
|
||||
krpc.Return
|
||||
}
|
||||
|
||||
// Stop the announce.
|
||||
func (a *Announce) Close() {
|
||||
a.StopTraversing()
|
||||
// This will prevent peer announces from proceeding.
|
||||
a.closed.Set()
|
||||
}
|
||||
|
||||
func (a *Announce) logger() log.Logger {
|
||||
return a.server.logger()
|
||||
}
|
||||
|
||||
// Halts traversal, but won't block peer announcing.
|
||||
func (a *Announce) StopTraversing() {
|
||||
a.traversal.Stop()
|
||||
}
|
||||
|
||||
// Traversal and peer announcing steps are done.
|
||||
func (a *Announce) Finished() events.Done {
|
||||
// This is the last step in an announce.
|
||||
return a.peerAnnounced.Done()
|
||||
}
|
||||
27
vendor/github.com/anacrolix/dht/v2/bep44/error.go
generated
vendored
Normal file
27
vendor/github.com/anacrolix/dht/v2/bep44/error.go
generated
vendored
Normal file
@@ -0,0 +1,27 @@
|
||||
package bep44
|
||||
|
||||
import "github.com/anacrolix/dht/v2/krpc"
|
||||
|
||||
var (
|
||||
ErrValueFieldTooBig = krpc.Error{
|
||||
Code: krpc.ErrorCodeMessageValueFieldTooBig,
|
||||
Msg: "message (v field) too big",
|
||||
}
|
||||
ErrInvalidSignature = krpc.Error{
|
||||
Code: krpc.ErrorCodeInvalidSignature,
|
||||
Msg: "invalid signature",
|
||||
}
|
||||
|
||||
ErrSaltFieldTooBig = krpc.Error{
|
||||
Code: krpc.ErrorCodeSaltFieldTooBig,
|
||||
Msg: "salt (salt field) too big",
|
||||
}
|
||||
ErrCasHashMismatched = krpc.Error{
|
||||
Code: krpc.ErrorCodeCasHashMismatched,
|
||||
Msg: "the CAS hash mismatched, re-read value and try again",
|
||||
}
|
||||
ErrSequenceNumberLessThanCurrent = krpc.Error{
|
||||
Code: krpc.ErrorCodeSequenceNumberLessThanCurrent,
|
||||
Msg: "sequence number less than current",
|
||||
}
|
||||
)
|
||||
177
vendor/github.com/anacrolix/dht/v2/bep44/item.go
generated
vendored
Normal file
177
vendor/github.com/anacrolix/dht/v2/bep44/item.go
generated
vendored
Normal file
@@ -0,0 +1,177 @@
|
||||
package bep44
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"crypto/ed25519"
|
||||
"crypto/sha1"
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"github.com/anacrolix/torrent/bencode"
|
||||
)
|
||||
|
||||
var Empty32ByteArray [32]byte
|
||||
|
||||
type Item struct {
|
||||
// time when this object was added to storage
|
||||
created time.Time
|
||||
|
||||
// Value to be stored
|
||||
V interface{}
|
||||
|
||||
// 32 byte ed25519 public key
|
||||
K [32]byte
|
||||
Salt []byte
|
||||
Sig [64]byte
|
||||
Cas int64
|
||||
Seq int64
|
||||
}
|
||||
|
||||
func (i *Item) ToPut() Put {
|
||||
p := Put{
|
||||
V: i.V,
|
||||
Salt: i.Salt,
|
||||
Sig: i.Sig,
|
||||
Cas: i.Cas,
|
||||
Seq: i.Seq,
|
||||
}
|
||||
if i.K != Empty32ByteArray {
|
||||
p.K = &i.K
|
||||
}
|
||||
return p
|
||||
}
|
||||
|
||||
// NewItem creates a new arbitrary DHT element. The distinction between storing mutable
|
||||
// and immutable items is the inclusion of a public key, a sequence number, signature
|
||||
// and an optional salt.
|
||||
//
|
||||
// cas parameter is short for compare and swap, it has similar semantics as CAS CPU
|
||||
// instructions. It is used to avoid race conditions when multiple nodes are writing
|
||||
// to the same slot in the DHT. It is optional. If present it specifies the sequence
|
||||
// number of the data blob being overwritten by the put.
|
||||
//
|
||||
// salt parameter is used to make possible several targets using the same private key.
|
||||
//
|
||||
// The optional seq field specifies that an item's value should only be sent if its
|
||||
// sequence number is greater than the given value.
|
||||
func NewItem(value interface{}, salt []byte, seq, cas int64, k ed25519.PrivateKey) (*Item, error) {
|
||||
v, err := bencode.Marshal(value)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var kk [32]byte
|
||||
var sig [64]byte
|
||||
|
||||
if k != nil {
|
||||
pk := []byte(k.Public().(ed25519.PublicKey))
|
||||
copy(kk[:], pk)
|
||||
copy(sig[:], Sign(k, salt, seq, v))
|
||||
}
|
||||
|
||||
return &Item{
|
||||
V: value,
|
||||
Salt: salt,
|
||||
Cas: cas,
|
||||
Seq: seq,
|
||||
|
||||
K: kk,
|
||||
Sig: sig,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (i *Item) Target() Target {
|
||||
if i.IsMutable() {
|
||||
return sha1.Sum(append(i.K[:], i.Salt...))
|
||||
}
|
||||
|
||||
return sha1.Sum(bencode.MustMarshal(i.V))
|
||||
}
|
||||
|
||||
func (i *Item) Modify(value interface{}, k ed25519.PrivateKey) bool {
|
||||
if !i.IsMutable() {
|
||||
return false
|
||||
}
|
||||
|
||||
v, err := bencode.Marshal(value)
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
|
||||
i.V = value
|
||||
i.Seq++
|
||||
var sig [64]byte
|
||||
copy(sig[:], Sign(k, i.Salt, i.Seq, v))
|
||||
i.Sig = sig
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
func (s *Item) IsMutable() bool {
|
||||
return s.K != Empty32ByteArray
|
||||
}
|
||||
|
||||
func bufferToSign(salt, bv []byte, seq int64) []byte {
|
||||
var bts []byte
|
||||
if len(salt) != 0 {
|
||||
bts = append(bts, []byte("4:salt")...)
|
||||
x := bencode.MustMarshal(salt)
|
||||
bts = append(bts, x...)
|
||||
}
|
||||
bts = append(bts, []byte(fmt.Sprintf("3:seqi%de1:v", seq))...)
|
||||
bts = append(bts, bv...)
|
||||
return bts
|
||||
}
|
||||
|
||||
func Check(i *Item) error {
|
||||
bv, err := bencode.Marshal(i.V)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if len(bv) > 1000 {
|
||||
return ErrValueFieldTooBig
|
||||
}
|
||||
|
||||
if !i.IsMutable() {
|
||||
return nil
|
||||
}
|
||||
|
||||
if len(i.Salt) > 64 {
|
||||
return ErrSaltFieldTooBig
|
||||
}
|
||||
|
||||
if !Verify(i.K[:], i.Salt, i.Seq, bv, i.Sig[:]) {
|
||||
return ErrInvalidSignature
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func CheckIncoming(stored, incoming *Item) error {
|
||||
// If the sequence number is equal, and the value is also the same,
|
||||
// the node SHOULD reset its timeout counter.
|
||||
if stored.Seq == incoming.Seq {
|
||||
if bytes.Equal(
|
||||
bencode.MustMarshal(stored.V),
|
||||
bencode.MustMarshal(incoming.V),
|
||||
) {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
if stored.Seq >= incoming.Seq {
|
||||
return ErrSequenceNumberLessThanCurrent
|
||||
}
|
||||
|
||||
// Cas should be ignored if not present
|
||||
if stored.Cas == 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
if stored.Cas != incoming.Cas {
|
||||
return ErrCasHashMismatched
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
13
vendor/github.com/anacrolix/dht/v2/bep44/key.go
generated
vendored
Normal file
13
vendor/github.com/anacrolix/dht/v2/bep44/key.go
generated
vendored
Normal file
@@ -0,0 +1,13 @@
|
||||
package bep44
|
||||
|
||||
import (
|
||||
"crypto/ed25519"
|
||||
)
|
||||
|
||||
func Sign(k ed25519.PrivateKey, salt []byte, seq int64, bv []byte) []byte {
|
||||
return ed25519.Sign(k, bufferToSign(salt, bv, seq))
|
||||
}
|
||||
|
||||
func Verify(k ed25519.PublicKey, salt []byte, seq int64, bv []byte, sig []byte) bool {
|
||||
return ed25519.Verify(k, bufferToSign(salt, bv, seq), sig)
|
||||
}
|
||||
49
vendor/github.com/anacrolix/dht/v2/bep44/memory.go
generated
vendored
Normal file
49
vendor/github.com/anacrolix/dht/v2/bep44/memory.go
generated
vendored
Normal file
@@ -0,0 +1,49 @@
|
||||
package bep44
|
||||
|
||||
import (
|
||||
"sync"
|
||||
)
|
||||
|
||||
var _ Store = &Memory{}
|
||||
|
||||
type Memory struct {
|
||||
// protects m
|
||||
mu sync.RWMutex
|
||||
m map[Target]*Item
|
||||
}
|
||||
|
||||
func NewMemory() *Memory {
|
||||
return &Memory{
|
||||
m: make(map[Target]*Item),
|
||||
}
|
||||
}
|
||||
|
||||
func (m *Memory) Put(i *Item) error {
|
||||
m.mu.Lock()
|
||||
defer m.mu.Unlock()
|
||||
|
||||
m.m[i.Target()] = i
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *Memory) Get(t Target) (*Item, error) {
|
||||
m.mu.Lock()
|
||||
defer m.mu.Unlock()
|
||||
|
||||
i, ok := m.m[t]
|
||||
if !ok {
|
||||
return nil, ErrItemNotFound
|
||||
}
|
||||
|
||||
return i, nil
|
||||
}
|
||||
|
||||
func (m *Memory) Del(t Target) error {
|
||||
m.mu.Lock()
|
||||
defer m.mu.Unlock()
|
||||
|
||||
delete(m.m, t)
|
||||
|
||||
return nil
|
||||
}
|
||||
47
vendor/github.com/anacrolix/dht/v2/bep44/put.go
generated
vendored
Normal file
47
vendor/github.com/anacrolix/dht/v2/bep44/put.go
generated
vendored
Normal file
@@ -0,0 +1,47 @@
|
||||
package bep44
|
||||
|
||||
import (
|
||||
"crypto/ed25519"
|
||||
"crypto/sha1"
|
||||
|
||||
"github.com/anacrolix/torrent/bencode"
|
||||
)
|
||||
|
||||
type Put struct {
|
||||
V interface{}
|
||||
K *[32]byte
|
||||
Salt []byte
|
||||
Sig [64]byte
|
||||
Cas int64
|
||||
Seq int64
|
||||
}
|
||||
|
||||
func (p *Put) ToItem() *Item {
|
||||
i := &Item{
|
||||
V: p.V,
|
||||
Salt: p.Salt,
|
||||
Sig: p.Sig,
|
||||
Cas: p.Cas,
|
||||
Seq: p.Seq,
|
||||
}
|
||||
if p.K != nil {
|
||||
i.K = *p.K
|
||||
}
|
||||
return i
|
||||
}
|
||||
|
||||
func (p *Put) Sign(k ed25519.PrivateKey) {
|
||||
copy(p.Sig[:], Sign(k, p.Salt, p.Seq, bencode.MustMarshal(p.V)))
|
||||
}
|
||||
|
||||
func (i *Put) Target() Target {
|
||||
if i.IsMutable() {
|
||||
return MakeMutableTarget(*i.K, i.Salt)
|
||||
} else {
|
||||
return sha1.Sum(bencode.MustMarshal(i.V))
|
||||
}
|
||||
}
|
||||
|
||||
func (s *Put) IsMutable() bool {
|
||||
return s.K != nil
|
||||
}
|
||||
65
vendor/github.com/anacrolix/dht/v2/bep44/store.go
generated
vendored
Normal file
65
vendor/github.com/anacrolix/dht/v2/bep44/store.go
generated
vendored
Normal file
@@ -0,0 +1,65 @@
|
||||
package bep44
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"time"
|
||||
)
|
||||
|
||||
var ErrItemNotFound = errors.New("item not found")
|
||||
|
||||
type Store interface {
|
||||
Put(*Item) error
|
||||
Get(Target) (*Item, error)
|
||||
Del(Target) error
|
||||
}
|
||||
|
||||
// Wrapper is in charge of validate all new items and
|
||||
// decide when to store, or ignore them depending of the BEP 44 definition.
|
||||
// It is also in charge of removing expired items.
|
||||
type Wrapper struct {
|
||||
s Store
|
||||
exp time.Duration
|
||||
}
|
||||
|
||||
func NewWrapper(s Store, exp time.Duration) *Wrapper {
|
||||
return &Wrapper{s: s, exp: exp}
|
||||
}
|
||||
|
||||
func (w *Wrapper) Put(i *Item) error {
|
||||
if err := Check(i); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
is, err := w.s.Get(i.Target())
|
||||
if errors.Is(err, ErrItemNotFound) {
|
||||
i.created = time.Now().Local()
|
||||
return w.s.Put(i)
|
||||
}
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := CheckIncoming(is, i); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
i.created = time.Now().Local()
|
||||
return w.s.Put(i)
|
||||
}
|
||||
|
||||
func (w *Wrapper) Get(t Target) (*Item, error) {
|
||||
i, err := w.s.Get(t)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if i.created.Add(w.exp).After(time.Now().Local()) {
|
||||
return i, nil
|
||||
}
|
||||
|
||||
if err := w.s.Del(t); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return nil, ErrItemNotFound
|
||||
}
|
||||
11
vendor/github.com/anacrolix/dht/v2/bep44/target.go
generated
vendored
Normal file
11
vendor/github.com/anacrolix/dht/v2/bep44/target.go
generated
vendored
Normal file
@@ -0,0 +1,11 @@
|
||||
package bep44
|
||||
|
||||
import (
|
||||
"crypto/sha1"
|
||||
)
|
||||
|
||||
type Target = [sha1.Size]byte
|
||||
|
||||
func MakeMutableTarget(pubKey [32]byte, salt []byte) Target {
|
||||
return sha1.Sum(append(pubKey[:], salt...))
|
||||
}
|
||||
65
vendor/github.com/anacrolix/dht/v2/bootstrap.go
generated
vendored
Normal file
65
vendor/github.com/anacrolix/dht/v2/bootstrap.go
generated
vendored
Normal file
@@ -0,0 +1,65 @@
|
||||
package dht
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"time"
|
||||
|
||||
"github.com/anacrolix/dht/v2/krpc"
|
||||
"github.com/anacrolix/dht/v2/traversal"
|
||||
)
|
||||
|
||||
type TraversalStats = traversal.Stats
|
||||
|
||||
// See BootstrapContext.
|
||||
func (s *Server) Bootstrap() (TraversalStats, error) {
|
||||
return s.BootstrapContext(context.Background())
|
||||
}
|
||||
|
||||
// Populates the node table.
|
||||
func (s *Server) BootstrapContext(ctx context.Context) (_ TraversalStats, err error) {
|
||||
s.mu.Lock()
|
||||
if s.bootstrappingNow {
|
||||
s.mu.Unlock()
|
||||
err = errors.New("already bootstrapping")
|
||||
return
|
||||
}
|
||||
s.bootstrappingNow = true
|
||||
s.mu.Unlock()
|
||||
defer func() {
|
||||
s.mu.Lock()
|
||||
defer s.mu.Unlock()
|
||||
s.bootstrappingNow = false
|
||||
}()
|
||||
// Track number of responses, for STM use. (It's available via atomic in TraversalStats but that
|
||||
// won't let wake up STM transactions that are observing the value.)
|
||||
t := traversal.Start(traversal.OperationInput{
|
||||
Target: krpc.ID(s.id.AsByteArray()),
|
||||
K: 16,
|
||||
DoQuery: func(ctx context.Context, addr krpc.NodeAddr) traversal.QueryResult {
|
||||
return s.FindNode(NewAddr(addr.UDP()), s.id, QueryRateLimiting{}).TraversalQueryResult(addr)
|
||||
},
|
||||
NodeFilter: s.TraversalNodeFilter,
|
||||
})
|
||||
nodes, err := s.TraversalStartingNodes()
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
t.AddNodes(nodes)
|
||||
s.mu.Lock()
|
||||
s.lastBootstrap = time.Now()
|
||||
s.mu.Unlock()
|
||||
select {
|
||||
case <-ctx.Done():
|
||||
err = ctx.Err()
|
||||
case <-t.Stalled():
|
||||
}
|
||||
t.Stop()
|
||||
if err != nil {
|
||||
// Could test for Stopped and return stats here but the interface doesn't tell the caller if
|
||||
// we were successful in taking the stats. We could also take a snapshot instead.
|
||||
return
|
||||
}
|
||||
<-t.Stopped()
|
||||
return *t.Stats(), nil
|
||||
}
|
||||
17
vendor/github.com/anacrolix/dht/bucket.go → vendor/github.com/anacrolix/dht/v2/bucket.go
generated
vendored
17
vendor/github.com/anacrolix/dht/bucket.go → vendor/github.com/anacrolix/dht/v2/bucket.go
generated
vendored
@@ -1,7 +1,18 @@
|
||||
package dht
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"github.com/anacrolix/chansync"
|
||||
|
||||
"github.com/anacrolix/dht/v2/int160"
|
||||
)
|
||||
|
||||
type bucket struct {
|
||||
nodes map[*node]struct{}
|
||||
// Per the "Routing Table" section of BEP 5.
|
||||
changed chansync.BroadcastCond
|
||||
lastChanged time.Time
|
||||
nodes map[*node]struct{}
|
||||
}
|
||||
|
||||
func (b *bucket) Len() int {
|
||||
@@ -25,9 +36,11 @@ func (b *bucket) AddNode(n *node, k int) {
|
||||
b.nodes = make(map[*node]struct{}, k)
|
||||
}
|
||||
b.nodes[n] = struct{}{}
|
||||
b.lastChanged = time.Now()
|
||||
b.changed.Broadcast()
|
||||
}
|
||||
|
||||
func (b *bucket) GetNode(addr Addr, id int160) *node {
|
||||
func (b *bucket) GetNode(addr Addr, id int160.T) *node {
|
||||
for n := range b.nodes {
|
||||
if n.hasAddrAndID(addr, id) {
|
||||
return n
|
||||
45
vendor/github.com/anacrolix/dht/v2/containers/addr-maybe-ids-by-distance.go
generated
vendored
Normal file
45
vendor/github.com/anacrolix/dht/v2/containers/addr-maybe-ids-by-distance.go
generated
vendored
Normal file
@@ -0,0 +1,45 @@
|
||||
package containers
|
||||
|
||||
import (
|
||||
"github.com/anacrolix/missinggo/v2/iter"
|
||||
"github.com/anacrolix/stm/stmutil"
|
||||
|
||||
"github.com/anacrolix/dht/v2/int160"
|
||||
"github.com/anacrolix/dht/v2/types"
|
||||
)
|
||||
|
||||
type addrMaybeId = types.AddrMaybeId
|
||||
|
||||
type AddrMaybeIdsByDistance interface {
|
||||
Add(addrMaybeId) AddrMaybeIdsByDistance
|
||||
Next() addrMaybeId
|
||||
Delete(addrMaybeId) AddrMaybeIdsByDistance
|
||||
Len() int
|
||||
}
|
||||
|
||||
type stmSettishWrapper struct {
|
||||
set stmutil.Settish
|
||||
}
|
||||
|
||||
func (me stmSettishWrapper) Next() addrMaybeId {
|
||||
first, _ := iter.First(me.set.Iter)
|
||||
return first.(addrMaybeId)
|
||||
}
|
||||
|
||||
func (me stmSettishWrapper) Delete(x addrMaybeId) AddrMaybeIdsByDistance {
|
||||
return stmSettishWrapper{me.set.Delete(x)}
|
||||
}
|
||||
|
||||
func (me stmSettishWrapper) Len() int {
|
||||
return me.set.Len()
|
||||
}
|
||||
|
||||
func (me stmSettishWrapper) Add(x addrMaybeId) AddrMaybeIdsByDistance {
|
||||
return stmSettishWrapper{me.set.Add(x)}
|
||||
}
|
||||
|
||||
func NewImmutableAddrMaybeIdsByDistance(target int160.T) AddrMaybeIdsByDistance {
|
||||
return stmSettishWrapper{stmutil.NewSortedSet(func(l, r interface{}) bool {
|
||||
return l.(addrMaybeId).CloserThan(r.(addrMaybeId), target)
|
||||
})}
|
||||
}
|
||||
93
vendor/github.com/anacrolix/dht/dht.go → vendor/github.com/anacrolix/dht/v2/dht.go
generated
vendored
93
vendor/github.com/anacrolix/dht/dht.go → vendor/github.com/anacrolix/dht/v2/dht.go
generated
vendored
@@ -1,24 +1,28 @@
|
||||
package dht
|
||||
|
||||
import (
|
||||
"context"
|
||||
"crypto"
|
||||
crand "crypto/rand"
|
||||
_ "crypto/sha1"
|
||||
"errors"
|
||||
"log"
|
||||
"math/rand"
|
||||
"net"
|
||||
"time"
|
||||
|
||||
"github.com/anacrolix/dht/krpc"
|
||||
"github.com/anacrolix/missinggo"
|
||||
"github.com/anacrolix/missinggo/conntrack"
|
||||
"github.com/anacrolix/log"
|
||||
"github.com/anacrolix/missinggo/v2"
|
||||
"github.com/anacrolix/torrent/iplist"
|
||||
"github.com/anacrolix/torrent/metainfo"
|
||||
"golang.org/x/time/rate"
|
||||
|
||||
"github.com/anacrolix/dht/v2/bep44"
|
||||
"github.com/anacrolix/dht/v2/krpc"
|
||||
peer_store "github.com/anacrolix/dht/v2/peer-store"
|
||||
)
|
||||
|
||||
func defaultQueryResendDelay() time.Duration {
|
||||
return jitterDuration(5*time.Second, time.Second)
|
||||
// This should be the highest reasonable UDP latency an end-user might have.
|
||||
return 2 * time.Second
|
||||
}
|
||||
|
||||
// Uniquely identifies a transaction to us.
|
||||
@@ -29,38 +33,51 @@ type transactionKey struct {
|
||||
|
||||
type StartingNodesGetter func() ([]Addr, error)
|
||||
|
||||
// ServerConfig allows to set up a configuration of the `Server` instance
|
||||
// to be created with NewServer
|
||||
// ServerConfig allows setting up a configuration of the `Server` instance to be created with
|
||||
// NewServer.
|
||||
type ServerConfig struct {
|
||||
// Set NodeId Manually. Caller must ensure that if NodeId does not conform
|
||||
// to DHT Security Extensions, that NoSecurity is also set.
|
||||
NodeId [20]byte
|
||||
NodeId krpc.ID
|
||||
Conn net.PacketConn
|
||||
// Don't respond to queries from other nodes.
|
||||
Passive bool
|
||||
Passive bool
|
||||
// Whether to wait for rate limiting to allow us to reply.
|
||||
WaitToReply bool
|
||||
|
||||
StartingNodes StartingNodesGetter
|
||||
// Disable the DHT security extension:
|
||||
// http://www.libtorrent.org/dht_sec.html.
|
||||
// Disable the DHT security extension: http://www.libtorrent.org/dht_sec.html.
|
||||
NoSecurity bool
|
||||
// Initial IP blocklist to use. Applied before serving and bootstrapping
|
||||
// begins.
|
||||
IPBlocklist iplist.Ranger
|
||||
// Used to secure the server's ID. Defaults to the Conn's LocalAddr(). Set
|
||||
// to the IP that remote nodes will see, as that IP is what they'll use to
|
||||
// validate our ID.
|
||||
// Used to secure the server's ID. Defaults to the Conn's LocalAddr(). Set to the IP that remote
|
||||
// nodes will see, as that IP is what they'll use to validate our ID.
|
||||
PublicIP net.IP
|
||||
|
||||
// Hook received queries. Return false if you don't want to propagate to
|
||||
// the default handlers.
|
||||
// Hook received queries. Return false if you don't want to propagate to the default handlers.
|
||||
OnQuery func(query *krpc.Msg, source net.Addr) (propagate bool)
|
||||
// Called when a peer successfully announces to us.
|
||||
OnAnnouncePeer func(infoHash metainfo.Hash, peer Peer)
|
||||
// How long to wait before resending queries that haven't received a
|
||||
// response. Defaults to a random value between 4.5 and 5.5s.
|
||||
OnAnnouncePeer func(infoHash metainfo.Hash, ip net.IP, port int, portOk bool)
|
||||
// How long to wait before resending queries that haven't received a response. Defaults to a
|
||||
// random value between 4.5 and 5.5s.
|
||||
QueryResendDelay func() time.Duration
|
||||
// TODO: Expose Peers, to return NodeInfo for received get_peers queries.
|
||||
PeerStore peer_store.Interface
|
||||
// BEP-44: Storing arbitrary data in the DHT. If not store provided, a default in-memory
|
||||
// implementation will be used.
|
||||
Store bep44.Store
|
||||
// BEP-44: expiration time with non-announced items. Two hours by default
|
||||
Exp time.Duration
|
||||
|
||||
ConnectionTracking *conntrack.Instance
|
||||
// If no Logger is provided, log.Default is used and log.Debug messages are filtered out. Note
|
||||
// that all messages without a log.Level, have log.Debug added to them before being passed to
|
||||
// this Logger.
|
||||
Logger log.Logger
|
||||
|
||||
DefaultWant []krpc.Want
|
||||
|
||||
SendLimiter *rate.Limiter
|
||||
}
|
||||
|
||||
// ServerStats instance is returned by Server.Stats() and stores Server metrics
|
||||
@@ -85,23 +102,27 @@ func jitterDuration(average time.Duration, plusMinus time.Duration) time.Duratio
|
||||
|
||||
type Peer = krpc.NodeAddr
|
||||
|
||||
func GlobalBootstrapAddrs() (addrs []Addr, err error) {
|
||||
for _, s := range []string{
|
||||
"router.utorrent.com:6881",
|
||||
"router.bittorrent.com:6881",
|
||||
"dht.transmissionbt.com:6881",
|
||||
"dht.aelitis.com:6881", // Vuze
|
||||
"router.silotis.us:6881", // IPv6
|
||||
"dht.libtorrent.org:25401", // @arvidn's
|
||||
var DefaultGlobalBootstrapHostPorts = []string{
|
||||
"router.utorrent.com:6881",
|
||||
"router.bittorrent.com:6881",
|
||||
"dht.transmissionbt.com:6881",
|
||||
"dht.aelitis.com:6881", // Vuze
|
||||
"router.silotis.us:6881", // IPv6
|
||||
"dht.libtorrent.org:25401", // @arvidn's
|
||||
"dht.anacrolix.link:42069",
|
||||
"router.bittorrent.cloud:42069",
|
||||
}
|
||||
|
||||
} {
|
||||
func GlobalBootstrapAddrs(network string) (addrs []Addr, err error) {
|
||||
initDnsResolver()
|
||||
for _, s := range DefaultGlobalBootstrapHostPorts {
|
||||
host, port, err := net.SplitHostPort(s)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
hostAddrs, err := net.LookupHost(host)
|
||||
hostAddrs, err := dnsResolver.LookupHost(context.Background(), host)
|
||||
if err != nil {
|
||||
log.Printf("error looking up %q: %v", s, err)
|
||||
// log.Default.WithDefaultLevel(log.Debug).Printf("error looking up %q: %v", s, err)
|
||||
continue
|
||||
}
|
||||
for _, a := range hostAddrs {
|
||||
@@ -119,12 +140,12 @@ func GlobalBootstrapAddrs() (addrs []Addr, err error) {
|
||||
return
|
||||
}
|
||||
|
||||
func RandomNodeID() (id [20]byte) {
|
||||
crand.Read(id[:])
|
||||
return
|
||||
// Deprecated: Use function from krpc.
|
||||
func RandomNodeID() (id krpc.ID) {
|
||||
return krpc.RandomNodeID()
|
||||
}
|
||||
|
||||
func MakeDeterministicNodeID(public net.Addr) (id [20]byte) {
|
||||
func MakeDeterministicNodeID(public net.Addr) (id krpc.ID) {
|
||||
h := crypto.SHA1.New()
|
||||
h.Write([]byte(public.String()))
|
||||
h.Sum(id[:0:20])
|
||||
31
vendor/github.com/anacrolix/dht/v2/dns.go
generated
vendored
Normal file
31
vendor/github.com/anacrolix/dht/v2/dns.go
generated
vendored
Normal file
@@ -0,0 +1,31 @@
|
||||
package dht
|
||||
|
||||
import (
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/rs/dnscache"
|
||||
)
|
||||
|
||||
var (
|
||||
// A cache to prevent wasteful/excessive use of DNS when trying to bootstrap.
|
||||
dnsResolver *dnscache.Resolver
|
||||
dnsResolverInit sync.Once
|
||||
)
|
||||
|
||||
func dnsResolverRefresher() {
|
||||
ticker := time.NewTicker(5 * time.Minute)
|
||||
defer ticker.Stop()
|
||||
for {
|
||||
<-ticker.C
|
||||
dnsResolver.Refresh(false)
|
||||
}
|
||||
}
|
||||
|
||||
// https://github.com/anacrolix/dht/issues/43
|
||||
func initDnsResolver() {
|
||||
dnsResolverInit.Do(func() {
|
||||
dnsResolver = &dnscache.Resolver{}
|
||||
go dnsResolverRefresher()
|
||||
})
|
||||
}
|
||||
0
vendor/github.com/anacrolix/dht/doc.go → vendor/github.com/anacrolix/dht/v2/doc.go
generated
vendored
0
vendor/github.com/anacrolix/dht/doc.go → vendor/github.com/anacrolix/dht/v2/doc.go
generated
vendored
8
vendor/github.com/anacrolix/dht/v2/errnos-not-windows.go
generated
vendored
Normal file
8
vendor/github.com/anacrolix/dht/v2/errnos-not-windows.go
generated
vendored
Normal file
@@ -0,0 +1,8 @@
|
||||
//go:build !windows
|
||||
|
||||
package dht
|
||||
|
||||
func ignoreReadFromError(error) bool {
|
||||
// Good unix.
|
||||
return false
|
||||
}
|
||||
26
vendor/github.com/anacrolix/dht/v2/errnos_windows.go
generated
vendored
Normal file
26
vendor/github.com/anacrolix/dht/v2/errnos_windows.go
generated
vendored
Normal file
@@ -0,0 +1,26 @@
|
||||
package dht
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"syscall"
|
||||
|
||||
"golang.org/x/sys/windows"
|
||||
)
|
||||
|
||||
// See https://github.com/anacrolix/dht/issues/16.
|
||||
func ignoreReadFromError(err error) bool {
|
||||
var errno syscall.Errno
|
||||
if errors.As(err, &errno) {
|
||||
switch errno {
|
||||
case
|
||||
windows.WSAENETRESET,
|
||||
windows.WSAECONNRESET,
|
||||
windows.WSAECONNABORTED,
|
||||
windows.WSAECONNREFUSED,
|
||||
windows.WSAENETUNREACH,
|
||||
windows.WSAETIMEDOUT: // Why does Go have braindead syntax?
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
@@ -5,13 +5,10 @@ import (
|
||||
)
|
||||
|
||||
var (
|
||||
read = expvar.NewInt("dhtRead")
|
||||
readZeroPort = expvar.NewInt("dhtReadZeroPort")
|
||||
readBlocked = expvar.NewInt("dhtReadBlocked")
|
||||
readNotKRPCDict = expvar.NewInt("dhtReadNotKRPCDict")
|
||||
readUnmarshalError = expvar.NewInt("dhtReadUnmarshalError")
|
||||
readQuery = expvar.NewInt("dhtReadQuery")
|
||||
readAnnouncePeer = expvar.NewInt("dhtReadAnnouncePeer")
|
||||
announceErrors = expvar.NewInt("dhtAnnounceErrors")
|
||||
writeErrors = expvar.NewInt("dhtWriteErrors")
|
||||
writes = expvar.NewInt("dhtWrites")
|
||||
7
vendor/github.com/anacrolix/dht/v2/globals.go
generated
vendored
Normal file
7
vendor/github.com/anacrolix/dht/v2/globals.go
generated
vendored
Normal file
@@ -0,0 +1,7 @@
|
||||
package dht
|
||||
|
||||
import (
|
||||
"golang.org/x/time/rate"
|
||||
)
|
||||
|
||||
var DefaultSendLimiter = rate.NewLimiter(25, 25)
|
||||
16
vendor/github.com/anacrolix/dht/v2/hash-tuple.go
generated
vendored
Normal file
16
vendor/github.com/anacrolix/dht/v2/hash-tuple.go
generated
vendored
Normal file
@@ -0,0 +1,16 @@
|
||||
package dht
|
||||
|
||||
import (
|
||||
"crypto/sha1"
|
||||
)
|
||||
|
||||
func HashTuple(bs ...[]byte) (ret [20]byte) {
|
||||
h := sha1.New()
|
||||
for _, b := range bs {
|
||||
h.Reset()
|
||||
h.Write(ret[:])
|
||||
h.Write(b)
|
||||
h.Sum(ret[:0])
|
||||
}
|
||||
return
|
||||
}
|
||||
110
vendor/github.com/anacrolix/dht/v2/int160/int160.go
generated
vendored
Normal file
110
vendor/github.com/anacrolix/dht/v2/int160/int160.go
generated
vendored
Normal file
@@ -0,0 +1,110 @@
|
||||
package int160
|
||||
|
||||
import (
|
||||
"encoding/hex"
|
||||
"math"
|
||||
"math/big"
|
||||
)
|
||||
|
||||
type T struct {
|
||||
bits [20]uint8
|
||||
}
|
||||
|
||||
func (me T) String() string {
|
||||
return hex.EncodeToString(me.bits[:])
|
||||
}
|
||||
|
||||
func (me *T) AsByteArray() [20]byte {
|
||||
return me.bits
|
||||
}
|
||||
|
||||
func (me *T) ByteString() string {
|
||||
return string(me.bits[:])
|
||||
}
|
||||
|
||||
func (me *T) BitLen() int {
|
||||
var a big.Int
|
||||
a.SetBytes(me.bits[:])
|
||||
return a.BitLen()
|
||||
}
|
||||
|
||||
func (me *T) SetBytes(b []byte) {
|
||||
n := copy(me.bits[:], b)
|
||||
if n != 20 {
|
||||
panic(n)
|
||||
}
|
||||
}
|
||||
|
||||
func (me *T) SetBit(index int, val bool) {
|
||||
var orVal uint8
|
||||
if val {
|
||||
orVal = 1 << (7 - index%8)
|
||||
}
|
||||
var mask uint8 = ^(1 << (7 - index%8))
|
||||
me.bits[index/8] = me.bits[index/8]&mask | orVal
|
||||
}
|
||||
|
||||
func (me *T) GetBit(index int) bool {
|
||||
return me.bits[index/8]>>(7-index%8)&1 == 1
|
||||
}
|
||||
|
||||
func (me T) Bytes() []byte {
|
||||
return me.bits[:]
|
||||
}
|
||||
|
||||
func (l T) Cmp(r T) int {
|
||||
for i := range l.bits {
|
||||
if l.bits[i] < r.bits[i] {
|
||||
return -1
|
||||
} else if l.bits[i] > r.bits[i] {
|
||||
return 1
|
||||
}
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func (me *T) SetMax() {
|
||||
for i := range me.bits {
|
||||
me.bits[i] = math.MaxUint8
|
||||
}
|
||||
}
|
||||
|
||||
func (me *T) Xor(a, b *T) {
|
||||
for i := range me.bits {
|
||||
me.bits[i] = a.bits[i] ^ b.bits[i]
|
||||
}
|
||||
}
|
||||
|
||||
func (me *T) IsZero() bool {
|
||||
for _, b := range me.bits {
|
||||
if b != 0 {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
func FromBytes(b []byte) (ret T) {
|
||||
ret.SetBytes(b)
|
||||
return
|
||||
}
|
||||
|
||||
func FromByteArray(b [20]byte) (ret T) {
|
||||
ret.SetBytes(b[:])
|
||||
return
|
||||
}
|
||||
|
||||
func FromByteString(s string) (ret T) {
|
||||
ret.SetBytes([]byte(s))
|
||||
return
|
||||
}
|
||||
|
||||
func Distance(a, b T) (ret T) {
|
||||
ret.Xor(&a, &b)
|
||||
return
|
||||
}
|
||||
|
||||
func (a T) Distance(b T) (ret T) {
|
||||
ret.Xor(&a, &b)
|
||||
return
|
||||
}
|
||||
103
vendor/github.com/anacrolix/dht/v2/k-nearest-nodes/k-nearest-nodes.go.go
generated
vendored
Normal file
103
vendor/github.com/anacrolix/dht/v2/k-nearest-nodes/k-nearest-nodes.go.go
generated
vendored
Normal file
@@ -0,0 +1,103 @@
|
||||
package k_nearest_nodes
|
||||
|
||||
import (
|
||||
"hash/maphash"
|
||||
|
||||
"github.com/anacrolix/multiless"
|
||||
"github.com/benbjohnson/immutable"
|
||||
|
||||
"github.com/anacrolix/dht/v2/int160"
|
||||
"github.com/anacrolix/dht/v2/krpc"
|
||||
)
|
||||
|
||||
type Key = krpc.NodeInfo
|
||||
|
||||
type Elem struct {
|
||||
Key
|
||||
Data interface{}
|
||||
}
|
||||
|
||||
type Type struct {
|
||||
inner *immutable.SortedMap
|
||||
k int
|
||||
}
|
||||
|
||||
func New(target int160.T, k int) Type {
|
||||
seed := maphash.MakeSeed()
|
||||
return Type{
|
||||
k: k,
|
||||
inner: immutable.NewSortedMap(lessComparer{less: func(_l, _r interface{}) bool {
|
||||
l := _l.(Key)
|
||||
r := _r.(Key)
|
||||
return multiless.New().Cmp(
|
||||
l.ID.Int160().Distance(target).Cmp(r.ID.Int160().Distance(target)),
|
||||
).Lazy(func() multiless.Computation {
|
||||
var lh, rh maphash.Hash
|
||||
lh.SetSeed(seed)
|
||||
rh.SetSeed(seed)
|
||||
lh.WriteString(l.Addr.String())
|
||||
rh.WriteString(r.Addr.String())
|
||||
return multiless.New().Int64(int64(lh.Sum64()), int64(rh.Sum64()))
|
||||
}).Less()
|
||||
}}),
|
||||
}
|
||||
}
|
||||
|
||||
func (me *Type) Range(f func(Elem)) {
|
||||
iter := me.inner.Iterator()
|
||||
for !iter.Done() {
|
||||
key, value := iter.Next()
|
||||
f(Elem{
|
||||
Key: key.(Key),
|
||||
Data: value,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func (me Type) Len() int {
|
||||
return me.inner.Len()
|
||||
}
|
||||
|
||||
func (me Type) Push(elem Elem) Type {
|
||||
me.inner = me.inner.Set(elem.Key, elem.Data)
|
||||
for me.inner.Len() > me.k {
|
||||
iter := me.inner.Iterator()
|
||||
iter.Last()
|
||||
key, _ := iter.Next()
|
||||
me.inner = me.inner.Delete(key)
|
||||
}
|
||||
return me
|
||||
}
|
||||
|
||||
func (me Type) Farthest() (elem Elem) {
|
||||
iter := me.inner.Iterator()
|
||||
iter.Last()
|
||||
if iter.Done() {
|
||||
panic(me.k)
|
||||
}
|
||||
key, value := iter.Next()
|
||||
return Elem{
|
||||
Key: key.(Key),
|
||||
Data: value,
|
||||
}
|
||||
}
|
||||
|
||||
func (me Type) Full() bool {
|
||||
return me.Len() >= me.k
|
||||
}
|
||||
|
||||
type lessFunc func(l, r interface{}) bool
|
||||
|
||||
type lessComparer struct {
|
||||
less lessFunc
|
||||
}
|
||||
|
||||
func (me lessComparer) Compare(i, j interface{}) int {
|
||||
if me.less(i, j) {
|
||||
return -1
|
||||
} else if me.less(j, i) {
|
||||
return 1
|
||||
} else {
|
||||
return 0
|
||||
}
|
||||
}
|
||||
@@ -1,11 +1,18 @@
|
||||
package krpc
|
||||
|
||||
import "github.com/anacrolix/missinggo/slices"
|
||||
|
||||
type CompactIPv4NodeAddrs []NodeAddr
|
||||
|
||||
func (CompactIPv4NodeAddrs) ElemSize() int { return 6 }
|
||||
|
||||
func (me CompactIPv4NodeAddrs) MarshalBinary() ([]byte, error) {
|
||||
return marshalBinarySlice(me)
|
||||
return marshalBinarySlice(slices.Map(func(addr NodeAddr) NodeAddr {
|
||||
if a := addr.IP.To4(); a != nil {
|
||||
addr.IP = a
|
||||
}
|
||||
return addr
|
||||
}, me).(CompactIPv4NodeAddrs))
|
||||
}
|
||||
|
||||
func (me CompactIPv4NodeAddrs) MarshalBencode() ([]byte, error) {
|
||||
@@ -23,3 +30,7 @@ func (me *CompactIPv4NodeAddrs) UnmarshalBencode(b []byte) error {
|
||||
func (me CompactIPv4NodeAddrs) NodeAddrs() []NodeAddr {
|
||||
return me
|
||||
}
|
||||
|
||||
func (me CompactIPv4NodeAddrs) Index(x NodeAddr) int {
|
||||
return addrIndex(me, x)
|
||||
}
|
||||
@@ -28,3 +28,7 @@ func (me *CompactIPv6NodeAddrs) UnmarshalBencode(b []byte) error {
|
||||
func (me CompactIPv6NodeAddrs) NodeAddrs() []NodeAddr {
|
||||
return me
|
||||
}
|
||||
|
||||
func (me CompactIPv6NodeAddrs) Index(x NodeAddr) int {
|
||||
return addrIndex(me, x)
|
||||
}
|
||||
49
vendor/github.com/anacrolix/dht/v2/krpc/bep33.go
generated
vendored
Normal file
49
vendor/github.com/anacrolix/dht/v2/krpc/bep33.go
generated
vendored
Normal file
@@ -0,0 +1,49 @@
|
||||
package krpc
|
||||
|
||||
import (
|
||||
"crypto/sha1"
|
||||
"math"
|
||||
"math/bits"
|
||||
"net"
|
||||
)
|
||||
|
||||
const (
|
||||
m = 256 * 8
|
||||
k = 2
|
||||
)
|
||||
|
||||
type ScrapeBloomFilter [256]byte
|
||||
|
||||
// Note that if you intend for an IP to be in the IPv4 space, you might want to trim it to 4 bytes
|
||||
// with IP.To4.
|
||||
func (me *ScrapeBloomFilter) AddIp(ip net.IP) {
|
||||
h := sha1.New()
|
||||
h.Write(ip)
|
||||
var sum [20]byte
|
||||
h.Sum(sum[:0])
|
||||
me.addK(int(sum[0]) | int(sum[1])<<8)
|
||||
me.addK(int(sum[2]) | int(sum[3])<<8)
|
||||
}
|
||||
|
||||
func (me *ScrapeBloomFilter) addK(index int) {
|
||||
index %= m
|
||||
me[index/8] |= 1 << (index % 8)
|
||||
}
|
||||
|
||||
func (me ScrapeBloomFilter) countZeroes() (ret int) {
|
||||
for _, i := range me {
|
||||
ret += 8 - bits.OnesCount8(i)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func (me *ScrapeBloomFilter) EstimateCount() float64 {
|
||||
if me == nil {
|
||||
return 0
|
||||
}
|
||||
c := float64(me.countZeroes())
|
||||
if c > m-1 {
|
||||
c = m - 1
|
||||
}
|
||||
return math.Log(c/m) / (k * math.Log(1.-1./m))
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user