Repository: creachadair/jrpc2
Pull request #51 (2021-08-04 14:55:34)

Update the Network helper to return a tuple.
Instead of returning only the inferred network type, return also the address
that the caller passed in. This allows a call to jrpc2.Network to be passed
directly in argument position to net.Listen, without having to echo the address
explicitly.

This is a breaking change for uses of the Network function, but does not affect
any other part of the module API.


Patch:
diff --git a/base.go b/base.go
index 3498067..8be3b23 100644
--- a/base.go
+++ b/base.go
@@ -398,8 +398,10 @@ func encode(ch channel.Sender, rsps jmessages) (int, error) {
 	return len(bits), ch.Send(bits)
 }
 
-// Network guesses a network type for the specified address.  The assignment of
-// a network type uses the following heuristics:
+// Network guesses a network type for the specified address and returns a tuple
+// of that type and the address.
+//
+// The assignment of a network type uses the following heuristics:
 //
 // If s does not have the form [host]:port, the network is assigned as "unix".
 // The network "unix" is also assigned if port == "", port contains characters
@@ -407,18 +409,18 @@ func encode(ch channel.Sender, rsps jmessages) (int, error) {
 //
 // Otherwise, the network is assigned as "tcp". Note that this function does
 // not verify whether the address is lexically valid.
-func Network(s string) string {
+func Network(s string) (network, address string) {
 	i := strings.LastIndex(s, ":")
 	if i < 0 {
-		return "unix"
+		return "unix", s
 	}
 	host, port := s[:i], s[i+1:]
 	if port == "" || !isServiceName(port) {
-		return "unix"
+		return "unix", s
 	} else if strings.IndexByte(host, '/') >= 0 {
-		return "unix"
+		return "unix", s
 	}
-	return "tcp"
+	return "tcp", s
 }
 
 // isServiceName reports whether s looks like a legal service name from the
diff --git a/cmd/examples/client/client.go b/cmd/examples/client/client.go
index 43c62ef..efecf6a 100644
--- a/cmd/examples/client/client.go
+++ b/cmd/examples/client/client.go
@@ -60,7 +60,7 @@ func main() {
 		log.Fatal("You must provide -server address to connect to")
 	}
 
-	conn, err := net.Dial(jrpc2.Network(*serverAddr), *serverAddr)
+	conn, err := net.Dial(jrpc2.Network(*serverAddr))
 	if err != nil {
 		log.Fatalf("Dial %q: %v", *serverAddr, err)
 	}
diff --git a/cmd/examples/server/server.go b/cmd/examples/server/server.go
index 21f3fd7..400f3ee 100644
--- a/cmd/examples/server/server.go
+++ b/cmd/examples/server/server.go
@@ -95,7 +95,7 @@ func main() {
 		},
 	}
 
-	lst, err := net.Listen(jrpc2.Network(*address), *address)
+	lst, err := net.Listen(jrpc2.Network(*address))
 	if err != nil {
 		log.Fatalln("Listen:", err)
 	}
diff --git a/cmd/jcall/jcall.go b/cmd/jcall/jcall.go
index d50c242..160e00e 100644
--- a/cmd/jcall/jcall.go
+++ b/cmd/jcall/jcall.go
@@ -115,7 +115,7 @@ func main() {
 	} else if nc := chanutil.Framing(*chanFraming); nc == nil {
 		log.Fatalf("Unknown channel framing %q", *chanFraming)
 	} else {
-		ntype := jrpc2.Network(flag.Arg(0))
+		ntype, _ := jrpc2.Network(flag.Arg(0))
 		conn, err := net.DialTimeout(ntype, flag.Arg(0), *dialTimeout)
 		if err != nil {
 			log.Fatalf("Dial %q: %v", flag.Arg(0), err)


Test patch:
diff --git a/jrpc2_test.go b/jrpc2_test.go
index 2206280..97ff5a7 100644
--- a/jrpc2_test.go
+++ b/jrpc2_test.go
@@ -1012,9 +1012,12 @@ func TestNetwork(t *testing.T) {
 		{"localhost:http", "tcp"}, // host and service name
 	}
 	for _, test := range tests {
-		got := jrpc2.Network(test.input)
+		got, addr := jrpc2.Network(test.input)
 		if got != test.want {
-			t.Errorf("Network(%q): got %q, want %q", test.input, got, test.want)
+			t.Errorf("Network(%q) type: got %q, want %q", test.input, got, test.want)
+		}
+		if addr != test.input {
+			t.Errorf("Network(%q) addr: got %q, want %q", test.input, addr, test.input)
 		}
 	}
 }