Clean up some unused or underused utilities (#316)

- Remove methods that have no calls.
- Replace a call to `writeStreamToSink` with the built in `addStream`.
- Replace a legacy style predicate matcher with a `TypeMatcher.having`.
diff --git a/lib/src/multipart_request.dart b/lib/src/multipart_request.dart
index 0f15451..e66e2d5 100644
--- a/lib/src/multipart_request.dart
+++ b/lib/src/multipart_request.dart
@@ -109,11 +109,10 @@
       writeLine();
     });
 
-    Future.forEach(_files, (file) {
+    Future.forEach(_files, (MultipartFile file) {
       writeAscii('--$boundary\r\n');
       writeAscii(_headerForFile(file));
-      return writeStreamToSink(file.finalize(), controller)
-          .then((_) => writeLine());
+      return controller.addStream(file.finalize()).then((_) => writeLine());
     }).then((_) {
       // TODO(nweiz): pass any errors propagated through this future on to
       // the stream. See issue 3657.
diff --git a/lib/src/utils.dart b/lib/src/utils.dart
index 58c6fd2..f24994e 100644
--- a/lib/src/utils.dart
+++ b/lib/src/utils.dart
@@ -21,24 +21,6 @@
   return pairs.map((pair) => '${pair[0]}=${pair[1]}').join('&');
 }
 
-/// Like [String.split], but only splits on the first occurrence of the pattern.
-///
-/// This will always return an array of two elements or fewer.
-///
-///     split1("foo,bar,baz", ","); //=> ["foo", "bar,baz"]
-///     split1("foo", ","); //=> ["foo"]
-///     split1("", ","); //=> []
-List<String> split1(String toSplit, String pattern) {
-  if (toSplit.isEmpty) return <String>[];
-
-  var index = toSplit.indexOf(pattern);
-  if (index == -1) return [toSplit];
-  return [
-    toSplit.substring(0, index),
-    toSplit.substring(index + pattern.length)
-  ];
-}
-
 /// Returns the [Encoding] that corresponds to [charset].
 ///
 /// Returns [fallback] if [charset] is null or if no [Encoding] was found that
@@ -92,51 +74,3 @@
       sink.close();
       onDone();
     }));
-
-// TODO(nweiz): remove this when issue 7786 is fixed.
-/// Pipes all data and errors from [stream] into [sink]. When [stream] is done,
-/// [sink] is closed and the returned [Future] is completed.
-Future store(Stream stream, EventSink sink) {
-  var completer = Completer();
-  stream.listen(sink.add, onError: sink.addError, onDone: () {
-    sink.close();
-    completer.complete();
-  });
-  return completer.future;
-}
-
-/// Pipes all data and errors from [stream] into [sink]. Completes [Future] once
-/// [stream] is done. Unlike [store], [sink] remains open after [stream] is
-/// done.
-Future writeStreamToSink(Stream stream, EventSink sink) {
-  var completer = Completer();
-  stream.listen(sink.add,
-      onError: sink.addError, onDone: () => completer.complete());
-  return completer.future;
-}
-
-/// A pair of values.
-class Pair<E, F> {
-  E first;
-  F last;
-
-  Pair(this.first, this.last);
-
-  @override
-  String toString() => '($first, $last)';
-
-  @override
-  bool operator ==(other) {
-    if (other is! Pair) return false;
-    return other.first == first && other.last == last;
-  }
-
-  @override
-  int get hashCode => first.hashCode ^ last.hashCode;
-}
-
-/// Configures [future] so that its result (success or exception) is passed on
-/// to [completer].
-void chainToCompleter(Future future, Completer completer) {
-  future.then(completer.complete, onError: completer.completeError);
-}
diff --git a/test/utils.dart b/test/utils.dart
index f37f9a1..44cf12d 100644
--- a/test/utils.dart
+++ b/test/utils.dart
@@ -106,17 +106,9 @@
   }
 }
 
-/// A matcher that matches a [http.ClientException] with the given [message].
-///
-/// [message] can be a String or a [Matcher].
-Matcher isClientException(message) => predicate((error) {
-      expect(error, TypeMatcher<http.ClientException>());
-      expect(error.message, message);
-      return true;
-    });
-
 /// A matcher that matches function or future that throws a
 /// [http.ClientException] with the given [message].
 ///
 /// [message] can be a String or a [Matcher].
-Matcher throwsClientException(message) => throwsA(isClientException(message));
+Matcher throwsClientException(message) => throwsA(
+    isA<http.ClientException>().having((e) => e.message, 'message', message));