Use BytesBuilder for collectBytes (#185)

When this utility was first written `BytesBuilder` was only importable
from `dart:io`. Now that it may be imported from the cross platform
`dart:typed_data` it can be used in `package:async`.
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 2e366fe..51c067d 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,4 +1,4 @@
-## 2.7.0-dev
+## 2.7.1-dev
 
 * Improve performance for `ChunkedStreamReader` by creating fewer internal
   sublists and specializing to create views for `Uint8List` chunks.
diff --git a/lib/src/byte_collector.dart b/lib/src/byte_collector.dart
index 0226dea..a7a5435 100644
--- a/lib/src/byte_collector.dart
+++ b/lib/src/byte_collector.dart
@@ -42,30 +42,11 @@
 /// so it can cancel the operation.
 T _collectBytes<T>(Stream<List<int>> source,
     T Function(StreamSubscription<List<int>>, Future<Uint8List>) result) {
-  var byteLists = <List<int>>[];
-  var length = 0;
+  var bytes = BytesBuilder();
   var completer = Completer<Uint8List>.sync();
-  var subscription = source.listen(
-      (bytes) {
-        byteLists.add(bytes);
-        length += bytes.length;
-      },
-      onError: completer.completeError,
-      onDone: () {
-        completer.complete(_collect(length, byteLists));
-      },
-      cancelOnError: true);
+  var subscription =
+      source.listen(bytes.add, onError: completer.completeError, onDone: () {
+    completer.complete(bytes.takeBytes());
+  }, cancelOnError: true);
   return result(subscription, completer.future);
 }
-
-// Join a lists of bytes with a known total length into a single [Uint8List].
-Uint8List _collect(int length, List<List<int>> byteLists) {
-  var result = Uint8List(length);
-  var i = 0;
-  for (var byteList in byteLists) {
-    var end = i + byteList.length;
-    result.setRange(i, end, byteList);
-    i = end;
-  }
-  return result;
-}