 	///
 	/// No further chunks will occur after this has been sent.
 	case Aggregated(NSData)
-
-	/// Convenience constructor for a `Chunk` from `dispatch_data_t`.
-	static func chunk(data: dispatch_data_t) -> ReadData {
-		return .Chunk(data as! NSData)
-	}
-
-	/// Convenience constructor for an `Aggregated` from `dispatch_data_t`.
-	static func aggregated(data: dispatch_data_t?) -> ReadData {
-		if let data = data {
-			return .Aggregated(data as! NSData)
-		} else {
-			return .Aggregated(NSData())
-		}
-	}
+}
+
+private func +(lhs: NSData, rhs: NSData) -> NSData {
+	let result = NSMutableData()
+	result.appendData(lhs)
+	result.appendData(rhs)
+	return result
 }
 
 /// Takes ownership of the read handle from the given pipe, then sends

			dispatch_io_set_low_water(channel, 1)
			dispatch_io_read(channel, 0, Int.max, self.queue) { (done, data, error) in
				if let data = data {
					observer.sendNext(data)
				}

				if error == ECANCELED {

	///
	/// After starting the returned producer, `readFD` should not be used
	/// anywhere else, as it may close unexpectedly.
	func transferReadsToProducer() -> SignalProducer<NSData, TaskError> {
		return SignalProducer { observer, disposable in
			dispatch_group_enter(self.group)
			let channel = dispatch_io_create(DISPATCH_IO_STREAM, self.readFD, self.queue) { error in
