Merge pull request #1283 from phausler/swift-4.0-branch-data_sync

diff --git a/CoreFoundation/Base.subproj/ForSwiftFoundationOnly.h b/CoreFoundation/Base.subproj/ForSwiftFoundationOnly.h
index c580409..df0f6f3 100644
--- a/CoreFoundation/Base.subproj/ForSwiftFoundationOnly.h
+++ b/CoreFoundation/Base.subproj/ForSwiftFoundationOnly.h
@@ -343,6 +343,54 @@
 /// a single base directory relative to which user-specific runtime files and other file objects should be placed. This directory is defined by the environment variable $XDG_RUNTIME_DIR.
 CF_EXPORT CFStringRef _CFXDGCreateRuntimeDirectoryPath(void);
 
+
+typedef struct {
+    void *_Nonnull memory;
+    size_t capacity;
+    _Bool onStack;
+} _ConditionalAllocationBuffer;
+
+static inline _Bool _resizeConditionalAllocationBuffer(_ConditionalAllocationBuffer *_Nonnull buffer, size_t amt) {
+#if TARGET_OS_MAC
+    size_t amount = malloc_good_size(amt);
+#else
+    size_t amount = amt;
+#endif
+    if (amount <= buffer->capacity) { return true; }
+    void *newMemory;
+    if (buffer->onStack) {
+        newMemory = malloc(amount);
+        if (newMemory == NULL) { return false; }
+        memcpy(newMemory, buffer->memory, buffer->capacity);
+        buffer->onStack = false;
+    } else {
+        newMemory = realloc(buffer->memory, amount);
+        if (newMemory == NULL) { return false; }
+    }
+    if (newMemory == NULL) { return false; }
+    buffer->memory = newMemory;
+    buffer->capacity = amount;
+    return true;
+}
+
+static inline _Bool _withStackOrHeapBuffer(size_t amount, void (__attribute__((noescape)) ^ _Nonnull applier)(_ConditionalAllocationBuffer *_Nonnull)) {
+    _ConditionalAllocationBuffer buffer;
+#if TARGET_OS_MAC
+    buffer.capacity = malloc_good_size(amount);
+#else
+    buffer.capacity = amount;
+#endif
+    buffer.onStack = (_CFIsMainThread() != 0 ? buffer.capacity < 2048 : buffer.capacity < 512);
+    buffer.memory = buffer.onStack ? alloca(buffer.capacity) : malloc(buffer.capacity);
+    if (buffer.memory == NULL) { return false; }
+    applier(&buffer);
+    if (!buffer.onStack) {
+        free(buffer.memory);
+    }
+    return true;
+}
+
+
 _CF_EXPORT_SCOPE_END
 
 #endif /* __COREFOUNDATION_FORSWIFTFOUNDATIONONLY__ */
diff --git a/Foundation/Data.swift b/Foundation/Data.swift
index aa63929..0102662 100644
--- a/Foundation/Data.swift
+++ b/Foundation/Data.swift
@@ -27,6 +27,10 @@
 internal func __NSDataInvokeDeallocatorFree(_ mem: UnsafeMutableRawPointer, _ length: Int) {
     free(mem)
 }
+
+internal func __NSDataIsCompact(_ data: NSData) -> Bool {
+    return data._isCompact()
+}
     
 #else
     
@@ -34,6 +38,22 @@
 import _SwiftFoundationOverlayShims
 import _SwiftCoreFoundationOverlayShims
     
+internal func __NSDataIsCompact(_ data: NSData) -> Bool {
+    if #available(OSX 10.10, iOS 9.0, tvOS 9.0, watchOS 2.0, *) {
+        return data._isCompact()
+    } else {
+        var compact = true
+        let len = data.length
+        data.enumerateBytes { (_, byteRange, stop) in
+            if byteRange.length != len {
+                compact = false
+            }
+            stop.pointee = true
+        }
+        return compact
+    }
+}
+
 @_silgen_name("__NSDataWriteToURL")
 internal func __NSDataWriteToURL(_ data: NSData, _ url: NSURL, _ options: UInt, _ error: NSErrorPointer) -> Bool
     
@@ -98,47 +118,140 @@
     public var _needToZero: Bool
     public var _deallocator: ((UnsafeMutableRawPointer, Int) -> Void)?
     public var _backing: Backing = .swift
+    public var _offset: Int
     
     public var bytes: UnsafeRawPointer? {
         @inline(__always)
         get {
             switch _backing {
             case .swift:
-                return UnsafeRawPointer(_bytes)
+                return UnsafeRawPointer(_bytes)?.advanced(by: -_offset)
             case .immutable:
-                return UnsafeRawPointer(_bytes)
+                return UnsafeRawPointer(_bytes)?.advanced(by: -_offset)
             case .mutable:
-                return UnsafeRawPointer(_bytes)
+                return UnsafeRawPointer(_bytes)?.advanced(by: -_offset)
             case .customReference(let d):
-                return d.bytes
+                return d.bytes.advanced(by: -_offset)
             case .customMutableReference(let d):
-                return d.bytes
+                return d.bytes.advanced(by: -_offset)
+            }
+        }
+    }
+
+    @discardableResult
+    public func withUnsafeBytes<Result>(in range: Range<Int>, apply: (UnsafeRawBufferPointer) throws -> Result) rethrows -> Result {
+        switch _backing {
+        case .swift: fallthrough
+        case .immutable: fallthrough
+        case .mutable:
+            return try apply(UnsafeRawBufferPointer(start: _bytes?.advanced(by: range.lowerBound - _offset), count: Swift.min(range.count, _length)))
+        case .customReference(let d):
+            if __NSDataIsCompact(d) {
+                let len = d.length
+                guard len > 0 else {
+                    return try apply(UnsafeRawBufferPointer(start: nil, count: 0))
+                }
+                return try apply(UnsafeRawBufferPointer(start: d.bytes.advanced(by: range.lowerBound - _offset), count: Swift.min(range.count, len)))
+            } else {
+                var buffer = UnsafeMutableRawBufferPointer.allocate(count: range.count)
+                defer { buffer.deallocate() }
+                let sliceRange = NSRange(location: range.lowerBound - _offset, length: range.count)
+                var enumerated = 0
+                d.enumerateBytes { (ptr, byteRange, stop) in
+                    if NSIntersectionRange(sliceRange, byteRange).length > 0 {
+                        let lower = Swift.max(byteRange.location, sliceRange.location)
+                        let upper = Swift.min(byteRange.location + byteRange.length, sliceRange.location + sliceRange.length)
+                        let offset = lower - byteRange.location
+                        let effectiveRange = NSRange(location: lower, length: upper - lower)
+                        if effectiveRange == sliceRange {
+                            memcpy(buffer.baseAddress!, ptr, effectiveRange.length)
+                            stop.pointee = true
+                        } else {
+                            memcpy(buffer.baseAddress!.advanced(by: enumerated), ptr, effectiveRange.length)
+                        }
+                        enumerated += byteRange.length
+                    } else if sliceRange.location + sliceRange.length < byteRange.location {
+                        stop.pointee = true
+                    }
+                }
+                return try apply(UnsafeRawBufferPointer(buffer))
+            }
+        case .customMutableReference(let d):
+            if __NSDataIsCompact(d) {
+                let len = d.length
+                guard len > 0 else {
+                    return try apply(UnsafeRawBufferPointer(start: nil, count: 0))
+                }
+                return try apply(UnsafeRawBufferPointer(start: d.bytes.advanced(by: range.lowerBound - _offset), count: Swift.min(range.count, len)))
+            } else {
+                var buffer = UnsafeMutableRawBufferPointer.allocate(count: range.count)
+                defer { buffer.deallocate() }
+                let sliceRange = NSRange(location: range.lowerBound - _offset, length: range.count)
+                var enumerated = 0
+                d.enumerateBytes { (ptr, byteRange, stop) in
+                    if NSIntersectionRange(sliceRange, byteRange).length > 0 {
+                        let lower = Swift.max(byteRange.location, sliceRange.location)
+                        let upper = Swift.min(byteRange.location + byteRange.length, sliceRange.location + sliceRange.length)
+                        let effectiveRange = NSRange(location: lower, length: upper - lower)
+                        if effectiveRange == sliceRange {
+                            memcpy(buffer.baseAddress!, ptr, effectiveRange.length)
+                            stop.pointee = true
+                        } else {
+                            memcpy(buffer.baseAddress!.advanced(by: enumerated), ptr, effectiveRange.length)
+                        }
+                        enumerated += byteRange.length
+                    } else if sliceRange.location + sliceRange.length < byteRange.location {
+                        stop.pointee = true
+                    }
+                }
+                return try apply(UnsafeRawBufferPointer(buffer))
             }
         }
     }
     
+    @discardableResult
+    public func withUnsafeMutableBytes<Result>(in range: Range<Int>, apply: (UnsafeMutableRawBufferPointer) throws -> Result) rethrows -> Result {
+        switch _backing {
+        case .swift: fallthrough
+        case .mutable:
+            return try apply(UnsafeMutableRawBufferPointer(start: _bytes!.advanced(by:range.lowerBound - _offset), count: Swift.min(range.count, _length - range.lowerBound)))
+        case .customMutableReference(let d):
+            let len = d.length
+            return try apply(UnsafeMutableRawBufferPointer(start: d.mutableBytes.advanced(by:range.lowerBound - _offset), count: Swift.min(range.count, len - range.lowerBound)))
+        case .immutable(let d):
+            let data = d.mutableCopy() as! NSMutableData
+            _backing = .mutable(data)
+            _bytes = data.mutableBytes
+            return try apply(UnsafeMutableRawBufferPointer(start: _bytes!.advanced(by:range.lowerBound - _offset), count: Swift.min(range.count, _length - range.lowerBound)))
+        case .customReference(let d):
+            let data = d.mutableCopy() as! NSMutableData
+            _backing = .customMutableReference(data)
+            let len = data.length
+            return try apply(UnsafeMutableRawBufferPointer(start: data.mutableBytes.advanced(by:range.lowerBound - _offset), count: Swift.min(range.count, len - range.lowerBound)))
+        }
+    }
+
     public var mutableBytes: UnsafeMutableRawPointer? {
         @inline(__always)
         get {
             switch _backing {
             case .swift:
-                return _bytes
+                return _bytes?.advanced(by: -_offset)
             case .immutable(let d):
                 let data = d.mutableCopy() as! NSMutableData
                 data.length = length
                 _backing = .mutable(data)
                 _bytes = data.mutableBytes
-                return data.mutableBytes
+                return _bytes?.advanced(by: -_offset)
             case .mutable:
-                return _bytes
+                return _bytes?.advanced(by: -_offset)
             case .customReference(let d):
                 let data = d.mutableCopy() as! NSMutableData
                 data.length = length
                 _backing = .customMutableReference(data)
-                _bytes = data.mutableBytes
-                return data.mutableBytes
+                return data.mutableBytes.advanced(by: -_offset)
             case .customMutableReference(let d):
-                return d.mutableBytes
+                return d.mutableBytes.advanced(by: -_offset)
             }
         }
     }
@@ -176,32 +289,34 @@
         }
     }
     
-    public func enumerateBytes(_ block: (_ buffer: UnsafeBufferPointer<UInt8>, _ byteIndex: Data.Index, _ stop: inout Bool) -> Void) {
-        var stop: Bool = false
+    public func enumerateBytes(in range: Range<Int>, _ block: (_ buffer: UnsafeBufferPointer<UInt8>, _ byteIndex: Data.Index, _ stop: inout Bool) -> Void) {
+        var stopv: Bool = false
+        var data: NSData
         switch _backing {
-        case .swift:
-            block(UnsafeBufferPointer<UInt8>(start: _bytes?.assumingMemoryBound(to: UInt8.self), count: _length), 0, &stop)
-        case .immutable:
-            block(UnsafeBufferPointer<UInt8>(start: _bytes?.assumingMemoryBound(to: UInt8.self), count: _length), 0, &stop)
-        case .mutable:
-            block(UnsafeBufferPointer<UInt8>(start: _bytes?.assumingMemoryBound(to: UInt8.self), count: _length), 0, &stop)
+        case .swift: fallthrough
+        case .immutable: fallthrough
+        case .mutable: 
+            block(UnsafeBufferPointer<UInt8>(start: _bytes?.advanced(by: range.lowerBound - _offset).assumingMemoryBound(to: UInt8.self), count: Swift.min(range.count, _length)), 0, &stopv)
+            return
         case .customReference(let d):
-            d.enumerateBytes { (ptr, range, stop) in
-                var stopv = false
-                let bytePtr = ptr.bindMemory(to: UInt8.self, capacity: range.length)
-                block(UnsafeBufferPointer(start: bytePtr, count: range.length), range.location, &stopv)
-                if stopv {
-                    stop.pointee = true
-                }
-            }
+            data = d
+            break
         case .customMutableReference(let d):
-            d.enumerateBytes { (ptr, range, stop) in
-                var stopv = false
-                let bytePtr = ptr.bindMemory(to: UInt8.self, capacity: range.length)
-                block(UnsafeBufferPointer(start: bytePtr, count: range.length), range.location, &stopv)
-                if stopv {
-                    stop.pointee = true
-                }
+            data = d
+            break
+        }
+        data.enumerateBytes { (ptr, region, stop) in
+            // any region that is not in the range should be skipped
+            guard range.contains(region.lowerBound) || range.contains(region.upperBound) else { return }
+            var regionAdjustment = 0
+            if region.lowerBound < range.lowerBound {
+                regionAdjustment = range.lowerBound - (region.lowerBound - _offset)
+            }
+            let bytePtr  = ptr.advanced(by: regionAdjustment).assumingMemoryBound(to: UInt8.self)
+            let effectiveLength = Swift.min((region.location - _offset) + region.length, range.upperBound) - (region.location - _offset)
+            block(UnsafeBufferPointer(start: bytePtr, count: effectiveLength - regionAdjustment), region.location + regionAdjustment - _offset, &stopv)
+            if stopv {
+                stop.pointee = true
             }
         }
     }
@@ -319,7 +434,7 @@
     
     @inline(__always)
     public func append(_ bytes: UnsafeRawPointer, length: Int) {
-        precondition(length >= 0, "Length of appending bytes must be positive")
+        precondition(length >= 0, "Length of appending bytes must not be negative")
         switch _backing {
         case .swift:
             let origLength = _length
@@ -398,6 +513,43 @@
         }
         
     }
+
+    public func get(_ index: Int) -> UInt8 {
+        switch _backing {
+        case .swift: fallthrough
+        case .immutable: fallthrough
+        case .mutable:
+            return _bytes!.advanced(by: index - _offset).assumingMemoryBound(to: UInt8.self).pointee
+        case .customReference(let d):
+            if __NSDataIsCompact(d) {
+                return d.bytes.advanced(by: index - _offset).assumingMemoryBound(to: UInt8.self).pointee
+            } else {
+                var byte: UInt8 = 0
+                d.enumerateBytes { (ptr, range, stop) in
+                    if NSLocationInRange(index, range) {
+                        let offset = index - range.location - _offset
+                        byte = ptr.advanced(by: offset).assumingMemoryBound(to: UInt8.self).pointee
+                        stop.pointee = true
+                    }
+                }
+                return byte
+            }
+        case .customMutableReference(let d):
+            if __NSDataIsCompact(d) {
+                return d.bytes.advanced(by: index - _offset).assumingMemoryBound(to: UInt8.self).pointee
+            } else {
+                var byte: UInt8 = 0
+                d.enumerateBytes { (ptr, range, stop) in
+                    if NSLocationInRange(index, range) {
+                        let offset = index - range.location - _offset
+                        byte = ptr.advanced(by: offset).assumingMemoryBound(to: UInt8.self).pointee
+                        stop.pointee = true
+                    }
+                }
+                return byte
+            }
+        }
+    }
     
     @inline(__always)
     public func set(_ index: Int, to value: UInt8) {
@@ -405,7 +557,7 @@
         case .swift:
             fallthrough
         case .mutable:
-            _bytes!.advanced(by: index).assumingMemoryBound(to: UInt8.self).pointee = value
+            _bytes!.advanced(by: index - _offset).assumingMemoryBound(to: UInt8.self).pointee = value
         default:
             var theByte = value
             let range = NSRange(location: index, length: 1)
@@ -427,28 +579,29 @@
                 }
                 _length = newLength
             }
-            _DataStorage.move(_bytes!.advanced(by: range.location), bytes!, range.length)
+            _DataStorage.move(_bytes!.advanced(by: range.location - _offset), bytes!, range.length)
         case .immutable(let d):
             let data = d.mutableCopy() as! NSMutableData
-            data.replaceBytes(in: range, withBytes: bytes!)
+            data.replaceBytes(in: NSRange(location: range.location - _offset, length: range.length), withBytes: bytes!)
             _backing = .mutable(data)
             _length = data.length
             _bytes = data.mutableBytes
         case .mutable(let d):
-            d.replaceBytes(in: range, withBytes: bytes!)
+            d.replaceBytes(in: NSRange(location: range.location - _offset, length: range.length), withBytes: bytes!)
             _length = d.length
             _bytes = d.mutableBytes
         case .customReference(let d):
             let data = d.mutableCopy() as! NSMutableData
-            data.replaceBytes(in: range, withBytes: bytes!)
+            data.replaceBytes(in: NSRange(location: range.location - _offset, length: range.length), withBytes: bytes!)
             _backing = .customMutableReference(data)
         case .customMutableReference(let d):
-            d.replaceBytes(in: range, withBytes: bytes!)
+            d.replaceBytes(in: NSRange(location: range.location - _offset, length: range.length), withBytes: bytes!)
         }
     }
     
     @inline(__always)
-    public func replaceBytes(in range: NSRange, with replacementBytes: UnsafeRawPointer?, length replacementLength: Int) {
+    public func replaceBytes(in range_: NSRange, with replacementBytes: UnsafeRawPointer?, length replacementLength: Int) {
+        let range = NSRange(location: range_.location - _offset, length: range_.length)
         let currentLength = _length
         let resultingLength = currentLength - range.length + replacementLength
         switch _backing {
@@ -480,12 +633,12 @@
             let data = d.mutableCopy() as! NSMutableData
             data.replaceBytes(in: range, withBytes: replacementBytes, length: replacementLength)
             _backing = .mutable(data)
-            _length = replacementLength
+            _length = data.length
             _bytes = data.mutableBytes
         case .mutable(let d):
             d.replaceBytes(in: range, withBytes: replacementBytes, length: replacementLength)
             _backing = .mutable(d)
-            _length = replacementLength
+            _length = d.length
             _bytes = d.mutableBytes
         case .customReference(let d):
             let data = d.mutableCopy() as! NSMutableData
@@ -497,7 +650,8 @@
     }
     
     @inline(__always)
-    public func resetBytes(in range: NSRange) {
+    public func resetBytes(in range_: NSRange) {
+        let range = NSRange(location: range_.location - _offset, length: range_.length)
         if range.length == 0 { return }
         switch _backing {
         case .swift:
@@ -546,6 +700,7 @@
         _capacity = capacity
         _needToZero = !clear
         _length = 0
+        _offset = 0
         setLength(length)
     }
     
@@ -560,10 +715,12 @@
         _bytes = _DataStorage.allocate(capacity, false)!
         _capacity = capacity
         _needToZero = true
+        _offset = 0
     }
     
     public init(bytes: UnsafeRawPointer?, length: Int) {
         precondition(length < _DataStorage.maxSize)
+        _offset = 0
         if length == 0 {
             _capacity = 0
             _length = 0
@@ -588,8 +745,9 @@
         }
     }
     
-    public init(bytes: UnsafeMutableRawPointer?, length: Int, copy: Bool, deallocator: ((UnsafeMutableRawPointer, Int) -> Void)?) {
+    public init(bytes: UnsafeMutableRawPointer?, length: Int, copy: Bool, deallocator: ((UnsafeMutableRawPointer, Int) -> Void)?, offset: Int) {
         precondition(length < _DataStorage.maxSize)
+        _offset = offset
         if length == 0 {
             _capacity = 0
             _length = 0
@@ -630,7 +788,8 @@
         }
     }
     
-    public init(immutableReference: NSData) {
+    public init(immutableReference: NSData, offset: Int) {
+        _offset = offset
         _bytes = UnsafeMutableRawPointer(mutating: immutableReference.bytes)
         _capacity = 0
         _needToZero = false
@@ -638,7 +797,8 @@
         _backing = .immutable(immutableReference)
     }
     
-    public init(mutableReference: NSMutableData) {
+    public init(mutableReference: NSMutableData, offset: Int) {
+        _offset = offset
         _bytes = mutableReference.mutableBytes
         _capacity = 0
         _needToZero = false
@@ -646,7 +806,8 @@
         _backing = .mutable(mutableReference)
     }
     
-    public init(customReference: NSData) {
+    public init(customReference: NSData, offset: Int) {
+        _offset = offset
         _bytes = nil
         _capacity = 0
         _needToZero = false
@@ -654,7 +815,8 @@
         _backing = .customReference(customReference)
     }
     
-    public init(customMutableReference: NSMutableData) {
+    public init(customMutableReference: NSMutableData, offset: Int) {
+        _offset = offset
         _bytes = nil
         _capacity = 0
         _needToZero = false
@@ -675,30 +837,30 @@
     public func mutableCopy(_ range: Range<Int>) -> _DataStorage {
         switch _backing {
         case .swift:
-            return _DataStorage(bytes: _bytes?.advanced(by: range.lowerBound), length: range.count, copy: true, deallocator: nil)
+            return _DataStorage(bytes: _bytes?.advanced(by: range.lowerBound - _offset), length: range.count, copy: true, deallocator: nil, offset: range.lowerBound)
         case .immutable(let d):
             if range.lowerBound == 0 && range.upperBound == _length {
-                return _DataStorage(mutableReference: d.mutableCopy() as! NSMutableData)
+                return _DataStorage(mutableReference: d.mutableCopy() as! NSMutableData, offset: range.lowerBound)
             } else {
-                return _DataStorage(mutableReference: d.subdata(with: NSRange(location: range.lowerBound, length: range.count))._bridgeToObjectiveC().mutableCopy() as! NSMutableData)
+                return _DataStorage(mutableReference: d.subdata(with: NSRange(location: range.lowerBound, length: range.count))._bridgeToObjectiveC().mutableCopy() as! NSMutableData, offset: range.lowerBound)
             }
         case .mutable(let d):
             if range.lowerBound == 0 && range.upperBound == _length {
-                return _DataStorage(mutableReference: d.mutableCopy() as! NSMutableData)
+                return _DataStorage(mutableReference: d.mutableCopy() as! NSMutableData, offset: range.lowerBound)
             } else {
-                return _DataStorage(mutableReference: d.subdata(with: NSRange(location: range.lowerBound, length: range.count))._bridgeToObjectiveC().mutableCopy() as! NSMutableData)
+                return _DataStorage(mutableReference: d.subdata(with: NSRange(location: range.lowerBound, length: range.count))._bridgeToObjectiveC().mutableCopy() as! NSMutableData, offset: range.lowerBound)
             }
         case .customReference(let d):
             if range.lowerBound == 0 && range.upperBound == _length {
-                return _DataStorage(mutableReference: d.mutableCopy() as! NSMutableData)
+                return _DataStorage(mutableReference: d.mutableCopy() as! NSMutableData, offset: range.lowerBound)
             } else {
-                return _DataStorage(mutableReference: d.subdata(with: NSRange(location: range.lowerBound, length: range.count))._bridgeToObjectiveC().mutableCopy() as! NSMutableData)
+                return _DataStorage(mutableReference: d.subdata(with: NSRange(location: range.lowerBound, length: range.count))._bridgeToObjectiveC().mutableCopy() as! NSMutableData, offset: range.lowerBound)
             }
         case .customMutableReference(let d):
             if range.lowerBound == 0 && range.upperBound == _length {
-                return _DataStorage(mutableReference: d.mutableCopy() as! NSMutableData)
+                return _DataStorage(mutableReference: d.mutableCopy() as! NSMutableData, offset: range.lowerBound)
             } else {
-                return _DataStorage(mutableReference: d.subdata(with: NSRange(location: range.lowerBound, length: range.count))._bridgeToObjectiveC().mutableCopy() as! NSMutableData)
+                return _DataStorage(mutableReference: d.subdata(with: NSRange(location: range.lowerBound, length: range.count))._bridgeToObjectiveC().mutableCopy() as! NSMutableData, offset: range.lowerBound)
             }
         }
     }
@@ -710,26 +872,26 @@
         
         switch _backing {
         case .swift:
-            return try work(NSData(bytesNoCopy: _bytes!.advanced(by: range.lowerBound), length: range.count, freeWhenDone: false))
+            return try work(NSData(bytesNoCopy: _bytes!.advanced(by: range.lowerBound - _offset), length: range.count, freeWhenDone: false))
         case .immutable(let d):
             guard range.lowerBound == 0 && range.upperBound == _length else {
-                return try work(NSData(bytesNoCopy: _bytes!.advanced(by: range.lowerBound), length: range.count, freeWhenDone: false))
+                return try work(NSData(bytesNoCopy: _bytes!.advanced(by: range.lowerBound - _offset), length: range.count, freeWhenDone: false))
             }
             return try work(d)
         case .mutable(let d):
             guard range.lowerBound == 0 && range.upperBound == _length else {
-                return try work(NSData(bytesNoCopy: _bytes!.advanced(by: range.lowerBound), length: range.count, freeWhenDone: false))
+                return try work(NSData(bytesNoCopy: _bytes!.advanced(by: range.lowerBound - _offset), length: range.count, freeWhenDone: false))
             }
             return try work(d)
         case .customReference(let d):
             guard range.lowerBound == 0 && range.upperBound == _length else {
                 
-                return try work(NSData(bytesNoCopy: UnsafeMutableRawPointer(mutating: d.bytes.advanced(by: range.lowerBound)), length: range.count, freeWhenDone: false))
+                return try work(NSData(bytesNoCopy: UnsafeMutableRawPointer(mutating: d.bytes.advanced(by: range.lowerBound - _offset)), length: range.count, freeWhenDone: false))
             }
             return try work(d)
         case .customMutableReference(let d):
             guard range.lowerBound == 0 && range.upperBound == _length else {
-                return try work(NSData(bytesNoCopy: UnsafeMutableRawPointer(mutating: d.bytes.advanced(by: range.lowerBound)), length: range.count, freeWhenDone: false))
+                return try work(NSData(bytesNoCopy: UnsafeMutableRawPointer(mutating: d.bytes.advanced(by: range.lowerBound - _offset)), length: range.count, freeWhenDone: false))
             }
             return try work(d)
         }
@@ -766,26 +928,14 @@
         }
     }
     
-    public var hashValue: Int {
-        switch _backing {
-        case .customReference(let d):
-            return d.hash
-        case .customMutableReference(let d):
-            return d.hash
-        default:
-            let len = _length
-            return Int(bitPattern: CFHashBytes(_bytes?.assumingMemoryBound(to: UInt8.self), Swift.min(len, 80)))
-        }
-    }
-    
     public func subdata(in range: Range<Data.Index>) -> Data {
         switch _backing {
         case .customReference(let d):
-            return d.subdata(with: NSRange(location: range.lowerBound, length: range.count))
+            return d.subdata(with: NSRange(location: range.lowerBound - _offset, length: range.count))
         case .customMutableReference(let d):
-            return d.subdata(with: NSRange(location: range.lowerBound, length: range.count))
+            return d.subdata(with: NSRange(location: range.lowerBound - _offset, length: range.count))
         default:
-            return Data(bytes: _bytes!.advanced(by: range.lowerBound), count: range.count)
+            return Data(bytes: _bytes!.advanced(by: range.lowerBound - _offset), count: range.count)
         }
     }
 }
@@ -827,7 +977,7 @@
     }
     
 #if !DEPLOYMENT_RUNTIME_SWIFT
-    @objc
+    @objc override
     func _isCompact() -> Bool {
         return true
     }
@@ -1015,7 +1165,7 @@
     /// - parameter deallocator: Specifies the mechanism to free the indicated buffer, or `.none`.
     public init(bytesNoCopy bytes: UnsafeMutableRawPointer, count: Int, deallocator: Deallocator) {
         let whichDeallocator = deallocator._deallocator
-        _backing = _DataStorage(bytes: bytes, length: count, copy: false, deallocator: whichDeallocator)
+        _backing = _DataStorage(bytes: bytes, length: count, copy: false, deallocator: whichDeallocator, offset: 0)
         _sliceRange = 0..<count
     }
     
@@ -1026,7 +1176,7 @@
     /// - throws: An error in the Cocoa domain, if `url` cannot be read.
     public init(contentsOf url: URL, options: Data.ReadingOptions = []) throws {
         let d = try NSData(contentsOf: url, options: ReadingOptions(rawValue: options.rawValue))
-        _backing = _DataStorage(immutableReference: d)
+        _backing = _DataStorage(immutableReference: d, offset: 0)
         _sliceRange = 0..<d.length
     }
     
@@ -1037,7 +1187,7 @@
     /// - parameter options: Encoding options. Default value is `[]`.
     public init?(base64Encoded base64String: String, options: Data.Base64DecodingOptions = []) {
         if let d = NSData(base64Encoded: base64String, options: Base64DecodingOptions(rawValue: options.rawValue)) {
-            _backing = _DataStorage(immutableReference: d)
+            _backing = _DataStorage(immutableReference: d, offset: 0)
             _sliceRange = 0..<d.length
         } else {
             return nil
@@ -1052,7 +1202,7 @@
     /// - parameter options: Decoding options. Default value is `[]`.
     public init?(base64Encoded base64Data: Data, options: Data.Base64DecodingOptions = []) {
         if let d = NSData(base64Encoded: base64Data, options: Base64DecodingOptions(rawValue: options.rawValue)) {
-            _backing = _DataStorage(immutableReference: d)
+            _backing = _DataStorage(immutableReference: d, offset: 0)
             _sliceRange = 0..<d.length
         } else {
             return nil
@@ -1073,10 +1223,10 @@
         let providesConcreteBacking = (reference as AnyObject)._providesConcreteBacking?() ?? false
 #endif
         if providesConcreteBacking {
-            _backing = _DataStorage(immutableReference: reference.copy() as! NSData)
+            _backing = _DataStorage(immutableReference: reference.copy() as! NSData, offset: 0)
             _sliceRange = 0..<reference.length
         } else {
-            _backing = _DataStorage(customReference: reference.copy() as! NSData)
+            _backing = _DataStorage(customReference: reference.copy() as! NSData, offset: 0)
             _sliceRange = 0..<reference.length
         }
         
@@ -1085,40 +1235,30 @@
     // slightly faster paths for common sequences
     
     public init<S: Sequence>(_ elements: S) where S.Iterator.Element == UInt8 {
-        let underestimatedCount = elements.underestimatedCount
-        self.init(count: underestimatedCount)
-        var idx = 0
-        for byte in elements {
-            if idx < underestimatedCount {
-                self[idx] = byte
-            } else {
-                self.append(byte)
+        if elements is Array<UInt8> {
+            self.init(bytes: _identityCast(elements, to: Array<UInt8>.self))
+        } else if elements is ArraySlice<UInt8> {
+            self.init(bytes: _identityCast(elements, to: ArraySlice<UInt8>.self))
+        } else if elements is UnsafeBufferPointer<UInt8> {
+            self.init(buffer: _identityCast(elements, to: UnsafeBufferPointer<UInt8>.self))
+        } else if let buffer = elements as? UnsafeMutableBufferPointer<UInt8> {
+            self.init(buffer: buffer)
+        } else if let data = elements as? Data {
+            let len = data.count
+            let backing = data.withUnsafeBytes { (bytes: UnsafePointer<UInt8>) in
+                return _DataStorage(bytes: bytes, length: len)
             }
-            idx += 1
+            self.init(backing: backing, range: 0..<len)
+        } else {
+            let underestimatedCount = elements.underestimatedCount
+            self.init(count: underestimatedCount)
+            
+            let (endIterator, _) = UnsafeMutableBufferPointer(start: _backing._bytes?.assumingMemoryBound(to: UInt8.self), count: underestimatedCount).initialize(from: elements)
+            var iter = endIterator
+            while let byte = iter.next() { self.append(byte) }
         }
     }
-    
-    public init(_ bytes: Array<UInt8>) {
-        self.init(bytes: bytes)
-    }
-    
-    public init(_ bytes: ArraySlice<UInt8>) {
-        self.init(bytes: bytes)
-    }
-    
-    public init(_ buffer: UnsafeBufferPointer<UInt8>) {
-        self.init(buffer: buffer)
-    }
-    
-    public init(_ buffer: UnsafeMutableBufferPointer<UInt8>) {
-        self.init(buffer: buffer)
-    }
-    
-    public init(_ data: Data) {
-        _sliceRange = 0..<data.count
-        _backing = data._backing.mutableCopy(data._sliceRange)
-    }
-    
+
     @_versioned
     internal init(backing: _DataStorage, range: Range<Index>) {
         _backing = backing
@@ -1151,7 +1291,7 @@
         }
         @inline(__always)
         set {
-            precondition(count >= 0, "count must be positive")
+            precondition(count >= 0, "count must not be negative")
             if !isKnownUniquelyReferenced(&_backing) {
                 _backing = _backing.mutableCopy(_sliceRange)
             }
@@ -1165,9 +1305,9 @@
     /// - warning: The byte pointer argument should not be stored and used outside of the lifetime of the call to the closure.
     @inline(__always)
     public func withUnsafeBytes<ResultType, ContentType>(_ body: (UnsafePointer<ContentType>) throws -> ResultType) rethrows -> ResultType {
-        let bytes =  _backing.bytes?.advanced(by: _sliceRange.lowerBound) ?? UnsafeRawPointer(bitPattern: 0xBAD0)!
-        let contentPtr = bytes.bindMemory(to: ContentType.self, capacity: count / MemoryLayout<ContentType>.stride)
-        return try body(contentPtr)
+        return try _backing.withUnsafeBytes(in: _sliceRange) {
+            return try body($0.baseAddress?.assumingMemoryBound(to: ContentType.self) ?? UnsafePointer<ContentType>(bitPattern: 0xBAD0)!)
+        }
     }
     
     
@@ -1180,9 +1320,9 @@
         if !isKnownUniquelyReferenced(&_backing) {
             _backing = _backing.mutableCopy(_sliceRange)
         }
-        let mutableBytes = _backing.mutableBytes?.advanced(by: _sliceRange.lowerBound) ?? UnsafeMutableRawPointer(bitPattern: 0xBAD0)!
-        let contentPtr = mutableBytes.bindMemory(to: ContentType.self, capacity: count / MemoryLayout<ContentType>.stride)
-        return try body(UnsafeMutablePointer(contentPtr))
+        return try _backing.withUnsafeMutableBytes(in: _sliceRange) {
+            return try body($0.baseAddress?.assumingMemoryBound(to: ContentType.self) ?? UnsafeMutablePointer<ContentType>(bitPattern: 0xBAD0)!)
+        }
     }
     
     // MARK: -
@@ -1195,15 +1335,19 @@
     /// - warning: This method does not verify that the contents at pointer have enough space to hold `count` bytes.
     @inline(__always)
     public func copyBytes(to pointer: UnsafeMutablePointer<UInt8>, count: Int) {
-        precondition(count >= 0, "count of bytes to copy must be positive")
+        precondition(count >= 0, "count of bytes to copy must not be negative")
         if count == 0 { return }
-        memcpy(UnsafeMutableRawPointer(pointer), _backing.bytes!.advanced(by: _sliceRange.lowerBound), Swift.min(count, _sliceRange.count))
+        _backing.withUnsafeBytes(in: _sliceRange) {
+            memcpy(UnsafeMutableRawPointer(pointer), $0.baseAddress!, Swift.min(count, $0.count))
+        }
     }
     
     @inline(__always)
     private func _copyBytesHelper(to pointer: UnsafeMutableRawPointer, from range: NSRange) {
         if range.length == 0 { return }
-        memcpy(UnsafeMutableRawPointer(pointer), _backing.bytes!.advanced(by: range.location), Swift.min(range.length, _sliceRange.count))
+        _backing.withUnsafeBytes(in: range.lowerBound..<range.upperBound) {
+            memcpy(UnsafeMutableRawPointer(pointer), $0.baseAddress!, Swift.min(range.length, $0.count))
+        }
     }
     
     /// Copy a subset of the contents of the data to a pointer.
@@ -1311,27 +1455,20 @@
     /// In some cases, (for example, a `Data` backed by a `dispatch_data_t`, the bytes may be stored discontiguously. In those cases, this function invokes the closure for each contiguous region of bytes.
     /// - parameter block: The closure to invoke for each region of data. You may stop the enumeration by setting the `stop` parameter to `true`.
     public func enumerateBytes(_ block: (_ buffer: UnsafeBufferPointer<UInt8>, _ byteIndex: Index, _ stop: inout Bool) -> Void) {
-        _backing.enumerateBytes(block)
+        _backing.enumerateBytes(in: _sliceRange, block)
     }
     
     @inline(__always)
     public mutating func append(_ bytes: UnsafePointer<UInt8>, count: Int) {
-        precondition(count >= 0, "count must be positive")
         if count == 0 { return }
-        if !isKnownUniquelyReferenced(&_backing) {
-            _backing = _backing.mutableCopy(_sliceRange)
-        }
-        _backing.append(bytes, length: count)
-        _sliceRange = _sliceRange.lowerBound..<(_sliceRange.upperBound + count)
+        append(UnsafeBufferPointer(start: bytes, count: count))
     }
     
     @inline(__always)
     public mutating func append(_ other: Data) {
-        if !isKnownUniquelyReferenced(&_backing) {
-            _backing = _backing.mutableCopy(_sliceRange)
+        other.enumerateBytes { (buffer, _, _) in
+            append(buffer)
         }
-        _backing.append(other._backing, startingAt: other._sliceRange.lowerBound, endingAt: other._sliceRange.upperBound)
-        _sliceRange = _sliceRange.lowerBound..<(_sliceRange.upperBound + other.count)
     }
     
     /// Append a buffer of bytes to the data.
@@ -1343,22 +1480,26 @@
         if !isKnownUniquelyReferenced(&_backing) {
             _backing = _backing.mutableCopy(_sliceRange)
         }
-        _backing.append(buffer.baseAddress!, length: buffer.count * MemoryLayout<SourceType>.stride)
+        _backing.replaceBytes(in: NSRange(location: _sliceRange.upperBound, length: _backing.length - (_sliceRange.upperBound - _backing._offset)), with: buffer.baseAddress, length: buffer.count * MemoryLayout<SourceType>.stride)
         _sliceRange = _sliceRange.lowerBound..<(_sliceRange.upperBound + buffer.count * MemoryLayout<SourceType>.stride)
     }
     
     @inline(__always)
     public mutating func append<S : Sequence>(contentsOf newElements: S) where S.Iterator.Element == Iterator.Element {
         let estimatedCount = newElements.underestimatedCount
-        var idx = count
-        count += estimatedCount
-        for byte in newElements {
-            let newIndex = idx + 1
-            if newIndex > count {
-                count = newIndex
+        guard estimatedCount > 0 else {
+            for byte in newElements {
+                append(byte)
             }
-            self[idx] = byte
-            idx = newIndex
+            return
+        }
+        _withStackOrHeapBuffer(estimatedCount) { allocation in
+            let buffer = UnsafeMutableBufferPointer(start: allocation.pointee.memory.assumingMemoryBound(to: UInt8.self), count: estimatedCount)
+            var (iterator, endPoint) = newElements._copyContents(initializing: buffer)
+            append(buffer.baseAddress!, count: endPoint - buffer.startIndex)
+            while let byte = iterator.next() {
+                append(byte)
+            }
         }
     }
     
@@ -1378,16 +1519,15 @@
     @inline(__always)
     public mutating func resetBytes(in range: Range<Index>) {
         // it is worth noting that the range here may be out of bounds of the Data itself (which triggers a growth)
-        precondition(range.lowerBound >= 0, "Ranges must be positive bounds")
-        precondition(range.upperBound >= 0, "Ranges must be positive bounds")
+        precondition(range.lowerBound >= 0, "Ranges must not be negative bounds")
+        precondition(range.upperBound >= 0, "Ranges must not be negative bounds")
         let range = NSMakeRange(range.lowerBound, range.upperBound - range.lowerBound)
         if !isKnownUniquelyReferenced(&_backing) {
             _backing = _backing.mutableCopy(_sliceRange)
         }
         _backing.resetBytes(in: range)
-        if _sliceRange.count < range.location + range.length {
-            let newLength = range.location + range.length
-            _sliceRange = _sliceRange.lowerBound..<(_sliceRange.lowerBound + newLength)
+        if _sliceRange.upperBound < range.upperBound {
+            _sliceRange = _sliceRange.lowerBound..<range.upperBound
         }
     }
     
@@ -1400,34 +1540,16 @@
     /// - parameter data: The replacement data.
     @inline(__always)
     public mutating func replaceSubrange(_ subrange: Range<Index>, with data: Data) {
-        _validateRange(subrange)
-        let nsRange = NSMakeRange(subrange.lowerBound, subrange.upperBound - subrange.lowerBound)
         let cnt = data.count
-        if !isKnownUniquelyReferenced(&_backing) {
-            _backing = _backing.mutableCopy(_sliceRange)
+        data.withUnsafeBytes {
+            replaceSubrange(subrange, with: $0, count: cnt)
         }
-        let resultingLength = data.withUnsafeBytes { (bytes: UnsafePointer<UInt8>) -> Int in
-            let currentLength = _backing.length
-            _backing.replaceBytes(in: nsRange, with: bytes, length: cnt)
-            return currentLength - nsRange.length + cnt
-        }
-        _sliceRange = _sliceRange.lowerBound..<(_sliceRange.lowerBound + resultingLength)
     }
     
     @inline(__always)
     public mutating func replaceSubrange(_ subrange: CountableRange<Index>, with data: Data) {
-        _validateRange(subrange)
-        let nsRange = NSMakeRange(subrange.lowerBound, subrange.upperBound - subrange.lowerBound)
-        let cnt = data.count
-        if !isKnownUniquelyReferenced(&_backing) {
-            _backing = _backing.mutableCopy(_sliceRange)
-        }
-        let resultingLength = data.withUnsafeBytes { (bytes: UnsafePointer<UInt8>) -> Int in
-            let currentLength = _backing.length
-            _backing.replaceBytes(in: nsRange, with: bytes, length: cnt)
-            return currentLength - nsRange.length + cnt
-        }
-        _sliceRange = _sliceRange.lowerBound..<(_sliceRange.lowerBound + resultingLength)
+        let range: Range<Int> = subrange.lowerBound..<subrange.upperBound
+        replaceSubrange(range, with: data)
     }
     
     /// Replace a region of bytes in the data with new bytes from a buffer.
@@ -1439,17 +1561,8 @@
     /// - parameter buffer: The replacement bytes.
     @inline(__always)
     public mutating func replaceSubrange<SourceType>(_ subrange: Range<Index>, with buffer: UnsafeBufferPointer<SourceType>) {
-        _validateRange(subrange)
-        let nsRange = NSMakeRange(subrange.lowerBound, subrange.upperBound - subrange.lowerBound)
-        let bufferCount = buffer.count * MemoryLayout<SourceType>.stride
-        
-        if !isKnownUniquelyReferenced(&_backing) {
-            _backing = _backing.mutableCopy(_sliceRange)
-        }
-        let currentLength = _backing.length
-        _backing.replaceBytes(in: nsRange, with: buffer.baseAddress, length: bufferCount)
-        let resultingLength = currentLength - nsRange.length + bufferCount
-        _sliceRange = _sliceRange.lowerBound..<(_sliceRange.lowerBound + resultingLength)
+        guard buffer.count > 0  else { return }
+        replaceSubrange(subrange, with: buffer.baseAddress!, count: buffer.count * MemoryLayout<SourceType>.stride)
     }
     
     /// Replace a region of bytes in the data with new bytes from a collection.
@@ -1460,39 +1573,18 @@
     /// - parameter subrange: The range in the data to replace.
     /// - parameter newElements: The replacement bytes.
     @inline(__always)
-    public mutating func replaceSubrange<ByteCollection : Collection>(_ subrange: Range<Index>, with newElements: ByteCollection)
-        where ByteCollection.Iterator.Element == Data.Iterator.Element {
-            _validateRange(subrange)
-            // Calculate this once, it may not be O(1)
-            let replacementCount: Int = numericCast(newElements.count)
-            let currentCount = self.count
-            let subrangeCount = subrange.count
-            
-            _validateRange(subrange)
-            
-            let resultCount = currentCount - subrangeCount + replacementCount
-            if resultCount != currentCount {
-                // This may realloc.
-                // In the future, if we keep the malloced pointer and count inside this struct/ref instead of deferring to NSData, we may be able to do this more efficiently.
-                self.count = resultCount
+    public mutating func replaceSubrange<ByteCollection : Collection>(_ subrange: Range<Index>, with newElements: ByteCollection) where ByteCollection.Iterator.Element == Data.Iterator.Element {
+        _validateRange(subrange)
+        let totalCount: Int = numericCast(newElements.count)
+        _withStackOrHeapBuffer(totalCount) { conditionalBuffer in
+            let buffer = UnsafeMutableBufferPointer(start: conditionalBuffer.pointee.memory.assumingMemoryBound(to: UInt8.self), count: totalCount)
+            var (iterator, index) = newElements._copyContents(initializing: buffer)
+            while let byte = iterator.next() {
+                buffer[index] = byte
+                index = buffer.index(after: index)
             }
-            
-            let shift = resultCount - currentCount
-            let start = subrange.lowerBound
-            
-            self.withUnsafeMutableBytes { (bytes : UnsafeMutablePointer<UInt8>) -> Void in
-                if shift != 0 {
-                    let destination = bytes + start + replacementCount
-                    let source = bytes + start + subrangeCount
-                    memmove(destination, source, currentCount - start - subrangeCount)
-                }
-                
-                if replacementCount != 0 {
-                    let buf = UnsafeMutableBufferPointer(start: bytes + start, count: replacementCount)
-                    var (it,idx) = newElements._copyContents(initializing: buf)
-                    precondition(it.next() == nil && idx == buf.endIndex, "newElements iterator returned different count to newElements.count")
-                }
-            }
+            replaceSubrange(subrange, with: conditionalBuffer.pointee.memory, count: totalCount)
+        }
     }
     
     @inline(__always)
@@ -1502,10 +1594,10 @@
         if !isKnownUniquelyReferenced(&_backing) {
             _backing = _backing.mutableCopy(_sliceRange)
         }
-        let currentLength = _backing.length
+        let upper = _sliceRange.upperBound
         _backing.replaceBytes(in: nsRange, with: bytes, length: cnt)
-        let resultingLength = currentLength - nsRange.length + cnt
-        _sliceRange = _sliceRange.lowerBound..<(_sliceRange.lowerBound + resultingLength)
+        let resultingUpper = upper - nsRange.length + cnt
+        _sliceRange = _sliceRange.lowerBound..<resultingUpper
     }
     
     /// Return a new copy of the data in a specified range.
@@ -1548,7 +1640,17 @@
     
     /// The hash value for the data.
     public var hashValue: Int {
-        return _backing.hashValue
+        var hashValue = 0
+        let hashRange: Range<Int> = _sliceRange.lowerBound..<Swift.min(_sliceRange.lowerBound + 80, _sliceRange.upperBound)
+        _withStackOrHeapBuffer(hashRange.count + 1) { buffer in
+            if hashRange.count > 0 {
+                _backing.withUnsafeBytes(in: hashRange) {
+                    memcpy(buffer.pointee.memory, $0.baseAddress!, hashRange.count)
+                }
+            }
+            hashValue = Int(bitPattern: CFHashBytes(buffer.pointee.memory.assumingMemoryBound(to: UInt8.self), hashRange.count))
+        }
+        return hashValue
     }
     
     @inline(__always)
@@ -1571,7 +1673,7 @@
         @inline(__always)
         get {
             _validateIndex(index)
-            return _backing.bytes!.advanced(by: index).assumingMemoryBound(to: UInt8.self).pointee
+            return _backing.get(index)
         }
         @inline(__always)
         set {
@@ -1657,11 +1759,24 @@
         }
     }
     
+    public func _copyContents(initializing buffer: UnsafeMutableBufferPointer<UInt8>) -> (Iterator, UnsafeMutableBufferPointer<UInt8>.Index) {
+        guard !isEmpty else { return (makeIterator(), buffer.startIndex) }
+        guard let p = buffer.baseAddress else {
+            preconditionFailure("Attempt to copy contents into nil buffer pointer")
+        }
+        let cnt = count
+        precondition(cnt <= buffer.count, "Insufficient space allocated to copy Data contents")
+        
+        withUnsafeBytes { p.initialize(from: $0, count: cnt) }
+        
+        return (Iterator(endOf: self), buffer.index(buffer.startIndex, offsetBy: cnt))
+    }
+    
     /// An iterator over the contents of the data.
     ///
     /// The iterator will increment byte-by-byte.
     public func makeIterator() -> Data.Iterator {
-        return Iterator(_data: self)
+        return Iterator(self)
     }
     
     public struct Iterator : IteratorProtocol {
@@ -1674,11 +1789,18 @@
         private var _idx: Data.Index
         private let _endIdx: Data.Index
         
-        fileprivate init(_data: Data) {
-            self._data = _data
+        fileprivate init(_ data: Data) {
+            _data = data
             _buffer = (0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0)
-            _idx = _data.startIndex
-            _endIdx = _data.endIndex
+            _idx = data.startIndex
+            _endIdx = data.endIndex
+        }
+        
+        fileprivate init(endOf data: Data) {
+            self._data = data
+            _buffer = (0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0)
+            _idx = data.endIndex
+            _endIdx = data.endIndex
         }
         
         public mutating func next() -> UInt8? {
@@ -1764,7 +1886,7 @@
         
         // Minimal size data is output as an array
         if nBytes < 64 {
-            children.append((label: "bytes", value: Array(self[0..<nBytes])))
+            children.append((label: "bytes", value: Array(self[startIndex..<Swift.min(nBytes + startIndex, endIndex)])))
         }
         
         let m = Mirror(self, children:children, displayStyle: Mirror.DisplayStyle.struct)
@@ -1862,4 +1984,3 @@
         }
     }
 }
-
diff --git a/Foundation/NSData.swift b/Foundation/NSData.swift
index 6dd8048..3066406 100644
--- a/Foundation/NSData.swift
+++ b/Foundation/NSData.swift
@@ -146,6 +146,7 @@
     public convenience init(bytesNoCopy bytes: UnsafeMutableRawPointer, length: Int, deallocator: ((UnsafeMutableRawPointer, Int) -> Void)? = nil) {
         self.init(bytes: bytes, length: length, copy: false, deallocator: deallocator)
     }
+
     public convenience init(contentsOfFile path: String, options readOptionsMask: ReadingOptions = []) throws {
         let readResult = try NSData.readBytesFromFileWithExtendedAttributes(path, options: readOptionsMask)
         self.init(bytes: readResult.bytes, length: readResult.length, copy: false, deallocator: readResult.deallocator)
@@ -380,7 +381,10 @@
         }
         
         let length = Int(info.st_size)
-        
+        if length == 0 && (info.st_mode & S_IFMT == S_IFREG) {
+            return try readZeroSizeFile(fd)
+        }
+
         if options.contains(.alwaysMapped) {
             let data = mmap(nil, length, PROT_READ, MAP_PRIVATE, fd, 0)
             
@@ -414,6 +418,37 @@
             free(buffer)
         }
     }
+
+    internal static func readZeroSizeFile(_ fd: Int32) throws -> NSDataReadResult {
+        let blockSize = 1024 * 1024 // 1MB
+        var data: UnsafeMutableRawPointer? = nil
+        var bytesRead = 0
+        var amt = 0
+
+        repeat {
+            data = realloc(data, bytesRead + blockSize)
+            amt = read(fd, data!.advanced(by: bytesRead), blockSize)
+
+            // Dont continue on EINTR or EAGAIN as the file position may not
+            // have changed, see read(2).
+            if amt < 0 {
+                free(data!)
+                throw NSError(domain: NSPOSIXErrorDomain, code: Int(errno), userInfo: nil)
+            }
+            bytesRead += amt
+        } while amt > 0
+
+        if bytesRead == 0 {
+            free(data!)
+            data = malloc(0)
+        } else {
+            data = realloc(data, bytesRead) // shrink down the allocated block.
+        }
+
+        return NSDataReadResult(bytes: data!, length: bytesRead) { buffer, length in
+            free(buffer)
+        }
+    }
     
     internal func makeTemporaryFile(inDirectory dirPath: String) throws -> (Int32, String) {
         let template = dirPath._nsObject.appendingPathComponent("tmp.XXXXXX")
@@ -956,6 +991,19 @@
     }
 }
 
+extension NSData {
+    internal func _isCompact() -> Bool {
+        var regions = 0
+        enumerateBytes { (_, _, stop) in
+            regions += 1
+            if regions > 1 {
+                stop.pointee = true
+            }
+        }
+        return regions <= 1
+    }
+}
+
 extension NSData : _StructTypeBridgeable {
     public typealias _StructType = Data
     public func _bridgeToSwift() -> Data {