         self.init(data: dispatch_data_create(start, count * DispatchData <Element>.elementSize, nil, nil))
     }
 
+    // MARK: Mapping data.
+
+    // TODO: Rename to "with", "withUnsafeBufferPointer", "withDataAndUnsafeBufferPointer"
+
+    /// IMPORTANT: If you need to keep the buffer beyond the scope of block you must hold on to data DispatchData instance too. The DispatchData and the buffer share the same life time.
+    public func createMap <R> (@noescape block: (DispatchData <Element>, UnsafeBufferPointer <Element>) throws -> R) rethrows -> R {
+        var pointer: UnsafePointer <Void> = nil
+        var size: Int = 0
+        let mappedData = dispatch_data_create_map(data, &pointer, &size)
+        let buffer = UnsafeBufferPointer <Element> (start: UnsafePointer <Element> (pointer), count: size)
+        return try block(DispatchData <Element> (data: mappedData), buffer)
+    }
+
     // MARK: -
+
+    /// Unfortunately cannot make this method "rethrows" or @noescape because it gets passed across a non-swift closure
+    public func apply(applier: (Range<Int>, UnsafeBufferPointer <Element>) -> Bool) {
+        dispatch_data_apply(data) {
+            (region: dispatch_data_t!, offset: Int, buffer: UnsafePointer <Void>, size: Int) -> Bool in
+            let buffer = UnsafeBufferPointer <Element> (start: UnsafePointer <Element> (buffer), count: size / self.elementSize)
+            return applier(offset..<offset + size, buffer)
+        }
+    }
+
+    public func convert <U> () -> DispatchData <U> {
+        return DispatchData <U> (data: data)
+    }
+}
+
+// MARK: -
+
+public func + <Element> (lhs: DispatchData <Element>, rhs: DispatchData <Element>) -> DispatchData <Element> {
+    let data = dispatch_data_create_concat(lhs.data, rhs.data)
+    return DispatchData <Element> (data: data)
+}
+
+// MARK: -
+
+public extension DispatchData {
+    public subscript (range: Range <Int>) -> DispatchData <Element> {
+        return subBuffer(range)
+    }
+}
+
+// MARK: -
+
+/// Do not really like these function names but they're very useful.
+public extension DispatchData {
 
     public func subBuffer(range: Range <Int>) -> DispatchData <Element> {
         assert(range.startIndex >= startIndex && range.startIndex <= endIndex)

        return false
    }

    return lhs.map() {
        (lhsData, lhsBuffer) -> Bool in

        return rhs.map() {
            (rhsData, rhsBuffer) -> Bool in

            let result = memcmp(lhsBuffer.baseAddress, rhsBuffer.baseAddress, lhsBuffer.length)

        return DispatchData <Element> (data: dispatch_data_create_subrange(data, range.startIndex * elementSize, (range.endIndex - range.startIndex) * elementSize))
    }

    public func subBuffer(startIndex startIndex: Int, count: Int) -> DispatchData <Element> {
        return subBuffer(Range <Int> (start: startIndex, end: startIndex + count))
    }
