From 5501f994cac03f329f692ffb7fc804a94ca8fa2b Mon Sep 17 00:00:00 2001
From: Matt Joiner <anacrolix@gmail.com>
Date: Wed, 2 Nov 2022 23:03:25 +1100
Subject: [PATCH] Move a bunch of stuff into subpackages

The core package is very large now, and often only parts of it are needed.
---
 dialer.go                  | 34 +++-------------
 dialer/dialer.go           | 34 ++++++++++++++++
 metainfo/hash.go           | 76 +++---------------------------------
 metainfo/info.go           |  2 +-
 misc.go                    |  6 ++-
 peerid.go                  | 13 +------
 socket.go                  |  3 +-
 test/unix_test.go          |  3 +-
 types/infohash/infohash.go | 80 ++++++++++++++++++++++++++++++++++++++
 types/peerid.go            | 14 +++++++
 10 files changed, 151 insertions(+), 114 deletions(-)
 create mode 100644 dialer/dialer.go
 create mode 100644 types/infohash/infohash.go
 create mode 100644 types/peerid.go

diff --git a/dialer.go b/dialer.go
index d499af30..5cdf3fcc 100644
--- a/dialer.go
+++ b/dialer.go
@@ -1,34 +1,12 @@
 package torrent
 
 import (
-	"context"
-	"net"
+	"github.com/anacrolix/torrent/dialer"
 )
 
-// Dialers have the network locked in.
-type Dialer interface {
-	Dial(_ context.Context, addr string) (net.Conn, error)
-	DialerNetwork() string
-}
-
-// An interface to ease wrapping dialers that explicitly include a network parameter.
-type DialContexter interface {
-	DialContext(ctx context.Context, network, addr string) (net.Conn, error)
-}
-
-// Used by wrappers of standard library network types.
-var DefaultNetDialer = &net.Dialer{}
-
-// Adapts a DialContexter to the Dial interface in this package.
-type NetworkDialer struct {
-	Network string
-	Dialer  DialContexter
-}
-
-func (me NetworkDialer) DialerNetwork() string {
-	return me.Network
-}
+type (
+	Dialer        = dialer.T
+	NetworkDialer = dialer.WithNetwork
+)
 
-func (me NetworkDialer) Dial(ctx context.Context, addr string) (_ net.Conn, err error) {
-	return me.Dialer.DialContext(ctx, me.Network, addr)
-}
+var DefaultNetDialer = &dialer.Default
diff --git a/dialer/dialer.go b/dialer/dialer.go
new file mode 100644
index 00000000..5e5dff49
--- /dev/null
+++ b/dialer/dialer.go
@@ -0,0 +1,34 @@
+package dialer
+
+import (
+	"context"
+	"net"
+)
+
+// Dialers have the network locked in.
+type T interface {
+	Dial(_ context.Context, addr string) (net.Conn, error)
+	DialerNetwork() string
+}
+
+// An interface to ease wrapping dialers that explicitly include a network parameter.
+type WithContext interface {
+	DialContext(ctx context.Context, network, addr string) (net.Conn, error)
+}
+
+// Used by wrappers of standard library network types.
+var Default = &net.Dialer{}
+
+// Adapts a WithContext to the Dial interface in this package.
+type WithNetwork struct {
+	Network string
+	Dialer  WithContext
+}
+
+func (me WithNetwork) DialerNetwork() string {
+	return me.Network
+}
+
+func (me WithNetwork) Dial(ctx context.Context, addr string) (_ net.Conn, err error) {
+	return me.Dialer.DialContext(ctx, me.Network, addr)
+}
diff --git a/metainfo/hash.go b/metainfo/hash.go
index a1f688a7..39daf6f3 100644
--- a/metainfo/hash.go
+++ b/metainfo/hash.go
@@ -1,80 +1,16 @@
 package metainfo
 
 import (
-	"crypto/sha1"
-	"encoding"
-	"encoding/hex"
-	"fmt"
+	"github.com/anacrolix/torrent/types/infohash"
 )
 
-const HashSize = 20
+// This type has been moved to allow avoiding importing everything in metainfo to get at it.
 
-// 20-byte SHA1 hash used for info and pieces.
-type Hash [HashSize]byte
+const HashSize = infohash.Size
 
-var _ fmt.Formatter = (*Hash)(nil)
-
-func (h Hash) Format(f fmt.State, c rune) {
-	// TODO: I can't figure out a nice way to just override the 'x' rune, since it's meaningless
-	// with the "default" 'v', or .String() already returning the hex.
-	f.Write([]byte(h.HexString()))
-}
-
-func (h Hash) Bytes() []byte {
-	return h[:]
-}
-
-func (h Hash) AsString() string {
-	return string(h[:])
-}
-
-func (h Hash) String() string {
-	return h.HexString()
-}
-
-func (h Hash) HexString() string {
-	return fmt.Sprintf("%x", h[:])
-}
-
-func (h *Hash) FromHexString(s string) (err error) {
-	if len(s) != 2*HashSize {
-		err = fmt.Errorf("hash hex string has bad length: %d", len(s))
-		return
-	}
-	n, err := hex.Decode(h[:], []byte(s))
-	if err != nil {
-		return
-	}
-	if n != HashSize {
-		panic(n)
-	}
-	return
-}
+type Hash = infohash.T
 
 var (
-	_ encoding.TextUnmarshaler = (*Hash)(nil)
-	_ encoding.TextMarshaler   = Hash{}
+	NewHashFromHex = infohash.FromHexString
+	HashBytes      = infohash.HashBytes
 )
-
-func (h *Hash) UnmarshalText(b []byte) error {
-	return h.FromHexString(string(b))
-}
-
-func (h Hash) MarshalText() (text []byte, err error) {
-	return []byte(h.HexString()), nil
-}
-
-func NewHashFromHex(s string) (h Hash) {
-	err := h.FromHexString(s)
-	if err != nil {
-		panic(err)
-	}
-	return
-}
-
-func HashBytes(b []byte) (ret Hash) {
-	hasher := sha1.New()
-	hasher.Write(b)
-	copy(ret[:], hasher.Sum(nil))
-	return
-}
diff --git a/metainfo/info.go b/metainfo/info.go
index bab08af9..1ee2704e 100644
--- a/metainfo/info.go
+++ b/metainfo/info.go
@@ -8,7 +8,7 @@ import (
 	"path/filepath"
 	"strings"
 
-	"github.com/anacrolix/missinggo/slices"
+	"github.com/anacrolix/missinggo/v2/slices"
 )
 
 // The info dictionary.
diff --git a/misc.go b/misc.go
index 4041b776..6b638a28 100644
--- a/misc.go
+++ b/misc.go
@@ -7,6 +7,7 @@ import (
 	"github.com/RoaringBitmap/roaring"
 	"github.com/anacrolix/missinggo/v2"
 	"github.com/anacrolix/torrent/types"
+	"github.com/anacrolix/torrent/types/infohash"
 	"golang.org/x/time/rate"
 
 	"github.com/anacrolix/torrent/metainfo"
@@ -177,8 +178,9 @@ var unlimited = rate.NewLimiter(rate.Inf, 0)
 
 type (
 	pieceIndex = int
-	InfoHash   = metainfo.Hash
-	IpPort     = missinggo.IpPort
+	// Deprecated: Use infohash.T directly to avoid unnecessary imports.
+	InfoHash = infohash.T
+	IpPort   = missinggo.IpPort
 )
 
 func boolSliceToBitmap(slice []bool) (rb roaring.Bitmap) {
diff --git a/peerid.go b/peerid.go
index b689d304..301c0e94 100644
--- a/peerid.go
+++ b/peerid.go
@@ -1,14 +1,5 @@
 package torrent
 
-// Peer client ID.
-type PeerID [20]byte
+import "github.com/anacrolix/torrent/types"
 
-// // Pretty prints the ID as hex, except parts that adher to the PeerInfo ID
-// // Conventions of BEP 20.
-// func (me PeerID) String() string {
-// 	// if me[0] == '-' && me[7] == '-' {
-// 	// 	return string(me[:8]) + hex.EncodeToString(me[8:])
-// 	// }
-// 	// return hex.EncodeToString(me[:])
-// 	return fmt.Sprintf("%+q", me[:])
-// }
+type PeerID = types.PeerID
diff --git a/socket.go b/socket.go
index d5b690ff..aee11df8 100644
--- a/socket.go
+++ b/socket.go
@@ -8,6 +8,7 @@ import (
 	"github.com/anacrolix/log"
 	"github.com/anacrolix/missinggo/perf"
 	"github.com/anacrolix/missinggo/v2"
+	"github.com/anacrolix/torrent/dialer"
 	"github.com/pkg/errors"
 )
 
@@ -42,7 +43,7 @@ func listenTcp(network, address string) (s socket, err error) {
 		Listener: l,
 		NetworkDialer: NetworkDialer{
 			Network: network,
-			Dialer:  DefaultNetDialer,
+			Dialer:  dialer.Default,
 		},
 	}, err
 }
diff --git a/test/unix_test.go b/test/unix_test.go
index d8a3ff9f..e4ffa7e4 100644
--- a/test/unix_test.go
+++ b/test/unix_test.go
@@ -8,6 +8,7 @@ import (
 	"testing"
 
 	"github.com/anacrolix/torrent"
+	"github.com/anacrolix/torrent/dialer"
 )
 
 func TestUnixConns(t *testing.T) {
@@ -24,7 +25,7 @@ func TestUnixConns(t *testing.T) {
 			cfg.Debug = true
 		},
 		Client: func(cl *torrent.Client) {
-			cl.AddDialer(torrent.NetworkDialer{Network: "unix", Dialer: torrent.DefaultNetDialer})
+			cl.AddDialer(torrent.NetworkDialer{Network: "unix", Dialer: dialer.Default})
 			l, err := net.Listen("unix", filepath.Join(t.TempDir(), "socket"))
 			if err != nil {
 				panic(err)
diff --git a/types/infohash/infohash.go b/types/infohash/infohash.go
new file mode 100644
index 00000000..0763b01e
--- /dev/null
+++ b/types/infohash/infohash.go
@@ -0,0 +1,80 @@
+package infohash
+
+import (
+	"crypto/sha1"
+	"encoding"
+	"encoding/hex"
+	"fmt"
+)
+
+const Size = 20
+
+// 20-byte SHA1 hash used for info and pieces.
+type T [Size]byte
+
+var _ fmt.Formatter = (*T)(nil)
+
+func (t T) Format(f fmt.State, c rune) {
+	// TODO: I can't figure out a nice way to just override the 'x' rune, since it's meaningless
+	// with the "default" 'v', or .String() already returning the hex.
+	f.Write([]byte(t.HexString()))
+}
+
+func (t T) Bytes() []byte {
+	return t[:]
+}
+
+func (t T) AsString() string {
+	return string(t[:])
+}
+
+func (t T) String() string {
+	return t.HexString()
+}
+
+func (t T) HexString() string {
+	return fmt.Sprintf("%x", t[:])
+}
+
+func (t *T) FromHexString(s string) (err error) {
+	if len(s) != 2*Size {
+		err = fmt.Errorf("hash hex string has bad length: %d", len(s))
+		return
+	}
+	n, err := hex.Decode(t[:], []byte(s))
+	if err != nil {
+		return
+	}
+	if n != Size {
+		panic(n)
+	}
+	return
+}
+
+var (
+	_ encoding.TextUnmarshaler = (*T)(nil)
+	_ encoding.TextMarshaler   = T{}
+)
+
+func (t *T) UnmarshalText(b []byte) error {
+	return t.FromHexString(string(b))
+}
+
+func (t T) MarshalText() (text []byte, err error) {
+	return []byte(t.HexString()), nil
+}
+
+func FromHexString(s string) (h T) {
+	err := h.FromHexString(s)
+	if err != nil {
+		panic(err)
+	}
+	return
+}
+
+func HashBytes(b []byte) (ret T) {
+	hasher := sha1.New()
+	hasher.Write(b)
+	copy(ret[:], hasher.Sum(nil))
+	return
+}
diff --git a/types/peerid.go b/types/peerid.go
new file mode 100644
index 00000000..0e13473e
--- /dev/null
+++ b/types/peerid.go
@@ -0,0 +1,14 @@
+package types
+
+// Peer client ID.
+type PeerID [20]byte
+
+// // Pretty prints the ID as hex, except parts that adher to the PeerInfo ID
+// // Conventions of BEP 20.
+// func (me PeerID) String() string {
+// 	// if me[0] == '-' && me[7] == '-' {
+// 	// 	return string(me[:8]) + hex.EncodeToString(me[8:])
+// 	// }
+// 	// return hex.EncodeToString(me[:])
+// 	return fmt.Sprintf("%+q", me[:])
+// }
-- 
2.51.0