init
This commit is contained in:
		
							
								
								
									
										21
									
								
								vendor/github.com/anacrolix/missinggo/LICENSE
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										21
									
								
								vendor/github.com/anacrolix/missinggo/LICENSE
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,21 @@
 | 
			
		||||
The MIT License (MIT)
 | 
			
		||||
 | 
			
		||||
Copyright (c) 2015 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.
 | 
			
		||||
							
								
								
									
										4
									
								
								vendor/github.com/anacrolix/missinggo/README.md
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										4
									
								
								vendor/github.com/anacrolix/missinggo/README.md
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,4 @@
 | 
			
		||||
# missinggo
 | 
			
		||||
[](https://godoc.org/github.com/anacrolix/missinggo)
 | 
			
		||||
 | 
			
		||||
Stuff that supplements Go's stdlib, or isn't significant enough to be in its own repo.
 | 
			
		||||
							
								
								
									
										44
									
								
								vendor/github.com/anacrolix/missinggo/addr.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										44
									
								
								vendor/github.com/anacrolix/missinggo/addr.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,44 @@
 | 
			
		||||
package missinggo
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"net"
 | 
			
		||||
	"strconv"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// Extracts the port as an integer from an address string.
 | 
			
		||||
func AddrPort(addr net.Addr) int {
 | 
			
		||||
	switch raw := addr.(type) {
 | 
			
		||||
	case *net.UDPAddr:
 | 
			
		||||
		return raw.Port
 | 
			
		||||
	case *net.TCPAddr:
 | 
			
		||||
		return raw.Port
 | 
			
		||||
	default:
 | 
			
		||||
		_, port, err := net.SplitHostPort(addr.String())
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			panic(err)
 | 
			
		||||
		}
 | 
			
		||||
		i64, err := strconv.ParseInt(port, 0, 0)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			panic(err)
 | 
			
		||||
		}
 | 
			
		||||
		return int(i64)
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func AddrIP(addr net.Addr) net.IP {
 | 
			
		||||
	if addr == nil {
 | 
			
		||||
		return nil
 | 
			
		||||
	}
 | 
			
		||||
	switch raw := addr.(type) {
 | 
			
		||||
	case *net.UDPAddr:
 | 
			
		||||
		return raw.IP
 | 
			
		||||
	case *net.TCPAddr:
 | 
			
		||||
		return raw.IP
 | 
			
		||||
	default:
 | 
			
		||||
		host, _, err := net.SplitHostPort(addr.String())
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			panic(err)
 | 
			
		||||
		}
 | 
			
		||||
		return net.ParseIP(host)
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										11
									
								
								vendor/github.com/anacrolix/missinggo/atime.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										11
									
								
								vendor/github.com/anacrolix/missinggo/atime.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,11 @@
 | 
			
		||||
package missinggo
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"os"
 | 
			
		||||
	"time"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// Extracts the access time from the FileInfo internals.
 | 
			
		||||
func FileInfoAccessTime(fi os.FileInfo) time.Time {
 | 
			
		||||
	return fileInfoAccessTime(fi)
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										14
									
								
								vendor/github.com/anacrolix/missinggo/atime_atim.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										14
									
								
								vendor/github.com/anacrolix/missinggo/atime_atim.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,14 @@
 | 
			
		||||
// +build linux dragonfly openbsd solaris
 | 
			
		||||
 | 
			
		||||
package missinggo
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"os"
 | 
			
		||||
	"syscall"
 | 
			
		||||
	"time"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
func fileInfoAccessTime(fi os.FileInfo) time.Time {
 | 
			
		||||
	ts := fi.Sys().(*syscall.Stat_t).Atim
 | 
			
		||||
	return time.Unix(int64(ts.Sec), int64(ts.Nsec))
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										14
									
								
								vendor/github.com/anacrolix/missinggo/atime_atimespec.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										14
									
								
								vendor/github.com/anacrolix/missinggo/atime_atimespec.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,14 @@
 | 
			
		||||
// +build darwin freebsd netbsd
 | 
			
		||||
 | 
			
		||||
package missinggo
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"os"
 | 
			
		||||
	"syscall"
 | 
			
		||||
	"time"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
func fileInfoAccessTime(fi os.FileInfo) time.Time {
 | 
			
		||||
	ts := fi.Sys().(*syscall.Stat_t).Atimespec
 | 
			
		||||
	return time.Unix(int64(ts.Sec), int64(ts.Nsec))
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										12
									
								
								vendor/github.com/anacrolix/missinggo/atime_plan9.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										12
									
								
								vendor/github.com/anacrolix/missinggo/atime_plan9.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,12 @@
 | 
			
		||||
package missinggo
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"os"
 | 
			
		||||
	"syscall"
 | 
			
		||||
	"time"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
func fileInfoAccessTime(fi os.FileInfo) time.Time {
 | 
			
		||||
	sec := fi.Sys().(*syscall.Dir).Atime
 | 
			
		||||
	return time.Unix(int64(sec), 0)
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										12
									
								
								vendor/github.com/anacrolix/missinggo/atime_windows.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										12
									
								
								vendor/github.com/anacrolix/missinggo/atime_windows.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,12 @@
 | 
			
		||||
package missinggo
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"os"
 | 
			
		||||
	"syscall"
 | 
			
		||||
	"time"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
func fileInfoAccessTime(fi os.FileInfo) time.Time {
 | 
			
		||||
	ts := fi.Sys().(*syscall.Win32FileAttributeData).LastAccessTime
 | 
			
		||||
	return time.Unix(0, int64(ts.Nanoseconds()))
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										171
									
								
								vendor/github.com/anacrolix/missinggo/bitmap/bitmap.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										171
									
								
								vendor/github.com/anacrolix/missinggo/bitmap/bitmap.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,171 @@
 | 
			
		||||
// Package bitmap provides a []bool/bitmap implementation with standardized
 | 
			
		||||
// iteration. Bitmaps are the equivalent of []bool, with improved compression
 | 
			
		||||
// for runs of similar values, and faster operations on ranges and the like.
 | 
			
		||||
package bitmap
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"math"
 | 
			
		||||
 | 
			
		||||
	"github.com/RoaringBitmap/roaring"
 | 
			
		||||
 | 
			
		||||
	"github.com/anacrolix/missinggo/iter"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
const MaxInt = -1
 | 
			
		||||
 | 
			
		||||
type BitIndex = int
 | 
			
		||||
 | 
			
		||||
type Interface interface {
 | 
			
		||||
	Len() int
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Bitmaps store the existence of values in [0,math.MaxUint32] more
 | 
			
		||||
// efficiently than []bool. The empty value starts with no bits set.
 | 
			
		||||
type Bitmap struct {
 | 
			
		||||
	rb *roaring.Bitmap
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
var ToEnd int = -1
 | 
			
		||||
 | 
			
		||||
// The number of set bits in the bitmap. Also known as cardinality.
 | 
			
		||||
func (me *Bitmap) Len() int {
 | 
			
		||||
	if me.rb == nil {
 | 
			
		||||
		return 0
 | 
			
		||||
	}
 | 
			
		||||
	return int(me.rb.GetCardinality())
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (me Bitmap) ToSortedSlice() (ret []int) {
 | 
			
		||||
	if me.rb == nil {
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
	for _, ui32 := range me.rb.ToArray() {
 | 
			
		||||
		ret = append(ret, int(int32(ui32)))
 | 
			
		||||
	}
 | 
			
		||||
	return
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (me *Bitmap) lazyRB() *roaring.Bitmap {
 | 
			
		||||
	if me.rb == nil {
 | 
			
		||||
		me.rb = roaring.NewBitmap()
 | 
			
		||||
	}
 | 
			
		||||
	return me.rb
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (me Bitmap) Iter(cb iter.Callback) {
 | 
			
		||||
	me.IterTyped(func(i int) bool {
 | 
			
		||||
		return cb(i)
 | 
			
		||||
	})
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Returns true if all values were traversed without early termination.
 | 
			
		||||
func (me Bitmap) IterTyped(f func(int) bool) bool {
 | 
			
		||||
	if me.rb == nil {
 | 
			
		||||
		return true
 | 
			
		||||
	}
 | 
			
		||||
	it := me.rb.Iterator()
 | 
			
		||||
	for it.HasNext() {
 | 
			
		||||
		if !f(int(it.Next())) {
 | 
			
		||||
			return false
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	return true
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func checkInt(i BitIndex) {
 | 
			
		||||
	if i < math.MinInt32 || i > math.MaxInt32 {
 | 
			
		||||
		panic("out of bounds")
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (me *Bitmap) Add(is ...BitIndex) {
 | 
			
		||||
	rb := me.lazyRB()
 | 
			
		||||
	for _, i := range is {
 | 
			
		||||
		checkInt(i)
 | 
			
		||||
		rb.AddInt(i)
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (me *Bitmap) AddRange(begin, end BitIndex) {
 | 
			
		||||
	if begin >= end {
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
	me.lazyRB().AddRange(uint64(begin), uint64(end))
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (me *Bitmap) Remove(i BitIndex) bool {
 | 
			
		||||
	if me.rb == nil {
 | 
			
		||||
		return false
 | 
			
		||||
	}
 | 
			
		||||
	return me.rb.CheckedRemove(uint32(i))
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (me *Bitmap) Union(other Bitmap) {
 | 
			
		||||
	me.lazyRB().Or(other.lazyRB())
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (me *Bitmap) Contains(i int) bool {
 | 
			
		||||
	if me.rb == nil {
 | 
			
		||||
		return false
 | 
			
		||||
	}
 | 
			
		||||
	return me.rb.Contains(uint32(i))
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (me *Bitmap) Sub(other Bitmap) {
 | 
			
		||||
	if other.rb == nil {
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
	if me.rb == nil {
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
	me.rb.AndNot(other.rb)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (me *Bitmap) Clear() {
 | 
			
		||||
	if me.rb == nil {
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
	me.rb.Clear()
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (me Bitmap) Copy() (ret Bitmap) {
 | 
			
		||||
	ret = me
 | 
			
		||||
	if ret.rb != nil {
 | 
			
		||||
		ret.rb = ret.rb.Clone()
 | 
			
		||||
	}
 | 
			
		||||
	return
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (me *Bitmap) FlipRange(begin, end BitIndex) {
 | 
			
		||||
	me.lazyRB().FlipInt(begin, end)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (me *Bitmap) Get(bit BitIndex) bool {
 | 
			
		||||
	return me.rb != nil && me.rb.ContainsInt(bit)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (me *Bitmap) Set(bit BitIndex, value bool) {
 | 
			
		||||
	if value {
 | 
			
		||||
		me.lazyRB().AddInt(bit)
 | 
			
		||||
	} else {
 | 
			
		||||
		if me.rb != nil {
 | 
			
		||||
			me.rb.Remove(uint32(bit))
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (me *Bitmap) RemoveRange(begin, end BitIndex) *Bitmap {
 | 
			
		||||
	if me.rb == nil {
 | 
			
		||||
		return me
 | 
			
		||||
	}
 | 
			
		||||
	rangeEnd := uint64(end)
 | 
			
		||||
	if end == ToEnd {
 | 
			
		||||
		rangeEnd = 0x100000000
 | 
			
		||||
	}
 | 
			
		||||
	me.rb.RemoveRange(uint64(begin), rangeEnd)
 | 
			
		||||
	return me
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (me Bitmap) IsEmpty() bool {
 | 
			
		||||
	return me.rb == nil || me.rb.IsEmpty()
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										15
									
								
								vendor/github.com/anacrolix/missinggo/bitmap/global.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										15
									
								
								vendor/github.com/anacrolix/missinggo/bitmap/global.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,15 @@
 | 
			
		||||
package bitmap
 | 
			
		||||
 | 
			
		||||
import "github.com/RoaringBitmap/roaring"
 | 
			
		||||
 | 
			
		||||
func Sub(left, right Bitmap) Bitmap {
 | 
			
		||||
	return Bitmap{
 | 
			
		||||
		rb: roaring.AndNot(left.lazyRB(), right.lazyRB()),
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func Flip(bm Bitmap, start, end int) Bitmap {
 | 
			
		||||
	return Bitmap{
 | 
			
		||||
		rb: roaring.FlipInt(bm.lazyRB(), start, end),
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										24
									
								
								vendor/github.com/anacrolix/missinggo/bitmap/iter.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										24
									
								
								vendor/github.com/anacrolix/missinggo/bitmap/iter.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,24 @@
 | 
			
		||||
package bitmap
 | 
			
		||||
 | 
			
		||||
import "github.com/RoaringBitmap/roaring"
 | 
			
		||||
 | 
			
		||||
type Iter struct {
 | 
			
		||||
	ii roaring.IntIterable
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (me *Iter) Next() bool {
 | 
			
		||||
	if me == nil {
 | 
			
		||||
		return false
 | 
			
		||||
	}
 | 
			
		||||
	return me.ii.HasNext()
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (me *Iter) Value() interface{} {
 | 
			
		||||
	return me.ValueInt()
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (me *Iter) ValueInt() int {
 | 
			
		||||
	return int(me.ii.Next())
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (me *Iter) Stop() {}
 | 
			
		||||
							
								
								
									
										46
									
								
								vendor/github.com/anacrolix/missinggo/certdir.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										46
									
								
								vendor/github.com/anacrolix/missinggo/certdir.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,46 @@
 | 
			
		||||
package missinggo
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"crypto/tls"
 | 
			
		||||
	"log"
 | 
			
		||||
	"os"
 | 
			
		||||
	"path/filepath"
 | 
			
		||||
	"strings"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
func LoadCertificateDir(dir string) (certs []tls.Certificate, err error) {
 | 
			
		||||
	d, err := os.Open(dir)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
	defer d.Close()
 | 
			
		||||
	const defaultPEMFile = "default.pem"
 | 
			
		||||
	if p := filepath.Join(dir, defaultPEMFile); FilePathExists(p) {
 | 
			
		||||
		cert, err := tls.LoadX509KeyPair(p, p)
 | 
			
		||||
		if err == nil {
 | 
			
		||||
			certs = append(certs, cert)
 | 
			
		||||
		} else {
 | 
			
		||||
			log.Printf("error loading default certicate: %s", err)
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	files, err := d.Readdir(-1)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
	for _, f := range files {
 | 
			
		||||
		if f.Name() == defaultPEMFile {
 | 
			
		||||
			continue
 | 
			
		||||
		}
 | 
			
		||||
		if !strings.HasSuffix(f.Name(), ".pem") {
 | 
			
		||||
			continue
 | 
			
		||||
		}
 | 
			
		||||
		p := filepath.Join(dir, f.Name())
 | 
			
		||||
		cert, err := tls.LoadX509KeyPair(p, p)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			log.Printf("error loading key pair from %q: %s", p, err)
 | 
			
		||||
			continue
 | 
			
		||||
		}
 | 
			
		||||
		certs = append(certs, cert)
 | 
			
		||||
	}
 | 
			
		||||
	return
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										36
									
								
								vendor/github.com/anacrolix/missinggo/chancond.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										36
									
								
								vendor/github.com/anacrolix/missinggo/chancond.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,36 @@
 | 
			
		||||
package missinggo
 | 
			
		||||
 | 
			
		||||
import "sync"
 | 
			
		||||
 | 
			
		||||
type ChanCond struct {
 | 
			
		||||
	mu sync.Mutex
 | 
			
		||||
	ch chan struct{}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (me *ChanCond) Wait() <-chan struct{} {
 | 
			
		||||
	me.mu.Lock()
 | 
			
		||||
	defer me.mu.Unlock()
 | 
			
		||||
	if me.ch == nil {
 | 
			
		||||
		me.ch = make(chan struct{})
 | 
			
		||||
	}
 | 
			
		||||
	return me.ch
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (me *ChanCond) Signal() {
 | 
			
		||||
	me.mu.Lock()
 | 
			
		||||
	defer me.mu.Unlock()
 | 
			
		||||
	select {
 | 
			
		||||
	case me.ch <- struct{}{}:
 | 
			
		||||
	default:
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (me *ChanCond) Broadcast() {
 | 
			
		||||
	me.mu.Lock()
 | 
			
		||||
	defer me.mu.Unlock()
 | 
			
		||||
	if me.ch == nil {
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
	close(me.ch)
 | 
			
		||||
	me.ch = nil
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										34
									
								
								vendor/github.com/anacrolix/missinggo/copy.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										34
									
								
								vendor/github.com/anacrolix/missinggo/copy.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,34 @@
 | 
			
		||||
package missinggo
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"fmt"
 | 
			
		||||
	"reflect"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// Copy elements from src to dst. Panics if the length of src and dst are
 | 
			
		||||
// different.
 | 
			
		||||
func CopyExact(dest interface{}, src interface{}) {
 | 
			
		||||
	dV := reflect.ValueOf(dest)
 | 
			
		||||
	sV := reflect.ValueOf(src)
 | 
			
		||||
	if dV.Kind() == reflect.Ptr {
 | 
			
		||||
		dV = dV.Elem()
 | 
			
		||||
	}
 | 
			
		||||
	if dV.Kind() == reflect.Array && !dV.CanAddr() {
 | 
			
		||||
		panic(fmt.Sprintf("dest not addressable: %T", dest))
 | 
			
		||||
	}
 | 
			
		||||
	if sV.Kind() == reflect.Ptr {
 | 
			
		||||
		sV = sV.Elem()
 | 
			
		||||
	}
 | 
			
		||||
	if sV.Kind() == reflect.String {
 | 
			
		||||
		sV = sV.Convert(reflect.SliceOf(dV.Type().Elem()))
 | 
			
		||||
	}
 | 
			
		||||
	if !sV.IsValid() {
 | 
			
		||||
		panic("invalid source, probably nil")
 | 
			
		||||
	}
 | 
			
		||||
	if dV.Len() != sV.Len() {
 | 
			
		||||
		panic(fmt.Sprintf("dest len (%d) != src len (%d)", dV.Len(), sV.Len()))
 | 
			
		||||
	}
 | 
			
		||||
	if dV.Len() != reflect.Copy(dV, sV) {
 | 
			
		||||
		panic("dammit")
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										18
									
								
								vendor/github.com/anacrolix/missinggo/croak.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										18
									
								
								vendor/github.com/anacrolix/missinggo/croak.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,18 @@
 | 
			
		||||
package missinggo
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"fmt"
 | 
			
		||||
	"os"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
func Unchomp(s string) string {
 | 
			
		||||
	if len(s) > 0 && s[len(s)-1] == '\n' {
 | 
			
		||||
		return s
 | 
			
		||||
	}
 | 
			
		||||
	return s + "\n"
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func Fatal(msg interface{}) {
 | 
			
		||||
	os.Stderr.WriteString(Unchomp(fmt.Sprint(msg)))
 | 
			
		||||
	os.Exit(1)
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										3
									
								
								vendor/github.com/anacrolix/missinggo/doc.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										3
									
								
								vendor/github.com/anacrolix/missinggo/doc.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,3 @@
 | 
			
		||||
// Package missinggo contains miscellaneous helpers used in many of anacrolix'
 | 
			
		||||
// projects.
 | 
			
		||||
package missinggo
 | 
			
		||||
							
								
								
									
										33
									
								
								vendor/github.com/anacrolix/missinggo/empty_value.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										33
									
								
								vendor/github.com/anacrolix/missinggo/empty_value.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,33 @@
 | 
			
		||||
package missinggo
 | 
			
		||||
 | 
			
		||||
import "reflect"
 | 
			
		||||
 | 
			
		||||
func IsZeroValue(i interface{}) bool {
 | 
			
		||||
	return IsEmptyValue(reflect.ValueOf(i))
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Returns whether the value represents the empty value for its type. Used for
 | 
			
		||||
// example to determine if complex types satisfy the common "omitempty" tag
 | 
			
		||||
// option for marshalling. Taken from
 | 
			
		||||
// http://stackoverflow.com/a/23555352/149482.
 | 
			
		||||
func IsEmptyValue(v reflect.Value) bool {
 | 
			
		||||
	switch v.Kind() {
 | 
			
		||||
	case reflect.Func, reflect.Map, reflect.Slice:
 | 
			
		||||
		return v.IsNil()
 | 
			
		||||
	case reflect.Array:
 | 
			
		||||
		z := true
 | 
			
		||||
		for i := 0; i < v.Len(); i++ {
 | 
			
		||||
			z = z && IsEmptyValue(v.Index(i))
 | 
			
		||||
		}
 | 
			
		||||
		return z
 | 
			
		||||
	case reflect.Struct:
 | 
			
		||||
		z := true
 | 
			
		||||
		for i := 0; i < v.NumField(); i++ {
 | 
			
		||||
			z = z && IsEmptyValue(v.Field(i))
 | 
			
		||||
		}
 | 
			
		||||
		return z
 | 
			
		||||
	}
 | 
			
		||||
	// Compare other types directly:
 | 
			
		||||
	z := reflect.Zero(v.Type())
 | 
			
		||||
	return v.Interface() == z.Interface()
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										15
									
								
								vendor/github.com/anacrolix/missinggo/encoding.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										15
									
								
								vendor/github.com/anacrolix/missinggo/encoding.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,15 @@
 | 
			
		||||
package missinggo
 | 
			
		||||
 | 
			
		||||
// An interface for "encoding/base64".Encoder
 | 
			
		||||
type Encoding interface {
 | 
			
		||||
	EncodeToString([]byte) string
 | 
			
		||||
	DecodeString(string) ([]byte, error)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// An encoding that does nothing.
 | 
			
		||||
type IdentityEncoding struct{}
 | 
			
		||||
 | 
			
		||||
var _ Encoding = IdentityEncoding{}
 | 
			
		||||
 | 
			
		||||
func (IdentityEncoding) EncodeToString(b []byte) string        { return string(b) }
 | 
			
		||||
func (IdentityEncoding) DecodeString(s string) ([]byte, error) { return []byte(s), nil }
 | 
			
		||||
							
								
								
									
										65
									
								
								vendor/github.com/anacrolix/missinggo/event.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										65
									
								
								vendor/github.com/anacrolix/missinggo/event.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,65 @@
 | 
			
		||||
package missinggo
 | 
			
		||||
 | 
			
		||||
import "sync"
 | 
			
		||||
 | 
			
		||||
// Events are boolean flags that provide a channel that's closed when true.
 | 
			
		||||
// This could go in the sync package, but that's more of a debug wrapper on
 | 
			
		||||
// the standard library sync.
 | 
			
		||||
type Event struct {
 | 
			
		||||
	ch     chan struct{}
 | 
			
		||||
	closed bool
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (me *Event) LockedChan(lock sync.Locker) <-chan struct{} {
 | 
			
		||||
	lock.Lock()
 | 
			
		||||
	ch := me.C()
 | 
			
		||||
	lock.Unlock()
 | 
			
		||||
	return ch
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Returns a chan that is closed when the event is true.
 | 
			
		||||
func (me *Event) C() <-chan struct{} {
 | 
			
		||||
	if me.ch == nil {
 | 
			
		||||
		me.ch = make(chan struct{})
 | 
			
		||||
	}
 | 
			
		||||
	return me.ch
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// TODO: Merge into Set.
 | 
			
		||||
func (me *Event) Clear() {
 | 
			
		||||
	if me.closed {
 | 
			
		||||
		me.ch = nil
 | 
			
		||||
		me.closed = false
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Set the event to true/on.
 | 
			
		||||
func (me *Event) Set() (first bool) {
 | 
			
		||||
	if me.closed {
 | 
			
		||||
		return false
 | 
			
		||||
	}
 | 
			
		||||
	if me.ch == nil {
 | 
			
		||||
		me.ch = make(chan struct{})
 | 
			
		||||
	}
 | 
			
		||||
	close(me.ch)
 | 
			
		||||
	me.closed = true
 | 
			
		||||
	return true
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// TODO: Change to Get.
 | 
			
		||||
func (me *Event) IsSet() bool {
 | 
			
		||||
	return me.closed
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (me *Event) Wait() {
 | 
			
		||||
	<-me.C()
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// TODO: Merge into Set.
 | 
			
		||||
func (me *Event) SetBool(b bool) {
 | 
			
		||||
	if b {
 | 
			
		||||
		me.Set()
 | 
			
		||||
	} else {
 | 
			
		||||
		me.Clear()
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										26
									
								
								vendor/github.com/anacrolix/missinggo/event_synchronized.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										26
									
								
								vendor/github.com/anacrolix/missinggo/event_synchronized.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,26 @@
 | 
			
		||||
package missinggo
 | 
			
		||||
 | 
			
		||||
import "sync"
 | 
			
		||||
 | 
			
		||||
type SynchronizedEvent struct {
 | 
			
		||||
	mu sync.Mutex
 | 
			
		||||
	e  Event
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (me *SynchronizedEvent) Set() {
 | 
			
		||||
	me.mu.Lock()
 | 
			
		||||
	me.e.Set()
 | 
			
		||||
	me.mu.Unlock()
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (me *SynchronizedEvent) Clear() {
 | 
			
		||||
	me.mu.Lock()
 | 
			
		||||
	me.e.Clear()
 | 
			
		||||
	me.mu.Unlock()
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (me *SynchronizedEvent) C() <-chan struct{} {
 | 
			
		||||
	me.mu.Lock()
 | 
			
		||||
	defer me.mu.Unlock()
 | 
			
		||||
	return me.e.C()
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										63
									
								
								vendor/github.com/anacrolix/missinggo/expect/assert.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										63
									
								
								vendor/github.com/anacrolix/missinggo/expect/assert.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,63 @@
 | 
			
		||||
package expect // import "github.com/anacrolix/missinggo/expect"
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"database/sql"
 | 
			
		||||
	"fmt"
 | 
			
		||||
	"reflect"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
func Nil(x interface{}) {
 | 
			
		||||
	if x != nil {
 | 
			
		||||
		panic(fmt.Sprintf("expected nil; got %v", x))
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func NotNil(x interface{}) {
 | 
			
		||||
	if x == nil {
 | 
			
		||||
		panic(x)
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func Equal(x, y interface{}) {
 | 
			
		||||
	if x == y {
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
	yAsXType := reflect.ValueOf(y).Convert(reflect.TypeOf(x)).Interface()
 | 
			
		||||
	if !reflect.DeepEqual(x, yAsXType) {
 | 
			
		||||
		panic(fmt.Sprintf("%v != %v", x, y))
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func StrictlyEqual(x, y interface{}) {
 | 
			
		||||
	if x != y {
 | 
			
		||||
		panic(fmt.Sprintf("%s != %s", x, y))
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func OneRowAffected(r sql.Result) {
 | 
			
		||||
	count, err := r.RowsAffected()
 | 
			
		||||
	Nil(err)
 | 
			
		||||
	if count != 1 {
 | 
			
		||||
		panic(count)
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func True(b bool) {
 | 
			
		||||
	if !b {
 | 
			
		||||
		panic(b)
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
var Ok = True
 | 
			
		||||
 | 
			
		||||
func False(b bool) {
 | 
			
		||||
	if b {
 | 
			
		||||
		panic(b)
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func Zero(x interface{}) {
 | 
			
		||||
	if x != reflect.Zero(reflect.TypeOf(x)).Interface() {
 | 
			
		||||
		panic(x)
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										35
									
								
								vendor/github.com/anacrolix/missinggo/expvarIndentMap.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										35
									
								
								vendor/github.com/anacrolix/missinggo/expvarIndentMap.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,35 @@
 | 
			
		||||
package missinggo
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"bytes"
 | 
			
		||||
	"expvar"
 | 
			
		||||
	"fmt"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
type IndentMap struct {
 | 
			
		||||
	expvar.Map
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
var _ expvar.Var = (*IndentMap)(nil)
 | 
			
		||||
 | 
			
		||||
func NewExpvarIndentMap(name string) *IndentMap {
 | 
			
		||||
	v := new(IndentMap)
 | 
			
		||||
	v.Init()
 | 
			
		||||
	expvar.Publish(name, v)
 | 
			
		||||
	return v
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (v *IndentMap) String() string {
 | 
			
		||||
	var b bytes.Buffer
 | 
			
		||||
	fmt.Fprintf(&b, "{")
 | 
			
		||||
	first := true
 | 
			
		||||
	v.Do(func(kv expvar.KeyValue) {
 | 
			
		||||
		if !first {
 | 
			
		||||
			fmt.Fprintf(&b, ",")
 | 
			
		||||
		}
 | 
			
		||||
		fmt.Fprintf(&b, "\n\t%q: %v", kv.Key, kv.Value)
 | 
			
		||||
		first = false
 | 
			
		||||
	})
 | 
			
		||||
	fmt.Fprintf(&b, "}")
 | 
			
		||||
	return b.String()
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										41
									
								
								vendor/github.com/anacrolix/missinggo/flag.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										41
									
								
								vendor/github.com/anacrolix/missinggo/flag.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,41 @@
 | 
			
		||||
package missinggo
 | 
			
		||||
 | 
			
		||||
import "sync"
 | 
			
		||||
 | 
			
		||||
// Flag represents a boolean value, that signals sync.Cond's when it changes.
 | 
			
		||||
// It's not concurrent safe by intention.
 | 
			
		||||
type Flag struct {
 | 
			
		||||
	Conds map[*sync.Cond]struct{}
 | 
			
		||||
	value bool
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (me *Flag) Set(value bool) {
 | 
			
		||||
	if value != me.value {
 | 
			
		||||
		me.broadcastChange()
 | 
			
		||||
	}
 | 
			
		||||
	me.value = value
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (me *Flag) Get() bool {
 | 
			
		||||
	return me.value
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (me *Flag) broadcastChange() {
 | 
			
		||||
	for cond := range me.Conds {
 | 
			
		||||
		cond.Broadcast()
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (me *Flag) addCond(c *sync.Cond) {
 | 
			
		||||
	if me.Conds == nil {
 | 
			
		||||
		me.Conds = make(map[*sync.Cond]struct{})
 | 
			
		||||
	}
 | 
			
		||||
	me.Conds[c] = struct{}{}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Adds the sync.Cond to all the given Flag's.
 | 
			
		||||
func AddCondToFlags(cond *sync.Cond, flags ...*Flag) {
 | 
			
		||||
	for _, f := range flags {
 | 
			
		||||
		f.addCond(cond)
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										18
									
								
								vendor/github.com/anacrolix/missinggo/go.mod
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										18
									
								
								vendor/github.com/anacrolix/missinggo/go.mod
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,18 @@
 | 
			
		||||
module github.com/anacrolix/missinggo
 | 
			
		||||
 | 
			
		||||
require (
 | 
			
		||||
	github.com/RoaringBitmap/roaring v0.4.7
 | 
			
		||||
	github.com/anacrolix/envpprof v0.0.0-20180404065416-323002cec2fa
 | 
			
		||||
	github.com/anacrolix/tagflag v0.0.0-20180109131632-2146c8d41bf0
 | 
			
		||||
	github.com/bradfitz/iter v0.0.0-20140124041915-454541ec3da2
 | 
			
		||||
	github.com/docopt/docopt-go v0.0.0-20180111231733-ee0de3bc6815
 | 
			
		||||
	github.com/dustin/go-humanize v0.0.0-20180421182945-02af3965c54e
 | 
			
		||||
	github.com/glycerine/go-unsnap-stream v0.0.0-20180323001048-9f0cb55181dd
 | 
			
		||||
	github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db
 | 
			
		||||
	github.com/google/btree v0.0.0-20180124185431-e89373fe6b4a
 | 
			
		||||
	github.com/huandu/xstrings v1.0.0
 | 
			
		||||
	github.com/philhofer/fwd v1.0.0
 | 
			
		||||
	github.com/ryszard/goskiplist v0.0.0-20150312221310-2dfbae5fcf46
 | 
			
		||||
	github.com/stretchr/testify v1.2.1
 | 
			
		||||
	github.com/tinylib/msgp v1.0.2
 | 
			
		||||
)
 | 
			
		||||
							
								
								
									
										52
									
								
								vendor/github.com/anacrolix/missinggo/hostmaybeport.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										52
									
								
								vendor/github.com/anacrolix/missinggo/hostmaybeport.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,52 @@
 | 
			
		||||
package missinggo
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"net"
 | 
			
		||||
	"strconv"
 | 
			
		||||
	"strings"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// Represents a split host port.
 | 
			
		||||
type HostMaybePort struct {
 | 
			
		||||
	Host   string // Just the host, with no port.
 | 
			
		||||
	Port   int    // The port if NoPort is false.
 | 
			
		||||
	NoPort bool   // Whether a port is specified.
 | 
			
		||||
	Err    error  // The error returned from net.SplitHostPort.
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (me *HostMaybePort) String() string {
 | 
			
		||||
	if me.NoPort {
 | 
			
		||||
		return me.Host
 | 
			
		||||
	}
 | 
			
		||||
	return net.JoinHostPort(me.Host, strconv.FormatInt(int64(me.Port), 10))
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Parse a "hostport" string, a concept that floats around the stdlib a lot
 | 
			
		||||
// and is painful to work with. If no port is present, what's usually present
 | 
			
		||||
// is just the host.
 | 
			
		||||
func SplitHostMaybePort(hostport string) HostMaybePort {
 | 
			
		||||
	host, portStr, err := net.SplitHostPort(hostport)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		if strings.Contains(err.Error(), "missing port") {
 | 
			
		||||
			return HostMaybePort{
 | 
			
		||||
				Host:   hostport,
 | 
			
		||||
				NoPort: true,
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
		return HostMaybePort{
 | 
			
		||||
			Err: err,
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	portI64, err := strconv.ParseInt(portStr, 0, 0)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return HostMaybePort{
 | 
			
		||||
			Host: host,
 | 
			
		||||
			Port: -1,
 | 
			
		||||
			Err:  err,
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	return HostMaybePort{
 | 
			
		||||
		Host: host,
 | 
			
		||||
		Port: int(portI64),
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										19
									
								
								vendor/github.com/anacrolix/missinggo/hostport.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										19
									
								
								vendor/github.com/anacrolix/missinggo/hostport.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,19 @@
 | 
			
		||||
package missinggo
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"net"
 | 
			
		||||
	"strconv"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
func ParseHostPort(hostport string) (host string, port int, err error) {
 | 
			
		||||
	host, portStr, err := net.SplitHostPort(hostport)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
	port64, err := strconv.ParseInt(portStr, 0, 0)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
	port = int(port64)
 | 
			
		||||
	return
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										75
									
								
								vendor/github.com/anacrolix/missinggo/httpresponsestatus.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										75
									
								
								vendor/github.com/anacrolix/missinggo/httpresponsestatus.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,75 @@
 | 
			
		||||
package missinggo
 | 
			
		||||
 | 
			
		||||
// todo move to httptoo as ResponseRecorder
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"bufio"
 | 
			
		||||
	"net"
 | 
			
		||||
	"net/http"
 | 
			
		||||
	"time"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// A http.ResponseWriter that tracks the status of the response. The status
 | 
			
		||||
// code, and number of bytes written for example.
 | 
			
		||||
type StatusResponseWriter struct {
 | 
			
		||||
	http.ResponseWriter
 | 
			
		||||
	Code         int
 | 
			
		||||
	BytesWritten int64
 | 
			
		||||
	Started      time.Time
 | 
			
		||||
	Ttfb         time.Duration // Time to first byte
 | 
			
		||||
	GotFirstByte bool
 | 
			
		||||
	WroteHeader  Event
 | 
			
		||||
	Hijacked     bool
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
var _ interface {
 | 
			
		||||
	http.ResponseWriter
 | 
			
		||||
	http.Hijacker
 | 
			
		||||
} = (*StatusResponseWriter)(nil)
 | 
			
		||||
 | 
			
		||||
func (me *StatusResponseWriter) Write(b []byte) (n int, err error) {
 | 
			
		||||
	// Exactly how it's done in the standard library. This ensures Code is
 | 
			
		||||
	// correct.
 | 
			
		||||
	if !me.WroteHeader.IsSet() {
 | 
			
		||||
		me.WriteHeader(http.StatusOK)
 | 
			
		||||
	}
 | 
			
		||||
	if !me.GotFirstByte && len(b) > 0 {
 | 
			
		||||
		if me.Started.IsZero() {
 | 
			
		||||
			panic("Started was not initialized")
 | 
			
		||||
		}
 | 
			
		||||
		me.Ttfb = time.Since(me.Started)
 | 
			
		||||
		me.GotFirstByte = true
 | 
			
		||||
	}
 | 
			
		||||
	n, err = me.ResponseWriter.Write(b)
 | 
			
		||||
	me.BytesWritten += int64(n)
 | 
			
		||||
	return
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (me *StatusResponseWriter) WriteHeader(code int) {
 | 
			
		||||
	me.ResponseWriter.WriteHeader(code)
 | 
			
		||||
	if !me.WroteHeader.IsSet() {
 | 
			
		||||
		me.Code = code
 | 
			
		||||
		me.WroteHeader.Set()
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (me *StatusResponseWriter) Hijack() (c net.Conn, b *bufio.ReadWriter, err error) {
 | 
			
		||||
	me.Hijacked = true
 | 
			
		||||
	c, b, err = me.ResponseWriter.(http.Hijacker).Hijack()
 | 
			
		||||
	if b.Writer.Buffered() != 0 {
 | 
			
		||||
		panic("unexpected buffered writes")
 | 
			
		||||
	}
 | 
			
		||||
	c = responseConn{c, me}
 | 
			
		||||
	return
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type responseConn struct {
 | 
			
		||||
	net.Conn
 | 
			
		||||
	s *StatusResponseWriter
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (me responseConn) Write(b []byte) (n int, err error) {
 | 
			
		||||
	n, err = me.Conn.Write(b)
 | 
			
		||||
	me.s.BytesWritten += int64(n)
 | 
			
		||||
	return
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										42
									
								
								vendor/github.com/anacrolix/missinggo/httptoo/accept.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										42
									
								
								vendor/github.com/anacrolix/missinggo/httptoo/accept.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,42 @@
 | 
			
		||||
package httptoo
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"fmt"
 | 
			
		||||
	"strconv"
 | 
			
		||||
	"strings"
 | 
			
		||||
 | 
			
		||||
	"github.com/anacrolix/missinggo/mime"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
func ParseAccept(line string) (parsed AcceptDirectives, err error) {
 | 
			
		||||
	dirs := strings.Split(line, ",")
 | 
			
		||||
	for _, d := range dirs {
 | 
			
		||||
		p := AcceptDirective{
 | 
			
		||||
			Q: 1,
 | 
			
		||||
		}
 | 
			
		||||
		ss := strings.Split(d, ";")
 | 
			
		||||
		switch len(ss) {
 | 
			
		||||
		case 2:
 | 
			
		||||
			p.Q, err = strconv.ParseFloat(ss[1], 32)
 | 
			
		||||
			if err != nil {
 | 
			
		||||
				return
 | 
			
		||||
			}
 | 
			
		||||
			fallthrough
 | 
			
		||||
		case 1:
 | 
			
		||||
			p.MimeType.FromString(ss[0])
 | 
			
		||||
		default:
 | 
			
		||||
			err = fmt.Errorf("error parsing %q", d)
 | 
			
		||||
			return
 | 
			
		||||
		}
 | 
			
		||||
		parsed = append(parsed, p)
 | 
			
		||||
	}
 | 
			
		||||
	return
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type (
 | 
			
		||||
	AcceptDirectives []AcceptDirective
 | 
			
		||||
	AcceptDirective  struct {
 | 
			
		||||
		MimeType mime.Type
 | 
			
		||||
		Q        float64
 | 
			
		||||
	}
 | 
			
		||||
)
 | 
			
		||||
							
								
								
									
										106
									
								
								vendor/github.com/anacrolix/missinggo/httptoo/bytes_content_range.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										106
									
								
								vendor/github.com/anacrolix/missinggo/httptoo/bytes_content_range.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,106 @@
 | 
			
		||||
package httptoo
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"fmt"
 | 
			
		||||
	"math"
 | 
			
		||||
	"regexp"
 | 
			
		||||
	"strconv"
 | 
			
		||||
	"strings"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
type BytesContentRange struct {
 | 
			
		||||
	First, Last, Length int64
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type BytesRange struct {
 | 
			
		||||
	First, Last int64
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (me BytesRange) String() string {
 | 
			
		||||
	if me.Last == math.MaxInt64 {
 | 
			
		||||
		return fmt.Sprintf("bytes=%d-", me.First)
 | 
			
		||||
	}
 | 
			
		||||
	return fmt.Sprintf("bytes=%d-%d", me.First, me.Last)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
var (
 | 
			
		||||
	httpBytesRangeRegexp = regexp.MustCompile(`bytes[ =](\d+)-(\d*)`)
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
func ParseBytesRange(s string) (ret BytesRange, ok bool) {
 | 
			
		||||
	ss := httpBytesRangeRegexp.FindStringSubmatch(s)
 | 
			
		||||
	if ss == nil {
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
	var err error
 | 
			
		||||
	ret.First, err = strconv.ParseInt(ss[1], 10, 64)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
	if ss[2] == "" {
 | 
			
		||||
		ret.Last = math.MaxInt64
 | 
			
		||||
	} else {
 | 
			
		||||
		ret.Last, err = strconv.ParseInt(ss[2], 10, 64)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	ok = true
 | 
			
		||||
	return
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func parseUnitRanges(s string) (unit, ranges string) {
 | 
			
		||||
	s = strings.TrimSpace(s)
 | 
			
		||||
	i := strings.IndexAny(s, " =")
 | 
			
		||||
	if i == -1 {
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
	unit = s[:i]
 | 
			
		||||
	ranges = s[i+1:]
 | 
			
		||||
	return
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func parseFirstLast(s string) (first, last int64) {
 | 
			
		||||
	ss := strings.SplitN(s, "-", 2)
 | 
			
		||||
	first, err := strconv.ParseInt(ss[0], 10, 64)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		panic(err)
 | 
			
		||||
	}
 | 
			
		||||
	last, err = strconv.ParseInt(ss[1], 10, 64)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		panic(err)
 | 
			
		||||
	}
 | 
			
		||||
	return
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func parseContentRange(s string) (ret BytesContentRange) {
 | 
			
		||||
	ss := strings.SplitN(s, "/", 2)
 | 
			
		||||
	firstLast := strings.TrimSpace(ss[0])
 | 
			
		||||
	if firstLast == "*" {
 | 
			
		||||
		ret.First = -1
 | 
			
		||||
		ret.Last = -1
 | 
			
		||||
	} else {
 | 
			
		||||
		ret.First, ret.Last = parseFirstLast(firstLast)
 | 
			
		||||
	}
 | 
			
		||||
	il := strings.TrimSpace(ss[1])
 | 
			
		||||
	if il == "*" {
 | 
			
		||||
		ret.Length = -1
 | 
			
		||||
	} else {
 | 
			
		||||
		var err error
 | 
			
		||||
		ret.Length, err = strconv.ParseInt(il, 10, 64)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			panic(err)
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	return
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func ParseBytesContentRange(s string) (ret BytesContentRange, ok bool) {
 | 
			
		||||
	unit, ranges := parseUnitRanges(s)
 | 
			
		||||
	if unit != "bytes" {
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
	ret = parseContentRange(ranges)
 | 
			
		||||
	ok = true
 | 
			
		||||
	return
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										19
									
								
								vendor/github.com/anacrolix/missinggo/httptoo/client.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										19
									
								
								vendor/github.com/anacrolix/missinggo/httptoo/client.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,19 @@
 | 
			
		||||
package httptoo
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"crypto/tls"
 | 
			
		||||
	"net/http"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// Returns the http.Client's TLS Config, traversing and generating any
 | 
			
		||||
// defaults along the way to get it.
 | 
			
		||||
func ClientTLSConfig(cl *http.Client) *tls.Config {
 | 
			
		||||
	if cl.Transport == nil {
 | 
			
		||||
		cl.Transport = http.DefaultTransport
 | 
			
		||||
	}
 | 
			
		||||
	tr := cl.Transport.(*http.Transport)
 | 
			
		||||
	if tr.TLSClientConfig == nil {
 | 
			
		||||
		tr.TLSClientConfig = &tls.Config{}
 | 
			
		||||
	}
 | 
			
		||||
	return tr.TLSClientConfig
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										31
									
								
								vendor/github.com/anacrolix/missinggo/httptoo/fs.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										31
									
								
								vendor/github.com/anacrolix/missinggo/httptoo/fs.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,31 @@
 | 
			
		||||
package httptoo
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"net/http"
 | 
			
		||||
	"os"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// Wraps a http.FileSystem, disabling directory listings, per the commonly
 | 
			
		||||
// requested feature at https://groups.google.com/forum/#!topic/golang-
 | 
			
		||||
// nuts/bStLPdIVM6w .
 | 
			
		||||
type JustFilesFilesystem struct {
 | 
			
		||||
	Fs http.FileSystem
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (fs JustFilesFilesystem) Open(name string) (http.File, error) {
 | 
			
		||||
	f, err := fs.Fs.Open(name)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
	d, err := f.Stat()
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		f.Close()
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
	if d.IsDir() {
 | 
			
		||||
		f.Close()
 | 
			
		||||
		// This triggers http.FileServer to show a 404.
 | 
			
		||||
		return nil, os.ErrNotExist
 | 
			
		||||
	}
 | 
			
		||||
	return f, nil
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										49
									
								
								vendor/github.com/anacrolix/missinggo/httptoo/gzip.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										49
									
								
								vendor/github.com/anacrolix/missinggo/httptoo/gzip.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,49 @@
 | 
			
		||||
package httptoo
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"compress/gzip"
 | 
			
		||||
	"io"
 | 
			
		||||
	"net/http"
 | 
			
		||||
	"strings"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
type gzipResponseWriter struct {
 | 
			
		||||
	io.Writer
 | 
			
		||||
	http.ResponseWriter
 | 
			
		||||
	haveWritten bool
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
var _ http.ResponseWriter = &gzipResponseWriter{}
 | 
			
		||||
 | 
			
		||||
func (w *gzipResponseWriter) Write(b []byte) (int, error) {
 | 
			
		||||
	if w.haveWritten {
 | 
			
		||||
		goto write
 | 
			
		||||
	}
 | 
			
		||||
	w.haveWritten = true
 | 
			
		||||
	if w.Header().Get("Content-Type") != "" {
 | 
			
		||||
		goto write
 | 
			
		||||
	}
 | 
			
		||||
	if type_ := http.DetectContentType(b); type_ != "application/octet-stream" {
 | 
			
		||||
		w.Header().Set("Content-Type", type_)
 | 
			
		||||
	}
 | 
			
		||||
write:
 | 
			
		||||
	return w.Writer.Write(b)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Gzips response body if the request says it'll allow it.
 | 
			
		||||
func GzipHandler(h http.Handler) http.Handler {
 | 
			
		||||
	return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
 | 
			
		||||
		if !strings.Contains(r.Header.Get("Accept-Encoding"), "gzip") || w.Header().Get("Content-Encoding") != "" || w.Header().Get("Vary") != "" {
 | 
			
		||||
			h.ServeHTTP(w, r)
 | 
			
		||||
			return
 | 
			
		||||
		}
 | 
			
		||||
		w.Header().Set("Content-Encoding", "gzip")
 | 
			
		||||
		w.Header().Set("Vary", "Accept-Encoding")
 | 
			
		||||
		gz := gzip.NewWriter(w)
 | 
			
		||||
		defer gz.Close()
 | 
			
		||||
		h.ServeHTTP(&gzipResponseWriter{
 | 
			
		||||
			Writer:         gz,
 | 
			
		||||
			ResponseWriter: w,
 | 
			
		||||
		}, r)
 | 
			
		||||
	})
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										61
									
								
								vendor/github.com/anacrolix/missinggo/httptoo/headers.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										61
									
								
								vendor/github.com/anacrolix/missinggo/httptoo/headers.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,61 @@
 | 
			
		||||
package httptoo
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"fmt"
 | 
			
		||||
	"strings"
 | 
			
		||||
	"time"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
type Visibility int
 | 
			
		||||
 | 
			
		||||
const (
 | 
			
		||||
	Default = 0
 | 
			
		||||
	Public  = 1
 | 
			
		||||
	Private = 2
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
type CacheControlHeader struct {
 | 
			
		||||
	MaxAge  time.Duration
 | 
			
		||||
	Caching Visibility
 | 
			
		||||
	NoStore bool
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (me *CacheControlHeader) caching() []string {
 | 
			
		||||
	switch me.Caching {
 | 
			
		||||
	case Public:
 | 
			
		||||
		return []string{"public"}
 | 
			
		||||
	case Private:
 | 
			
		||||
		return []string{"private"}
 | 
			
		||||
	default:
 | 
			
		||||
		return nil
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (me *CacheControlHeader) maxAge() []string {
 | 
			
		||||
	if me.MaxAge == 0 {
 | 
			
		||||
		return nil
 | 
			
		||||
	}
 | 
			
		||||
	d := me.MaxAge
 | 
			
		||||
	if d < 0 {
 | 
			
		||||
		d = 0
 | 
			
		||||
	}
 | 
			
		||||
	return []string{fmt.Sprintf("max-age=%d", d/time.Second)}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (me *CacheControlHeader) noStore() []string {
 | 
			
		||||
	if me.NoStore {
 | 
			
		||||
		return []string{"no-store"}
 | 
			
		||||
	}
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (me *CacheControlHeader) concat(sss ...[]string) (ret []string) {
 | 
			
		||||
	for _, ss := range sss {
 | 
			
		||||
		ret = append(ret, ss...)
 | 
			
		||||
	}
 | 
			
		||||
	return
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (me CacheControlHeader) String() string {
 | 
			
		||||
	return strings.Join(me.concat(me.caching(), me.maxAge()), ", ")
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										42
									
								
								vendor/github.com/anacrolix/missinggo/httptoo/httptoo.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										42
									
								
								vendor/github.com/anacrolix/missinggo/httptoo/httptoo.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,42 @@
 | 
			
		||||
package httptoo
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"net/http"
 | 
			
		||||
	"strconv"
 | 
			
		||||
	"strings"
 | 
			
		||||
 | 
			
		||||
	"github.com/bradfitz/iter"
 | 
			
		||||
 | 
			
		||||
	"github.com/anacrolix/missinggo"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
func OriginatingProtocol(r *http.Request) string {
 | 
			
		||||
	if fp := r.Header.Get("X-Forwarded-Proto"); fp != "" {
 | 
			
		||||
		return fp
 | 
			
		||||
	} else if r.TLS != nil {
 | 
			
		||||
		return "https"
 | 
			
		||||
	} else {
 | 
			
		||||
		return "http"
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Clears the named cookie for every domain that leads to the current one.
 | 
			
		||||
func NukeCookie(w http.ResponseWriter, r *http.Request, name, path string) {
 | 
			
		||||
	parts := strings.Split(missinggo.SplitHostMaybePort(r.Host).Host, ".")
 | 
			
		||||
	for i := range iter.N(len(parts) + 1) { // Include the empty domain.
 | 
			
		||||
		http.SetCookie(w, &http.Cookie{
 | 
			
		||||
			Name:   name,
 | 
			
		||||
			MaxAge: -1,
 | 
			
		||||
			Path:   path,
 | 
			
		||||
			Domain: strings.Join(parts[i:], "."),
 | 
			
		||||
		})
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Performs quoted-string from http://www.w3.org/Protocols/rfc2616/rfc2616-sec2.html
 | 
			
		||||
func EncodeQuotedString(s string) string {
 | 
			
		||||
	return strconv.Quote(s)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// https://httpstatuses.com/499
 | 
			
		||||
const StatusClientCancelledRequest = 499
 | 
			
		||||
							
								
								
									
										112
									
								
								vendor/github.com/anacrolix/missinggo/httptoo/inproc_roundtrip.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										112
									
								
								vendor/github.com/anacrolix/missinggo/httptoo/inproc_roundtrip.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,112 @@
 | 
			
		||||
package httptoo
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"context"
 | 
			
		||||
	"io"
 | 
			
		||||
	"net/http"
 | 
			
		||||
	"sync"
 | 
			
		||||
 | 
			
		||||
	"github.com/anacrolix/missinggo"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
type responseWriter struct {
 | 
			
		||||
	mu            sync.Mutex
 | 
			
		||||
	r             http.Response
 | 
			
		||||
	headerWritten missinggo.Event
 | 
			
		||||
	bodyWriter    io.WriteCloser
 | 
			
		||||
	bodyClosed    missinggo.SynchronizedEvent
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
var _ interface {
 | 
			
		||||
	http.ResponseWriter
 | 
			
		||||
	// We're able to emulate this easily enough.
 | 
			
		||||
	http.CloseNotifier
 | 
			
		||||
} = &responseWriter{}
 | 
			
		||||
 | 
			
		||||
// Use Request.Context.Done instead.
 | 
			
		||||
func (me *responseWriter) CloseNotify() <-chan bool {
 | 
			
		||||
	ret := make(chan bool, 1)
 | 
			
		||||
	go func() {
 | 
			
		||||
		<-me.bodyClosed.C()
 | 
			
		||||
		ret <- true
 | 
			
		||||
	}()
 | 
			
		||||
	return ret
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (me *responseWriter) Header() http.Header {
 | 
			
		||||
	if me.r.Header == nil {
 | 
			
		||||
		me.r.Header = make(http.Header)
 | 
			
		||||
	}
 | 
			
		||||
	return me.r.Header
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (me *responseWriter) Write(b []byte) (int, error) {
 | 
			
		||||
	me.mu.Lock()
 | 
			
		||||
	if !me.headerWritten.IsSet() {
 | 
			
		||||
		me.writeHeader(200)
 | 
			
		||||
	}
 | 
			
		||||
	me.mu.Unlock()
 | 
			
		||||
	return me.bodyWriter.Write(b)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (me *responseWriter) WriteHeader(status int) {
 | 
			
		||||
	me.mu.Lock()
 | 
			
		||||
	me.writeHeader(status)
 | 
			
		||||
	me.mu.Unlock()
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (me *responseWriter) writeHeader(status int) {
 | 
			
		||||
	if me.headerWritten.IsSet() {
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
	me.r.StatusCode = status
 | 
			
		||||
	me.headerWritten.Set()
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (me *responseWriter) runHandler(h http.Handler, req *http.Request) {
 | 
			
		||||
	var pr *io.PipeReader
 | 
			
		||||
	pr, me.bodyWriter = io.Pipe()
 | 
			
		||||
	me.r.Body = struct {
 | 
			
		||||
		io.Reader
 | 
			
		||||
		io.Closer
 | 
			
		||||
	}{pr, eventCloser{pr, &me.bodyClosed}}
 | 
			
		||||
	// Shouldn't be writing to the response after the handler returns.
 | 
			
		||||
	defer me.bodyWriter.Close()
 | 
			
		||||
	// Send a 200 if nothing was written yet.
 | 
			
		||||
	defer me.WriteHeader(200)
 | 
			
		||||
	// Wrap the context in the given Request with one that closes when either
 | 
			
		||||
	// the handler returns, or the response body is closed.
 | 
			
		||||
	ctx, cancel := context.WithCancel(req.Context())
 | 
			
		||||
	defer cancel()
 | 
			
		||||
	go func() {
 | 
			
		||||
		<-me.bodyClosed.C()
 | 
			
		||||
		cancel()
 | 
			
		||||
	}()
 | 
			
		||||
	h.ServeHTTP(me, req.WithContext(ctx))
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type eventCloser struct {
 | 
			
		||||
	c      io.Closer
 | 
			
		||||
	closed *missinggo.SynchronizedEvent
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (me eventCloser) Close() (err error) {
 | 
			
		||||
	err = me.c.Close()
 | 
			
		||||
	me.closed.Set()
 | 
			
		||||
	return
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func RoundTripHandler(req *http.Request, h http.Handler) (*http.Response, error) {
 | 
			
		||||
	rw := responseWriter{}
 | 
			
		||||
	go rw.runHandler(h, req)
 | 
			
		||||
	<-rw.headerWritten.LockedChan(&rw.mu)
 | 
			
		||||
	return &rw.r, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type InProcRoundTripper struct {
 | 
			
		||||
	Handler http.Handler
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (me *InProcRoundTripper) RoundTrip(req *http.Request) (*http.Response, error) {
 | 
			
		||||
	return RoundTripHandler(req, me.Handler)
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										23
									
								
								vendor/github.com/anacrolix/missinggo/httptoo/request.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										23
									
								
								vendor/github.com/anacrolix/missinggo/httptoo/request.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,23 @@
 | 
			
		||||
package httptoo
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"net"
 | 
			
		||||
	"net/http"
 | 
			
		||||
 | 
			
		||||
	"github.com/anacrolix/missinggo"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// Request is intended for localhost, either with a localhost name, or
 | 
			
		||||
// loopback IP.
 | 
			
		||||
func RequestIsForLocalhost(r *http.Request) bool {
 | 
			
		||||
	hostHost := missinggo.SplitHostMaybePort(r.Host).Host
 | 
			
		||||
	if ip := net.ParseIP(hostHost); ip != nil {
 | 
			
		||||
		return ip.IsLoopback()
 | 
			
		||||
	}
 | 
			
		||||
	return hostHost == "localhost"
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Request originated from a loopback IP.
 | 
			
		||||
func RequestIsFromLocalhost(r *http.Request) bool {
 | 
			
		||||
	return net.ParseIP(missinggo.SplitHostMaybePort(r.RemoteAddr).Host).IsLoopback()
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										138
									
								
								vendor/github.com/anacrolix/missinggo/httptoo/reverse_proxy.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										138
									
								
								vendor/github.com/anacrolix/missinggo/httptoo/reverse_proxy.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,138 @@
 | 
			
		||||
package httptoo
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"bufio"
 | 
			
		||||
	"encoding/gob"
 | 
			
		||||
	"io"
 | 
			
		||||
	"net"
 | 
			
		||||
	"net/http"
 | 
			
		||||
	"net/url"
 | 
			
		||||
	"sync"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
func deepCopy(dst, src interface{}) error {
 | 
			
		||||
	r, w := io.Pipe()
 | 
			
		||||
	e := gob.NewEncoder(w)
 | 
			
		||||
	d := gob.NewDecoder(r)
 | 
			
		||||
	var decErr, encErr error
 | 
			
		||||
	var wg sync.WaitGroup
 | 
			
		||||
	wg.Add(1)
 | 
			
		||||
	go func() {
 | 
			
		||||
		defer wg.Done()
 | 
			
		||||
		decErr = d.Decode(dst)
 | 
			
		||||
		r.Close()
 | 
			
		||||
	}()
 | 
			
		||||
	encErr = e.Encode(src)
 | 
			
		||||
	// Always returns nil.
 | 
			
		||||
	w.CloseWithError(encErr)
 | 
			
		||||
	wg.Wait()
 | 
			
		||||
	if encErr != nil {
 | 
			
		||||
		return encErr
 | 
			
		||||
	}
 | 
			
		||||
	return decErr
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Takes a request, and alters its destination fields, for proxying.
 | 
			
		||||
func RedirectedRequest(r *http.Request, newUrl string) (ret *http.Request, err error) {
 | 
			
		||||
	u, err := url.Parse(newUrl)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
	ret = new(http.Request)
 | 
			
		||||
	*ret = *r
 | 
			
		||||
	ret.Header = nil
 | 
			
		||||
	err = deepCopy(&ret.Header, r.Header)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
	ret.URL = u
 | 
			
		||||
	ret.RequestURI = ""
 | 
			
		||||
	return
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func CopyHeaders(w http.ResponseWriter, r *http.Response) {
 | 
			
		||||
	for h, vs := range r.Header {
 | 
			
		||||
		for _, v := range vs {
 | 
			
		||||
			w.Header().Add(h, v)
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func ForwardResponse(w http.ResponseWriter, r *http.Response) {
 | 
			
		||||
	CopyHeaders(w, r)
 | 
			
		||||
	w.WriteHeader(r.StatusCode)
 | 
			
		||||
	// Errors frequently occur writing the body when the client hangs up.
 | 
			
		||||
	io.Copy(w, r.Body)
 | 
			
		||||
	r.Body.Close()
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func SetOriginRequestForwardingHeaders(o, f *http.Request) {
 | 
			
		||||
	xff := o.Header.Get("X-Forwarded-For")
 | 
			
		||||
	hop, _, _ := net.SplitHostPort(f.RemoteAddr)
 | 
			
		||||
	if xff == "" {
 | 
			
		||||
		xff = hop
 | 
			
		||||
	} else {
 | 
			
		||||
		xff += "," + hop
 | 
			
		||||
	}
 | 
			
		||||
	o.Header.Set("X-Forwarded-For", xff)
 | 
			
		||||
	o.Header.Set("X-Forwarded-Proto", OriginatingProtocol(f))
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// w is for the client response. r is the request to send to the origin
 | 
			
		||||
// (already "forwarded"). originUrl is where to send the request.
 | 
			
		||||
func ReverseProxyUpgrade(w http.ResponseWriter, r *http.Request, originUrl string) (err error) {
 | 
			
		||||
	u, err := url.Parse(originUrl)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
	oc, err := net.Dial("tcp", u.Host)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
	defer oc.Close()
 | 
			
		||||
	err = r.Write(oc)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
	originConnReadBuffer := bufio.NewReader(oc)
 | 
			
		||||
	originResp, err := http.ReadResponse(originConnReadBuffer, r)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
	if originResp.StatusCode != 101 {
 | 
			
		||||
		ForwardResponse(w, originResp)
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
	cc, _, err := w.(http.Hijacker).Hijack()
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
	defer cc.Close()
 | 
			
		||||
	originResp.Write(cc)
 | 
			
		||||
	go io.Copy(oc, cc)
 | 
			
		||||
	// Let the origin connection control when this routine returns, as we
 | 
			
		||||
	// should trust it more.
 | 
			
		||||
	io.Copy(cc, originConnReadBuffer)
 | 
			
		||||
	return
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func ReverseProxy(w http.ResponseWriter, r *http.Request, originUrl string, client *http.Client) (err error) {
 | 
			
		||||
	originRequest, err := RedirectedRequest(r, originUrl)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
	SetOriginRequestForwardingHeaders(originRequest, r)
 | 
			
		||||
	if r.Header.Get("Connection") == "Upgrade" {
 | 
			
		||||
		return ReverseProxyUpgrade(w, originRequest, originUrl)
 | 
			
		||||
	}
 | 
			
		||||
	rt := client.Transport
 | 
			
		||||
	if rt == nil {
 | 
			
		||||
		rt = http.DefaultTransport
 | 
			
		||||
	}
 | 
			
		||||
	originResp, err := rt.RoundTrip(originRequest)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
	ForwardResponse(w, originResp)
 | 
			
		||||
	return
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										64
									
								
								vendor/github.com/anacrolix/missinggo/httptoo/url.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										64
									
								
								vendor/github.com/anacrolix/missinggo/httptoo/url.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,64 @@
 | 
			
		||||
package httptoo
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"net/http"
 | 
			
		||||
	"net/url"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// Deep copies a URL. I could call it DeepCopyURL, but what else would you be
 | 
			
		||||
// copying when you have a *url.URL? Of note is that the Userinfo is deep
 | 
			
		||||
// copied. The returned URL shares no references with the original.
 | 
			
		||||
func CopyURL(u *url.URL) (ret *url.URL) {
 | 
			
		||||
	ret = new(url.URL)
 | 
			
		||||
	*ret = *u
 | 
			
		||||
	if u.User != nil {
 | 
			
		||||
		ret.User = new(url.Userinfo)
 | 
			
		||||
		*ret.User = *u.User
 | 
			
		||||
	}
 | 
			
		||||
	return
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Reconstructs the URL that would have produced the given Request.
 | 
			
		||||
// Request.URLs are not fully populated in http.Server handlers.
 | 
			
		||||
func RequestedURL(r *http.Request) (ret *url.URL) {
 | 
			
		||||
	ret = CopyURL(r.URL)
 | 
			
		||||
	ret.Host = r.Host
 | 
			
		||||
	ret.Scheme = OriginatingProtocol(r)
 | 
			
		||||
	return
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// The official URL struct parameters, for tracking changes and reference
 | 
			
		||||
// here.
 | 
			
		||||
//
 | 
			
		||||
// 	Scheme     string
 | 
			
		||||
// 	Opaque     string    // encoded opaque data
 | 
			
		||||
// 	User       *Userinfo // username and password information
 | 
			
		||||
// 	Host       string    // host or host:port
 | 
			
		||||
// 	Path       string
 | 
			
		||||
// 	RawPath    string // encoded path hint (Go 1.5 and later only; see EscapedPath method)
 | 
			
		||||
// 	ForceQuery bool   // append a query ('?') even if RawQuery is empty
 | 
			
		||||
// 	RawQuery   string // encoded query values, without '?'
 | 
			
		||||
// 	Fragment   string // fragment for references, without '#'
 | 
			
		||||
 | 
			
		||||
// Return the first URL extended with elements of the second, in the manner
 | 
			
		||||
// that occurs throughout my projects. Noteworthy difference from
 | 
			
		||||
// url.URL.ResolveReference is that if the reference has a scheme, the base is
 | 
			
		||||
// not completely ignored.
 | 
			
		||||
func AppendURL(u, v *url.URL) *url.URL {
 | 
			
		||||
	u = CopyURL(u)
 | 
			
		||||
	clobberString(&u.Scheme, v.Scheme)
 | 
			
		||||
	clobberString(&u.Host, v.Host)
 | 
			
		||||
	u.Path += v.Path
 | 
			
		||||
	q := u.Query()
 | 
			
		||||
	for k, v := range v.Query() {
 | 
			
		||||
		q[k] = append(q[k], v...)
 | 
			
		||||
	}
 | 
			
		||||
	u.RawQuery = q.Encode()
 | 
			
		||||
	return u
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func clobberString(s *string, value string) {
 | 
			
		||||
	if value != "" {
 | 
			
		||||
		*s = value
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										226
									
								
								vendor/github.com/anacrolix/missinggo/inproc/inproc.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										226
									
								
								vendor/github.com/anacrolix/missinggo/inproc/inproc.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,226 @@
 | 
			
		||||
package inproc
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"errors"
 | 
			
		||||
	"io"
 | 
			
		||||
	"math"
 | 
			
		||||
	"net"
 | 
			
		||||
	"strconv"
 | 
			
		||||
	"sync"
 | 
			
		||||
	"time"
 | 
			
		||||
 | 
			
		||||
	"github.com/anacrolix/missinggo"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
var (
 | 
			
		||||
	mu       sync.Mutex
 | 
			
		||||
	cond         = sync.Cond{L: &mu}
 | 
			
		||||
	nextPort int = 1
 | 
			
		||||
	conns        = map[int]*packetConn{}
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
type Addr struct {
 | 
			
		||||
	Port int
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (Addr) Network() string {
 | 
			
		||||
	return "inproc"
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (me Addr) String() string {
 | 
			
		||||
	return ":" + strconv.FormatInt(int64(me.Port), 10)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func getPort() (port int) {
 | 
			
		||||
	mu.Lock()
 | 
			
		||||
	defer mu.Unlock()
 | 
			
		||||
	port = nextPort
 | 
			
		||||
	nextPort++
 | 
			
		||||
	return
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func ResolveAddr(network, str string) (net.Addr, error) {
 | 
			
		||||
	return ResolveInprocAddr(network, str)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func ResolveInprocAddr(network, str string) (addr Addr, err error) {
 | 
			
		||||
	if str == "" {
 | 
			
		||||
		addr.Port = getPort()
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
	_, p, err := net.SplitHostPort(str)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
	i64, err := strconv.ParseInt(p, 10, 0)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
	addr.Port = int(i64)
 | 
			
		||||
	if addr.Port == 0 {
 | 
			
		||||
		addr.Port = getPort()
 | 
			
		||||
	}
 | 
			
		||||
	return
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func ListenPacket(network, addrStr string) (nc net.PacketConn, err error) {
 | 
			
		||||
	addr, err := ResolveInprocAddr(network, addrStr)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
	mu.Lock()
 | 
			
		||||
	defer mu.Unlock()
 | 
			
		||||
	if _, ok := conns[addr.Port]; ok {
 | 
			
		||||
		err = errors.New("address in use")
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
	pc := &packetConn{
 | 
			
		||||
		addr:          addr,
 | 
			
		||||
		readDeadline:  newCondDeadline(&cond),
 | 
			
		||||
		writeDeadline: newCondDeadline(&cond),
 | 
			
		||||
	}
 | 
			
		||||
	conns[addr.Port] = pc
 | 
			
		||||
	nc = pc
 | 
			
		||||
	return
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type packet struct {
 | 
			
		||||
	data []byte
 | 
			
		||||
	addr Addr
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type packetConn struct {
 | 
			
		||||
	closed        bool
 | 
			
		||||
	addr          Addr
 | 
			
		||||
	reads         []packet
 | 
			
		||||
	readDeadline  *condDeadline
 | 
			
		||||
	writeDeadline *condDeadline
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (me *packetConn) Close() error {
 | 
			
		||||
	mu.Lock()
 | 
			
		||||
	defer mu.Unlock()
 | 
			
		||||
	me.closed = true
 | 
			
		||||
	delete(conns, me.addr.Port)
 | 
			
		||||
	cond.Broadcast()
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (me *packetConn) LocalAddr() net.Addr {
 | 
			
		||||
	return me.addr
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type errTimeout struct{}
 | 
			
		||||
 | 
			
		||||
func (errTimeout) Error() string {
 | 
			
		||||
	return "i/o timeout"
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (errTimeout) Temporary() bool {
 | 
			
		||||
	return false
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (errTimeout) Timeout() bool {
 | 
			
		||||
	return true
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
var _ net.Error = errTimeout{}
 | 
			
		||||
 | 
			
		||||
func (me *packetConn) WriteTo(b []byte, na net.Addr) (n int, err error) {
 | 
			
		||||
	mu.Lock()
 | 
			
		||||
	defer mu.Unlock()
 | 
			
		||||
	if me.closed {
 | 
			
		||||
		err = errors.New("closed")
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
	if me.writeDeadline.exceeded() {
 | 
			
		||||
		err = errTimeout{}
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
	n = len(b)
 | 
			
		||||
	port := missinggo.AddrPort(na)
 | 
			
		||||
	c, ok := conns[port]
 | 
			
		||||
	if !ok {
 | 
			
		||||
		// log.Printf("no conn for port %d", port)
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
	c.reads = append(c.reads, packet{append([]byte(nil), b...), me.addr})
 | 
			
		||||
	cond.Broadcast()
 | 
			
		||||
	return
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (me *packetConn) ReadFrom(b []byte) (n int, addr net.Addr, err error) {
 | 
			
		||||
	mu.Lock()
 | 
			
		||||
	defer mu.Unlock()
 | 
			
		||||
	for {
 | 
			
		||||
		if len(me.reads) != 0 {
 | 
			
		||||
			r := me.reads[0]
 | 
			
		||||
			me.reads = me.reads[1:]
 | 
			
		||||
			n = copy(b, r.data)
 | 
			
		||||
			addr = r.addr
 | 
			
		||||
			// log.Println(addr)
 | 
			
		||||
			return
 | 
			
		||||
		}
 | 
			
		||||
		if me.closed {
 | 
			
		||||
			err = io.EOF
 | 
			
		||||
			return
 | 
			
		||||
		}
 | 
			
		||||
		if me.readDeadline.exceeded() {
 | 
			
		||||
			err = errTimeout{}
 | 
			
		||||
			return
 | 
			
		||||
		}
 | 
			
		||||
		cond.Wait()
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (me *packetConn) SetDeadline(t time.Time) error {
 | 
			
		||||
	me.writeDeadline.setDeadline(t)
 | 
			
		||||
	me.readDeadline.setDeadline(t)
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (me *packetConn) SetReadDeadline(t time.Time) error {
 | 
			
		||||
	me.readDeadline.setDeadline(t)
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (me *packetConn) SetWriteDeadline(t time.Time) error {
 | 
			
		||||
	me.writeDeadline.setDeadline(t)
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func newCondDeadline(cond *sync.Cond) (ret *condDeadline) {
 | 
			
		||||
	ret = &condDeadline{
 | 
			
		||||
		timer: time.AfterFunc(math.MaxInt64, func() {
 | 
			
		||||
			mu.Lock()
 | 
			
		||||
			ret._exceeded = true
 | 
			
		||||
			mu.Unlock()
 | 
			
		||||
			cond.Broadcast()
 | 
			
		||||
		}),
 | 
			
		||||
	}
 | 
			
		||||
	ret.setDeadline(time.Time{})
 | 
			
		||||
	return
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type condDeadline struct {
 | 
			
		||||
	mu        sync.Mutex
 | 
			
		||||
	_exceeded bool
 | 
			
		||||
	timer     *time.Timer
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (me *condDeadline) setDeadline(t time.Time) {
 | 
			
		||||
	me.mu.Lock()
 | 
			
		||||
	defer me.mu.Unlock()
 | 
			
		||||
	me._exceeded = false
 | 
			
		||||
	if t.IsZero() {
 | 
			
		||||
		me.timer.Stop()
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
	me.timer.Reset(t.Sub(time.Now()))
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (me *condDeadline) exceeded() bool {
 | 
			
		||||
	me.mu.Lock()
 | 
			
		||||
	defer me.mu.Unlock()
 | 
			
		||||
	return me._exceeded
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										30
									
								
								vendor/github.com/anacrolix/missinggo/ioutil.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										30
									
								
								vendor/github.com/anacrolix/missinggo/ioutil.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,30 @@
 | 
			
		||||
package missinggo
 | 
			
		||||
 | 
			
		||||
import "io"
 | 
			
		||||
 | 
			
		||||
type StatWriter struct {
 | 
			
		||||
	Written int64
 | 
			
		||||
	w       io.Writer
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (me *StatWriter) Write(b []byte) (n int, err error) {
 | 
			
		||||
	n, err = me.w.Write(b)
 | 
			
		||||
	me.Written += int64(n)
 | 
			
		||||
	return
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func NewStatWriter(w io.Writer) *StatWriter {
 | 
			
		||||
	return &StatWriter{w: w}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
var ZeroReader zeroReader
 | 
			
		||||
 | 
			
		||||
type zeroReader struct{}
 | 
			
		||||
 | 
			
		||||
func (me zeroReader) Read(b []byte) (n int, err error) {
 | 
			
		||||
	for i := range b {
 | 
			
		||||
		b[i] = 0
 | 
			
		||||
	}
 | 
			
		||||
	n = len(b)
 | 
			
		||||
	return
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										11
									
								
								vendor/github.com/anacrolix/missinggo/iter/chain.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										11
									
								
								vendor/github.com/anacrolix/missinggo/iter/chain.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,11 @@
 | 
			
		||||
package iter
 | 
			
		||||
 | 
			
		||||
func Chain(fs ...Func) Func {
 | 
			
		||||
	return func(cb Callback) {
 | 
			
		||||
		for _, f := range fs {
 | 
			
		||||
			if !All(cb, f) {
 | 
			
		||||
				break
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										22
									
								
								vendor/github.com/anacrolix/missinggo/iter/func.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										22
									
								
								vendor/github.com/anacrolix/missinggo/iter/func.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,22 @@
 | 
			
		||||
package iter
 | 
			
		||||
 | 
			
		||||
// Callback receives a value and returns true if another value should be
 | 
			
		||||
// received or false to stop iteration.
 | 
			
		||||
type Callback func(value interface{}) (more bool)
 | 
			
		||||
 | 
			
		||||
// Func iterates by calling Callback for each of its values.
 | 
			
		||||
type Func func(Callback)
 | 
			
		||||
 | 
			
		||||
func All(cb Callback, fs ...Func) bool {
 | 
			
		||||
	for _, f := range fs {
 | 
			
		||||
		all := true
 | 
			
		||||
		f(func(v interface{}) bool {
 | 
			
		||||
			all = all && cb(v)
 | 
			
		||||
			return all
 | 
			
		||||
		})
 | 
			
		||||
		if !all {
 | 
			
		||||
			return false
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	return true
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										105
									
								
								vendor/github.com/anacrolix/missinggo/iter/groupby.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										105
									
								
								vendor/github.com/anacrolix/missinggo/iter/groupby.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,105 @@
 | 
			
		||||
package iter
 | 
			
		||||
 | 
			
		||||
type groupBy struct {
 | 
			
		||||
	curKey     interface{}
 | 
			
		||||
	curKeyOk   bool
 | 
			
		||||
	curValue   interface{}
 | 
			
		||||
	keyFunc    func(interface{}) interface{}
 | 
			
		||||
	input      Iterator
 | 
			
		||||
	groupKey   interface{}
 | 
			
		||||
	groupKeyOk bool
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type Group interface {
 | 
			
		||||
	Iterator
 | 
			
		||||
	Key() interface{}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type group struct {
 | 
			
		||||
	gb      *groupBy
 | 
			
		||||
	key     interface{}
 | 
			
		||||
	first   bool
 | 
			
		||||
	stopped bool
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (me *group) Stop() {
 | 
			
		||||
	me.stopped = true
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (me *group) Next() (ok bool) {
 | 
			
		||||
	if me.stopped {
 | 
			
		||||
		return false
 | 
			
		||||
	}
 | 
			
		||||
	if me.first {
 | 
			
		||||
		me.first = false
 | 
			
		||||
		return true
 | 
			
		||||
	}
 | 
			
		||||
	me.gb.advance()
 | 
			
		||||
	if !me.gb.curKeyOk || me.gb.curKey != me.key {
 | 
			
		||||
		me.Stop()
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
	ok = true
 | 
			
		||||
	return
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (me group) Value() (ret interface{}) {
 | 
			
		||||
	if me.stopped {
 | 
			
		||||
		panic("iterator stopped")
 | 
			
		||||
	}
 | 
			
		||||
	ret = me.gb.curValue
 | 
			
		||||
	return
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (me group) Key() interface{} {
 | 
			
		||||
	return me.key
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (me *groupBy) advance() {
 | 
			
		||||
	me.curKeyOk = me.input.Next()
 | 
			
		||||
	if me.curKeyOk {
 | 
			
		||||
		me.curValue = me.input.Value()
 | 
			
		||||
		me.curKey = me.keyFunc(me.curValue)
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (me *groupBy) Next() (ok bool) {
 | 
			
		||||
	for me.curKey == me.groupKey {
 | 
			
		||||
		ok = me.input.Next()
 | 
			
		||||
		if !ok {
 | 
			
		||||
			return
 | 
			
		||||
		}
 | 
			
		||||
		me.curValue = me.input.Value()
 | 
			
		||||
		me.curKey = me.keyFunc(me.curValue)
 | 
			
		||||
		me.curKeyOk = true
 | 
			
		||||
	}
 | 
			
		||||
	me.groupKey = me.curKey
 | 
			
		||||
	me.groupKeyOk = true
 | 
			
		||||
	return true
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (me *groupBy) Value() (ret interface{}) {
 | 
			
		||||
	return &group{me, me.groupKey, true, false}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (me *groupBy) Stop() {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Allows use of nil as a return from the key func.
 | 
			
		||||
var uniqueKey = new(int)
 | 
			
		||||
 | 
			
		||||
// Group by returns an iterator of iterators over the values of the input
 | 
			
		||||
// iterator that consecutively return the same value when input to the key
 | 
			
		||||
// function. Note that repeated calls to each value of the GroupBy Iterator
 | 
			
		||||
// does not return a new iterator over the values for that key.
 | 
			
		||||
func GroupBy(input Iterator, keyFunc func(interface{}) interface{}) Iterator {
 | 
			
		||||
	if keyFunc == nil {
 | 
			
		||||
		keyFunc = func(a interface{}) interface{} { return a }
 | 
			
		||||
	}
 | 
			
		||||
	return &groupBy{
 | 
			
		||||
		input:    input,
 | 
			
		||||
		keyFunc:  keyFunc,
 | 
			
		||||
		groupKey: uniqueKey,
 | 
			
		||||
		curKey:   uniqueKey,
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										16
									
								
								vendor/github.com/anacrolix/missinggo/iter/head.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										16
									
								
								vendor/github.com/anacrolix/missinggo/iter/head.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,16 @@
 | 
			
		||||
package iter
 | 
			
		||||
 | 
			
		||||
func Head(n int, f Func) Func {
 | 
			
		||||
	return func(cb Callback) {
 | 
			
		||||
		if n <= 0 {
 | 
			
		||||
			return
 | 
			
		||||
		}
 | 
			
		||||
		f(func(v interface{}) bool {
 | 
			
		||||
			n--
 | 
			
		||||
			if !cb(v) {
 | 
			
		||||
				return false
 | 
			
		||||
			}
 | 
			
		||||
			return n > 0
 | 
			
		||||
		})
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										69
									
								
								vendor/github.com/anacrolix/missinggo/iter/iterable.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										69
									
								
								vendor/github.com/anacrolix/missinggo/iter/iterable.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,69 @@
 | 
			
		||||
package iter
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"sync"
 | 
			
		||||
 | 
			
		||||
	"github.com/anacrolix/missinggo"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
type Iterable interface {
 | 
			
		||||
	Iter(Callback)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type iterator struct {
 | 
			
		||||
	it      Iterable
 | 
			
		||||
	ch      chan interface{}
 | 
			
		||||
	value   interface{}
 | 
			
		||||
	ok      bool
 | 
			
		||||
	mu      sync.Mutex
 | 
			
		||||
	stopped missinggo.Event
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func NewIterator(it Iterable) (ret *iterator) {
 | 
			
		||||
	ret = &iterator{
 | 
			
		||||
		it: it,
 | 
			
		||||
		ch: make(chan interface{}),
 | 
			
		||||
	}
 | 
			
		||||
	go func() {
 | 
			
		||||
		// Have to do this in a goroutine, because the interface is synchronous.
 | 
			
		||||
		it.Iter(func(value interface{}) bool {
 | 
			
		||||
			select {
 | 
			
		||||
			case ret.ch <- value:
 | 
			
		||||
				return true
 | 
			
		||||
			case <-ret.stopped.LockedChan(&ret.mu):
 | 
			
		||||
				return false
 | 
			
		||||
			}
 | 
			
		||||
		})
 | 
			
		||||
		close(ret.ch)
 | 
			
		||||
		ret.mu.Lock()
 | 
			
		||||
		ret.stopped.Set()
 | 
			
		||||
		ret.mu.Unlock()
 | 
			
		||||
	}()
 | 
			
		||||
	return
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (me *iterator) Value() interface{} {
 | 
			
		||||
	if !me.ok {
 | 
			
		||||
		panic("no value")
 | 
			
		||||
	}
 | 
			
		||||
	return me.value
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (me *iterator) Next() bool {
 | 
			
		||||
	me.value, me.ok = <-me.ch
 | 
			
		||||
	return me.ok
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (me *iterator) Stop() {
 | 
			
		||||
	me.mu.Lock()
 | 
			
		||||
	me.stopped.Set()
 | 
			
		||||
	me.mu.Unlock()
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func IterableAsSlice(it Iterable) (ret []interface{}) {
 | 
			
		||||
	it.Iter(func(value interface{}) bool {
 | 
			
		||||
		ret = append(ret, value)
 | 
			
		||||
		return true
 | 
			
		||||
	})
 | 
			
		||||
	return
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										69
									
								
								vendor/github.com/anacrolix/missinggo/iter/iterator.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										69
									
								
								vendor/github.com/anacrolix/missinggo/iter/iterator.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,69 @@
 | 
			
		||||
package iter
 | 
			
		||||
 | 
			
		||||
import "github.com/anacrolix/missinggo/slices"
 | 
			
		||||
 | 
			
		||||
type Iterator interface {
 | 
			
		||||
	// Advances to the next value. Returns false if there are no more values.
 | 
			
		||||
	// Must be called before the first value.
 | 
			
		||||
	Next() bool
 | 
			
		||||
	// Returns the current value. Should panic when the iterator is in an
 | 
			
		||||
	// invalid state.
 | 
			
		||||
	Value() interface{}
 | 
			
		||||
	// Ceases iteration prematurely. This should occur implicitly if Next
 | 
			
		||||
	// returns false.
 | 
			
		||||
	Stop()
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func ToFunc(it Iterator) Func {
 | 
			
		||||
	return func(cb Callback) {
 | 
			
		||||
		defer it.Stop()
 | 
			
		||||
		for it.Next() {
 | 
			
		||||
			if !cb(it.Value()) {
 | 
			
		||||
				break
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type sliceIterator struct {
 | 
			
		||||
	slice []interface{}
 | 
			
		||||
	value interface{}
 | 
			
		||||
	ok    bool
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (me *sliceIterator) Next() bool {
 | 
			
		||||
	if len(me.slice) == 0 {
 | 
			
		||||
		return false
 | 
			
		||||
	}
 | 
			
		||||
	me.value = me.slice[0]
 | 
			
		||||
	me.slice = me.slice[1:]
 | 
			
		||||
	me.ok = true
 | 
			
		||||
	return true
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (me *sliceIterator) Value() interface{} {
 | 
			
		||||
	if !me.ok {
 | 
			
		||||
		panic("no value; call Next")
 | 
			
		||||
	}
 | 
			
		||||
	return me.value
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (me *sliceIterator) Stop() {}
 | 
			
		||||
 | 
			
		||||
func Slice(a []interface{}) Iterator {
 | 
			
		||||
	return &sliceIterator{
 | 
			
		||||
		slice: a,
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func StringIterator(a string) Iterator {
 | 
			
		||||
	return Slice(slices.ToEmptyInterface(a))
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func ToSlice(f Func) (ret []interface{}) {
 | 
			
		||||
	f(func(v interface{}) bool {
 | 
			
		||||
		ret = append(ret, v)
 | 
			
		||||
		return true
 | 
			
		||||
	})
 | 
			
		||||
	return
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										42
									
								
								vendor/github.com/anacrolix/missinggo/iter/iterutils.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										42
									
								
								vendor/github.com/anacrolix/missinggo/iter/iterutils.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,42 @@
 | 
			
		||||
package iter
 | 
			
		||||
 | 
			
		||||
import "math/rand"
 | 
			
		||||
 | 
			
		||||
type seq struct {
 | 
			
		||||
	i []int
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Creates sequence of values from [0, n)
 | 
			
		||||
func newSeq(n int) seq {
 | 
			
		||||
	return seq{make([]int, n, n)}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (me seq) Index(i int) (ret int) {
 | 
			
		||||
	ret = me.i[i]
 | 
			
		||||
	if ret == 0 {
 | 
			
		||||
		ret = i
 | 
			
		||||
	}
 | 
			
		||||
	return
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (me seq) Len() int {
 | 
			
		||||
	return len(me.i)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Remove the nth value from the sequence.
 | 
			
		||||
func (me *seq) DeleteIndex(index int) {
 | 
			
		||||
	me.i[index] = me.Index(me.Len() - 1)
 | 
			
		||||
	me.i = me.i[:me.Len()-1]
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func ForPerm(n int, callback func(i int) (more bool)) bool {
 | 
			
		||||
	s := newSeq(n)
 | 
			
		||||
	for s.Len() > 0 {
 | 
			
		||||
		r := rand.Intn(s.Len())
 | 
			
		||||
		if !callback(s.Index(r)) {
 | 
			
		||||
			return false
 | 
			
		||||
		}
 | 
			
		||||
		s.DeleteIndex(r)
 | 
			
		||||
	}
 | 
			
		||||
	return true
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										7
									
								
								vendor/github.com/anacrolix/missinggo/iter/n.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										7
									
								
								vendor/github.com/anacrolix/missinggo/iter/n.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,7 @@
 | 
			
		||||
package iter
 | 
			
		||||
 | 
			
		||||
import "github.com/bradfitz/iter"
 | 
			
		||||
 | 
			
		||||
func N(n int) []struct{} {
 | 
			
		||||
	return iter.N(n)
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										17
									
								
								vendor/github.com/anacrolix/missinggo/jitter.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										17
									
								
								vendor/github.com/anacrolix/missinggo/jitter.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,17 @@
 | 
			
		||||
package missinggo
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"math/rand"
 | 
			
		||||
	"time"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// Returns random duration in the range [average-plusMinus,
 | 
			
		||||
// average+plusMinus]. Negative plusMinus will likely panic. Be aware that if
 | 
			
		||||
// plusMinus >= average, you may get a zero or negative Duration. The
 | 
			
		||||
// distribution function is unspecified, in case I find a more appropriate one
 | 
			
		||||
// in the future.
 | 
			
		||||
func JitterDuration(average, plusMinus time.Duration) (ret time.Duration) {
 | 
			
		||||
	ret = average - plusMinus
 | 
			
		||||
	ret += time.Duration(rand.Int63n(2*int64(plusMinus) + 1))
 | 
			
		||||
	return
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										7
									
								
								vendor/github.com/anacrolix/missinggo/limitlen.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										7
									
								
								vendor/github.com/anacrolix/missinggo/limitlen.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,7 @@
 | 
			
		||||
package missinggo
 | 
			
		||||
 | 
			
		||||
// Sets an upper bound on the len of b. max can be any type that will cast to
 | 
			
		||||
// int64.
 | 
			
		||||
func LimitLen(b []byte, max ...interface{}) []byte {
 | 
			
		||||
	return b[:MinInt(len(b), max...)]
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										18
									
								
								vendor/github.com/anacrolix/missinggo/mime/mime.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										18
									
								
								vendor/github.com/anacrolix/missinggo/mime/mime.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,18 @@
 | 
			
		||||
package mime
 | 
			
		||||
 | 
			
		||||
import "strings"
 | 
			
		||||
 | 
			
		||||
type Type struct {
 | 
			
		||||
	Class    string
 | 
			
		||||
	Specific string
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (t Type) String() string {
 | 
			
		||||
	return t.Class + "/" + t.Specific
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (t *Type) FromString(s string) {
 | 
			
		||||
	ss := strings.SplitN(s, "/", 1)
 | 
			
		||||
	t.Class = ss[0]
 | 
			
		||||
	t.Specific = ss[1]
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										34
									
								
								vendor/github.com/anacrolix/missinggo/minmax.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										34
									
								
								vendor/github.com/anacrolix/missinggo/minmax.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,34 @@
 | 
			
		||||
package missinggo
 | 
			
		||||
 | 
			
		||||
import "reflect"
 | 
			
		||||
 | 
			
		||||
func Max(_less interface{}, vals ...interface{}) interface{} {
 | 
			
		||||
	ret := reflect.ValueOf(vals[0])
 | 
			
		||||
	retType := ret.Type()
 | 
			
		||||
	less := reflect.ValueOf(_less)
 | 
			
		||||
	for _, _v := range vals[1:] {
 | 
			
		||||
		v := reflect.ValueOf(_v).Convert(retType)
 | 
			
		||||
		out := less.Call([]reflect.Value{ret, v})
 | 
			
		||||
		if out[0].Bool() {
 | 
			
		||||
			ret = v
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	return ret.Interface()
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func MaxInt(first int64, rest ...interface{}) int64 {
 | 
			
		||||
	return Max(func(l, r interface{}) bool {
 | 
			
		||||
		return l.(int64) < r.(int64)
 | 
			
		||||
	}, append([]interface{}{first}, rest...)...).(int64)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func MinInt(first interface{}, rest ...interface{}) int64 {
 | 
			
		||||
	ret := reflect.ValueOf(first).Int()
 | 
			
		||||
	for _, _i := range rest {
 | 
			
		||||
		i := reflect.ValueOf(_i).Int()
 | 
			
		||||
		if i < ret {
 | 
			
		||||
			ret = i
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	return ret
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										44
									
								
								vendor/github.com/anacrolix/missinggo/monotonic.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										44
									
								
								vendor/github.com/anacrolix/missinggo/monotonic.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,44 @@
 | 
			
		||||
package missinggo
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"sync"
 | 
			
		||||
	"time"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// Monotonic time represents time since an arbitrary point in the past, where
 | 
			
		||||
// the concept of now is only ever moving in a positive direction.
 | 
			
		||||
type MonotonicTime struct {
 | 
			
		||||
	skewedStdTime time.Time
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (me MonotonicTime) Sub(other MonotonicTime) time.Duration {
 | 
			
		||||
	return me.skewedStdTime.Sub(other.skewedStdTime)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
var (
 | 
			
		||||
	stdNowFunc    = time.Now
 | 
			
		||||
	monotonicMu   sync.Mutex
 | 
			
		||||
	lastStdNow    time.Time
 | 
			
		||||
	monotonicSkew time.Duration
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
func skewedStdNow() time.Time {
 | 
			
		||||
	monotonicMu.Lock()
 | 
			
		||||
	defer monotonicMu.Unlock()
 | 
			
		||||
	stdNow := stdNowFunc()
 | 
			
		||||
	if !lastStdNow.IsZero() && stdNow.Before(lastStdNow) {
 | 
			
		||||
		monotonicSkew += lastStdNow.Sub(stdNow)
 | 
			
		||||
	}
 | 
			
		||||
	lastStdNow = stdNow
 | 
			
		||||
	return stdNow.Add(monotonicSkew)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Consecutive calls always produce the same or greater time than previous
 | 
			
		||||
// calls.
 | 
			
		||||
func MonotonicNow() MonotonicTime {
 | 
			
		||||
	return MonotonicTime{skewedStdNow()}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func MonotonicSince(since MonotonicTime) (ret time.Duration) {
 | 
			
		||||
	return skewedStdNow().Sub(since.skewedStdTime)
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										7
									
								
								vendor/github.com/anacrolix/missinggo/net.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										7
									
								
								vendor/github.com/anacrolix/missinggo/net.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,7 @@
 | 
			
		||||
package missinggo
 | 
			
		||||
 | 
			
		||||
import "strings"
 | 
			
		||||
 | 
			
		||||
func IsAddrInUse(err error) bool {
 | 
			
		||||
	return strings.Contains(err.Error(), "address already in use")
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										7
									
								
								vendor/github.com/anacrolix/missinggo/openflags.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										7
									
								
								vendor/github.com/anacrolix/missinggo/openflags.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,7 @@
 | 
			
		||||
package missinggo
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"os"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
const O_ACCMODE = os.O_RDONLY | os.O_WRONLY | os.O_RDWR
 | 
			
		||||
							
								
								
									
										100
									
								
								vendor/github.com/anacrolix/missinggo/orderedmap/google_btree.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										100
									
								
								vendor/github.com/anacrolix/missinggo/orderedmap/google_btree.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,100 @@
 | 
			
		||||
package orderedmap
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"github.com/google/btree"
 | 
			
		||||
 | 
			
		||||
	"github.com/anacrolix/missinggo/iter"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
type GoogleBTree struct {
 | 
			
		||||
	bt     *btree.BTree
 | 
			
		||||
	lesser func(l, r interface{}) bool
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type googleBTreeItem struct {
 | 
			
		||||
	less  func(l, r interface{}) bool
 | 
			
		||||
	key   interface{}
 | 
			
		||||
	value interface{}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (me googleBTreeItem) Less(right btree.Item) bool {
 | 
			
		||||
	return me.less(me.key, right.(*googleBTreeItem).key)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func NewGoogleBTree(lesser func(l, r interface{}) bool) *GoogleBTree {
 | 
			
		||||
	return &GoogleBTree{
 | 
			
		||||
		bt:     btree.New(32),
 | 
			
		||||
		lesser: lesser,
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (me *GoogleBTree) Set(key interface{}, value interface{}) {
 | 
			
		||||
	me.bt.ReplaceOrInsert(&googleBTreeItem{me.lesser, key, value})
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (me *GoogleBTree) Get(key interface{}) interface{} {
 | 
			
		||||
	ret, _ := me.GetOk(key)
 | 
			
		||||
	return ret
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (me *GoogleBTree) GetOk(key interface{}) (interface{}, bool) {
 | 
			
		||||
	item := me.bt.Get(&googleBTreeItem{me.lesser, key, nil})
 | 
			
		||||
	if item == nil {
 | 
			
		||||
		return nil, false
 | 
			
		||||
	}
 | 
			
		||||
	return item.(*googleBTreeItem).value, true
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type googleBTreeIter struct {
 | 
			
		||||
	i  btree.Item
 | 
			
		||||
	bt *btree.BTree
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (me *googleBTreeIter) Next() bool {
 | 
			
		||||
	if me.bt == nil {
 | 
			
		||||
		return false
 | 
			
		||||
	}
 | 
			
		||||
	if me.i == nil {
 | 
			
		||||
		me.bt.Ascend(func(i btree.Item) bool {
 | 
			
		||||
			me.i = i
 | 
			
		||||
			return false
 | 
			
		||||
		})
 | 
			
		||||
	} else {
 | 
			
		||||
		var n int
 | 
			
		||||
		me.bt.AscendGreaterOrEqual(me.i, func(i btree.Item) bool {
 | 
			
		||||
			n++
 | 
			
		||||
			if n == 1 {
 | 
			
		||||
				return true
 | 
			
		||||
			}
 | 
			
		||||
			me.i = i
 | 
			
		||||
			return false
 | 
			
		||||
		})
 | 
			
		||||
		if n != 2 {
 | 
			
		||||
			me.i = nil
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	return me.i != nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (me *googleBTreeIter) Value() interface{} {
 | 
			
		||||
	return me.i.(*googleBTreeItem).value
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (me *googleBTreeIter) Stop() {
 | 
			
		||||
	me.bt = nil
 | 
			
		||||
	me.i = nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (me *GoogleBTree) Iter(f iter.Callback) {
 | 
			
		||||
	me.bt.Ascend(func(i btree.Item) bool {
 | 
			
		||||
		return f(i.(*googleBTreeItem).value)
 | 
			
		||||
	})
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (me *GoogleBTree) Unset(key interface{}) {
 | 
			
		||||
	me.bt.Delete(&googleBTreeItem{me.lesser, key, nil})
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (me *GoogleBTree) Len() int {
 | 
			
		||||
	return me.bt.Len()
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										16
									
								
								vendor/github.com/anacrolix/missinggo/orderedmap/orderedmap.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										16
									
								
								vendor/github.com/anacrolix/missinggo/orderedmap/orderedmap.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,16 @@
 | 
			
		||||
package orderedmap
 | 
			
		||||
 | 
			
		||||
import "github.com/anacrolix/missinggo/iter"
 | 
			
		||||
 | 
			
		||||
func New(lesser func(l, r interface{}) bool) OrderedMap {
 | 
			
		||||
	return NewGoogleBTree(lesser)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type OrderedMap interface {
 | 
			
		||||
	Get(key interface{}) interface{}
 | 
			
		||||
	GetOk(key interface{}) (interface{}, bool)
 | 
			
		||||
	iter.Iterable
 | 
			
		||||
	Set(key, value interface{})
 | 
			
		||||
	Unset(key interface{})
 | 
			
		||||
	Len() int
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										66
									
								
								vendor/github.com/anacrolix/missinggo/orderedmap/skiplist.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										66
									
								
								vendor/github.com/anacrolix/missinggo/orderedmap/skiplist.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,66 @@
 | 
			
		||||
package orderedmap
 | 
			
		||||
 | 
			
		||||
import "github.com/ryszard/goskiplist/skiplist"
 | 
			
		||||
 | 
			
		||||
type skiplistOrderedMap struct {
 | 
			
		||||
	sl *skiplist.SkipList
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func NewSkipList(lesser func(l, r interface{}) bool) *skiplistOrderedMap {
 | 
			
		||||
	return &skiplistOrderedMap{skiplist.NewCustomMap(lesser)}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (me *skiplistOrderedMap) Set(key interface{}, value interface{}) {
 | 
			
		||||
	me.sl.Set(key, value)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (me *skiplistOrderedMap) Get(key interface{}) interface{} {
 | 
			
		||||
	if me == nil {
 | 
			
		||||
		return nil
 | 
			
		||||
	}
 | 
			
		||||
	ret, _ := me.sl.Get(key)
 | 
			
		||||
	return ret
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (me *skiplistOrderedMap) GetOk(key interface{}) (interface{}, bool) {
 | 
			
		||||
	if me == nil {
 | 
			
		||||
		return nil, false
 | 
			
		||||
	}
 | 
			
		||||
	return me.sl.Get(key)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type Iter struct {
 | 
			
		||||
	it skiplist.Iterator
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (me *Iter) Next() bool {
 | 
			
		||||
	if me == nil {
 | 
			
		||||
		return false
 | 
			
		||||
	}
 | 
			
		||||
	return me.it.Next()
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (me *Iter) Value() interface{} {
 | 
			
		||||
	return me.it.Value()
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (me *skiplistOrderedMap) Iter() *Iter {
 | 
			
		||||
	if me == nil {
 | 
			
		||||
		return nil
 | 
			
		||||
	}
 | 
			
		||||
	return &Iter{me.sl.Iterator()}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (me *skiplistOrderedMap) Unset(key interface{}) {
 | 
			
		||||
	if me == nil {
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
	me.sl.Delete(key)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (me *skiplistOrderedMap) Len() int {
 | 
			
		||||
	if me.sl == nil {
 | 
			
		||||
		return 0
 | 
			
		||||
	}
 | 
			
		||||
	return me.sl.Len()
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										20
									
								
								vendor/github.com/anacrolix/missinggo/path.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										20
									
								
								vendor/github.com/anacrolix/missinggo/path.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,20 @@
 | 
			
		||||
package missinggo
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"os"
 | 
			
		||||
	"path"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// Splits the pathname p into Root and Ext, such that Root+Ext==p.
 | 
			
		||||
func PathSplitExt(p string) (ret struct {
 | 
			
		||||
	Root, Ext string
 | 
			
		||||
}) {
 | 
			
		||||
	ret.Ext = path.Ext(p)
 | 
			
		||||
	ret.Root = p[:len(p)-len(ret.Ext)]
 | 
			
		||||
	return
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func FilePathExists(p string) bool {
 | 
			
		||||
	_, err := os.Stat(p)
 | 
			
		||||
	return err == nil
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										38
									
								
								vendor/github.com/anacrolix/missinggo/perf/event.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										38
									
								
								vendor/github.com/anacrolix/missinggo/perf/event.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,38 @@
 | 
			
		||||
package perf
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"math"
 | 
			
		||||
	"sync"
 | 
			
		||||
	"time"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
type Event struct {
 | 
			
		||||
	Mu    sync.RWMutex
 | 
			
		||||
	Count int64
 | 
			
		||||
	Total time.Duration
 | 
			
		||||
	Min   time.Duration
 | 
			
		||||
	Max   time.Duration
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (e *Event) Add(t time.Duration) {
 | 
			
		||||
	e.Mu.Lock()
 | 
			
		||||
	defer e.Mu.Unlock()
 | 
			
		||||
	if t > e.Max {
 | 
			
		||||
		e.Max = t
 | 
			
		||||
	}
 | 
			
		||||
	if t < e.Min {
 | 
			
		||||
		e.Min = t
 | 
			
		||||
	}
 | 
			
		||||
	e.Count++
 | 
			
		||||
	e.Total += t
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (e *Event) MeanTime() time.Duration {
 | 
			
		||||
	e.Mu.RLock()
 | 
			
		||||
	defer e.Mu.RUnlock()
 | 
			
		||||
	return e.Total / time.Duration(e.Count)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (e *Event) Init() {
 | 
			
		||||
	e.Min = math.MaxInt64
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										47
									
								
								vendor/github.com/anacrolix/missinggo/perf/events.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										47
									
								
								vendor/github.com/anacrolix/missinggo/perf/events.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,47 @@
 | 
			
		||||
package perf
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"fmt"
 | 
			
		||||
	"io"
 | 
			
		||||
	"net/http"
 | 
			
		||||
	"sort"
 | 
			
		||||
	"sync"
 | 
			
		||||
	"text/tabwriter"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
var (
 | 
			
		||||
	mu     sync.RWMutex
 | 
			
		||||
	events = map[string]*Event{}
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
func init() {
 | 
			
		||||
	http.HandleFunc("/debug/perf", func(w http.ResponseWriter, r *http.Request) {
 | 
			
		||||
		w.Header().Set("Content-Type", "text/plain; charset=UTF-8")
 | 
			
		||||
		WriteEventsTable(w)
 | 
			
		||||
	})
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func WriteEventsTable(w io.Writer) {
 | 
			
		||||
	tw := tabwriter.NewWriter(w, 0, 0, 2, ' ', 0)
 | 
			
		||||
	fmt.Fprint(tw, "description\ttotal\tcount\tmin\tmean\tmax\n")
 | 
			
		||||
	type t struct {
 | 
			
		||||
		d string
 | 
			
		||||
		e Event
 | 
			
		||||
	}
 | 
			
		||||
	mu.RLock()
 | 
			
		||||
	es := make([]t, 0, len(events))
 | 
			
		||||
	for d, e := range events {
 | 
			
		||||
		e.Mu.RLock()
 | 
			
		||||
		es = append(es, t{d, *e})
 | 
			
		||||
		e.Mu.RUnlock()
 | 
			
		||||
	}
 | 
			
		||||
	mu.RUnlock()
 | 
			
		||||
	sort.Slice(es, func(i, j int) bool {
 | 
			
		||||
		return es[i].e.Total > es[j].e.Total
 | 
			
		||||
	})
 | 
			
		||||
	for _, el := range es {
 | 
			
		||||
		e := el.e
 | 
			
		||||
		fmt.Fprintf(tw, "%s\t%v\t%v\t%v\t%v\t%v\n", el.d, e.Total, e.Count, e.Min, e.MeanTime(), e.Max)
 | 
			
		||||
	}
 | 
			
		||||
	tw.Flush()
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										48
									
								
								vendor/github.com/anacrolix/missinggo/perf/mutex.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										48
									
								
								vendor/github.com/anacrolix/missinggo/perf/mutex.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,48 @@
 | 
			
		||||
package perf
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"sync"
 | 
			
		||||
 | 
			
		||||
	"github.com/anacrolix/missinggo"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
type TimedLocker struct {
 | 
			
		||||
	L    sync.Locker
 | 
			
		||||
	Desc string
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (me *TimedLocker) Lock() {
 | 
			
		||||
	tr := NewTimer()
 | 
			
		||||
	me.L.Lock()
 | 
			
		||||
	tr.Mark(me.Desc)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (me *TimedLocker) Unlock() {
 | 
			
		||||
	me.L.Unlock()
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type TimedRWLocker struct {
 | 
			
		||||
	RWL       missinggo.RWLocker
 | 
			
		||||
	WriteDesc string
 | 
			
		||||
	ReadDesc  string
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (me *TimedRWLocker) Lock() {
 | 
			
		||||
	tr := NewTimer()
 | 
			
		||||
	me.RWL.Lock()
 | 
			
		||||
	tr.Mark(me.WriteDesc)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (me *TimedRWLocker) Unlock() {
 | 
			
		||||
	me.RWL.Unlock()
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (me *TimedRWLocker) RLock() {
 | 
			
		||||
	tr := NewTimer()
 | 
			
		||||
	me.RWL.RLock()
 | 
			
		||||
	tr.Mark(me.ReadDesc)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (me *TimedRWLocker) RUnlock() {
 | 
			
		||||
	me.RWL.RUnlock()
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										39
									
								
								vendor/github.com/anacrolix/missinggo/perf/scope.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										39
									
								
								vendor/github.com/anacrolix/missinggo/perf/scope.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,39 @@
 | 
			
		||||
package perf
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"runtime"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
func ScopeTimer(opts ...timerOpt) func() {
 | 
			
		||||
	t := NewTimer(CallerName(1))
 | 
			
		||||
	return func() { t.Mark("returned") }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func ScopeTimerOk(ok *bool) func() {
 | 
			
		||||
	t := NewTimer(CallerName(1))
 | 
			
		||||
	return func() { t.MarkOk(*ok) }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func ScopeTimerErr(err *error) func() {
 | 
			
		||||
	t := NewTimer(CallerName(1))
 | 
			
		||||
	return func() {
 | 
			
		||||
		r := recover()
 | 
			
		||||
		if r != nil {
 | 
			
		||||
			t.Mark("panic")
 | 
			
		||||
			panic(r)
 | 
			
		||||
		}
 | 
			
		||||
		t.MarkErr(*err)
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func CallerName(skip int) timerOpt {
 | 
			
		||||
	return Name(getCallerName(skip))
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func getCallerName(skip int) string {
 | 
			
		||||
	var pc [1]uintptr
 | 
			
		||||
	runtime.Callers(3+skip, pc[:])
 | 
			
		||||
	fs := runtime.CallersFrames(pc[:])
 | 
			
		||||
	f, _ := fs.Next()
 | 
			
		||||
	return f.Func.Name()
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										104
									
								
								vendor/github.com/anacrolix/missinggo/perf/timer.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										104
									
								
								vendor/github.com/anacrolix/missinggo/perf/timer.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,104 @@
 | 
			
		||||
package perf
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"log"
 | 
			
		||||
	"runtime"
 | 
			
		||||
	"time"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
type Timer struct {
 | 
			
		||||
	started time.Time
 | 
			
		||||
	log     bool
 | 
			
		||||
	name    string
 | 
			
		||||
	marked  bool
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func NewTimer(opts ...timerOpt) (t *Timer) {
 | 
			
		||||
	t = &Timer{
 | 
			
		||||
		started: time.Now(),
 | 
			
		||||
	}
 | 
			
		||||
	for _, o := range opts {
 | 
			
		||||
		o(t)
 | 
			
		||||
	}
 | 
			
		||||
	if t.log && t.name != "" {
 | 
			
		||||
		log.Printf("starting timer %q", t.name)
 | 
			
		||||
	}
 | 
			
		||||
	runtime.SetFinalizer(t, func(t *Timer) {
 | 
			
		||||
		if t.marked {
 | 
			
		||||
			return
 | 
			
		||||
		}
 | 
			
		||||
		log.Printf("timer %#v was never marked", t)
 | 
			
		||||
	})
 | 
			
		||||
	return
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type timerOpt func(*Timer)
 | 
			
		||||
 | 
			
		||||
func Log(t *Timer) {
 | 
			
		||||
	t.log = true
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func Name(name string) func(*Timer) {
 | 
			
		||||
	return func(t *Timer) {
 | 
			
		||||
		t.name = name
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (t *Timer) Mark(events ...string) time.Duration {
 | 
			
		||||
	d := time.Since(t.started)
 | 
			
		||||
	if len(events) == 0 {
 | 
			
		||||
		if t.name == "" {
 | 
			
		||||
			panic("no name or events specified")
 | 
			
		||||
		}
 | 
			
		||||
		t.addDuration(t.name, d)
 | 
			
		||||
	} else {
 | 
			
		||||
		for _, e := range events {
 | 
			
		||||
			if t.name != "" {
 | 
			
		||||
				e = t.name + "/" + e
 | 
			
		||||
			}
 | 
			
		||||
			t.addDuration(e, d)
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	return d
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (t *Timer) MarkOk(ok bool) {
 | 
			
		||||
	if ok {
 | 
			
		||||
		t.Mark("ok")
 | 
			
		||||
	} else {
 | 
			
		||||
		t.Mark("not ok")
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (t *Timer) MarkErr(err error) {
 | 
			
		||||
	if err == nil {
 | 
			
		||||
		t.Mark("success")
 | 
			
		||||
	} else {
 | 
			
		||||
		t.Mark("error")
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (t *Timer) addDuration(desc string, d time.Duration) {
 | 
			
		||||
	t.marked = true
 | 
			
		||||
	mu.RLock()
 | 
			
		||||
	e := events[desc]
 | 
			
		||||
	mu.RUnlock()
 | 
			
		||||
	if e == nil {
 | 
			
		||||
		mu.Lock()
 | 
			
		||||
		e = events[desc]
 | 
			
		||||
		if e == nil {
 | 
			
		||||
			e = new(Event)
 | 
			
		||||
			e.Init()
 | 
			
		||||
			events[desc] = e
 | 
			
		||||
		}
 | 
			
		||||
		mu.Unlock()
 | 
			
		||||
	}
 | 
			
		||||
	e.Add(d)
 | 
			
		||||
	if t.log {
 | 
			
		||||
		if t.name != "" {
 | 
			
		||||
			log.Printf("timer %q got event %q after %s", t.name, desc, d)
 | 
			
		||||
		} else {
 | 
			
		||||
			log.Printf("marking event %q after %s", desc, d)
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										97
									
								
								vendor/github.com/anacrolix/missinggo/pproffd/pproffd.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										97
									
								
								vendor/github.com/anacrolix/missinggo/pproffd/pproffd.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,97 @@
 | 
			
		||||
// Package pproffd is for detecting resource leaks due to unclosed handles.
 | 
			
		||||
package pproffd
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"io"
 | 
			
		||||
	"net"
 | 
			
		||||
	"os"
 | 
			
		||||
	"runtime/pprof"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
const enabled = false
 | 
			
		||||
 | 
			
		||||
var p *pprof.Profile
 | 
			
		||||
 | 
			
		||||
func init() {
 | 
			
		||||
	if enabled {
 | 
			
		||||
		p = pprof.NewProfile("fds")
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type fd int
 | 
			
		||||
 | 
			
		||||
func (me *fd) Closed() {
 | 
			
		||||
	p.Remove(me)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func add(skip int) (ret *fd) {
 | 
			
		||||
	ret = new(fd)
 | 
			
		||||
	p.Add(ret, skip+2)
 | 
			
		||||
	return
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type closeWrapper struct {
 | 
			
		||||
	fd *fd
 | 
			
		||||
	c  io.Closer
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (me closeWrapper) Close() error {
 | 
			
		||||
	me.fd.Closed()
 | 
			
		||||
	return me.c.Close()
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func newCloseWrapper(c io.Closer) closeWrapper {
 | 
			
		||||
	return closeWrapper{
 | 
			
		||||
		fd: add(2),
 | 
			
		||||
		c:  c,
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type wrappedNetConn struct {
 | 
			
		||||
	net.Conn
 | 
			
		||||
	closeWrapper
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (me wrappedNetConn) Close() error {
 | 
			
		||||
	return me.closeWrapper.Close()
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Tracks a net.Conn until Close() is explicitly called.
 | 
			
		||||
func WrapNetConn(nc net.Conn) net.Conn {
 | 
			
		||||
	if !enabled {
 | 
			
		||||
		return nc
 | 
			
		||||
	}
 | 
			
		||||
	if nc == nil {
 | 
			
		||||
		return nil
 | 
			
		||||
	}
 | 
			
		||||
	return wrappedNetConn{
 | 
			
		||||
		nc,
 | 
			
		||||
		newCloseWrapper(nc),
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type OSFile interface {
 | 
			
		||||
	io.Reader
 | 
			
		||||
	io.Seeker
 | 
			
		||||
	io.Closer
 | 
			
		||||
	io.Writer
 | 
			
		||||
	Stat() (os.FileInfo, error)
 | 
			
		||||
	io.ReaderAt
 | 
			
		||||
	io.WriterAt
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type wrappedOSFile struct {
 | 
			
		||||
	*os.File
 | 
			
		||||
	closeWrapper
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (me wrappedOSFile) Close() error {
 | 
			
		||||
	return me.closeWrapper.Close()
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func WrapOSFile(f *os.File) OSFile {
 | 
			
		||||
	if !enabled {
 | 
			
		||||
		return f
 | 
			
		||||
	}
 | 
			
		||||
	return &wrappedOSFile{f, newCloseWrapper(f)}
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										178
									
								
								vendor/github.com/anacrolix/missinggo/prioritybitmap/prioritybitmap.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										178
									
								
								vendor/github.com/anacrolix/missinggo/prioritybitmap/prioritybitmap.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,178 @@
 | 
			
		||||
// Package prioritybitmap implements a set of integers ordered by attached
 | 
			
		||||
// priorities.
 | 
			
		||||
package prioritybitmap
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"sync"
 | 
			
		||||
 | 
			
		||||
	"github.com/anacrolix/missinggo/bitmap"
 | 
			
		||||
	"github.com/anacrolix/missinggo/iter"
 | 
			
		||||
	"github.com/anacrolix/missinggo/orderedmap"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
var (
 | 
			
		||||
	bitSets = sync.Pool{
 | 
			
		||||
		New: func() interface{} {
 | 
			
		||||
			return make(map[int]struct{}, 1)
 | 
			
		||||
		},
 | 
			
		||||
	}
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// Maintains set of ints ordered by priority.
 | 
			
		||||
type PriorityBitmap struct {
 | 
			
		||||
	mu sync.Mutex
 | 
			
		||||
	// From priority to singleton or set of bit indices.
 | 
			
		||||
	om orderedmap.OrderedMap
 | 
			
		||||
	// From bit index to priority
 | 
			
		||||
	priorities map[int]int
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
var _ bitmap.Interface = (*PriorityBitmap)(nil)
 | 
			
		||||
 | 
			
		||||
func (me *PriorityBitmap) Contains(bit int) bool {
 | 
			
		||||
	_, ok := me.priorities[bit]
 | 
			
		||||
	return ok
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (me *PriorityBitmap) Len() int {
 | 
			
		||||
	return len(me.priorities)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (me *PriorityBitmap) Clear() {
 | 
			
		||||
	me.om = nil
 | 
			
		||||
	me.priorities = nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (me *PriorityBitmap) deleteBit(bit int) (priority int, ok bool) {
 | 
			
		||||
	priority, ok = me.priorities[bit]
 | 
			
		||||
	if !ok {
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
	switch v := me.om.Get(priority).(type) {
 | 
			
		||||
	case int:
 | 
			
		||||
		if v != bit {
 | 
			
		||||
			panic("invariant broken")
 | 
			
		||||
		}
 | 
			
		||||
	case map[int]struct{}:
 | 
			
		||||
		if _, ok := v[bit]; !ok {
 | 
			
		||||
			panic("invariant broken")
 | 
			
		||||
		}
 | 
			
		||||
		delete(v, bit)
 | 
			
		||||
		if len(v) != 0 {
 | 
			
		||||
			return
 | 
			
		||||
		}
 | 
			
		||||
		bitSets.Put(v)
 | 
			
		||||
	}
 | 
			
		||||
	me.om.Unset(priority)
 | 
			
		||||
	if me.om.Len() == 0 {
 | 
			
		||||
		me.om = nil
 | 
			
		||||
	}
 | 
			
		||||
	return
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func bitLess(l, r interface{}) bool {
 | 
			
		||||
	return l.(int) < r.(int)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (me *PriorityBitmap) lazyInit() {
 | 
			
		||||
	me.om = orderedmap.New(func(l, r interface{}) bool {
 | 
			
		||||
		return l.(int) < r.(int)
 | 
			
		||||
	})
 | 
			
		||||
	me.priorities = make(map[int]int)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Returns true if the priority is changed, or the bit wasn't present.
 | 
			
		||||
func (me *PriorityBitmap) Set(bit int, priority int) bool {
 | 
			
		||||
	if p, ok := me.priorities[bit]; ok && p == priority {
 | 
			
		||||
		return false
 | 
			
		||||
	}
 | 
			
		||||
	if oldPriority, deleted := me.deleteBit(bit); deleted && oldPriority == priority {
 | 
			
		||||
		panic("should have already returned")
 | 
			
		||||
	}
 | 
			
		||||
	if me.priorities == nil {
 | 
			
		||||
		me.priorities = make(map[int]int)
 | 
			
		||||
	}
 | 
			
		||||
	me.priorities[bit] = priority
 | 
			
		||||
	if me.om == nil {
 | 
			
		||||
		me.om = orderedmap.New(bitLess)
 | 
			
		||||
	}
 | 
			
		||||
	_v, ok := me.om.GetOk(priority)
 | 
			
		||||
	if !ok {
 | 
			
		||||
		// No other bits with this priority, set it to a lone int.
 | 
			
		||||
		me.om.Set(priority, bit)
 | 
			
		||||
		return true
 | 
			
		||||
	}
 | 
			
		||||
	switch v := _v.(type) {
 | 
			
		||||
	case int:
 | 
			
		||||
		newV := bitSets.Get().(map[int]struct{})
 | 
			
		||||
		newV[v] = struct{}{}
 | 
			
		||||
		newV[bit] = struct{}{}
 | 
			
		||||
		me.om.Set(priority, newV)
 | 
			
		||||
	case map[int]struct{}:
 | 
			
		||||
		v[bit] = struct{}{}
 | 
			
		||||
	default:
 | 
			
		||||
		panic(v)
 | 
			
		||||
	}
 | 
			
		||||
	return true
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (me *PriorityBitmap) Remove(bit int) bool {
 | 
			
		||||
	me.mu.Lock()
 | 
			
		||||
	defer me.mu.Unlock()
 | 
			
		||||
	if _, ok := me.deleteBit(bit); !ok {
 | 
			
		||||
		return false
 | 
			
		||||
	}
 | 
			
		||||
	delete(me.priorities, bit)
 | 
			
		||||
	if len(me.priorities) == 0 {
 | 
			
		||||
		me.priorities = nil
 | 
			
		||||
	}
 | 
			
		||||
	if me.om != nil && me.om.Len() == 0 {
 | 
			
		||||
		me.om = nil
 | 
			
		||||
	}
 | 
			
		||||
	return true
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (me *PriorityBitmap) Iter(f iter.Callback) {
 | 
			
		||||
	me.IterTyped(func(i int) bool {
 | 
			
		||||
		return f(i)
 | 
			
		||||
	})
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (me *PriorityBitmap) IterTyped(_f func(i bitmap.BitIndex) bool) bool {
 | 
			
		||||
	me.mu.Lock()
 | 
			
		||||
	defer me.mu.Unlock()
 | 
			
		||||
	if me == nil || me.om == nil {
 | 
			
		||||
		return true
 | 
			
		||||
	}
 | 
			
		||||
	f := func(i int) bool {
 | 
			
		||||
		me.mu.Unlock()
 | 
			
		||||
		defer me.mu.Lock()
 | 
			
		||||
		return _f(i)
 | 
			
		||||
	}
 | 
			
		||||
	return iter.All(func(value interface{}) bool {
 | 
			
		||||
		switch v := value.(type) {
 | 
			
		||||
		case int:
 | 
			
		||||
			return f(v)
 | 
			
		||||
		case map[int]struct{}:
 | 
			
		||||
			for i := range v {
 | 
			
		||||
				if !f(i) {
 | 
			
		||||
					return false
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
		return true
 | 
			
		||||
	}, me.om.Iter)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (me *PriorityBitmap) IsEmpty() bool {
 | 
			
		||||
	if me.om == nil {
 | 
			
		||||
		return true
 | 
			
		||||
	}
 | 
			
		||||
	return me.om.Len() == 0
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ok is false if the bit is not set.
 | 
			
		||||
func (me *PriorityBitmap) GetPriority(bit int) (prio int, ok bool) {
 | 
			
		||||
	prio, ok = me.priorities[bit]
 | 
			
		||||
	return
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										117
									
								
								vendor/github.com/anacrolix/missinggo/pubsub/pubsub.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										117
									
								
								vendor/github.com/anacrolix/missinggo/pubsub/pubsub.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,117 @@
 | 
			
		||||
package pubsub
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"sync"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
type PubSub struct {
 | 
			
		||||
	mu     sync.Mutex
 | 
			
		||||
	next   chan item
 | 
			
		||||
	closed bool
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type item struct {
 | 
			
		||||
	value interface{}
 | 
			
		||||
	next  chan item
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type Subscription struct {
 | 
			
		||||
	next   chan item
 | 
			
		||||
	Values chan interface{}
 | 
			
		||||
	mu     sync.Mutex
 | 
			
		||||
	closed chan struct{}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func NewPubSub() (ret *PubSub) {
 | 
			
		||||
	return new(PubSub)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (me *PubSub) init() {
 | 
			
		||||
	me.next = make(chan item, 1)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (me *PubSub) lazyInit() {
 | 
			
		||||
	me.mu.Lock()
 | 
			
		||||
	defer me.mu.Unlock()
 | 
			
		||||
	if me.closed {
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
	if me.next == nil {
 | 
			
		||||
		me.init()
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (me *PubSub) Publish(v interface{}) {
 | 
			
		||||
	me.lazyInit()
 | 
			
		||||
	next := make(chan item, 1)
 | 
			
		||||
	i := item{v, next}
 | 
			
		||||
	me.mu.Lock()
 | 
			
		||||
	if !me.closed {
 | 
			
		||||
		me.next <- i
 | 
			
		||||
		me.next = next
 | 
			
		||||
	}
 | 
			
		||||
	me.mu.Unlock()
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (me *Subscription) Close() {
 | 
			
		||||
	me.mu.Lock()
 | 
			
		||||
	defer me.mu.Unlock()
 | 
			
		||||
	select {
 | 
			
		||||
	case <-me.closed:
 | 
			
		||||
	default:
 | 
			
		||||
		close(me.closed)
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (me *Subscription) runner() {
 | 
			
		||||
	defer close(me.Values)
 | 
			
		||||
	for {
 | 
			
		||||
		select {
 | 
			
		||||
		case i, ok := <-me.next:
 | 
			
		||||
			if !ok {
 | 
			
		||||
				me.Close()
 | 
			
		||||
				return
 | 
			
		||||
			}
 | 
			
		||||
			// Send the value back into the channel for someone else. This
 | 
			
		||||
			// won't block because the channel has a capacity of 1, and this
 | 
			
		||||
			// is currently the only copy of this value being sent to this
 | 
			
		||||
			// channel.
 | 
			
		||||
			me.next <- i
 | 
			
		||||
			// The next value comes from the channel given to us by the value
 | 
			
		||||
			// we just got.
 | 
			
		||||
			me.next = i.next
 | 
			
		||||
			select {
 | 
			
		||||
			case me.Values <- i.value:
 | 
			
		||||
			case <-me.closed:
 | 
			
		||||
				return
 | 
			
		||||
			}
 | 
			
		||||
		case <-me.closed:
 | 
			
		||||
			return
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (me *PubSub) Subscribe() (ret *Subscription) {
 | 
			
		||||
	me.lazyInit()
 | 
			
		||||
	ret = &Subscription{
 | 
			
		||||
		closed: make(chan struct{}),
 | 
			
		||||
		Values: make(chan interface{}),
 | 
			
		||||
	}
 | 
			
		||||
	me.mu.Lock()
 | 
			
		||||
	ret.next = me.next
 | 
			
		||||
	me.mu.Unlock()
 | 
			
		||||
	go ret.runner()
 | 
			
		||||
	return
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (me *PubSub) Close() {
 | 
			
		||||
	me.mu.Lock()
 | 
			
		||||
	defer me.mu.Unlock()
 | 
			
		||||
	if me.closed {
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
	if me.next != nil {
 | 
			
		||||
		close(me.next)
 | 
			
		||||
	}
 | 
			
		||||
	me.closed = true
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										16
									
								
								vendor/github.com/anacrolix/missinggo/reader_context.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										16
									
								
								vendor/github.com/anacrolix/missinggo/reader_context.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,16 @@
 | 
			
		||||
package missinggo
 | 
			
		||||
 | 
			
		||||
import "context"
 | 
			
		||||
 | 
			
		||||
type ContextedReader struct {
 | 
			
		||||
	R   ReadContexter
 | 
			
		||||
	Ctx context.Context
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (me ContextedReader) Read(b []byte) (int, error) {
 | 
			
		||||
	return me.R.ReadContext(me.Ctx, b)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type ReadContexter interface {
 | 
			
		||||
	ReadContext(context.Context, []byte) (int, error)
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										196
									
								
								vendor/github.com/anacrolix/missinggo/resource/http.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										196
									
								
								vendor/github.com/anacrolix/missinggo/resource/http.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,196 @@
 | 
			
		||||
package resource
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"bytes"
 | 
			
		||||
	"errors"
 | 
			
		||||
	"fmt"
 | 
			
		||||
	"io"
 | 
			
		||||
	"net/http"
 | 
			
		||||
	"net/url"
 | 
			
		||||
	"os"
 | 
			
		||||
	"strconv"
 | 
			
		||||
	"time"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// Provides access to resources through a http.Client.
 | 
			
		||||
type HTTPProvider struct {
 | 
			
		||||
	Client *http.Client
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
var _ Provider = &HTTPProvider{}
 | 
			
		||||
 | 
			
		||||
func (me *HTTPProvider) NewInstance(urlStr string) (r Instance, err error) {
 | 
			
		||||
	_r := new(httpInstance)
 | 
			
		||||
	_r.URL, err = url.Parse(urlStr)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
	_r.Client = me.Client
 | 
			
		||||
	if _r.Client == nil {
 | 
			
		||||
		_r.Client = http.DefaultClient
 | 
			
		||||
	}
 | 
			
		||||
	r = _r
 | 
			
		||||
	return
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type httpInstance struct {
 | 
			
		||||
	Client *http.Client
 | 
			
		||||
	URL    *url.URL
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
var _ Instance = &httpInstance{}
 | 
			
		||||
 | 
			
		||||
func mustNewRequest(method, urlStr string, body io.Reader) *http.Request {
 | 
			
		||||
	req, err := http.NewRequest(method, urlStr, body)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		panic(err)
 | 
			
		||||
	}
 | 
			
		||||
	return req
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func responseError(r *http.Response) error {
 | 
			
		||||
	if r.StatusCode == http.StatusNotFound {
 | 
			
		||||
		return os.ErrNotExist
 | 
			
		||||
	}
 | 
			
		||||
	return errors.New(r.Status)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (me *httpInstance) Get() (ret io.ReadCloser, err error) {
 | 
			
		||||
	resp, err := me.Client.Get(me.URL.String())
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
	if resp.StatusCode == http.StatusOK {
 | 
			
		||||
		ret = resp.Body
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
	resp.Body.Close()
 | 
			
		||||
	err = responseError(resp)
 | 
			
		||||
	return
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (me *httpInstance) Put(r io.Reader) (err error) {
 | 
			
		||||
	resp, err := me.Client.Do(mustNewRequest("PUT", me.URL.String(), r))
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
	resp.Body.Close()
 | 
			
		||||
	if resp.StatusCode == http.StatusOK {
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
	err = responseError(resp)
 | 
			
		||||
	return
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (me *httpInstance) ReadAt(b []byte, off int64) (n int, err error) {
 | 
			
		||||
	req := mustNewRequest("GET", me.URL.String(), nil)
 | 
			
		||||
	req.Header.Set("Range", fmt.Sprintf("bytes=%d-%d", off, off+int64(len(b))-1))
 | 
			
		||||
	resp, err := me.Client.Do(req)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
	defer resp.Body.Close()
 | 
			
		||||
	switch resp.StatusCode {
 | 
			
		||||
	case http.StatusPartialContent:
 | 
			
		||||
	case http.StatusRequestedRangeNotSatisfiable:
 | 
			
		||||
		err = io.EOF
 | 
			
		||||
		return
 | 
			
		||||
	default:
 | 
			
		||||
		err = responseError(resp)
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
	// TODO: This will crash if ContentLength was not provided (-1). Do
 | 
			
		||||
	// something about that.
 | 
			
		||||
	b = b[:resp.ContentLength]
 | 
			
		||||
	return io.ReadFull(resp.Body, b)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (me *httpInstance) WriteAt(b []byte, off int64) (n int, err error) {
 | 
			
		||||
	req := mustNewRequest("PATCH", me.URL.String(), bytes.NewReader(b))
 | 
			
		||||
	req.ContentLength = int64(len(b))
 | 
			
		||||
	req.Header.Set("Content-Range", fmt.Sprintf("bytes=%d-%d", off, off+int64(len(b))-1))
 | 
			
		||||
	resp, err := me.Client.Do(req)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
	resp.Body.Close()
 | 
			
		||||
	if resp.StatusCode != http.StatusOK {
 | 
			
		||||
		err = responseError(resp)
 | 
			
		||||
	}
 | 
			
		||||
	n = len(b)
 | 
			
		||||
	return
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (me *httpInstance) Stat() (fi os.FileInfo, err error) {
 | 
			
		||||
	resp, err := me.Client.Head(me.URL.String())
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
	resp.Body.Close()
 | 
			
		||||
	if resp.StatusCode == http.StatusNotFound {
 | 
			
		||||
		err = os.ErrNotExist
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
	if resp.StatusCode != http.StatusOK {
 | 
			
		||||
		err = errors.New(resp.Status)
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
	var _fi httpFileInfo
 | 
			
		||||
	if h := resp.Header.Get("Last-Modified"); h != "" {
 | 
			
		||||
		_fi.lastModified, err = time.Parse(http.TimeFormat, h)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			err = fmt.Errorf("error parsing Last-Modified header: %s", err)
 | 
			
		||||
			return
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	if h := resp.Header.Get("Content-Length"); h != "" {
 | 
			
		||||
		_fi.contentLength, err = strconv.ParseInt(h, 10, 64)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			err = fmt.Errorf("error parsing Content-Length header: %s", err)
 | 
			
		||||
			return
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	fi = _fi
 | 
			
		||||
	return
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (me *httpInstance) Delete() (err error) {
 | 
			
		||||
	resp, err := me.Client.Do(mustNewRequest("DELETE", me.URL.String(), nil))
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
	err = responseError(resp)
 | 
			
		||||
	resp.Body.Close()
 | 
			
		||||
	return
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type httpFileInfo struct {
 | 
			
		||||
	lastModified  time.Time
 | 
			
		||||
	contentLength int64
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
var _ os.FileInfo = httpFileInfo{}
 | 
			
		||||
 | 
			
		||||
func (fi httpFileInfo) IsDir() bool {
 | 
			
		||||
	return false
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (fi httpFileInfo) Mode() os.FileMode {
 | 
			
		||||
	return 0
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (fi httpFileInfo) Name() string {
 | 
			
		||||
	return ""
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (fi httpFileInfo) Size() int64 {
 | 
			
		||||
	return fi.contentLength
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (fi httpFileInfo) ModTime() time.Time {
 | 
			
		||||
	return fi.lastModified
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (fi httpFileInfo) Sys() interface{} {
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										61
									
								
								vendor/github.com/anacrolix/missinggo/resource/osfile.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										61
									
								
								vendor/github.com/anacrolix/missinggo/resource/osfile.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,61 @@
 | 
			
		||||
package resource
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"io"
 | 
			
		||||
	"os"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// Provides access to resources through the native OS filesystem.
 | 
			
		||||
type OSFileProvider struct{}
 | 
			
		||||
 | 
			
		||||
var _ Provider = OSFileProvider{}
 | 
			
		||||
 | 
			
		||||
func (me OSFileProvider) NewInstance(filePath string) (r Instance, err error) {
 | 
			
		||||
	return &osFileInstance{filePath}, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type osFileInstance struct {
 | 
			
		||||
	path string
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
var _ Instance = &osFileInstance{}
 | 
			
		||||
 | 
			
		||||
func (me *osFileInstance) Get() (ret io.ReadCloser, err error) {
 | 
			
		||||
	return os.Open(me.path)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (me *osFileInstance) Put(r io.Reader) (err error) {
 | 
			
		||||
	f, err := os.OpenFile(me.path, os.O_CREATE|os.O_TRUNC|os.O_WRONLY, 0640)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
	defer f.Close()
 | 
			
		||||
	_, err = io.Copy(f, r)
 | 
			
		||||
	return
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (me *osFileInstance) ReadAt(b []byte, off int64) (n int, err error) {
 | 
			
		||||
	f, err := os.Open(me.path)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
	defer f.Close()
 | 
			
		||||
	return f.ReadAt(b, off)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (me *osFileInstance) WriteAt(b []byte, off int64) (n int, err error) {
 | 
			
		||||
	f, err := os.OpenFile(me.path, os.O_CREATE|os.O_WRONLY, 0640)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
	defer f.Close()
 | 
			
		||||
	return f.WriteAt(b, off)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (me *osFileInstance) Stat() (fi os.FileInfo, err error) {
 | 
			
		||||
	return os.Stat(me.path)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (me *osFileInstance) Delete() error {
 | 
			
		||||
	return os.Remove(me.path)
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										21
									
								
								vendor/github.com/anacrolix/missinggo/resource/provider.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										21
									
								
								vendor/github.com/anacrolix/missinggo/resource/provider.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,21 @@
 | 
			
		||||
package resource
 | 
			
		||||
 | 
			
		||||
type Provider interface {
 | 
			
		||||
	NewInstance(string) (Instance, error)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// TranslatedProvider manipulates resource locations, so as to allow
 | 
			
		||||
// sandboxing, or relative paths for example.
 | 
			
		||||
type TranslatedProvider struct {
 | 
			
		||||
	// The underlying Provider.
 | 
			
		||||
	BaseProvider Provider
 | 
			
		||||
	// Some location used in calculating final locations.
 | 
			
		||||
	BaseLocation string
 | 
			
		||||
	// Function that takes BaseLocation, and the caller location and returns
 | 
			
		||||
	// the location to be used with the BaseProvider.
 | 
			
		||||
	JoinLocations func(base, rel string) string
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (me *TranslatedProvider) NewInstance(rel string) (Instance, error) {
 | 
			
		||||
	return me.BaseProvider.NewInstance(me.JoinLocations(me.BaseLocation, rel))
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										46
									
								
								vendor/github.com/anacrolix/missinggo/resource/resource.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										46
									
								
								vendor/github.com/anacrolix/missinggo/resource/resource.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,46 @@
 | 
			
		||||
package resource
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"io"
 | 
			
		||||
	"os"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// An Instance represents the content at some location accessed through some
 | 
			
		||||
// Provider. It's the data at some URL.
 | 
			
		||||
type Instance interface {
 | 
			
		||||
	Get() (io.ReadCloser, error)
 | 
			
		||||
	Put(io.Reader) error
 | 
			
		||||
	Stat() (os.FileInfo, error)
 | 
			
		||||
	ReadAt([]byte, int64) (int, error)
 | 
			
		||||
	WriteAt([]byte, int64) (int, error)
 | 
			
		||||
	Delete() error
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Creates a io.ReadSeeker to an Instance.
 | 
			
		||||
func ReadSeeker(r Instance) io.ReadSeeker {
 | 
			
		||||
	fi, err := r.Stat()
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil
 | 
			
		||||
	}
 | 
			
		||||
	return io.NewSectionReader(r, 0, fi.Size())
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Move instance content, deleting the source if it succeeds.
 | 
			
		||||
func Move(from, to Instance) (err error) {
 | 
			
		||||
	rc, err := from.Get()
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
	defer rc.Close()
 | 
			
		||||
	err = to.Put(rc)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
	from.Delete()
 | 
			
		||||
	return
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func Exists(i Instance) bool {
 | 
			
		||||
	_, err := i.Stat()
 | 
			
		||||
	return err == nil
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										46
									
								
								vendor/github.com/anacrolix/missinggo/rle.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										46
									
								
								vendor/github.com/anacrolix/missinggo/rle.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,46 @@
 | 
			
		||||
package missinggo
 | 
			
		||||
 | 
			
		||||
// A RunLengthEncoder counts successive duplicate elements and emits the
 | 
			
		||||
// element and the run length when the element changes or the encoder is
 | 
			
		||||
// flushed.
 | 
			
		||||
type RunLengthEncoder interface {
 | 
			
		||||
	// Add a series of identical elements to the stream.
 | 
			
		||||
	Append(element interface{}, count uint64)
 | 
			
		||||
	// Emit the current element and its count if non-zero without waiting for
 | 
			
		||||
	// the element to change.
 | 
			
		||||
	Flush()
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type runLengthEncoder struct {
 | 
			
		||||
	eachRun func(element interface{}, count uint64)
 | 
			
		||||
	element interface{}
 | 
			
		||||
	count   uint64
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Creates a new RunLengthEncoder. eachRun is called when an element and its
 | 
			
		||||
// count is emitted, per the RunLengthEncoder interface.
 | 
			
		||||
func NewRunLengthEncoder(eachRun func(element interface{}, count uint64)) RunLengthEncoder {
 | 
			
		||||
	return &runLengthEncoder{
 | 
			
		||||
		eachRun: eachRun,
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (me *runLengthEncoder) Append(element interface{}, count uint64) {
 | 
			
		||||
	if element == me.element {
 | 
			
		||||
		me.count += count
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
	if me.count != 0 {
 | 
			
		||||
		me.eachRun(me.element, me.count)
 | 
			
		||||
	}
 | 
			
		||||
	me.count = count
 | 
			
		||||
	me.element = element
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (me *runLengthEncoder) Flush() {
 | 
			
		||||
	if me.count == 0 {
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
	me.eachRun(me.element, me.count)
 | 
			
		||||
	me.count = 0
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										75
									
								
								vendor/github.com/anacrolix/missinggo/section_read_seeker.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										75
									
								
								vendor/github.com/anacrolix/missinggo/section_read_seeker.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,75 @@
 | 
			
		||||
package missinggo
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"context"
 | 
			
		||||
	"fmt"
 | 
			
		||||
	"io"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
type sectionReadSeeker struct {
 | 
			
		||||
	base      io.ReadSeeker
 | 
			
		||||
	off, size int64
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type ReadSeekContexter interface {
 | 
			
		||||
	io.ReadSeeker
 | 
			
		||||
	ReadContexter
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Returns a ReadSeeker on a section of another ReadSeeker.
 | 
			
		||||
func NewSectionReadSeeker(base io.ReadSeeker, off, size int64) (ret ReadSeekContexter) {
 | 
			
		||||
	ret = §ionReadSeeker{
 | 
			
		||||
		base: base,
 | 
			
		||||
		off:  off,
 | 
			
		||||
		size: size,
 | 
			
		||||
	}
 | 
			
		||||
	seekOff, err := ret.Seek(0, io.SeekStart)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		panic(err)
 | 
			
		||||
	}
 | 
			
		||||
	if seekOff != 0 {
 | 
			
		||||
		panic(seekOff)
 | 
			
		||||
	}
 | 
			
		||||
	return
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (me *sectionReadSeeker) Seek(off int64, whence int) (ret int64, err error) {
 | 
			
		||||
	switch whence {
 | 
			
		||||
	case io.SeekStart:
 | 
			
		||||
		off += me.off
 | 
			
		||||
	case io.SeekCurrent:
 | 
			
		||||
	case io.SeekEnd:
 | 
			
		||||
		off += me.off + me.size
 | 
			
		||||
		whence = io.SeekStart
 | 
			
		||||
	default:
 | 
			
		||||
		err = fmt.Errorf("unhandled whence: %d", whence)
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
	ret, err = me.base.Seek(off, whence)
 | 
			
		||||
	ret -= me.off
 | 
			
		||||
	return
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (me *sectionReadSeeker) ReadContext(ctx context.Context, b []byte) (int, error) {
 | 
			
		||||
	off, err := me.Seek(0, io.SeekCurrent)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return 0, err
 | 
			
		||||
	}
 | 
			
		||||
	left := me.size - off
 | 
			
		||||
	if left <= 0 {
 | 
			
		||||
		return 0, io.EOF
 | 
			
		||||
	}
 | 
			
		||||
	b = LimitLen(b, left)
 | 
			
		||||
	if rc, ok := me.base.(ReadContexter); ok {
 | 
			
		||||
		return rc.ReadContext(ctx, b)
 | 
			
		||||
	}
 | 
			
		||||
	if ctx != context.Background() {
 | 
			
		||||
		// Can't handle cancellation.
 | 
			
		||||
		panic(ctx)
 | 
			
		||||
	}
 | 
			
		||||
	return me.base.Read(b)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (me *sectionReadSeeker) Read(b []byte) (int, error) {
 | 
			
		||||
	return me.ReadContext(context.Background(), b)
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										23
									
								
								vendor/github.com/anacrolix/missinggo/section_writer.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										23
									
								
								vendor/github.com/anacrolix/missinggo/section_writer.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,23 @@
 | 
			
		||||
package missinggo
 | 
			
		||||
 | 
			
		||||
import "io"
 | 
			
		||||
 | 
			
		||||
type SectionWriter struct {
 | 
			
		||||
	w        io.WriterAt
 | 
			
		||||
	off, len int64
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func NewSectionWriter(w io.WriterAt, off, len int64) *SectionWriter {
 | 
			
		||||
	return &SectionWriter{w, off, len}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (me *SectionWriter) WriteAt(b []byte, off int64) (n int, err error) {
 | 
			
		||||
	if off >= me.len {
 | 
			
		||||
		err = io.EOF
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
	if off+int64(len(b)) > me.len {
 | 
			
		||||
		b = b[:me.len-off]
 | 
			
		||||
	}
 | 
			
		||||
	return me.w.WriteAt(b, me.off+off)
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										60
									
								
								vendor/github.com/anacrolix/missinggo/selfcert.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										60
									
								
								vendor/github.com/anacrolix/missinggo/selfcert.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,60 @@
 | 
			
		||||
package missinggo
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"crypto/ecdsa"
 | 
			
		||||
	"crypto/rand"
 | 
			
		||||
	"crypto/rsa"
 | 
			
		||||
	"crypto/tls"
 | 
			
		||||
	"crypto/x509"
 | 
			
		||||
	"crypto/x509/pkix"
 | 
			
		||||
	"log"
 | 
			
		||||
	"math/big"
 | 
			
		||||
	"time"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
func publicKey(priv interface{}) interface{} {
 | 
			
		||||
	switch k := priv.(type) {
 | 
			
		||||
	case *rsa.PrivateKey:
 | 
			
		||||
		return &k.PublicKey
 | 
			
		||||
	case *ecdsa.PrivateKey:
 | 
			
		||||
		return &k.PublicKey
 | 
			
		||||
	default:
 | 
			
		||||
		return nil
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Creates a self-signed certificate in memory for use with tls.Config.
 | 
			
		||||
func NewSelfSignedCertificate() (cert tls.Certificate, err error) {
 | 
			
		||||
	cert.PrivateKey, err = rsa.GenerateKey(rand.Reader, 2048)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
	notBefore := time.Now()
 | 
			
		||||
	notAfter := notBefore.Add(365 * 24 * time.Hour)
 | 
			
		||||
 | 
			
		||||
	serialNumberLimit := new(big.Int).Lsh(big.NewInt(1), 128)
 | 
			
		||||
	serialNumber, err := rand.Int(rand.Reader, serialNumberLimit)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		log.Fatalf("failed to generate serial number: %s", err)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	template := x509.Certificate{
 | 
			
		||||
		SerialNumber: serialNumber,
 | 
			
		||||
		Subject: pkix.Name{
 | 
			
		||||
			Organization: []string{"Acme Co"},
 | 
			
		||||
		},
 | 
			
		||||
		NotBefore: notBefore,
 | 
			
		||||
		NotAfter:  notAfter,
 | 
			
		||||
 | 
			
		||||
		KeyUsage:              x509.KeyUsageKeyEncipherment | x509.KeyUsageDigitalSignature,
 | 
			
		||||
		ExtKeyUsage:           []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth},
 | 
			
		||||
		BasicConstraintsValid: true,
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	derBytes, err := x509.CreateCertificate(rand.Reader, &template, &template, publicKey(cert.PrivateKey), cert.PrivateKey)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		log.Fatalf("Failed to create certificate: %s", err)
 | 
			
		||||
	}
 | 
			
		||||
	cert.Certificate = [][]byte{derBytes}
 | 
			
		||||
	return
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										49
									
								
								vendor/github.com/anacrolix/missinggo/singleflight.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										49
									
								
								vendor/github.com/anacrolix/missinggo/singleflight.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,49 @@
 | 
			
		||||
package missinggo
 | 
			
		||||
 | 
			
		||||
import "sync"
 | 
			
		||||
 | 
			
		||||
type ongoing struct {
 | 
			
		||||
	do    sync.Mutex
 | 
			
		||||
	users int
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type SingleFlight struct {
 | 
			
		||||
	mu      sync.Mutex
 | 
			
		||||
	ongoing map[string]*ongoing
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type Operation struct {
 | 
			
		||||
	sf *SingleFlight
 | 
			
		||||
	id string
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (op Operation) Unlock() {
 | 
			
		||||
	op.sf.Unlock(op.id)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (me *SingleFlight) Lock(id string) Operation {
 | 
			
		||||
	me.mu.Lock()
 | 
			
		||||
	on, ok := me.ongoing[id]
 | 
			
		||||
	if !ok {
 | 
			
		||||
		on = new(ongoing)
 | 
			
		||||
		if me.ongoing == nil {
 | 
			
		||||
			me.ongoing = make(map[string]*ongoing)
 | 
			
		||||
		}
 | 
			
		||||
		me.ongoing[id] = on
 | 
			
		||||
	}
 | 
			
		||||
	on.users++
 | 
			
		||||
	me.mu.Unlock()
 | 
			
		||||
	on.do.Lock()
 | 
			
		||||
	return Operation{me, id}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (me *SingleFlight) Unlock(id string) {
 | 
			
		||||
	me.mu.Lock()
 | 
			
		||||
	on := me.ongoing[id]
 | 
			
		||||
	on.do.Unlock()
 | 
			
		||||
	on.users--
 | 
			
		||||
	if on.users == 0 {
 | 
			
		||||
		delete(me.ongoing, id)
 | 
			
		||||
	}
 | 
			
		||||
	me.mu.Unlock()
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										46
									
								
								vendor/github.com/anacrolix/missinggo/slices/cast.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										46
									
								
								vendor/github.com/anacrolix/missinggo/slices/cast.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,46 @@
 | 
			
		||||
package slices
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"reflect"
 | 
			
		||||
 | 
			
		||||
	"github.com/bradfitz/iter"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// Returns a copy of all the elements of slice []T as a slice of interface{}.
 | 
			
		||||
func ToEmptyInterface(slice interface{}) (ret []interface{}) {
 | 
			
		||||
	v := reflect.ValueOf(slice)
 | 
			
		||||
	l := v.Len()
 | 
			
		||||
	ret = make([]interface{}, 0, l)
 | 
			
		||||
	for i := range iter.N(v.Len()) {
 | 
			
		||||
		ret = append(ret, v.Index(i).Interface())
 | 
			
		||||
	}
 | 
			
		||||
	return
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Makes and sets a slice at *ptrTo, and type asserts all the elements from
 | 
			
		||||
// from to it.
 | 
			
		||||
func MakeInto(ptrTo interface{}, from interface{}) {
 | 
			
		||||
	fromSliceValue := reflect.ValueOf(from)
 | 
			
		||||
	fromLen := fromSliceValue.Len()
 | 
			
		||||
	if fromLen == 0 {
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
	// Deref the pointer to slice.
 | 
			
		||||
	slicePtrValue := reflect.ValueOf(ptrTo)
 | 
			
		||||
	if slicePtrValue.Kind() != reflect.Ptr {
 | 
			
		||||
		panic("destination is not a pointer")
 | 
			
		||||
	}
 | 
			
		||||
	destSliceValue := slicePtrValue.Elem()
 | 
			
		||||
	// The type of the elements of the destination slice.
 | 
			
		||||
	destSliceElemType := destSliceValue.Type().Elem()
 | 
			
		||||
	destSliceValue.Set(reflect.MakeSlice(destSliceValue.Type(), fromLen, fromLen))
 | 
			
		||||
	for i := range iter.N(fromSliceValue.Len()) {
 | 
			
		||||
		// The value inside the interface in the slice element.
 | 
			
		||||
		itemValue := fromSliceValue.Index(i)
 | 
			
		||||
		if itemValue.Kind() == reflect.Interface {
 | 
			
		||||
			itemValue = itemValue.Elem()
 | 
			
		||||
		}
 | 
			
		||||
		convertedItem := itemValue.Convert(destSliceElemType)
 | 
			
		||||
		destSliceValue.Index(i).Set(convertedItem)
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										5
									
								
								vendor/github.com/anacrolix/missinggo/slices/doc.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										5
									
								
								vendor/github.com/anacrolix/missinggo/slices/doc.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,5 @@
 | 
			
		||||
// Package slices has several utilities for operating on slices given Go's
 | 
			
		||||
// lack of generic types. Many functions take an argument of type func(l, r T)
 | 
			
		||||
// bool, that's expected to compute l < r where T is T in []T, the type of the
 | 
			
		||||
// given slice.
 | 
			
		||||
package slices
 | 
			
		||||
							
								
								
									
										17
									
								
								vendor/github.com/anacrolix/missinggo/slices/filter.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										17
									
								
								vendor/github.com/anacrolix/missinggo/slices/filter.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,17 @@
 | 
			
		||||
package slices
 | 
			
		||||
 | 
			
		||||
import "reflect"
 | 
			
		||||
 | 
			
		||||
// sl []T, f is func(*T) bool.
 | 
			
		||||
func FilterInPlace(sl interface{}, f interface{}) {
 | 
			
		||||
	v := reflect.ValueOf(sl).Elem()
 | 
			
		||||
	j := 0
 | 
			
		||||
	for i := 0; i < v.Len(); i++ {
 | 
			
		||||
		e := v.Index(i)
 | 
			
		||||
		if reflect.ValueOf(f).Call([]reflect.Value{e.Addr()})[0].Bool() {
 | 
			
		||||
			v.Index(j).Set(e)
 | 
			
		||||
			j++
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	v.SetLen(j)
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										49
									
								
								vendor/github.com/anacrolix/missinggo/slices/map.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										49
									
								
								vendor/github.com/anacrolix/missinggo/slices/map.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,49 @@
 | 
			
		||||
package slices
 | 
			
		||||
 | 
			
		||||
import "reflect"
 | 
			
		||||
 | 
			
		||||
type MapItem struct {
 | 
			
		||||
	Key, Elem interface{}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Creates a []struct{Key K; Value V} for map[K]V.
 | 
			
		||||
func FromMap(m interface{}) (slice []MapItem) {
 | 
			
		||||
	mapValue := reflect.ValueOf(m)
 | 
			
		||||
	for _, key := range mapValue.MapKeys() {
 | 
			
		||||
		slice = append(slice, MapItem{key.Interface(), mapValue.MapIndex(key).Interface()})
 | 
			
		||||
	}
 | 
			
		||||
	return
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Returns all the elements []T, from m where m is map[K]T.
 | 
			
		||||
func FromMapElems(m interface{}) interface{} {
 | 
			
		||||
	inValue := reflect.ValueOf(m)
 | 
			
		||||
	outValue := reflect.MakeSlice(reflect.SliceOf(inValue.Type().Elem()), inValue.Len(), inValue.Len())
 | 
			
		||||
	for i, key := range inValue.MapKeys() {
 | 
			
		||||
		outValue.Index(i).Set(inValue.MapIndex(key))
 | 
			
		||||
	}
 | 
			
		||||
	return outValue.Interface()
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Returns all the elements []K, from m where m is map[K]T.
 | 
			
		||||
func FromMapKeys(m interface{}) interface{} {
 | 
			
		||||
	inValue := reflect.ValueOf(m)
 | 
			
		||||
	outValue := reflect.MakeSlice(reflect.SliceOf(inValue.Type().Key()), inValue.Len(), inValue.Len())
 | 
			
		||||
	for i, key := range inValue.MapKeys() {
 | 
			
		||||
		outValue.Index(i).Set(key)
 | 
			
		||||
	}
 | 
			
		||||
	return outValue.Interface()
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// f: (T)T, input: []T, outout: []T
 | 
			
		||||
func Map(f, input interface{}) interface{} {
 | 
			
		||||
	inputValue := reflect.ValueOf(input)
 | 
			
		||||
	funcValue := reflect.ValueOf(f)
 | 
			
		||||
	_len := inputValue.Len()
 | 
			
		||||
	retValue := reflect.MakeSlice(reflect.TypeOf(input), _len, _len)
 | 
			
		||||
	for i := 0; i < _len; i++ {
 | 
			
		||||
		out := funcValue.Call([]reflect.Value{inputValue.Index(i)})
 | 
			
		||||
		retValue.Index(i).Set(out[0])
 | 
			
		||||
	}
 | 
			
		||||
	return retValue.Interface()
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										36
									
								
								vendor/github.com/anacrolix/missinggo/slices/sort.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										36
									
								
								vendor/github.com/anacrolix/missinggo/slices/sort.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,36 @@
 | 
			
		||||
package slices
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"container/heap"
 | 
			
		||||
	"reflect"
 | 
			
		||||
	"sort"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// Sorts the slice in place. Returns sl for convenience.
 | 
			
		||||
func Sort(sl interface{}, less interface{}) interface{} {
 | 
			
		||||
	sorter := sorter{
 | 
			
		||||
		sl:   reflect.ValueOf(sl),
 | 
			
		||||
		less: reflect.ValueOf(less),
 | 
			
		||||
	}
 | 
			
		||||
	sort.Sort(&sorter)
 | 
			
		||||
	return sorter.sl.Interface()
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Creates a modifiable copy of a slice reference. Because you can't modify
 | 
			
		||||
// non-pointer types inside an interface{}.
 | 
			
		||||
func addressableSlice(slice interface{}) reflect.Value {
 | 
			
		||||
	v := reflect.ValueOf(slice)
 | 
			
		||||
	p := reflect.New(v.Type())
 | 
			
		||||
	p.Elem().Set(v)
 | 
			
		||||
	return p.Elem()
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Returns a "container/heap".Interface for the provided slice.
 | 
			
		||||
func HeapInterface(sl interface{}, less interface{}) heap.Interface {
 | 
			
		||||
	ret := &sorter{
 | 
			
		||||
		sl:   addressableSlice(sl),
 | 
			
		||||
		less: reflect.ValueOf(less),
 | 
			
		||||
	}
 | 
			
		||||
	heap.Init(ret)
 | 
			
		||||
	return ret
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										36
									
								
								vendor/github.com/anacrolix/missinggo/slices/sorter.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										36
									
								
								vendor/github.com/anacrolix/missinggo/slices/sorter.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,36 @@
 | 
			
		||||
package slices
 | 
			
		||||
 | 
			
		||||
import "reflect"
 | 
			
		||||
 | 
			
		||||
type sorter struct {
 | 
			
		||||
	sl   reflect.Value
 | 
			
		||||
	less reflect.Value
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (s *sorter) Len() int {
 | 
			
		||||
	return s.sl.Len()
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (s *sorter) Less(i, j int) bool {
 | 
			
		||||
	return s.less.Call([]reflect.Value{
 | 
			
		||||
		s.sl.Index(i),
 | 
			
		||||
		s.sl.Index(j),
 | 
			
		||||
	})[0].Bool()
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (s *sorter) Swap(i, j int) {
 | 
			
		||||
	t := reflect.New(s.sl.Type().Elem()).Elem()
 | 
			
		||||
	t.Set(s.sl.Index(i))
 | 
			
		||||
	s.sl.Index(i).Set(s.sl.Index(j))
 | 
			
		||||
	s.sl.Index(j).Set(t)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (s *sorter) Pop() interface{} {
 | 
			
		||||
	ret := s.sl.Index(s.sl.Len() - 1).Interface()
 | 
			
		||||
	s.sl.SetLen(s.sl.Len() - 1)
 | 
			
		||||
	return ret
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (s *sorter) Push(val interface{}) {
 | 
			
		||||
	s.sl = reflect.Append(s.sl, reflect.ValueOf(val))
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										17
									
								
								vendor/github.com/anacrolix/missinggo/sqlite.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										17
									
								
								vendor/github.com/anacrolix/missinggo/sqlite.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,17 @@
 | 
			
		||||
package missinggo
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"database/sql"
 | 
			
		||||
	"time"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
type SqliteTime time.Time
 | 
			
		||||
 | 
			
		||||
var _ sql.Scanner = (*SqliteTime)(nil)
 | 
			
		||||
 | 
			
		||||
func (me *SqliteTime) Scan(src interface{}) error {
 | 
			
		||||
	var tt time.Time
 | 
			
		||||
	tt, err := time.Parse("2006-01-02 15:04:05", string(src.([]byte)))
 | 
			
		||||
	*me = SqliteTime(tt)
 | 
			
		||||
	return err
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										23
									
								
								vendor/github.com/anacrolix/missinggo/stack.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										23
									
								
								vendor/github.com/anacrolix/missinggo/stack.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,23 @@
 | 
			
		||||
package missinggo
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"fmt"
 | 
			
		||||
	"io"
 | 
			
		||||
	"runtime"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
func WriteStack(w io.Writer, stack []uintptr) {
 | 
			
		||||
	for _, pc := range stack {
 | 
			
		||||
		if pc == 0 {
 | 
			
		||||
			break
 | 
			
		||||
		}
 | 
			
		||||
		pc--
 | 
			
		||||
		f := runtime.FuncForPC(pc)
 | 
			
		||||
		if f.Name() == "runtime.goexit" {
 | 
			
		||||
			continue
 | 
			
		||||
		}
 | 
			
		||||
		file, line := f.FileLine(pc)
 | 
			
		||||
		fmt.Fprintf(w, "# %s:\t%s:%d\n", f.Name(), file, line)
 | 
			
		||||
	}
 | 
			
		||||
	fmt.Fprintf(w, "\n")
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										25
									
								
								vendor/github.com/anacrolix/missinggo/strbool.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										25
									
								
								vendor/github.com/anacrolix/missinggo/strbool.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,25 @@
 | 
			
		||||
package missinggo
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"strconv"
 | 
			
		||||
	"strings"
 | 
			
		||||
	"unicode"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
func StringTruth(s string) (ret bool) {
 | 
			
		||||
	s = strings.TrimFunc(s, func(r rune) bool {
 | 
			
		||||
		return r == 0 || unicode.IsSpace(r)
 | 
			
		||||
	})
 | 
			
		||||
	if s == "" {
 | 
			
		||||
		return false
 | 
			
		||||
	}
 | 
			
		||||
	ret, err := strconv.ParseBool(s)
 | 
			
		||||
	if err == nil {
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
	i, err := strconv.ParseInt(s, 0, 0)
 | 
			
		||||
	if err == nil {
 | 
			
		||||
		return i != 0
 | 
			
		||||
	}
 | 
			
		||||
	return true
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										11
									
								
								vendor/github.com/anacrolix/missinggo/strcase.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										11
									
								
								vendor/github.com/anacrolix/missinggo/strcase.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,11 @@
 | 
			
		||||
package missinggo
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"strings"
 | 
			
		||||
 | 
			
		||||
	"github.com/huandu/xstrings"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
func KebabCase(s string) string {
 | 
			
		||||
	return strings.Replace(xstrings.ToSnakeCase(s), "_", "-", -1)
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										11
									
								
								vendor/github.com/anacrolix/missinggo/sync.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										11
									
								
								vendor/github.com/anacrolix/missinggo/sync.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,11 @@
 | 
			
		||||
package missinggo
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"sync"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
type RWLocker interface {
 | 
			
		||||
	sync.Locker
 | 
			
		||||
	RLock()
 | 
			
		||||
	RUnlock()
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										25
									
								
								vendor/github.com/anacrolix/missinggo/testing.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										25
									
								
								vendor/github.com/anacrolix/missinggo/testing.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,25 @@
 | 
			
		||||
package missinggo
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"regexp"
 | 
			
		||||
	"runtime"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// It will be the one and only identifier after a package specifier.
 | 
			
		||||
var testNameRegexp = regexp.MustCompile(`\.(Test[\p{L}_\p{N}]*)`)
 | 
			
		||||
 | 
			
		||||
// Returns the name of the test function from the call stack. See
 | 
			
		||||
// http://stackoverflow.com/q/35535635/149482 for another method.
 | 
			
		||||
func GetTestName() string {
 | 
			
		||||
	pc := make([]uintptr, 32)
 | 
			
		||||
	n := runtime.Callers(0, pc)
 | 
			
		||||
	for i := 0; i < n; i++ {
 | 
			
		||||
		name := runtime.FuncForPC(pc[i]).Name()
 | 
			
		||||
		ms := testNameRegexp.FindStringSubmatch(name)
 | 
			
		||||
		if ms == nil {
 | 
			
		||||
			continue
 | 
			
		||||
		}
 | 
			
		||||
		return ms[1]
 | 
			
		||||
	}
 | 
			
		||||
	panic("test name could not be recovered")
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										15
									
								
								vendor/github.com/anacrolix/missinggo/timer.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										15
									
								
								vendor/github.com/anacrolix/missinggo/timer.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,15 @@
 | 
			
		||||
package missinggo
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"math"
 | 
			
		||||
	"time"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// Returns a time.Timer that calls f. The timer is initially stopped.
 | 
			
		||||
func StoppedFuncTimer(f func()) (t *time.Timer) {
 | 
			
		||||
	t = time.AfterFunc(math.MaxInt64, f)
 | 
			
		||||
	if !t.Stop() {
 | 
			
		||||
		panic("timer already fired")
 | 
			
		||||
	}
 | 
			
		||||
	return
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										32
									
								
								vendor/github.com/anacrolix/missinggo/tls.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										32
									
								
								vendor/github.com/anacrolix/missinggo/tls.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,32 @@
 | 
			
		||||
package missinggo
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"crypto/tls"
 | 
			
		||||
	"strings"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// Select the best named certificate per the usual behaviour if
 | 
			
		||||
// c.GetCertificate is nil, and c.NameToCertificate is not.
 | 
			
		||||
func BestNamedCertificate(c *tls.Config, clientHello *tls.ClientHelloInfo) (*tls.Certificate, bool) {
 | 
			
		||||
	name := strings.ToLower(clientHello.ServerName)
 | 
			
		||||
	for len(name) > 0 && name[len(name)-1] == '.' {
 | 
			
		||||
		name = name[:len(name)-1]
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if cert, ok := c.NameToCertificate[name]; ok {
 | 
			
		||||
		return cert, true
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// try replacing labels in the name with wildcards until we get a
 | 
			
		||||
	// match.
 | 
			
		||||
	labels := strings.Split(name, ".")
 | 
			
		||||
	for i := range labels {
 | 
			
		||||
		labels[i] = "*"
 | 
			
		||||
		candidate := strings.Join(labels, ".")
 | 
			
		||||
		if cert, ok := c.NameToCertificate[candidate]; ok {
 | 
			
		||||
			return cert, true
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return nil, false
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										3
									
								
								vendor/github.com/anacrolix/missinggo/units.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										3
									
								
								vendor/github.com/anacrolix/missinggo/units.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,3 @@
 | 
			
		||||
package missinggo
 | 
			
		||||
 | 
			
		||||
const MiB = 1 << 20
 | 
			
		||||
							
								
								
									
										42
									
								
								vendor/github.com/anacrolix/missinggo/url.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										42
									
								
								vendor/github.com/anacrolix/missinggo/url.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,42 @@
 | 
			
		||||
package missinggo
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"net/url"
 | 
			
		||||
	"path"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// Returns URL opaque as an unrooted path.
 | 
			
		||||
func URLOpaquePath(u *url.URL) string {
 | 
			
		||||
	if u.Opaque != "" {
 | 
			
		||||
		return u.Opaque
 | 
			
		||||
	}
 | 
			
		||||
	return u.Path
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Cleans the (absolute) URL path, removing unnecessary . and .. elements. See
 | 
			
		||||
// "net/http".cleanPath.
 | 
			
		||||
func CleanURLPath(p string) string {
 | 
			
		||||
	if p == "" {
 | 
			
		||||
		return "/"
 | 
			
		||||
	}
 | 
			
		||||
	if p[0] != '/' {
 | 
			
		||||
		p = "/" + p
 | 
			
		||||
	}
 | 
			
		||||
	cp := path.Clean(p)
 | 
			
		||||
	// Add the trailing slash back, as it's relevant to a URL.
 | 
			
		||||
	if p[len(p)-1] == '/' && cp != "/" {
 | 
			
		||||
		cp += "/"
 | 
			
		||||
	}
 | 
			
		||||
	return cp
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func URLJoinSubPath(base, rel string) string {
 | 
			
		||||
	baseURL, err := url.Parse(base)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		// Honey badger doesn't give a fuck.
 | 
			
		||||
		panic(err)
 | 
			
		||||
	}
 | 
			
		||||
	rel = CleanURLPath(rel)
 | 
			
		||||
	baseURL.Path = path.Join(baseURL.Path, rel)
 | 
			
		||||
	return baseURL.String()
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										19
									
								
								vendor/github.com/anacrolix/missinggo/wait_event.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										19
									
								
								vendor/github.com/anacrolix/missinggo/wait_event.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,19 @@
 | 
			
		||||
package missinggo
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"reflect"
 | 
			
		||||
	"sync"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
func WaitEvents(l sync.Locker, evs ...*Event) {
 | 
			
		||||
	cases := make([]reflect.SelectCase, 0, len(evs))
 | 
			
		||||
	for _, ev := range evs {
 | 
			
		||||
		cases = append(cases, reflect.SelectCase{
 | 
			
		||||
			Dir:  reflect.SelectRecv,
 | 
			
		||||
			Chan: reflect.ValueOf(ev.C()),
 | 
			
		||||
		})
 | 
			
		||||
	}
 | 
			
		||||
	l.Unlock()
 | 
			
		||||
	reflect.Select(cases)
 | 
			
		||||
	l.Lock()
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										51
									
								
								vendor/github.com/anacrolix/missinggo/wolf.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										51
									
								
								vendor/github.com/anacrolix/missinggo/wolf.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,51 @@
 | 
			
		||||
package missinggo
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"log"
 | 
			
		||||
	"runtime"
 | 
			
		||||
	"sync"
 | 
			
		||||
	"sync/atomic"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
const debug = false
 | 
			
		||||
 | 
			
		||||
// A Wolf represents some event that becomes less and less interesting as it
 | 
			
		||||
// occurs. Call CryHeard to see if we should pay attention this time.
 | 
			
		||||
type Wolf struct {
 | 
			
		||||
	cries uint64
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Returns true less and less often. Convenient for exponentially decreasing
 | 
			
		||||
// the amount of noise due to errors.
 | 
			
		||||
func (me *Wolf) CryHeard() bool {
 | 
			
		||||
	n := atomic.AddUint64(&me.cries, 1)
 | 
			
		||||
	return n&(n-1) == 0
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
var (
 | 
			
		||||
	mu     sync.Mutex
 | 
			
		||||
	wolves map[uintptr]*Wolf
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// Calls CryHeard() on a Wolf that is unique to the callers program counter.
 | 
			
		||||
// i.e. every CryHeard() expression has its own Wolf.
 | 
			
		||||
func CryHeard() bool {
 | 
			
		||||
	pc, file, line, ok := runtime.Caller(1)
 | 
			
		||||
	if debug {
 | 
			
		||||
		log.Println(pc, file, line, ok)
 | 
			
		||||
	}
 | 
			
		||||
	if !ok {
 | 
			
		||||
		return true
 | 
			
		||||
	}
 | 
			
		||||
	mu.Lock()
 | 
			
		||||
	if wolves == nil {
 | 
			
		||||
		wolves = make(map[uintptr]*Wolf)
 | 
			
		||||
	}
 | 
			
		||||
	w, ok := wolves[pc]
 | 
			
		||||
	if !ok {
 | 
			
		||||
		w = new(Wolf)
 | 
			
		||||
		wolves[pc] = w
 | 
			
		||||
	}
 | 
			
		||||
	mu.Unlock()
 | 
			
		||||
	return w.CryHeard()
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										8
									
								
								vendor/github.com/anacrolix/missinggo/x/panic.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										8
									
								
								vendor/github.com/anacrolix/missinggo/x/panic.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,8 @@
 | 
			
		||||
package x
 | 
			
		||||
 | 
			
		||||
// Panic if error. Just fucking add exceptions, please.
 | 
			
		||||
func Pie(err error) {
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		panic(err)
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
		Reference in New Issue
	
	Block a user