Merge pull request #1182 from weissi/jw-fix-httpcookiestorage-threading

diff --git a/CoreFoundation/Base.subproj/CFPlatform.c b/CoreFoundation/Base.subproj/CFPlatform.c
index 5f67510..896193f 100644
--- a/CoreFoundation/Base.subproj/CFPlatform.c
+++ b/CoreFoundation/Base.subproj/CFPlatform.c
@@ -180,6 +180,12 @@
     }
     return __CFProcessPath;
 }
+
+#else
+
+Boolean _CFIsMainThread(void) {
+    return pthread_main_np() == 1;
+}
 #endif
 
 CF_PRIVATE CFStringRef _CFProcessNameString(void) {
@@ -1295,7 +1301,7 @@
     return (CFTypeRef)pthread_getspecific(key);
 }
 
-void _CThreadSpecificSet(_CFThreadSpecificKey key, CFTypeRef _Nullable value) {
+void _CFThreadSpecificSet(_CFThreadSpecificKey key, CFTypeRef _Nullable value) {
     if (value != NULL) {
         swift_retain((void *)value);
         pthread_setspecific(key, value);
diff --git a/CoreFoundation/Base.subproj/ForSwiftFoundationOnly.h b/CoreFoundation/Base.subproj/ForSwiftFoundationOnly.h
index c580409..2d20856 100644
--- a/CoreFoundation/Base.subproj/ForSwiftFoundationOnly.h
+++ b/CoreFoundation/Base.subproj/ForSwiftFoundationOnly.h
@@ -27,6 +27,15 @@
 #include <CoreFoundation/ForFoundationOnly.h>
 #include <fts.h>
 #include <pthread.h>
+#include <execinfo.h>
+
+#if __has_include(<malloc/malloc.h>)
+#include <malloc/malloc.h>
+#endif
+
+#if __has_include(<malloc/malloc.h>)
+#include <malloc/malloc.h>
+#endif
 
 _CF_EXPORT_SCOPE_BEGIN
 
@@ -294,12 +303,13 @@
 CF_EXPORT void CFLog1(CFLogLevel lev, CFStringRef message);
 
 CF_EXPORT Boolean _CFIsMainThread(void);
+CF_EXPORT pthread_t _CFMainPThread;
 
 CF_EXPORT CFHashCode __CFHashDouble(double d);
 
 typedef pthread_key_t _CFThreadSpecificKey;
 CF_EXPORT CFTypeRef _Nullable _CFThreadSpecificGet(_CFThreadSpecificKey key);
-CF_EXPORT void _CThreadSpecificSet(_CFThreadSpecificKey key, CFTypeRef _Nullable value);
+CF_EXPORT void _CFThreadSpecificSet(_CFThreadSpecificKey key, CFTypeRef _Nullable value);
 CF_EXPORT _CFThreadSpecificKey _CFThreadSpecificKeyCreate(void);
 
 typedef pthread_attr_t _CFThreadAttributes;
@@ -343,6 +353,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/CoreFoundation/Preferences.subproj/CFApplicationPreferences.c b/CoreFoundation/Preferences.subproj/CFApplicationPreferences.c
index 1029622..6366a5b 100644
--- a/CoreFoundation/Preferences.subproj/CFApplicationPreferences.c
+++ b/CoreFoundation/Preferences.subproj/CFApplicationPreferences.c
@@ -17,7 +17,7 @@
 #include <CoreFoundation/CFNumberFormatter.h>
 #include <CoreFoundation/CFDateFormatter.h>
 #include <sys/types.h>
-#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED
+#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_LINUX
 #include <unistd.h>
 #endif
 
diff --git a/CoreFoundation/Preferences.subproj/CFPreferences.c b/CoreFoundation/Preferences.subproj/CFPreferences.c
index 8f00af0..18723c6 100644
--- a/CoreFoundation/Preferences.subproj/CFPreferences.c
+++ b/CoreFoundation/Preferences.subproj/CFPreferences.c
@@ -445,7 +445,7 @@
 static CFURLRef _CFPreferencesURLForStandardDomainWithSafetyLevel(CFStringRef domainName, CFStringRef userName, CFStringRef hostName, unsigned long safeLevel) {
     CFURLRef theURL = NULL;
     CFAllocatorRef prefAlloc = __CFPreferencesAllocator();
-#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_WINDOWS
+#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_LINUX || DEPLOYMENT_TARGET_WINDOWS
     CFURLRef prefDir = _preferencesDirectoryForUserHostSafetyLevel(userName, hostName, safeLevel);
     CFStringRef  appName;
     CFStringRef  fileName;
@@ -479,7 +479,7 @@
 	CFRelease(appName);
     }
     if (fileName) {
-#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED
+#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_LINUX
         theURL = CFURLCreateWithFileSystemPathRelativeToBase(prefAlloc, fileName, kCFURLPOSIXPathStyle, false, prefDir);
 #elif DEPLOYMENT_TARGET_WINDOWS
 		theURL = CFURLCreateWithFileSystemPathRelativeToBase(prefAlloc, fileName, kCFURLWindowsPathStyle, false, prefDir);
@@ -497,10 +497,6 @@
     return _CFPreferencesURLForStandardDomainWithSafetyLevel(domainName, userName, hostName, __CFSafeLaunchLevel);
 }
 
-const _CFPreferencesDomainCallBacks __kCFXMLPropertyListDomainCallBacks = {
-    
-};
-
 CFPreferencesDomainRef _CFPreferencesStandardDomain(CFStringRef  domainName, CFStringRef  userName, CFStringRef  hostName) {
     CFPreferencesDomainRef domain;
     CFStringRef  domainKey;
diff --git a/CoreFoundation/Preferences.subproj/CFXMLPreferencesDomain.c b/CoreFoundation/Preferences.subproj/CFXMLPreferencesDomain.c
index 5941118..8073848 100644
--- a/CoreFoundation/Preferences.subproj/CFXMLPreferencesDomain.c
+++ b/CoreFoundation/Preferences.subproj/CFXMLPreferencesDomain.c
@@ -16,10 +16,12 @@
 #include <CoreFoundation/CFDate.h>
 #include "CFInternal.h"
 #include <time.h>
-#if DEPLOYMENT_TARGET_MACOSX
+#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_LINUX
 #include <unistd.h>
 #include <stdio.h>
 #include <sys/stat.h>
+#endif
+#if DEPLOYMENT_TARGET_MACOSX
 #include <mach/mach.h>
 #include <mach/mach_syscalls.h>
 #endif
@@ -102,7 +104,7 @@
     if (parentURL) CFRelease(parentURL);
     if (!parentExists) return false;
 
-#if DEPLOYMENT_TARGET_MACOSX
+#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_LINUX
     mode = worldReadable ? S_IRWXU|S_IRWXG|S_IROTH|S_IXOTH : S_IRWXU;
 #else
     mode = 0666;
@@ -306,7 +308,7 @@
         CFDataRef data = CFPropertyListCreateData(alloc, dict, desiredFormat, 0, NULL);
         if (data) {
             SInt32 mode;
-#if DEPLOYMENT_TARGET_MACOSX
+#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_LINUX
             mode = isWorldReadable ? S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH : S_IRUSR|S_IWUSR;
 #else
 	    mode = 0666;
diff --git a/Docs/Status.md b/Docs/Status.md
index 13c9cfd..fa06c03 100644
--- a/Docs/Status.md
+++ b/Docs/Status.md
@@ -278,7 +278,7 @@
     | `Process`        | Mostly Complete | Substantial   | `interrupt()`, `terminate()`, `suspend()`, and `resume()` remain unimplemented                                            |
     | `Bundle`         | Mostly Complete | Incomplete    | `allBundles`, `init(for:)`, `unload()`, `classNamed()`, and `principalClass` remain unimplemented                         |
     | `ProcessInfo`    | Complete        | Substantial   |                                                                                                                           |
-    | `Thread`         | Incomplete      | Incomplete    | `isMainThread`, `mainThread`, `name`, `callStackReturnAddresses`, and `callStackSymbols` remain unimplemented             |
+    | `Thread`         | Complete        | Incomplete    |                                                                                                                           |
     | `Operation`      | Complete        | Incomplete    |                                                                                                                           |
     | `BlockOperation` | Complete        | Incomplete    |                                                                                                                           |
     | `OperationQueue` | Complete        | Incomplete    |                                                                                                                           |
diff --git a/Foundation.xcodeproj/project.pbxproj b/Foundation.xcodeproj/project.pbxproj
index ae314b4..eeace9e 100644
--- a/Foundation.xcodeproj/project.pbxproj
+++ b/Foundation.xcodeproj/project.pbxproj
@@ -14,12 +14,14 @@
 		231503DB1D8AEE5D0061694D /* TestDecimal.swift in Sources */ = {isa = PBXBuildFile; fileRef = 231503DA1D8AEE5D0061694D /* TestDecimal.swift */; };
 		294E3C1D1CC5E19300E4F44C /* TestNSAttributedString.swift in Sources */ = {isa = PBXBuildFile; fileRef = 294E3C1C1CC5E19300E4F44C /* TestNSAttributedString.swift */; };
 		2EBE67A51C77BF0E006583D5 /* TestDateFormatter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2EBE67A31C77BF05006583D5 /* TestDateFormatter.swift */; };
+		3E55A2331F52463B00082000 /* TestUnit.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3E55A2321F52463B00082000 /* TestUnit.swift */; };
 		3EA9D6701EF0532D00B362D6 /* TestJSONEncoder.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3EA9D66F1EF0532D00B362D6 /* TestJSONEncoder.swift */; };
 		3EDCE50C1EF04D8100C2EC04 /* Codable.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3EDCE5051EF04D8100C2EC04 /* Codable.swift */; };
 		3EDCE5101EF04D8100C2EC04 /* JSONEncoder.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3EDCE5091EF04D8100C2EC04 /* JSONEncoder.swift */; };
 		528776141BF2629700CB0090 /* FoundationErrors.swift in Sources */ = {isa = PBXBuildFile; fileRef = 522C253A1BF16E1600804FC6 /* FoundationErrors.swift */; };
 		528776191BF27D9500CB0090 /* Test.plist in Resources */ = {isa = PBXBuildFile; fileRef = 528776181BF27D9500CB0090 /* Test.plist */; };
 		555683BD1C1250E70041D4C6 /* TestUserDefaults.swift in Sources */ = {isa = PBXBuildFile; fileRef = 555683BC1C1250E70041D4C6 /* TestUserDefaults.swift */; };
+		559451EC1F706BFA002807FB /* CFXMLPreferencesDomain.c in Sources */ = {isa = PBXBuildFile; fileRef = 559451EA1F706BF5002807FB /* CFXMLPreferencesDomain.c */; };
 		5B0163BB1D024EB7003CCD96 /* DateComponents.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5B0163BA1D024EB7003CCD96 /* DateComponents.swift */; };
 		5B13B3251C582D4700651CE2 /* main.swift in Sources */ = {isa = PBXBuildFile; fileRef = EA66F6381BF1619600136161 /* main.swift */; };
 		5B13B3261C582D4C00651CE2 /* TestAffineTransform.swift in Sources */ = {isa = PBXBuildFile; fileRef = C93559281C12C49F009FD6A9 /* TestAffineTransform.swift */; };
@@ -308,6 +310,7 @@
 		61E011821C1B599A000037DD /* CFMachPort.c in Sources */ = {isa = PBXBuildFile; fileRef = 5B5D88D01BBC9AAC00234F36 /* CFMachPort.c */; };
 		63DCE9D21EAA430100E9CB02 /* ISO8601DateFormatter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 63DCE9D11EAA430100E9CB02 /* ISO8601DateFormatter.swift */; };
 		63DCE9D41EAA432400E9CB02 /* TestISO8601DateFormatter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 63DCE9D31EAA432400E9CB02 /* TestISO8601DateFormatter.swift */; };
+		684C79011F62B611005BD73E /* TestNSNumberBridging.swift in Sources */ = {isa = PBXBuildFile; fileRef = 684C79001F62B611005BD73E /* TestNSNumberBridging.swift */; };
 		6EB768281D18C12C00D4B719 /* UUID.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6EB768271D18C12C00D4B719 /* UUID.swift */; };
 		7900433B1CACD33E00ECCBF1 /* TestNSCompoundPredicate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 790043391CACD33E00ECCBF1 /* TestNSCompoundPredicate.swift */; };
 		7900433C1CACD33E00ECCBF1 /* TestNSPredicate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7900433A1CACD33E00ECCBF1 /* TestNSPredicate.swift */; };
@@ -490,6 +493,7 @@
 		231503DA1D8AEE5D0061694D /* TestDecimal.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TestDecimal.swift; sourceTree = "<group>"; };
 		294E3C1C1CC5E19300E4F44C /* TestNSAttributedString.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TestNSAttributedString.swift; sourceTree = "<group>"; };
 		2EBE67A31C77BF05006583D5 /* TestDateFormatter.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TestDateFormatter.swift; sourceTree = "<group>"; };
+		3E55A2321F52463B00082000 /* TestUnit.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TestUnit.swift; sourceTree = "<group>"; };
 		3EA9D66F1EF0532D00B362D6 /* TestJSONEncoder.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TestJSONEncoder.swift; sourceTree = "<group>"; };
 		3EDCE5051EF04D8100C2EC04 /* Codable.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Codable.swift; sourceTree = "<group>"; };
 		3EDCE5091EF04D8100C2EC04 /* JSONEncoder.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = JSONEncoder.swift; sourceTree = "<group>"; };
@@ -501,6 +505,7 @@
 		52829AD61C160D64003BC4EF /* TestCalendar.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TestCalendar.swift; sourceTree = "<group>"; };
 		528776181BF27D9500CB0090 /* Test.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Test.plist; sourceTree = "<group>"; };
 		555683BC1C1250E70041D4C6 /* TestUserDefaults.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TestUserDefaults.swift; sourceTree = "<group>"; usesTabs = 1; };
+		559451EA1F706BF5002807FB /* CFXMLPreferencesDomain.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = CFXMLPreferencesDomain.c; sourceTree = "<group>"; };
 		5B0163BA1D024EB7003CCD96 /* DateComponents.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DateComponents.swift; sourceTree = "<group>"; };
 		5B0C6C211C1E07E600705A0E /* TestNSRegularExpression.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TestNSRegularExpression.swift; sourceTree = "<group>"; };
 		5B1FD9C11D6D160F0080E83C /* CFURLSessionInterface.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = CFURLSessionInterface.c; sourceTree = "<group>"; };
@@ -765,6 +770,7 @@
 		61F8AE7C1C180FC600FB62F0 /* TestNotificationCenter.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TestNotificationCenter.swift; sourceTree = "<group>"; };
 		63DCE9D11EAA430100E9CB02 /* ISO8601DateFormatter.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ISO8601DateFormatter.swift; sourceTree = "<group>"; };
 		63DCE9D31EAA432400E9CB02 /* TestISO8601DateFormatter.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TestISO8601DateFormatter.swift; sourceTree = "<group>"; };
+		684C79001F62B611005BD73E /* TestNSNumberBridging.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TestNSNumberBridging.swift; sourceTree = "<group>"; };
 		6E203B8C1C1303BB003B2576 /* TestBundle.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TestBundle.swift; sourceTree = "<group>"; };
 		6EB768271D18C12C00D4B719 /* UUID.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = UUID.swift; sourceTree = "<group>"; };
 		790043391CACD33E00ECCBF1 /* TestNSCompoundPredicate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TestNSCompoundPredicate.swift; sourceTree = "<group>"; };
@@ -1030,6 +1036,7 @@
 			isa = PBXGroup;
 			children = (
 				5B5D886A1BBC948300234F36 /* CFApplicationPreferences.c */,
+				559451EA1F706BF5002807FB /* CFXMLPreferencesDomain.c */,
 				5B5D898B1BBDBF6500234F36 /* CFPreferences.c */,
 				5B5D886C1BBC94C400234F36 /* CFPreferences.h */,
 			);
@@ -1457,6 +1464,7 @@
 				5EF673AB1C28B527006212A3 /* TestNotificationQueue.swift */,
 				5B6F17921C48631C00935030 /* TestNSNull.swift */,
 				EA66F63F1BF1619600136161 /* TestNSNumber.swift */,
+				684C79001F62B611005BD73E /* TestNSNumberBridging.swift */,
 				D5C40F321CDA1D460005690C /* TestOperationQueue.swift */,
 				D834F9931C31C4060023812A /* TestNSOrderedSet.swift */,
 				BDFDF0A61DFF5B3E00C04CC5 /* TestPersonNameComponents.swift */,
@@ -1494,6 +1502,7 @@
 				D4FE895A1D703D1100DA7986 /* TestURLRequest.swift */,
 				5B6F17961C48631C00935030 /* TestUtils.swift */,
 				03B6F5831F15F339004F25AF /* TestURLProtocol.swift */,
+				3E55A2321F52463B00082000 /* TestUnit.swift */,
 			);
 			name = Tests;
 			sourceTree = "<group>";
@@ -2021,7 +2030,7 @@
 				TargetAttributes = {
 					5B5D885C1BBC938800234F36 = {
 						CreatedOnToolsVersion = 7.1;
-						LastSwiftMigration = 0800;
+						LastSwiftMigration = 0900;
 						LastSwiftUpdateCheck = 0800;
 						ProvisioningStyle = Manual;
 					};
@@ -2300,6 +2309,7 @@
 				5B7C8A8B1BEA7FE200C5B690 /* CFBigNumber.c in Sources */,
 				5B7C8A7D1BEA7FCE00C5B690 /* CFBinaryHeap.c in Sources */,
 				5B7C8A7E1BEA7FCE00C5B690 /* CFBitVector.c in Sources */,
+				559451EC1F706BFA002807FB /* CFXMLPreferencesDomain.c in Sources */,
 				5B7C8A8F1BEA7FEC00C5B690 /* CFBinaryPList.c in Sources */,
 				5B7C8A911BEA7FEC00C5B690 /* CFPropertyList.c in Sources */,
 				5B7C8AB41BEA801700C5B690 /* CFStringEncodingDatabase.c in Sources */,
@@ -2419,6 +2429,7 @@
 				F9E0BB371CA70B8000F7FF3C /* TestURLCredential.swift in Sources */,
 				5B13B3341C582D4C00651CE2 /* TestNSKeyedArchiver.swift in Sources */,
 				5B13B3441C582D4C00651CE2 /* TestNSSet.swift in Sources */,
+				3E55A2331F52463B00082000 /* TestUnit.swift in Sources */,
 				5B13B3321C582D4C00651CE2 /* TestIndexSet.swift in Sources */,
 				5B13B3511C582D4C00651CE2 /* TestByteCountFormatter.swift in Sources */,
 				BDFDF0A71DFF5B3E00C04CC5 /* TestPersonNameComponents.swift in Sources */,
@@ -2433,6 +2444,7 @@
 				3EA9D6701EF0532D00B362D6 /* TestJSONEncoder.swift in Sources */,
 				D512D17C1CD883F00032E6A5 /* TestFileHandle.swift in Sources */,
 				D4FE895B1D703D1100DA7986 /* TestURLRequest.swift in Sources */,
+				684C79011F62B611005BD73E /* TestNSNumberBridging.swift in Sources */,
 				5B13B33A1C582D4C00651CE2 /* TestNSNumber.swift in Sources */,
 				5B13B3521C582D4C00651CE2 /* TestNSValue.swift in Sources */,
 				5B13B3311C582D4C00651CE2 /* TestIndexPath.swift in Sources */,
diff --git a/Foundation/AffineTransform.swift b/Foundation/AffineTransform.swift
index cfd0504..3f1923f 100644
--- a/Foundation/AffineTransform.swift
+++ b/Foundation/AffineTransform.swift
@@ -338,6 +338,10 @@
         return other === self
             || (other.transformStruct == self.transformStruct)
     }
+
+    open override var hashValue: Int {
+        return transformStruct.hashValue
+    }
     
     public static var supportsSecureCoding: Bool {
         return true
diff --git a/Foundation/ByteCountFormatter.swift b/Foundation/ByteCountFormatter.swift
index e268880..3234e4e 100644
--- a/Foundation/ByteCountFormatter.swift
+++ b/Foundation/ByteCountFormatter.swift
@@ -13,8 +13,6 @@
         public let rawValue : UInt
         public init(rawValue: UInt) { self.rawValue = rawValue }
         
-        // This causes default units appropriate for the platform to be used. Specifying any units explicitly causes just those units to be used in showing the number.
-        public static let useDefault = Units(rawValue: 0)
         //  Specifying any of the following causes the specified units to be used in showing the number.
         public static let useBytes = Units(rawValue: 1 << 0)
         public static let useKB = Units(rawValue: 1 << 1)
@@ -50,9 +48,9 @@
         NSUnimplemented()
     }
     
-    /* Specify the units that can be used in the output. If ByteCountFormatter.Units.useDefault, uses platform-appropriate settings; otherwise will only use the specified units. This is the default value. Note that ZB and YB cannot be covered by the range of possible values, but you can still choose to use these units to get fractional display ("0.0035 ZB" for instance).
+    /* Specify the units that can be used in the output. If ByteCountFormatter.Units is empty, uses platform-appropriate settings; otherwise will only use the specified units. This is the default value. Note that ZB and YB cannot be covered by the range of possible values, but you can still choose to use these units to get fractional display ("0.0035 ZB" for instance).
      */
-    open var allowedUnits: Units = .useDefault
+    open var allowedUnits: Units = []
     
     /* Specify how the count is displayed by indicating the number of bytes to be used for kilobyte. The default setting is ByteCountFormatter.CountStyle.fileCount, which is the system specific value for file and storage sizes.
      */
@@ -127,52 +125,52 @@
      */
     private func convertValue(fromByteCount byteCount: Int64, for byteSize: [Unit: Double]) -> String {
         let byte = Double(byteCount)
-        if byte == 0, allowsNonnumericFormatting, allowedUnits == .useDefault, includesUnit, includesCount {
+        if byte == 0, allowsNonnumericFormatting, allowedUnits == [], includesUnit, includesCount {
             return partsToIncludeFor(value: "Zero", unit: Unit.KB)
         } else if byte == 1 || byte == -1 {
-            if allowedUnits.contains(.useAll) || allowedUnits == .useDefault {
+            if allowedUnits.contains(.useAll) || allowedUnits == [] {
                 return formatNumberFor(bytes: byte, unit: Unit.byte)
             } else {
                 return valueToUseFor(byteCount: byte, unit: allowedUnits)
             }
         } else if  byte < byteSize[Unit.KB]! && byte > -byteSize[Unit.KB]!{
-            if allowedUnits.contains(.useAll) || allowedUnits == .useDefault {
+            if allowedUnits.contains(.useAll) || allowedUnits == [] {
                 return formatNumberFor(bytes: byte, unit: Unit.bytes)
             } else {
                 return valueToUseFor(byteCount: byte, unit: allowedUnits)
             }
         } else if byte < byteSize[Unit.MB]! && byte > -byteSize[Unit.MB]! {
-            if allowedUnits.contains(.useAll) || allowedUnits == .useDefault {
+            if allowedUnits.contains(.useAll) || allowedUnits == [] {
                 return divide(byte, by: byteSize, for: .KB)
             }
             return valueToUseFor(byteCount: byte, unit: allowedUnits)
             
         } else if byte < byteSize[Unit.GB]! && byte > -byteSize[Unit.GB]! {
-            if allowedUnits.contains(.useAll) || allowedUnits == .useDefault {
+            if allowedUnits.contains(.useAll) || allowedUnits == [] {
                 return divide(byte, by: byteSize, for: .MB)
             }
             return valueToUseFor(byteCount: byte, unit: allowedUnits)
             
         } else if byte < byteSize[Unit.TB]! && byte > -byteSize[Unit.TB]! {
-            if allowedUnits.contains(.useAll) || allowedUnits == .useDefault {
+            if allowedUnits.contains(.useAll) || allowedUnits == [] {
                 return divide(byte, by: byteSize, for: .GB)
             }
             return valueToUseFor(byteCount: byte, unit: allowedUnits)
             
         } else if byte < byteSize[Unit.PB]! && byte > -byteSize[Unit.PB]! {
-            if allowedUnits.contains(.useAll) || allowedUnits == .useDefault {
+            if allowedUnits.contains(.useAll) || allowedUnits == [] {
                 return divide(byte, by: byteSize, for: .TB)
             }
             return valueToUseFor(byteCount: byte, unit: allowedUnits)
             
         } else if byte < byteSize[Unit.EB]! && byte > -byteSize[Unit.EB]! {
-            if allowedUnits.contains(.useAll) || allowedUnits == .useDefault {
+            if allowedUnits.contains(.useAll) || allowedUnits == [] {
                 return divide(byte, by: byteSize, for: .PB)
             }
             return valueToUseFor(byteCount: byte, unit: allowedUnits)
             
         } else {
-            if allowedUnits.contains(.useAll) || allowedUnits == .useDefault {
+            if allowedUnits.contains(.useAll) || allowedUnits == [] {
                 return divide(byte, by: byteSize, for: .EB)
             }
             return valueToUseFor(byteCount: byte, unit: allowedUnits)
@@ -297,7 +295,7 @@
             } else {
                 if lengthOfInt(number: Int(bytes)) == 3 {
                     numberFormatter.usesSignificantDigits = false
-                    numberFormatter.maximumFractionDigits = 1
+                    numberFormatter.maximumFractionDigits = 0
                 } else {
                     numberFormatter.maximumSignificantDigits = 3
                     numberFormatter.minimumSignificantDigits = 3
@@ -376,7 +374,7 @@
         } else if includesCount, includesUnit {
             return "\(value) \(unit)"
         } else if includesCount, !includesUnit {
-            if value == "Zero", allowedUnits == .useDefault {
+            if value == "Zero", allowedUnits == [] {
                 return "0"
             } else {
                 return value
diff --git a/Foundation/Data.swift b/Foundation/Data.swift
index 1436c88..5398567 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
     
@@ -98,47 +102,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 d._isCompact() {
+                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 d._isCompact() {
+                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 +273,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 +418,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 +497,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 d._isCompact() {
+                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 d._isCompact() {
+                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 +541,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 +563,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 +617,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 +634,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 +684,7 @@
         _capacity = capacity
         _needToZero = !clear
         _length = 0
+        _offset = 0
         setLength(length)
     }
     
@@ -560,10 +699,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 +729,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 +772,8 @@
         }
     }
     
-    public init(immutableReference: NSData) {
+    public init(immutableReference: NSData, offset: Int) {
+        _offset = offset
         _bytes = UnsafeMutableRawPointer(mutating: immutableReference.bytes)
         _capacity = 0
         _needToZero = false
@@ -638,7 +781,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 +790,8 @@
         _backing = .mutable(mutableReference)
     }
     
-    public init(customReference: NSData) {
+    public init(customReference: NSData, offset: Int) {
+        _offset = offset
         _bytes = nil
         _capacity = 0
         _needToZero = false
@@ -654,7 +799,8 @@
         _backing = .customReference(customReference)
     }
     
-    public init(customMutableReference: NSMutableData) {
+    public init(customMutableReference: NSMutableData, offset: Int) {
+        _offset = offset
         _bytes = nil
         _capacity = 0
         _needToZero = false
@@ -675,30 +821,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 +856,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,31 +912,18 @@
         }
     }
     
-    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)
         }
     }
 }
 
-@_versioned
 internal class _NSSwiftData : NSData {
     var _backing: _DataStorage!
     var _range: Range<Data.Index>!
@@ -828,7 +961,7 @@
     }
     
 #if !DEPLOYMENT_RUNTIME_SWIFT
-    @objc
+    @objc override
     func _isCompact() -> Bool {
         return true
     }
@@ -1016,7 +1149,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
     }
     
@@ -1027,7 +1160,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
     }
     
@@ -1038,7 +1171,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
@@ -1053,7 +1186,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
@@ -1074,10 +1207,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
         }
         
@@ -1086,40 +1219,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
@@ -1152,7 +1275,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)
             }
@@ -1166,9 +1289,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)!)
+        }
     }
     
     
@@ -1181,9 +1304,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: -
@@ -1196,15 +1319,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.
@@ -1312,27 +1439,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.
@@ -1344,22 +1464,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)
+            }
         }
     }
     
@@ -1379,16 +1503,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
         }
     }
     
@@ -1401,34 +1524,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.
@@ -1440,17 +1545,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.
@@ -1461,39 +1557,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)
@@ -1503,10 +1578,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.
@@ -1515,6 +1590,7 @@
     @inline(__always)
     public func subdata(in range: Range<Index>) -> Data {
         _validateRange(range)
+        let length = count
         if count == 0 {
             return Data()
         }
@@ -1549,7 +1625,15 @@
     
     /// 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) { buffer in
+            _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)
@@ -1572,7 +1656,7 @@
         @inline(__always)
         get {
             _validateIndex(index)
-            return _backing.bytes!.advanced(by: index).assumingMemoryBound(to: UInt8.self).pointee
+            return _backing.get(index)
         }
         @inline(__always)
         set {
@@ -1658,11 +1742,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 {
@@ -1675,11 +1772,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? {
@@ -1765,7 +1869,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)
@@ -1822,11 +1926,27 @@
 
 extension Data : Codable {
     public init(from decoder: Decoder) throws {
+        // FIXME: This is a hook for bypassing a conditional conformance implementation to apply a strategy (see SR-5206). Remove this once conditional conformance is available.
+        do {
+            let singleValueContainer = try decoder.singleValueContainer()
+            if let decoder = singleValueContainer as? _JSONDecoder {
+                switch decoder.options.dataDecodingStrategy {
+                case .deferredToData:
+                    break /* fall back to default implementation below; this would recurse */
+
+                default:
+                    // _JSONDecoder has a hook for Datas; this won't recurse since we're not going to defer back to Data in _JSONDecoder.
+                    self = try singleValueContainer.decode(Data.self)
+                    return
+                }
+            }
+        } catch { /* fall back to default implementation below */ }
+
         var container = try decoder.unkeyedContainer()
         
         // It's more efficient to pre-allocate the buffer if we can.
         if let count = container.count {
-            self.init(count: count)
+            self = Data(count: count)
             
             // Loop only until count, not while !container.isAtEnd, in case count is underestimated (this is misbehavior) and we haven't allocated enough space.
             // We don't want to write past the end of what we allocated.
@@ -1835,7 +1955,7 @@
                 self[i] = byte
             }
         } else {
-            self.init()
+            self = Data()
         }
         
         while !container.isAtEnd {
@@ -1845,6 +1965,21 @@
     }
     
     public func encode(to encoder: Encoder) throws {
+        // FIXME: This is a hook for bypassing a conditional conformance implementation to apply a strategy (see SR-5206). Remove this once conditional conformance is available.
+        // We are allowed to request this container as long as we don't encode anything through it when we need the unkeyed container below.
+        var singleValueContainer = encoder.singleValueContainer()
+        if let encoder = singleValueContainer as? _JSONEncoder {
+            switch encoder.options.dataEncodingStrategy {
+            case .deferredToData:
+                break /* fall back to default implementation below; this would recurse */
+
+            default:
+                // _JSONEncoder has a hook for Datas; this won't recurse since we're not going to defer back to Data in _JSONEncoder.
+                try singleValueContainer.encode(self)
+                return
+            }
+        }
+
         var container = encoder.unkeyedContainer()
         
         // Since enumerateBytes does not rethrow, we need to catch the error, stow it away, and rethrow if we stopped.
@@ -1863,4 +1998,3 @@
         }
     }
 }
-
diff --git a/Foundation/DateFormatter.swift b/Foundation/DateFormatter.swift
index 184b861..31292a0 100644
--- a/Foundation/DateFormatter.swift
+++ b/Foundation/DateFormatter.swift
@@ -142,9 +142,23 @@
         }
     }
 
-    open var dateStyle: Style = .none { willSet { _dateFormat = nil; _reset() } }
+    open var dateStyle: Style = .none {
+        willSet {
+            _dateFormat = nil
+        }
+        didSet {
+            _dateFormat = CFDateFormatterGetFormat(_cfObject)._swiftObject
+        }
+    }
 
-    open var timeStyle: Style = .none { willSet { _dateFormat = nil; _reset() } }
+    open var timeStyle: Style = .none {
+        willSet {
+            _dateFormat = nil
+        }
+        didSet {
+            _dateFormat = CFDateFormatterGetFormat(_cfObject)._swiftObject
+        }
+    }
 
     /*@NSCopying*/ open var locale: Locale! = .current { willSet { _reset() } }
 
diff --git a/Foundation/Decimal.swift b/Foundation/Decimal.swift
index 3174ca4..36417b1 100644
--- a/Foundation/Decimal.swift
+++ b/Foundation/Decimal.swift
@@ -327,6 +327,7 @@
     }
 
     public mutating func negate() {
+        guard _length != 0 else { return }
         _isNegative = _isNegative == 0 ? 1 : 0
     }
 }
@@ -1282,9 +1283,7 @@
 
 public func NSDecimalSubtract(_ result: UnsafeMutablePointer<Decimal>, _ leftOperand: UnsafePointer<Decimal>, _ rightOperand: UnsafePointer<Decimal>, _ roundingMode: NSDecimalNumber.RoundingMode) -> NSDecimalNumber.CalculationError {
     var r = rightOperand.pointee
-    if r._length != 0 {
-        r.negate()
-    }
+    r.negate()
     return NSDecimalAdd(result, leftOperand, &r, roundingMode)
 }
 // Exact operations. result may be a pointer to same space as leftOperand or rightOperand
diff --git a/Foundation/FileManager.swift b/Foundation/FileManager.swift
index f7ca2e1..0f8e634 100644
--- a/Foundation/FileManager.swift
+++ b/Foundation/FileManager.swift
@@ -158,7 +158,7 @@
                 } else if let attr = attributes {
                     try self.setAttributes(attr, ofItemAtPath: path)
                 }
-            } else if isDir {
+            } else if isDir.boolValue {
                 return
             } else {
                 throw _NSErrorWithErrno(EEXIST, reading: false, path: path)
@@ -406,9 +406,9 @@
     }
     
     open func linkItem(atPath srcPath: String, toPath dstPath: String) throws {
-        var isDir = false
+        var isDir: ObjCBool = false
         if self.fileExists(atPath: srcPath, isDirectory: &isDir) {
-            if !isDir {
+            if !isDir.boolValue {
                 // TODO: Symlinks should be copied instead of hard-linked.
                 if link(srcPath, dstPath) == -1 {
                     throw _NSErrorWithErrno(errno, reading: false, path: srcPath)
@@ -532,12 +532,13 @@
             if let isDirectory = isDirectory {
                 if (s.st_mode & S_IFMT) == S_IFLNK {
                     if stat(path, &s) >= 0 {
-                        isDirectory.pointee = (s.st_mode & S_IFMT) == S_IFDIR
+                        isDirectory.pointee = ObjCBool((s.st_mode & S_IFMT) == S_IFDIR)
                     } else {
                         return false
                     }
                 } else {
-                    isDirectory.pointee = (s.st_mode & S_IFMT) == S_IFDIR
+                    let isDir = (s.st_mode & S_IFMT) == S_IFDIR
+                    isDirectory.pointee = ObjCBool(isDir)
                 }
             }
 
diff --git a/Foundation/HTTPCookieStorage.swift b/Foundation/HTTPCookieStorage.swift
index 8a5e6df..2209818 100644
--- a/Foundation/HTTPCookieStorage.swift
+++ b/Foundation/HTTPCookieStorage.swift
@@ -69,7 +69,7 @@
         let bundlePath = Bundle.main.bundlePath
         var bundleName = bundlePath.components(separatedBy: "/").last!
         if let range = bundleName.range(of: ".", options: String.CompareOptions.backwards, range: nil, locale: nil) {
-            bundleName = bundleName.substring(to: range.lowerBound)
+            bundleName = String(bundleName[..<range.lowerBound])
         }
         let cookieFolderPath = _CFXDGCreateDataHomePath()._swiftObject + "/" + bundleName
         cookieFilePath = filePath(path: cookieFolderPath, fileName: "/.cookies." + cookieStorageName, bundleName: bundleName)
diff --git a/Foundation/JSONEncoder.swift b/Foundation/JSONEncoder.swift
index 59a3844..5c36e1f 100644
--- a/Foundation/JSONEncoder.swift
+++ b/Foundation/JSONEncoder.swift
@@ -64,8 +64,11 @@
 
     /// The strategy to use for encoding `Data` values.
     public enum DataEncodingStrategy {
+        /// Defer to `Data` for choosing an encoding.
+        case deferredToData
+        
         /// Encoded the `Data` as a Base64-encoded string. This is the default strategy.
-        case base64Encode
+        case base64
 
         /// Encode the `Data` as a custom value encoded by the given closure.
         ///
@@ -88,8 +91,8 @@
     /// The strategy to use in encoding dates. Defaults to `.deferredToDate`.
     open var dateEncodingStrategy: DateEncodingStrategy = .deferredToDate
 
-    /// The strategy to use in encoding binary data. Defaults to `.base64Encode`.
-    open var dataEncodingStrategy: DataEncodingStrategy = .base64Encode
+    /// The strategy to use in encoding binary data. Defaults to `.base64`.
+    open var dataEncodingStrategy: DataEncodingStrategy = .base64
 
     /// The strategy to use in encoding non-conforming numbers. Defaults to `.throw`.
     open var nonConformingFloatEncodingStrategy: NonConformingFloatEncodingStrategy = .throw
@@ -98,7 +101,7 @@
     open var userInfo: [CodingUserInfoKey : Any] = [:]
 
     /// Options set on the top-level encoder to pass down the encoding hierarchy.
-    fileprivate struct _Options {
+    internal struct _Options {
         let dateEncodingStrategy: DateEncodingStrategy
         let dataEncodingStrategy: DataEncodingStrategy
         let nonConformingFloatEncodingStrategy: NonConformingFloatEncodingStrategy
@@ -150,14 +153,14 @@
 
 // MARK: - _JSONEncoder
 
-fileprivate class _JSONEncoder : Encoder {
+internal class _JSONEncoder : Encoder {
     // MARK: Properties
 
     /// The encoder's storage.
     fileprivate var storage: _JSONEncodingStorage
 
     /// Options set on the top-level encoder.
-    fileprivate let options: JSONEncoder._Options
+    internal let options: JSONEncoder._Options
 
     /// The path to the current point in encoding.
     public var codingPath: [CodingKey]
@@ -672,7 +675,12 @@
 
     fileprivate func box(_ data: Data) throws -> NSObject {
         switch self.options.dataEncodingStrategy {
-        case .base64Encode:
+        case .deferredToData:
+            // Must be called with a surrounding with(pushedKey:) call.
+            try data.encode(to: self)
+            return self.storage.popContainer()
+            
+        case .base64:
             return NSString(string: data.base64EncodedString())
 
         case .custom(let closure):
@@ -826,8 +834,11 @@
 
     /// The strategy to use for decoding `Data` values.
     public enum DataDecodingStrategy {
+        /// Defer to `Data` for decoding.
+        case deferredToData
+        
         /// Decode the `Data` from a Base64-encoded string. This is the default strategy.
-        case base64Decode
+        case base64
 
         /// Decode the `Data` as a custom value decoded by the given closure.
         case custom((_ decoder: Decoder) throws -> Data)
@@ -845,8 +856,8 @@
     /// The strategy to use in decoding dates. Defaults to `.deferredToDate`.
     open var dateDecodingStrategy: DateDecodingStrategy = .deferredToDate
 
-    /// The strategy to use in decoding binary data. Defaults to `.base64Decode`.
-    open var dataDecodingStrategy: DataDecodingStrategy = .base64Decode
+    /// The strategy to use in decoding binary data. Defaults to `.base64`.
+    open var dataDecodingStrategy: DataDecodingStrategy = .base64
 
     /// The strategy to use in decoding non-conforming numbers. Defaults to `.throw`.
     open var nonConformingFloatDecodingStrategy: NonConformingFloatDecodingStrategy = .throw
@@ -855,7 +866,7 @@
     open var userInfo: [CodingUserInfoKey : Any] = [:]
 
     /// Options set on the top-level encoder to pass down the decoding hierarchy.
-    fileprivate struct _Options {
+    internal struct _Options {
         let dateDecodingStrategy: DateDecodingStrategy
         let dataDecodingStrategy: DataDecodingStrategy
         let nonConformingFloatDecodingStrategy: NonConformingFloatDecodingStrategy
@@ -893,14 +904,14 @@
 
 // MARK: - _JSONDecoder
 
-fileprivate class _JSONDecoder : Decoder {
+internal class _JSONDecoder : Decoder {
     // MARK: Properties
 
     /// The decoder's storage.
     fileprivate var storage: _JSONDecodingStorage
 
     /// Options set on the top-level decoder.
-    fileprivate let options: JSONDecoder._Options
+    internal let options: JSONDecoder._Options
 
     /// The path to the current point in encoding.
     private(set) public var codingPath: [CodingKey]
@@ -2042,7 +2053,13 @@
         guard !(value is NSNull) else { return nil }
 
         switch self.options.dataDecodingStrategy {
-        case .base64Decode:
+        case .deferredToData:
+            self.storage.push(container: value)
+            let data = try Data(from: self)
+            self.storage.popContainer()
+            return data
+            
+        case .base64:
             guard let string = value as? String else {
                 throw DecodingError._typeMismatch(at: self.codingPath, expectation: type, reality: value)
             }
diff --git a/Foundation/JSONSerialization.swift b/Foundation/JSONSerialization.swift
index d4a1201..c624e7a 100644
--- a/Foundation/JSONSerialization.swift
+++ b/Foundation/JSONSerialization.swift
@@ -62,8 +62,9 @@
                 return true
             }
             
-            // object is Swift.String, NSNull, Int, Bool, or UInt
-            if obj is String || obj is NSNull || obj is Int || obj is Bool || obj is UInt {
+            if obj is String || obj is NSNull || obj is Int || obj is Bool || obj is UInt ||
+                obj is Int8 || obj is Int16 || obj is Int32 || obj is Int64 ||
+                obj is UInt8 || obj is UInt16 || obj is UInt32 || obj is UInt64 {
                 return true
             }
 
@@ -76,6 +77,10 @@
                 return number.isFinite
             }
 
+            if let number = obj as? Decimal {
+                return number.isFinite
+            }
+
             // object is Swift.Array
             if let array = obj as? [Any?] {
                 for element in array {
@@ -99,8 +104,13 @@
             // object is NSNumber and is not NaN or infinity
             // For better performance, this (most expensive) test should be last.
             if let number = _SwiftValue.store(obj) as? NSNumber {
-                let invalid = number.doubleValue.isInfinite || number.doubleValue.isNaN
-                return !invalid
+                if CFNumberIsFloatType(number._cfObject) {
+                    let dv = number.doubleValue
+                    let invalid = dv.isInfinite || dv.isNaN
+                    return !invalid
+                } else {
+                    return true
+                }
             }
 
             // invalid object
@@ -285,9 +295,7 @@
 
 //MARK: - JSONSerializer
 private struct JSONWriter {
-    
-    private let maxUIntLength = String(describing: UInt.max).count
-    private let maxIntLength = String(describing: Int.max).count
+
     var indent = 0
     let pretty: Bool
     let sortedKeys: Bool
@@ -320,13 +328,37 @@
         case let boolValue as Bool:
             serializeBool(boolValue)
         case let num as Int:
-            try serializeInt(value: num)
+            serializeInteger(value: num)
+        case let num as Int8:
+            serializeInteger(value: num)
+        case let num as Int16:
+            serializeInteger(value: num)
+        case let num as Int32:
+            serializeInteger(value: num)
+        case let num as Int64:
+            serializeInteger(value: num)
         case let num as UInt:
-            try serializeUInt(value: num)
+            serializeInteger(value: num)
+        case let num as UInt8:
+            serializeInteger(value: num)
+        case let num as UInt16:
+            serializeInteger(value: num)
+        case let num as UInt32:
+            serializeInteger(value: num)
+        case let num as UInt64:
+            serializeInteger(value: num)
         case let array as Array<Any?>:
             try serializeArray(array)
         case let dict as Dictionary<AnyHashable, Any?>:
             try serializeDictionary(dict)
+        case let num as Float:
+            try serializeNumber(NSNumber(value: num))
+        case let num as Double:
+            try serializeNumber(NSNumber(value: num))
+        case let num as Decimal:
+            writer(num.description)
+        case let num as NSDecimalNumber:
+            writer(num.description)
         case is NSNull:
             try serializeNull()
         case _ where _SwiftValue.store(obj) is NSNumber:
@@ -336,92 +368,33 @@
         }
     }
 
-    private func serializeUInt(value: UInt) throws {
-        if value == 0 {
-            writer("0")
-            return
-        }
-        var array: [UInt] = []
-        var stringResult = ""
-        //Maximum length of an UInt
-        array.reserveCapacity(maxUIntLength)
-        stringResult.reserveCapacity(maxUIntLength)
-        var number = value
-        
-        while number != 0 {
-            array.append(number % 10)
+    private func serializeInteger<T: UnsignedInteger>(value: T, isNegative: Bool = false) {
+        let maxIntLength = 22   // 20 digits in UInt64 + optional sign + trailing '\0'
+        let asciiZero: CChar = 0x30  // ASCII '0' == 0x30
+        let asciiMinus: CChar = 0x2d // ASCII '-' == 0x2d
+
+        var number = UInt64(value)
+        var buffer = Array<CChar>(repeating: 0, count: maxIntLength)
+        var pos = maxIntLength - 1
+
+        repeat {
+            pos -= 1
+            buffer[pos] = asciiZero + CChar(number % 10)
             number /= 10
+        } while number != 0
+
+        if isNegative {
+            pos -= 1
+            buffer[pos] = asciiMinus
         }
-        
-        /*
-         Step backwards through the array and append the values to the string. This way the values are appended in the correct order.
-         */
-        var counter = array.count
-        while counter > 0 {
-            counter -= 1
-            let digit: UInt = array[counter]
-            switch digit {
-            case 0: stringResult.append("0")
-            case 1: stringResult.append("1")
-            case 2: stringResult.append("2")
-            case 3: stringResult.append("3")
-            case 4: stringResult.append("4")
-            case 5: stringResult.append("5")
-            case 6: stringResult.append("6")
-            case 7: stringResult.append("7")
-            case 8: stringResult.append("8")
-            case 9: stringResult.append("9")
-            default: fatalError()
-            }
-        }
-        
-        writer(stringResult)
+        let output = String(cString: Array(buffer.suffix(from: pos)))
+        writer(output)
     }
-    
-    private func serializeInt(value: Int) throws {
-        if value == 0 {
-            writer("0")
-            return
-        }
-        var array: [Int] = []
-        var stringResult = ""
-        array.reserveCapacity(maxIntLength)
-        //Account for a negative sign
-        stringResult.reserveCapacity(maxIntLength + 1)
-        var number = value
-        
-        while number != 0 {
-            array.append(number % 10)
-            number /= 10
-        }
-        //If negative add minus sign before adding any values
-        if value < 0 {
-            stringResult.append("-")
-        }
-        /*
-         Step backwards through the array and append the values to the string. This way the values are appended in the correct order.
-         */
-        var counter = array.count
-        while counter > 0 {
-            counter -= 1
-            let digit = array[counter]
-            switch digit {
-            case 0: stringResult.append("0")
-            case 1, -1: stringResult.append("1")
-            case 2, -2: stringResult.append("2")
-            case 3, -3: stringResult.append("3")
-            case 4, -4: stringResult.append("4")
-            case 5, -5: stringResult.append("5")
-            case 6, -6: stringResult.append("6")
-            case 7, -7: stringResult.append("7")
-            case 8, -8: stringResult.append("8")
-            case 9, -9: stringResult.append("9")
-            default: fatalError()
-            }
-        }
-        writer(stringResult)
+
+    private func serializeInteger<T: SignedInteger>(value: T) {
+        serializeInteger(value: UInt64(value.magnitude), isNegative: value < 0)
     }
-    
+
     func serializeString(_ str: String) throws {
         writer("\"")
         for scalar in str.unicodeScalars {
@@ -462,15 +435,30 @@
     }
 
     mutating func serializeNumber(_ num: NSNumber) throws {
-        if num.doubleValue.isInfinite || num.doubleValue.isNaN {
-            throw NSError(domain: NSCocoaErrorDomain, code: CocoaError.propertyListReadCorrupt.rawValue, userInfo: ["NSDebugDescription" : "Number cannot be infinity or NaN"])
-        }
-        
-        switch num._cfTypeID {
-        case CFBooleanGetTypeID():
-            serializeBool(num.boolValue)
-        default:
-            writer(_serializationString(for: num))
+        if CFNumberIsFloatType(num._cfObject) {
+            let dv = num.doubleValue
+            if !dv.isFinite {
+                let value: String
+                if dv.isNaN {
+                    value = "NaN"
+                } else if dv.isInfinite {
+                    value = "infinite"
+                } else {
+                    value = String(dv)
+                }
+
+                throw NSError(domain: NSCocoaErrorDomain, code: CocoaError.propertyListReadCorrupt.rawValue, userInfo: ["NSDebugDescription" : "Invalid number value (\(value)) in JSON write"])
+            }
+
+            let string = CFNumberFormatterCreateStringWithNumber(nil, _numberformatter, num._cfObject)._swiftObject
+            writer(string)
+        } else {
+            switch num._cfTypeID {
+            case CFBooleanGetTypeID():
+                serializeBool(num.boolValue)
+            default:
+                writer(num.stringValue)
+            }
         }
     }
 
@@ -524,7 +512,7 @@
             } else {
                 throw NSError(domain: NSCocoaErrorDomain, code: CocoaError.propertyListReadCorrupt.rawValue, userInfo: ["NSDebugDescription" : "NSDictionary key must be NSString"])
             }
-            pretty ? writer(": ") : writer(":")
+            pretty ? writer(" : ") : writer(":")
             try serializeJSON(value)
         }
 
@@ -577,11 +565,7 @@
             writer(" ")
         }
     }
-    
-    //[SR-2151] https://bugs.swift.org/browse/SR-2151
-    private mutating func _serializationString(for number: NSNumber) -> String {
-        return CFNumberFormatterCreateStringWithNumber(nil, _numberformatter, number._cfObject)._swiftObject
-    }
+
 }
 
 //MARK: - JSONDeserializer
diff --git a/Foundation/Measurement.swift b/Foundation/Measurement.swift
index 99f6904..b119af1 100644
--- a/Foundation/Measurement.swift
+++ b/Foundation/Measurement.swift
@@ -275,3 +275,60 @@
         return Measurement(value: source!.doubleValue, unit: u)
     }
 }
+
+extension Measurement : Codable {
+    private enum CodingKeys : Int, CodingKey {
+        case value
+        case unit
+    }
+
+    private enum UnitCodingKeys : Int, CodingKey {
+        case symbol
+        case converter
+    }
+
+    private enum LinearConverterCodingKeys : Int, CodingKey {
+        case coefficient
+        case constant
+    }
+
+    public init(from decoder: Decoder) throws {
+        let container = try decoder.container(keyedBy: CodingKeys.self)
+        let value = try container.decode(Double.self, forKey: .value)
+
+        let unitContainer = try container.nestedContainer(keyedBy: UnitCodingKeys.self, forKey: .unit)
+        let symbol = try unitContainer.decode(String.self, forKey: .symbol)
+
+        let unit: UnitType
+        if UnitType.self is Dimension.Type {
+            let converterContainer = try unitContainer.nestedContainer(keyedBy: LinearConverterCodingKeys.self, forKey: .converter)
+            let coefficient = try converterContainer.decode(Double.self, forKey: .coefficient)
+            let constant = try converterContainer.decode(Double.self, forKey: .constant)
+            let unitMetaType = (UnitType.self as! Dimension.Type)
+            unit = (unitMetaType.init(symbol: symbol, converter: UnitConverterLinear(coefficient: coefficient, constant: constant)) as! UnitType)
+        } else {
+            unit = UnitType(symbol: symbol)
+        }
+
+        self.init(value: value, unit: unit)
+    }
+
+    public func encode(to encoder: Encoder) throws {
+        var container = encoder.container(keyedBy: CodingKeys.self)
+        try container.encode(self.value, forKey: .value)
+
+        var unitContainer = container.nestedContainer(keyedBy: UnitCodingKeys.self, forKey: .unit)
+        try unitContainer.encode(self.unit.symbol, forKey: .symbol)
+
+        if UnitType.self is Dimension.Type {
+            guard type(of: (self.unit as! Dimension).converter) is UnitConverterLinear.Type else {
+                preconditionFailure("Cannot encode a Measurement whose UnitType has a non-linear unit converter.")
+            }
+
+            let converter = (self.unit as! Dimension).converter as! UnitConverterLinear
+            var converterContainer = unitContainer.nestedContainer(keyedBy: LinearConverterCodingKeys.self, forKey: .converter)
+            try converterContainer.encode(converter.coefficient, forKey: .coefficient)
+            try converterContainer.encode(converter.constant, forKey: .constant)
+        }
+    }
+}
diff --git a/Foundation/NSAttributedString.swift b/Foundation/NSAttributedString.swift
index 17dbe92..3877813 100644
--- a/Foundation/NSAttributedString.swift
+++ b/Foundation/NSAttributedString.swift
@@ -115,7 +115,7 @@
                 attributesInRange = attributes(at: currentIndex, longestEffectiveRange: &attributesEffectiveRange, in: enumerationRange)
             }
             
-            var shouldStop = false
+            var shouldStop: ObjCBool = false
             block(attributesInRange, attributesEffectiveRange, &shouldStop)
             stop.pointee = shouldStop
             
@@ -133,7 +133,7 @@
                 attributeInRange = attribute(attrName, at: currentIndex, longestEffectiveRange: &attributeEffectiveRange, in: enumerationRange)
             }
             
-            var shouldStop = false
+            var shouldStop: ObjCBool = false
             block(attributeInRange, attributeEffectiveRange, &shouldStop)
             stop.pointee = shouldStop
             
@@ -232,10 +232,10 @@
     func _enumerate(in enumerationRange: NSRange, reversed: Bool, using block: (Int, UnsafeMutablePointer<ObjCBool>) -> NSRange) {
         var attributeEnumerationRange = AttributeEnumerationRange(range: enumerationRange, reversed: reversed)
         while attributeEnumerationRange.hasMore {
-            var stop = false
+            var stop: ObjCBool = false
             let effectiveRange = block(attributeEnumerationRange.currentIndex, &stop)
             attributeEnumerationRange.advance(step: effectiveRange.length)
-            if stop {
+            if stop.boolValue {
                 break
             }
         }
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 {
diff --git a/Foundation/NSDictionary.swift b/Foundation/NSDictionary.swift
index f331104..8aa981f 100644
--- a/Foundation/NSDictionary.swift
+++ b/Foundation/NSDictionary.swift
@@ -467,11 +467,11 @@
                 lock.lock()
                 var stop = sharedStop
                 lock.unlock()
-                if stop { return }
+                if stop.boolValue { return }
                 
                 closure(keys[idx], objects[idx], &stop)
                 
-                if stop {
+                if stop.boolValue {
                     lock.lock()
                     sharedStop = stop
                     lock.unlock()
diff --git a/Foundation/NSIndexSet.swift b/Foundation/NSIndexSet.swift
index f621657..4a96e8a 100644
--- a/Foundation/NSIndexSet.swift
+++ b/Foundation/NSIndexSet.swift
@@ -396,9 +396,9 @@
         let iteration = withoutActuallyEscaping(block) { (closure: @escaping (P, UnsafeMutablePointer<ObjCBool>) -> R) -> (Int) -> Void in
             return { (rangeIdx) in
                 lock.lock()
-                var stop = sharedStop
+                var stop = ObjCBool(sharedStop)
                 lock.unlock()
-                if stop { return }
+                if stop.boolValue { return }
                 
                 let idx = rangeSequence.index(rangeSequence.startIndex, offsetBy: Int64(rangeIdx))
                 let curRange = rangeSequence[idx]
@@ -407,9 +407,9 @@
                     if intersection.length > 0 {
                         let _ = closure(intersection as! P, &stop)
                     }
-                    if stop {
+                    if stop.boolValue {
                         lock.lock()
-                        sharedStop = stop
+                        sharedStop = stop.boolValue
                         lock.unlock()
                         return
                     }
@@ -426,9 +426,9 @@
                         } else {
                             let _ = closure(idx as! P, &stop)
                         }
-                        if stop {
+                        if stop.boolValue {
                             lock.lock()
-                            sharedStop = stop
+                            sharedStop = stop.boolValue
                             lock.unlock()
                             return
                         }
diff --git a/Foundation/NSKeyedUnarchiver.swift b/Foundation/NSKeyedUnarchiver.swift
index b977cc8..d75a664 100644
--- a/Foundation/NSKeyedUnarchiver.swift
+++ b/Foundation/NSKeyedUnarchiver.swift
@@ -86,7 +86,7 @@
         return root
     }
     
-    public convenience init(forReadingWithData data: Data) {
+    public convenience init(forReadingWith data: Data) {
         self.init(stream: Stream.data(data))
     }
     
@@ -863,7 +863,7 @@
     }
 
     open class func unarchiveTopLevelObjectWithData(_ data: Data) throws -> Any? {
-        let keyedUnarchiver = NSKeyedUnarchiver(forReadingWithData: data)
+        let keyedUnarchiver = NSKeyedUnarchiver(forReadingWith: data)
         let root = try keyedUnarchiver.decodeTopLevelObject(forKey: NSKeyedArchiveRootObjectKey)
         keyedUnarchiver.finishDecoding()
         return root
diff --git a/Foundation/NSLock.swift b/Foundation/NSLock.swift
index e166b80..f4b41d0 100644
--- a/Foundation/NSLock.swift
+++ b/Foundation/NSLock.swift
@@ -230,12 +230,16 @@
         }
         var ts = timespec()
         ts.tv_sec = Int(floor(ti))
-        ts.tv_nsec = Int((ti - Double(ts.tv_sec)) * 1000000000.0)
+        ts.tv_nsec = Int((ti - Double(ts.tv_sec)) * 1_000_000_000.0)
         var tv = timeval()
         withUnsafeMutablePointer(to: &tv) { t in
             gettimeofday(t, nil)
             ts.tv_sec += t.pointee.tv_sec
-            ts.tv_nsec += Int((t.pointee.tv_usec * 1000000) / 1000000000)
+            ts.tv_nsec += Int(t.pointee.tv_usec) * 1000
+            if ts.tv_nsec >= 1_000_000_000 {
+                ts.tv_sec += ts.tv_nsec / 1_000_000_000
+                ts.tv_nsec = ts.tv_nsec % 1_000_000_000
+            }
         }
         let retVal: Int32 = withUnsafePointer(to: &ts) { t in
             return pthread_cond_timedwait(cond, mutex, t)
diff --git a/Foundation/NSNumber.swift b/Foundation/NSNumber.swift
index b72bdeb..7dc8cc8 100644
--- a/Foundation/NSNumber.swift
+++ b/Foundation/NSNumber.swift
@@ -32,158 +32,523 @@
 internal let kCFNumberSInt128Type: CFNumberType = 17
 #endif
 
+extension Int8 : _ObjectTypeBridgeable {
+    @available(swift, deprecated: 4, renamed: "init(truncating:)")
+    public init(_ number: NSNumber) {
+        self = number.int8Value
+    }
+
+    public init(truncating number: NSNumber) {
+        self = number.int8Value
+    }
+
+    public init?(exactly number: NSNumber) {
+        let value = number.int8Value
+        guard NSNumber(value: value) == number else { return nil }
+        self = value
+    }
+
+    public func _bridgeToObjectiveC() -> NSNumber {
+        return NSNumber(value: self)
+    }
+
+    public static func _forceBridgeFromObjectiveC(_ x: NSNumber, result: inout Int8?) {
+        result = _unconditionallyBridgeFromObjectiveC(x)
+    }
+
+    public static func _conditionallyBridgeFromObjectiveC(_ x: NSNumber, result: inout Int8?) -> Bool {
+        guard let value = Int8(exactly: x) else { return false }
+        result = value
+        return true
+    }
+
+    public static func _unconditionallyBridgeFromObjectiveC(_ source: NSNumber?) -> Int8 {
+        var result: Int8?
+        guard let src = source else { return Int8(0) }
+        guard _conditionallyBridgeFromObjectiveC(src, result: &result) else { return Int8(0) }
+        return result!
+    }
+}
+
+extension UInt8 : _ObjectTypeBridgeable {
+    @available(swift, deprecated: 4, renamed: "init(truncating:)")
+    public init(_ number: NSNumber) {
+        self = number.uint8Value
+    }
+
+    public init(truncating number: NSNumber) {
+        self = number.uint8Value
+    }
+
+    public init?(exactly number: NSNumber) {
+        let value = number.uint8Value
+        guard NSNumber(value: value) == number else { return nil }
+        self = value
+    }
+
+    public func _bridgeToObjectiveC() -> NSNumber {
+        return NSNumber(value: self)
+    }
+
+    public static func _forceBridgeFromObjectiveC(_ x: NSNumber, result: inout UInt8?) {
+        result = _unconditionallyBridgeFromObjectiveC(x)
+    }
+
+    public static func _conditionallyBridgeFromObjectiveC(_ x: NSNumber, result: inout UInt8?) -> Bool {
+        guard let value = UInt8(exactly: x) else { return false }
+        result = value
+        return true
+    }
+
+    public static func _unconditionallyBridgeFromObjectiveC(_ source: NSNumber?) -> UInt8 {
+        var result: UInt8?
+        guard let src = source else { return UInt8(0) }
+        guard _conditionallyBridgeFromObjectiveC(src, result: &result) else { return UInt8(0) }
+        return result!
+    }
+}
+
+extension Int16 : _ObjectTypeBridgeable {
+    @available(swift, deprecated: 4, renamed: "init(truncating:)")
+    public init(_ number: NSNumber) {
+        self = number.int16Value
+    }
+
+    public init(truncating number: NSNumber) {
+        self = number.int16Value
+    }
+
+    public init?(exactly number: NSNumber) {
+        let value = number.int16Value
+        guard NSNumber(value: value) == number else { return nil }
+        self = value
+    }
+
+    public func _bridgeToObjectiveC() -> NSNumber {
+        return NSNumber(value: self)
+    }
+
+    public static func _forceBridgeFromObjectiveC(_ x: NSNumber, result: inout Int16?) {
+        result = _unconditionallyBridgeFromObjectiveC(x)
+    }
+
+    public static func _conditionallyBridgeFromObjectiveC(_ x: NSNumber, result: inout Int16?) -> Bool {
+        guard let value = Int16(exactly: x) else { return false }
+        result = value
+        return true
+    }
+
+    public static func _unconditionallyBridgeFromObjectiveC(_ source: NSNumber?) -> Int16 {
+        var result: Int16?
+        guard let src = source else { return Int16(0) }
+        guard _conditionallyBridgeFromObjectiveC(src, result: &result) else { return Int16(0) }
+        return result!
+    }
+}
+
+extension UInt16 : _ObjectTypeBridgeable {
+    @available(swift, deprecated: 4, renamed: "init(truncating:)")
+    public init(_ number: NSNumber) {
+        self = number.uint16Value
+    }
+
+    public init(truncating number: NSNumber) {
+        self = number.uint16Value
+    }
+
+    public init?(exactly number: NSNumber) {
+        let value = number.uint16Value
+        guard NSNumber(value: value) == number else { return nil }
+        self = value
+    }
+
+    public func _bridgeToObjectiveC() -> NSNumber {
+        return NSNumber(value: self)
+    }
+
+    public static func _forceBridgeFromObjectiveC(_ x: NSNumber, result: inout UInt16?) {
+        result = _unconditionallyBridgeFromObjectiveC(x)
+    }
+
+    public static func _conditionallyBridgeFromObjectiveC(_ x: NSNumber, result: inout UInt16?) -> Bool {
+        guard let value = UInt16(exactly: x) else { return false }
+        result = value
+        return true
+    }
+
+    public static func _unconditionallyBridgeFromObjectiveC(_ source: NSNumber?) -> UInt16 {
+        var result: UInt16?
+        guard let src = source else { return UInt16(0) }
+        guard _conditionallyBridgeFromObjectiveC(src, result: &result) else { return UInt16(0) }
+        return result!
+    }
+}
+
+extension Int32 : _ObjectTypeBridgeable {
+    @available(swift, deprecated: 4, renamed: "init(truncating:)")
+    public init(_ number: NSNumber) {
+        self = number.int32Value
+    }
+
+    public init(truncating number: NSNumber) {
+        self = number.int32Value
+    }
+
+    public init?(exactly number: NSNumber) {
+        let value = number.int32Value
+        guard NSNumber(value: value) == number else { return nil }
+        self = value
+    }
+
+    public func _bridgeToObjectiveC() -> NSNumber {
+        return NSNumber(value: self)
+    }
+
+    public static func _forceBridgeFromObjectiveC(_ x: NSNumber, result: inout Int32?) {
+        result = _unconditionallyBridgeFromObjectiveC(x)
+    }
+
+    public static func _conditionallyBridgeFromObjectiveC(_ x: NSNumber, result: inout Int32?) -> Bool {
+        guard let value = Int32(exactly: x) else { return false }
+        result = value
+        return true
+    }
+
+    public static func _unconditionallyBridgeFromObjectiveC(_ source: NSNumber?) -> Int32 {
+        var result: Int32?
+        guard let src = source else { return Int32(0) }
+        guard _conditionallyBridgeFromObjectiveC(src, result: &result) else { return Int32(0) }
+        return result!
+    }
+}
+
+extension UInt32 : _ObjectTypeBridgeable {
+    @available(swift, deprecated: 4, renamed: "init(truncating:)")
+    public init(_ number: NSNumber) {
+        self = number.uint32Value
+    }
+
+    public init(truncating number: NSNumber) {
+        self = number.uint32Value
+    }
+
+    public init?(exactly number: NSNumber) {
+        let value = number.uint32Value
+        guard NSNumber(value: value) == number else { return nil }
+        self = value
+    }
+
+    public func _bridgeToObjectiveC() -> NSNumber {
+        return NSNumber(value: self)
+    }
+
+    public static func _forceBridgeFromObjectiveC(_ x: NSNumber, result: inout UInt32?) {
+        result = _unconditionallyBridgeFromObjectiveC(x)
+    }
+
+    public static func _conditionallyBridgeFromObjectiveC(_ x: NSNumber, result: inout UInt32?) -> Bool {
+        guard let value = UInt32(exactly: x) else { return false }
+        result = value
+        return true
+    }
+
+    public static func _unconditionallyBridgeFromObjectiveC(_ source: NSNumber?) -> UInt32 {
+        var result: UInt32?
+        guard let src = source else { return UInt32(0) }
+        guard _conditionallyBridgeFromObjectiveC(src, result: &result) else { return UInt32(0) }
+        return result!
+    }
+}
+
+extension Int64 : _ObjectTypeBridgeable {
+    @available(swift, deprecated: 4, renamed: "init(truncating:)")
+    public init(_ number: NSNumber) {
+        self = number.int64Value
+    }
+
+    public init(truncating number: NSNumber) {
+        self = number.int64Value
+    }
+
+    public init?(exactly number: NSNumber) {
+        let value = number.int64Value
+        guard NSNumber(value: value) == number else { return nil }
+        self = value
+    }
+
+    public func _bridgeToObjectiveC() -> NSNumber {
+        return NSNumber(value: self)
+    }
+
+    public static func _forceBridgeFromObjectiveC(_ x: NSNumber, result: inout Int64?) {
+        result = _unconditionallyBridgeFromObjectiveC(x)
+    }
+
+    public static func _conditionallyBridgeFromObjectiveC(_ x: NSNumber, result: inout Int64?) -> Bool {
+        guard let value = Int64(exactly: x) else { return false }
+        result = value
+        return true
+    }
+
+    public static func _unconditionallyBridgeFromObjectiveC(_ source: NSNumber?) -> Int64 {
+        var result: Int64?
+        guard let src = source else { return Int64(0) }
+        guard _conditionallyBridgeFromObjectiveC(src, result: &result) else { return Int64(0) }
+        return result!
+    }
+}
+
+extension UInt64 : _ObjectTypeBridgeable {
+    @available(swift, deprecated: 4, renamed: "init(truncating:)")
+    public init(_ number: NSNumber) {
+        self = number.uint64Value
+    }
+
+    public init(truncating number: NSNumber) {
+        self = number.uint64Value
+    }
+
+    public init?(exactly number: NSNumber) {
+        let value = number.uint64Value
+        guard NSNumber(value: value) == number else { return nil }
+        self = value
+    }
+
+    public func _bridgeToObjectiveC() -> NSNumber {
+        return NSNumber(value: self)
+    }
+
+    public static func _forceBridgeFromObjectiveC(_ x: NSNumber, result: inout UInt64?) {
+        result = _unconditionallyBridgeFromObjectiveC(x)
+    }
+
+    public static func _conditionallyBridgeFromObjectiveC(_ x: NSNumber, result: inout UInt64?) -> Bool {
+        guard let value = UInt64(exactly: x) else { return false }
+        result = value
+        return true
+    }
+
+    public static func _unconditionallyBridgeFromObjectiveC(_ source: NSNumber?) -> UInt64 {
+        var result: UInt64?
+        guard let src = source else { return UInt64(0) }
+        guard _conditionallyBridgeFromObjectiveC(src, result: &result) else { return UInt64(0) }
+        return result!
+    }
+}
+
 extension Int : _ObjectTypeBridgeable {
+    @available(swift, deprecated: 4, renamed: "init(truncating:)")
     public init(_ number: NSNumber) {
         self = number.intValue
     }
-    
-    public typealias _ObjectType = NSNumber
-    public func _bridgeToObjectiveC() -> _ObjectType {
+
+    public init(truncating number: NSNumber) {
+        self = number.intValue
+    }
+
+    public init?(exactly number: NSNumber) {
+        let value = number.intValue
+        guard NSNumber(value: value) == number else { return nil }
+        self = value
+    }
+
+    public func _bridgeToObjectiveC() -> NSNumber {
         return NSNumber(value: self)
     }
     
-    static public func _forceBridgeFromObjectiveC(_ source: _ObjectType, result: inout Int?) {
-        result = _unconditionallyBridgeFromObjectiveC(source)
+    public static func _forceBridgeFromObjectiveC(_ x: NSNumber, result: inout Int?) {
+        result = _unconditionallyBridgeFromObjectiveC(x)
     }
     
-    @discardableResult
-    static public func _conditionallyBridgeFromObjectiveC(_ source: _ObjectType, result: inout Int?) -> Bool {
-        result = source.intValue
+    public static func _conditionallyBridgeFromObjectiveC(_ x: NSNumber, result: inout Int?) -> Bool {
+        guard let value = Int(exactly: x) else { return false }
+        result = value
         return true
     }
     
-    static public func _unconditionallyBridgeFromObjectiveC(_ source: _ObjectType?) -> Int {
-        if let object = source {
-            var value: Int?
-            _conditionallyBridgeFromObjectiveC(object, result: &value)
-            return value!
-        } else {
-            return 0
-        }
+    public static func _unconditionallyBridgeFromObjectiveC(_ source: NSNumber?) -> Int {
+        var result: Int?
+        guard let src = source else { return Int(0) }
+        guard _conditionallyBridgeFromObjectiveC(src, result: &result) else { return Int(0) }
+        return result!
     }
 }
 
 extension UInt : _ObjectTypeBridgeable {
+    @available(swift, deprecated: 4, renamed: "init(truncating:)")
     public init(_ number: NSNumber) {
         self = number.uintValue
     }
 
-    public typealias _ObjectType = NSNumber
-    public func _bridgeToObjectiveC() -> _ObjectType {
+    public init(truncating number: NSNumber) {
+        self = number.uintValue
+    }
+
+    public init?(exactly number: NSNumber) {
+        let value = number.uintValue
+        guard NSNumber(value: value) == number else { return nil }
+        self = value
+    }
+
+    public func _bridgeToObjectiveC() -> NSNumber {
         return NSNumber(value: self)
     }
     
-    static public func _forceBridgeFromObjectiveC(_ source: _ObjectType, result: inout UInt?) {
-        result = _unconditionallyBridgeFromObjectiveC(source)
+    public static func _forceBridgeFromObjectiveC(_ x: NSNumber, result: inout UInt?) {
+        result = _unconditionallyBridgeFromObjectiveC(x)
     }
     
-    @discardableResult
-    static public func _conditionallyBridgeFromObjectiveC(_ source: _ObjectType, result: inout UInt?) -> Bool {
-        result = source.uintValue
+    public static func _conditionallyBridgeFromObjectiveC(_ x: NSNumber, result: inout UInt?) -> Bool {
+        guard let value = UInt(exactly: x) else { return false }
+        result = value
         return true
     }
     
-    static public func _unconditionallyBridgeFromObjectiveC(_ source: _ObjectType?) -> UInt {
-        if let object = source {
-            var value: UInt?
-            _conditionallyBridgeFromObjectiveC(object, result: &value)
-            return value!
-        } else {
-            return 0
-        }
+    public static func _unconditionallyBridgeFromObjectiveC(_ source: NSNumber?) -> UInt {
+        var result: UInt?
+        guard let src = source else { return UInt(0) }
+        guard _conditionallyBridgeFromObjectiveC(src, result: &result) else { return UInt(0) }
+        return result!
     }
 }
 
 extension Float : _ObjectTypeBridgeable {
+    @available(swift, deprecated: 4, renamed: "init(truncating:)")
     public init(_ number: NSNumber) {
         self = number.floatValue
     }
-    
-    public typealias _ObjectType = NSNumber
-    public func _bridgeToObjectiveC() -> _ObjectType {
+
+    public init(truncating number: NSNumber) {
+        self = number.floatValue
+    }
+
+    public init?(exactly number: NSNumber) {
+        guard let value = Double(exactly: number) else { return nil }
+        guard let result = Float(exactly: value) else { return nil }
+        self = result
+    }
+
+    public func _bridgeToObjectiveC() -> NSNumber {
         return NSNumber(value: self)
     }
     
-    static public func _forceBridgeFromObjectiveC(_ source: _ObjectType, result: inout Float?) {
-        result = _unconditionallyBridgeFromObjectiveC(source)
+    public static func _forceBridgeFromObjectiveC(_ x: NSNumber, result: inout Float?) {
+        result = _unconditionallyBridgeFromObjectiveC(x)
     }
     
-    @discardableResult
-    static public func _conditionallyBridgeFromObjectiveC(_ source: _ObjectType, result: inout Float?) -> Bool {
-        result = source.floatValue
+    public static func _conditionallyBridgeFromObjectiveC(_ x: NSNumber, result: inout Float?) -> Bool {
+        guard let value = Double(exactly: x) else { return false }
+        guard !value.isNaN else {
+            result = Float.nan
+            return true
+        }
+        guard !value.isInfinite else {
+            if value.sign == .minus {
+                result = -Float.infinity
+            } else {
+                result = Float.infinity
+            }
+            return true
+        }
+        guard Swift.abs(value) <= Double(Float.greatestFiniteMagnitude) else {
+            return false
+        }
+
+        result = Float(value)
         return true
     }
     
-    static public func _unconditionallyBridgeFromObjectiveC(_ source: _ObjectType?) -> Float {
-        if let object = source {
-            var value: Float?
-            _conditionallyBridgeFromObjectiveC(object, result: &value)
-            return value!
-        } else {
-            return 0.0
-        }
+    public static func _unconditionallyBridgeFromObjectiveC(_ source: NSNumber?) -> Float {
+        var result: Float?
+        guard let src = source else { return Float(0) }
+        guard _conditionallyBridgeFromObjectiveC(src, result: &result) else { return Float(0) }
+        return result!
     }
 }
 
 extension Double : _ObjectTypeBridgeable {
+    @available(swift, deprecated: 4, renamed: "init(truncating:)")
     public init(_ number: NSNumber) {
         self = number.doubleValue
     }
-    
-    public typealias _ObjectType = NSNumber
-    public func _bridgeToObjectiveC() -> _ObjectType {
+
+    public init(truncating number: NSNumber) {
+        self = number.doubleValue
+    }
+
+    public init?(exactly number: NSNumber) {
+        let type = number.objCType.pointee
+        if type == 0x51 {
+            guard let result = Double(exactly: number.uint64Value) else { return nil }
+            self = result
+        } else if type == 0x71 {
+            guard let result = Double(exactly: number.int64Value) else  { return nil }
+            self = result
+        } else {
+            self = number.doubleValue
+        }
+    }
+
+    public func _bridgeToObjectiveC() -> NSNumber {
         return NSNumber(value: self)
     }
     
-    static public func _forceBridgeFromObjectiveC(_ source: _ObjectType, result: inout Double?) {
-        result = _unconditionallyBridgeFromObjectiveC(source)
+    public static func _forceBridgeFromObjectiveC(_ x: NSNumber, result: inout Double?) {
+        result = _unconditionallyBridgeFromObjectiveC(x)
     }
     
-    @discardableResult
-    static public func _conditionallyBridgeFromObjectiveC(_ source: _ObjectType, result: inout Double?) -> Bool {
-        result = source.doubleValue
+    public static func _conditionallyBridgeFromObjectiveC(_ x: NSNumber, result: inout Double?) -> Bool {
+        guard let value = Double(exactly: x) else { return false }
+        result = value
         return true
     }
     
-    static public func _unconditionallyBridgeFromObjectiveC(_ source: _ObjectType?) -> Double {
-        if let object = source {
-            var value: Double?
-            _conditionallyBridgeFromObjectiveC(object, result: &value)
-            return value!
-        } else {
-            return 0.0
-        }
+    public static func _unconditionallyBridgeFromObjectiveC(_ source: NSNumber?) -> Double {
+        var result: Double?
+        guard let src = source else { return Double(0) }
+        guard _conditionallyBridgeFromObjectiveC(src, result: &result) else { return Double(0) }
+        return result!
     }
 }
 
 extension Bool : _ObjectTypeBridgeable {
+    @available(swift, deprecated: 4, renamed: "init(truncating:)")
     public init(_ number: NSNumber) {
         self = number.boolValue
     }
-    
-    public typealias _ObjectType = NSNumber
-    public func _bridgeToObjectiveC() -> _ObjectType {
+
+    public init(truncating number: NSNumber) {
+        self = number.boolValue
+    }
+
+    public init?(exactly number: NSNumber) {
+        if number === kCFBooleanTrue || NSNumber(value: 1) == number {
+            self = true
+        } else if number === kCFBooleanFalse || NSNumber(value: 0) == number {
+            self = false
+        } else {
+            return nil
+        }
+    }
+
+    public func _bridgeToObjectiveC() -> NSNumber {
         return unsafeBitCast(self ? kCFBooleanTrue : kCFBooleanFalse, to: NSNumber.self)
     }
     
-    static public func _forceBridgeFromObjectiveC(_ source: _ObjectType, result: inout Bool?) {
-        result = _unconditionallyBridgeFromObjectiveC(source)
+    public static func _forceBridgeFromObjectiveC(_ x: NSNumber, result: inout Bool?) {
+        result = _unconditionallyBridgeFromObjectiveC(x)
     }
     
-    @discardableResult
-    static public func _conditionallyBridgeFromObjectiveC(_ source: _ObjectType, result: inout Bool?) -> Bool {
-        result = source.boolValue
+    public static func _conditionallyBridgeFromObjectiveC(_ x: NSNumber, result: inout Bool?) -> Bool {
+        result = x.boolValue
         return true
     }
     
-    static public func _unconditionallyBridgeFromObjectiveC(_ source: _ObjectType?) -> Bool {
-        if let object = source {
-            var value: Bool?
-            _conditionallyBridgeFromObjectiveC(object, result: &value)
-            return value!
-        } else {
-            return false
-        }
+    public static func _unconditionallyBridgeFromObjectiveC(_ source: NSNumber?) -> Bool {
+        var result: Bool?
+        guard let src = source else { return false }
+        guard _conditionallyBridgeFromObjectiveC(src, result: &result) else { return false }
+        return result!
     }
 }
 
@@ -226,7 +591,7 @@
         case let other as Bool:
             return boolValue == other
         case let other as NSNumber:
-            return CFEqual(_cfObject, other._cfObject)
+            return compare(other) == .orderedSame
         default:
             return false
         }
@@ -256,7 +621,7 @@
             fatalError("unsupported CFNumberType: '\(numberType)'")
         }
     }
-    
+
     deinit {
         _CFDeinit(self)
     }
@@ -460,6 +825,12 @@
         CFNumberGetValue(_cfObject, kCFNumberSInt128Type, &value)
         return .init(truncatingIfNeeded: value.low)
     }
+
+    private var int128Value: CFSInt128Struct {
+        var value = CFSInt128Struct(high: 0, low: 0)
+        CFNumberGetValue(_cfObject, kCFNumberSInt128Type, &value)
+        return value
+    }
     
     open var floatValue: Float {
         var value: Float = 0
@@ -516,33 +887,49 @@
     }
 
     open func compare(_ otherNumber: NSNumber) -> ComparisonResult {
-        switch (objCType.pointee, otherNumber.objCType.pointee) {
-        case (0x66, _), (_, 0x66), (0x66, 0x66): fallthrough // 'f' float
-        case (0x64, _), (_, 0x64), (0x64, 0x64):             // 'd' double
+        switch (_cfNumberType(), otherNumber._cfNumberType()) {
+        case (kCFNumberFloatType, _), (_, kCFNumberFloatType): fallthrough
+        case (kCFNumberDoubleType, _), (_, kCFNumberDoubleType):
             let (lhs, rhs) = (doubleValue, otherNumber.doubleValue)
+            // Apply special handling for NaN as <, >, == always return false
+            // when comparing with NaN
+            if lhs.isNaN && rhs.isNaN { return .orderedSame }
+            if lhs.isNaN { return .orderedAscending }
+            if rhs.isNaN { return .orderedDescending }
+
             if lhs < rhs { return .orderedAscending }
             if lhs > rhs { return .orderedDescending }
             return .orderedSame
-        case (0x51, _), (_, 0x51), (0x51, 0x51):             // 'q' unsigned long long
-            let (lhs, rhs) = (uint64Value, otherNumber.uint64Value)
-            if lhs < rhs { return .orderedAscending }
-            if lhs > rhs { return .orderedDescending }
-            return .orderedSame
-        case (_, _):
-            let (lhs, rhs) = (int64Value, otherNumber.int64Value)
-            if lhs < rhs { return .orderedAscending }
-            if lhs > rhs { return .orderedDescending }
+
+        default: // For signed and unsigned integers expand upto S128Int
+            let (lhs, rhs) = (int128Value, otherNumber.int128Value)
+            if lhs.high < rhs.high { return .orderedAscending }
+            if lhs.high > rhs.high { return .orderedDescending }
+            if lhs.low < rhs.low { return .orderedAscending }
+            if lhs.low > rhs.low { return .orderedDescending }
             return .orderedSame
         }
     }
 
+    private static let _numberFormatterForNilLocale: CFNumberFormatter = {
+        let formatter: CFNumberFormatter
+        formatter = CFNumberFormatterCreate(nil, CFLocaleCopyCurrent(), kCFNumberFormatterNoStyle)
+        CFNumberFormatterSetProperty(formatter, kCFNumberFormatterMaxFractionDigits, 15._bridgeToObjectiveC())
+        return formatter
+    }()
+
     open func description(withLocale locale: Locale?) -> String {
+        // CFNumberFormatterCreateStringWithNumber() does not like numbers of type
+        // SInt128Type, as it loses the type when looking it up and treats it as
+        // an SInt64Type, so special case them.
+        if _CFNumberGetType2(_cfObject) == kCFNumberSInt128Type {
+            return String(format: "%@", unsafeBitCast(_cfObject, to: UnsafePointer<CFNumber>.self))
+        }
+
         let aLocale = locale
         let formatter: CFNumberFormatter
         if (aLocale == nil) {
-            formatter = CFNumberFormatterCreate(nil, CFLocaleCopyCurrent(), kCFNumberFormatterNoStyle)
-            CFNumberFormatterSetProperty(formatter, kCFNumberFormatterMaxFractionDigits, 15._bridgeToObjectiveC())
-
+            formatter = NSNumber._numberFormatterForNilLocale
         } else {
             formatter = CFNumberFormatterCreate(nil, aLocale?._cfObject, kCFNumberFormatterDecimalStyle)
         }
diff --git a/Foundation/NSPathUtilities.swift b/Foundation/NSPathUtilities.swift
index 0126716..f0b65b4 100644
--- a/Foundation/NSPathUtilities.swift
+++ b/Foundation/NSPathUtilities.swift
@@ -408,9 +408,9 @@
             return false
         }
         
-        var isDirectory = false
+        var isDirectory: ObjCBool = false
         let exists = FileManager.default.fileExists(atPath: path, isDirectory: &isDirectory)
-        return exists && isDirectory
+        return exists && isDirectory.boolValue
     }
     
     internal typealias _FileNamePredicate = (String?) -> Bool
diff --git a/Foundation/NSSet.swift b/Foundation/NSSet.swift
index fdd5b99..939c358 100644
--- a/Foundation/NSSet.swift
+++ b/Foundation/NSSet.swift
@@ -255,7 +255,7 @@
             withUnsafeMutablePointer(to: &stop) { stop in
                 block(obj, stop)
             }
-            if stop {
+            if stop.boolValue {
                 break
             }
         }
diff --git a/Foundation/NSString.swift b/Foundation/NSString.swift
index 54fe91f..26c45b5 100644
--- a/Foundation/NSString.swift
+++ b/Foundation/NSString.swift
@@ -1221,18 +1221,6 @@
             free(bytes)
         }
     }
-    
-    public convenience init?(CString nullTerminatedCString: UnsafePointer<Int8>, encoding: UInt) {
-        guard let cf = CFStringCreateWithCString(kCFAllocatorSystemDefault, nullTerminatedCString, CFStringConvertNSStringEncodingToEncoding(encoding)) else {
-            return nil
-        }
-        var str: String?
-        if String._conditionallyBridgeFromObjectiveC(cf._nsObject, result: &str) {
-            self.init(str!)
-        } else {
-            return nil
-        }
-    }
 
     public convenience init(contentsOf url: URL, encoding enc: UInt) throws {
         let readResult = try NSData(contentsOf: url, options: [])
diff --git a/Foundation/NSStringAPI.swift b/Foundation/NSStringAPI.swift
index a5e1b00..03ebc30 100644
--- a/Foundation/NSStringAPI.swift
+++ b/Foundation/NSStringAPI.swift
@@ -2,11 +2,11 @@
 //
 // This source file is part of the Swift.org open source project
 //
-// Copyright (c) 2014 - 2016 Apple Inc. and the Swift project authors
+// Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors
 // Licensed under Apache License v2.0 with Runtime Library Exception
 //
-// See http://swift.org/LICENSE.txt for license information
-// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
+// See https://swift.org/LICENSE.txt for license information
+// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
 //
 //===----------------------------------------------------------------------===//
 //
@@ -14,6 +14,20 @@
 //
 //===----------------------------------------------------------------------===//
 
+// Important Note
+// ==============
+//
+// This file is shared between two projects:
+//
+// 1. https://github.com/apple/swift/tree/master/stdlib/public/SDK/Foundation
+// 2. https://github.com/apple/swift-corelibs-foundation/tree/master/Foundation
+//
+// If you change this file, you must update it in both places.
+
+#if !DEPLOYMENT_RUNTIME_SWIFT
+@_exported import Foundation // Clang module
+#endif
+
 // Open Issues
 // ===========
 //
@@ -34,70 +48,38 @@
     length: r.upperBound.encodedOffset - r.lowerBound.encodedOffset)
 }
 
+#if !DEPLOYMENT_RUNTIME_SWIFT
+// We only need this for UnsafeMutablePointer, but there's not currently a way
+// to write that constraint.
+extension Optional {
+  /// Invokes `body` with `nil` if `self` is `nil`; otherwise, passes the
+  /// address of `object` to `body`.
+  ///
+  /// This is intended for use with Foundation APIs that return an Objective-C
+  /// type via out-parameter where it is important to be able to *ignore* that
+  /// parameter by passing `nil`. (For some APIs, this may allow the
+  /// implementation to avoid some work.)
+  ///
+  /// In most cases it would be simpler to just write this code inline, but if
+  /// `body` is complicated than that results in unnecessarily repeated code.
+  internal func _withNilOrAddress<NSType : AnyObject, ResultType>(
+    of object: inout NSType?,
+    _ body:
+      (AutoreleasingUnsafeMutablePointer<NSType?>?) -> ResultType
+  ) -> ResultType {
+    return self == nil ? body(nil) : body(&object)
+  }
+}
+#endif
+
 extension String {
-
-  //===--- Bridging Helpers -----------------------------------------------===//
-  //===--------------------------------------------------------------------===//
-
-  /// The corresponding `NSString` - a convenience for bridging code.
-  var _ns: NSString {
-    return self._bridgeToObjectiveC()
-  }
-
-  /// Return an `Index` corresponding to the given offset in our UTF-16
-  /// representation.
-  func _index(_ utf16Index: Int) -> Index {
-    return Index(encodedOffset: utf16Index)
-  }
-
-  /// Return a `Range<Index>` corresponding to the given `NSRange` of
-  /// our UTF-16 representation.
-  func _range(_ r: NSRange) -> Range<Index> {
-    return _index(r.location)..<_index(r.location + r.length)
-  }
-
-  /// Return a `Range<Index>?` corresponding to the given `NSRange` of
-  /// our UTF-16 representation.
-  func _optionalRange(_ r: NSRange) -> Range<Index>? {
-    if r.location == NSNotFound {
-      return nil
-    }
-    return _range(r)
-  }
-
-  /// Invoke `body` on an `Int` buffer.  If `index` was converted from
-  /// non-`nil`, convert the buffer to an `Index` and write it into the
-  /// memory referred to by `index`
-  func _withOptionalOutParameter<Result>(
-    _ index: UnsafeMutablePointer<Index>?,
-    _ body: (UnsafeMutablePointer<Int>?) -> Result
-  ) -> Result {
-    var utf16Index: Int = 0
-    let result = (index != nil ? body(&utf16Index) : body(nil))
-    index?.pointee = self._index(utf16Index)
-    return result
-  }
-
-  /// Invoke `body` on an `NSRange` buffer.  If `range` was converted
-  /// from non-`nil`, convert the buffer to a `Range<Index>` and write
-  /// it into the memory referred to by `range`
-  func _withOptionalOutParameter<Result>(
-    _ range: UnsafeMutablePointer<Range<Index>>?,
-    _ body: (UnsafeMutablePointer<NSRange>?) -> Result
-  ) -> Result {
-    var nsRange = NSRange(location: 0, length: 0)
-    let result = (range != nil ? body(&nsRange) : body(nil))
-    range?.pointee = self._range(nsRange)
-    return result
-  }
-
   //===--- Class Methods --------------------------------------------------===//
   //===--------------------------------------------------------------------===//
 
   // @property (class) const NSStringEncoding *availableStringEncodings;
 
-  /// Returns an Array of the encodings string objects support
-  /// in the application's environment.
+  /// An array of the encodings that strings support in the application's
+  /// environment.
   public static var availableStringEncodings: [Encoding] {
     var result = [Encoding]()
     var p = NSString.availableStringEncodings
@@ -110,15 +92,20 @@
 
   // @property (class) NSStringEncoding defaultCStringEncoding;
 
-  /// Returns the C-string encoding assumed for any method accepting
-  /// a C string as an argument.
+  /// The C-string encoding assumed for any method accepting a C string as an
+  /// argument.
   public static var defaultCStringEncoding: Encoding {
     return Encoding(rawValue: NSString.defaultCStringEncoding)
   }
 
   // + (NSString *)localizedNameOfStringEncoding:(NSStringEncoding)encoding
 
-  /// Returns a human-readable string giving the name of a given encoding.
+  /// Returns a human-readable string giving the name of the specified encoding.
+  ///
+  /// - Parameter encoding: A string encoding. For possible values, see
+  ///   `String.Encoding`.
+  /// - Returns: A human-readable string giving the name of `encoding` in the
+  ///   current locale.
   public static func localizedName(
     of encoding: Encoding
   ) -> String {
@@ -137,15 +124,6 @@
       arguments: arguments)
   }
 
-  // + (NSString *)pathWithComponents:(NSArray *)components
-
-  /// Returns a string built from the strings in a given array
-  /// by concatenating them with a path separator between each pair.
-  @available(*, unavailable, message: "Use fileURL(withPathComponents:) on URL instead.")
-  public static func path(withComponents components: [String]) -> String {
-    return (NSURL.fileURL(withPathComponents: components)?.path)!
-  }
-
   //===--------------------------------------------------------------------===//
   // NSString factory functions that have a corresponding constructor
   // are omitted.
@@ -188,453 +166,18 @@
 
   // + (instancetype)stringWithUTF8String:(const char *)bytes
 
-  /// Produces a string created by copying the data from a given
+  /// Creates a string by copying the data from a given
   /// C array of UTF8-encoded bytes.
   public init?(utf8String bytes: UnsafePointer<CChar>) {
     if let ns = NSString(utf8String: bytes) {
-      self = ns._swiftObject
+      self = String._unconditionallyBridgeFromObjectiveC(ns)
     } else {
       return nil
     }
   }
+}
 
-  //===--- Instance Methods/Properties-------------------------------------===//
-  //===--------------------------------------------------------------------===//
-
-  //===--- Omitted by agreement during API review 5/20/2014 ---------------===//
-  // @property BOOL boolValue;
-
-  // - (BOOL)canBeConvertedToEncoding:(NSStringEncoding)encoding
-
-  /// Returns a Boolean value that indicates whether the
-  /// `String` can be converted to a given encoding without loss of
-  /// information.
-  public func canBeConverted(to encoding: Encoding) -> Bool {
-    return _ns.canBeConverted(to: encoding.rawValue)
-  }
-
-  // @property NSString* capitalizedString
-
-  /// Produce a string with the first character from each word changed
-  /// to the corresponding uppercase value.
-  public var capitalized: String {
-    return _ns.capitalized as String
-  }
-
-  // @property (readonly, copy) NSString *localizedCapitalizedString NS_AVAILABLE(10_11, 9_0);
-
-  /// A capitalized representation of the `String` that is produced
-  /// using the current locale.
-  public var localizedCapitalized: String {
-    return _ns.localizedCapitalized
-  }
-
-  // - (NSString *)capitalizedStringWithLocale:(Locale *)locale
-
-  /// Returns a capitalized representation of the `String`
-  /// using the specified locale.
-  public func capitalized(with locale: Locale?) -> String {
-    return _ns.capitalized(with: locale) as String
-  }
-
-  // - (NSComparisonResult)caseInsensitiveCompare:(NSString *)aString
-
-  /// Returns the result of invoking `compare:options:` with
-  /// `NSCaseInsensitiveSearch` as the only option.
-  public func caseInsensitiveCompare(_ aString: String) -> ComparisonResult {
-    return _ns.caseInsensitiveCompare(aString)
-  }
-
-  //===--- Omitted by agreement during API review 5/20/2014 ---------------===//
-  // - (unichar)characterAtIndex:(NSUInteger)index
-  //
-  // We have a different meaning for "Character" in Swift, and we are
-  // trying not to expose error-prone UTF-16 integer indexes
-
-  // - (NSString *)
-  //     commonPrefixWithString:(NSString *)aString
-  //     options:(StringCompareOptions)mask
-
-  /// Returns a string containing characters the `String` and a
-  /// given string have in common, starting from the beginning of each
-  /// up to the first characters that aren't equivalent.
-  public func commonPrefix(
-    with aString: String, options: CompareOptions = []) -> String {
-    return _ns.commonPrefix(with: aString, options: options)
-  }
-
-  // - (NSComparisonResult)
-  //     compare:(NSString *)aString
-  //
-  // - (NSComparisonResult)
-  //     compare:(NSString *)aString options:(StringCompareOptions)mask
-  //
-  // - (NSComparisonResult)
-  //     compare:(NSString *)aString options:(StringCompareOptions)mask
-  //     range:(NSRange)range
-  //
-  // - (NSComparisonResult)
-  //     compare:(NSString *)aString options:(StringCompareOptions)mask
-  //     range:(NSRange)range locale:(id)locale
-
-  /// Compares the string using the specified options and
-  /// returns the lexical ordering for the range.
-  public func compare(
-    _ aString: String,
-    options mask: CompareOptions = [],
-    range: Range<Index>? = nil,
-    locale: Locale? = nil
-  ) -> ComparisonResult {
-    // According to Ali Ozer, there may be some real advantage to
-    // dispatching to the minimal selector for the supplied options.
-    // So let's do that; the switch should compile away anyhow.
-    return locale != nil ? _ns.compare(
-      aString,
-      options: mask,
-      range: _toNSRange(
-        range ?? self.startIndex..<self.endIndex
-      ),
-      locale: locale?._bridgeToObjectiveC()
-    )
-
-    : range != nil ? _ns.compare(
-      aString,
-      options: mask,
-      range: _toNSRange(range!)
-    )
-
-    : !mask.isEmpty ? _ns.compare(aString, options: mask)
-
-    : _ns.compare(aString)
-  }
-
-  // - (NSUInteger)
-  //     completePathIntoString:(NSString **)outputName
-  //     caseSensitive:(BOOL)flag
-  //     matchesIntoArray:(NSArray **)outputArray
-  //     filterTypes:(NSArray *)filterTypes
-
-  /// Interprets the `String` as a path in the file system and
-  /// attempts to perform filename completion, returning a numeric
-  /// value that indicates whether a match was possible, and by
-  /// reference the longest path that matches the `String`.
-  /// Returns the actual number of matching paths.
-  public func completePath(
-    into outputName: UnsafeMutablePointer<String>? = nil,
-    caseSensitive: Bool,
-    matchesInto outputArray: UnsafeMutablePointer<[String]>? = nil,
-    filterTypes: [String]? = nil
-  ) -> Int {
-
-    var outputNamePlaceholder: String?
-    var outputArrayPlaceholder = [String]()
-    let res = self._ns.completePath(
-        into: &outputNamePlaceholder,
-        caseSensitive: caseSensitive,
-        matchesInto: &outputArrayPlaceholder,
-        filterTypes: filterTypes
-    )
-    if let n = outputNamePlaceholder {
-        outputName?.pointee = n
-    } else {
-        outputName?.pointee = ""
-    }
-    outputArray?.pointee = outputArrayPlaceholder
-    return res
-  }
-
-  // - (NSArray *)
-  //     componentsSeparatedByCharactersInSet:(NSCharacterSet *)separator
-
-  /// Returns an array containing substrings from the `String`
-  /// that have been divided by characters in a given set.
-  public func components(separatedBy separator: CharacterSet) -> [String] {
-    return _ns.components(separatedBy: separator)
-  }
-
-
-  // - (NSArray *)componentsSeparatedByString:(NSString *)separator
-
-  /// Returns an array containing substrings from the `String`
-  /// that have been divided by a given separator.
-  public func components(separatedBy separator: String) -> [String] {
-    return _ns.components(separatedBy: separator)
-  }
-
-  // - (const char *)cStringUsingEncoding:(NSStringEncoding)encoding
-
-  /// Returns a representation of the `String` as a C string
-  /// using a given encoding.
-  public func cString(using encoding: Encoding) -> [CChar]? {
-    return withExtendedLifetime(_ns) {
-      (s: NSString) -> [CChar]? in
-      _persistCString(s.cString(using: encoding.rawValue))
-    }
-  }
-
-  // - (NSData *)dataUsingEncoding:(NSStringEncoding)encoding
-  //
-  // - (NSData *)
-  //     dataUsingEncoding:(NSStringEncoding)encoding
-  //     allowLossyConversion:(BOOL)flag
-
-  /// Returns a `Data` containing a representation of
-  /// the `String` encoded using a given encoding.
-  public func data(
-    using encoding: Encoding,
-    allowLossyConversion: Bool = false
-  ) -> Data? {
-    return _ns.data(
-      using: encoding.rawValue,
-      allowLossyConversion: allowLossyConversion)
-  }
-
-  // @property NSString* decomposedStringWithCanonicalMapping;
-
-  /// Returns a string made by normalizing the `String`'s
-  /// contents using Form D.
-  public var decomposedStringWithCanonicalMapping: String {
-    return _ns.decomposedStringWithCanonicalMapping
-  }
-
-  // @property NSString* decomposedStringWithCompatibilityMapping;
-
-  /// Returns a string made by normalizing the `String`'s
-  /// contents using Form KD.
-  public var decomposedStringWithCompatibilityMapping: String {
-    return _ns.decomposedStringWithCompatibilityMapping
-  }
-
-  //===--- Importing Foundation should not affect String printing ---------===//
-  // Therefore, we're not exposing this:
-  //
-  //   @property NSString* description
-
-
-  //===--- Omitted for consistency with API review results 5/20/2014 -----===//
-  // @property double doubleValue;
-
-  // - (void)
-  //     enumerateLinesUsing:(void (^)(NSString *line, BOOL *stop))block
-
-  /// Enumerates all the lines in a string.
-  public func enumerateLines(
-    invoking body: @escaping (_ line: String, _ stop: inout Bool) -> Void
-  ) {
-    _ns.enumerateLines {
-      (line: String, stop: UnsafeMutablePointer<ObjCBool>)
-    in
-      var stop_ = false
-      body(line, &stop_)
-      if stop_ {
-        stop.pointee = true
-      }
-    }
-  }
-
-
-  // - (void)
-  //     enumerateSubstringsInRange:(NSRange)range
-  //     options:(NSStringEnumerationOptions)opts
-  //     usingBlock:(
-  //       void (^)(
-  //         NSString *substring,
-  //         NSRange substringRange,
-  //         NSRange enclosingRange,
-  //         BOOL *stop)
-  //       )block
-
-  /// Enumerates the substrings of the specified type in the
-  /// specified range of the string.
-  public func enumerateSubstrings(
-    in range: Range<Index>,
-    options opts: EnumerationOptions = [],
-    _ body: @escaping (
-      _ substring: String?, _ substringRange: Range<Index>,
-      _ enclosingRange: Range<Index>, inout Bool
-    ) -> Void
-  ) {
-    _ns.enumerateSubstrings(in: _toNSRange(range), options: opts) {
-      var stop_ = false
-
-      body($0,
-        self._range($1),
-        self._range($2),
-        &stop_)
-
-      if stop_ {
-        UnsafeMutablePointer($3).pointee = true
-      }
-    }
-  }
-
-  // @property NSStringEncoding fastestEncoding;
-
-  /// Returns the fastest encoding to which the `String` may be
-  /// converted without loss of information.
-  public var fastestEncoding: Encoding {
-    return Encoding(rawValue: _ns.fastestEncoding)
-  }
-
-  // - (const char *)fileSystemRepresentation
-
-  /// Returns a file system-specific representation of the `String`.
-  @available(*, unavailable, message: "Use getFileSystemRepresentation on URL instead.")
-  public var fileSystemRepresentation: [CChar] {
-    return _persistCString(_ns.fileSystemRepresentation)!
-  }
-
-  //===--- Omitted for consistency with API review results 5/20/2014 ------===//
-  // @property float floatValue;
-
-  // - (BOOL)
-  //     getBytes:(void *)buffer
-  //     maxLength:(NSUInteger)maxBufferCount
-  //     usedLength:(NSUInteger*)usedBufferCount
-  //     encoding:(NSStringEncoding)encoding
-  //     options:(StringEncodingConversionOptions)options
-  //     range:(NSRange)range
-  //     remainingRange:(NSRangePointer)leftover
-
-  /// Writes the given `range` of characters into `buffer` in a given
-  /// `encoding`, without any allocations.  Does not NULL-terminate.
-  ///
-  /// - Parameter buffer: A buffer into which to store the bytes from
-  ///   the receiver. The returned bytes are not NUL-terminated.
-  ///
-  /// - Parameter maxBufferCount: The maximum number of bytes to write
-  ///   to buffer.
-  ///
-  /// - Parameter usedBufferCount: The number of bytes used from
-  ///   buffer. Pass `nil` if you do not need this value.
-  ///
-  /// - Parameter encoding: The encoding to use for the returned bytes.
-  ///
-  /// - Parameter options: A mask to specify options to use for
-  ///   converting the receiver's contents to `encoding` (if conversion
-  ///   is necessary).
-  ///
-  /// - Parameter range: The range of characters in the receiver to get.
-  ///
-  /// - Parameter leftover: The remaining range. Pass `nil` If you do
-  ///   not need this value.
-  ///
-  /// - Returns: `true` iff some characters were converted.
-  ///
-  /// - Note: Conversion stops when the buffer fills or when the
-  ///   conversion isn't possible due to the chosen encoding.
-  ///
-  /// - Note: will get a maximum of `min(buffer.count, maxLength)` bytes.
-  public func getBytes(
-    _ buffer: inout [UInt8],
-    maxLength maxBufferCount: Int,
-    usedLength usedBufferCount: UnsafeMutablePointer<Int>,
-    encoding: Encoding,
-    options: EncodingConversionOptions = [],
-    range: Range<Index>,
-    remaining leftover: UnsafeMutablePointer<Range<Index>>
-  ) -> Bool {
-    return _withOptionalOutParameter(leftover) {
-      self._ns.getBytes(
-        &buffer,
-        maxLength: min(buffer.count, maxBufferCount),
-        usedLength: usedBufferCount,
-        encoding: encoding.rawValue,
-        options: options,
-        range: _toNSRange(range),
-        remaining: $0)
-    }
-  }
-
-  // - (BOOL)
-  //     getCString:(char *)buffer
-  //     maxLength:(NSUInteger)maxBufferCount
-  //     encoding:(NSStringEncoding)encoding
-
-  /// Converts the `String`'s content to a given encoding and
-  /// stores them in a buffer.
-  /// - Note: will store a maximum of `min(buffer.count, maxLength)` bytes.
-  public func getCString(
-    _ buffer: inout [CChar], maxLength: Int, encoding: Encoding
-  ) -> Bool {
-    return _ns.getCString(&buffer, maxLength: min(buffer.count, maxLength),
-                          encoding: encoding.rawValue)
-  }
-
-  // - (BOOL)
-  //     getFileSystemRepresentation:(char *)buffer
-  //     maxLength:(NSUInteger)maxLength
-
-  /// Interprets the `String` as a system-independent path and
-  /// fills a buffer with a C-string in a format and encoding suitable
-  /// for use with file-system calls.
-  /// - Note: will store a maximum of `min(buffer.count, maxLength)` bytes.
-  @available(*, unavailable, message: "Use getFileSystemRepresentation on URL instead.")
-  public func getFileSystemRepresentation(
-    _ buffer: inout [CChar], maxLength: Int) -> Bool {
-    return _ns.getFileSystemRepresentation(
-      &buffer, maxLength: min(buffer.count, maxLength))
-  }
-
-  // - (void)
-  //     getLineStart:(NSUInteger *)startIndex
-  //     end:(NSUInteger *)lineEndIndex
-  //     contentsEnd:(NSUInteger *)contentsEndIndex
-  //     forRange:(NSRange)aRange
-
-  /// Returns by reference the beginning of the first line and
-  /// the end of the last line touched by the given range.
-  public func getLineStart(
-    _ start: UnsafeMutablePointer<Index>,
-    end: UnsafeMutablePointer<Index>,
-    contentsEnd: UnsafeMutablePointer<Index>,
-    for range: Range<Index>
-  ) {
-    _withOptionalOutParameter(start) {
-      start in self._withOptionalOutParameter(end) {
-        end in self._withOptionalOutParameter(contentsEnd) {
-          contentsEnd in self._ns.getLineStart(
-            start, end: end,
-            contentsEnd: contentsEnd,
-            for: _toNSRange(range))
-        }
-      }
-    }
-  }
-
-  // - (void)
-  //     getParagraphStart:(NSUInteger *)startIndex
-  //     end:(NSUInteger *)endIndex
-  //     contentsEnd:(NSUInteger *)contentsEndIndex
-  //     forRange:(NSRange)aRange
-
-  /// Returns by reference the beginning of the first paragraph
-  /// and the end of the last paragraph touched by the given range.
-  public func getParagraphStart(
-    _ start: UnsafeMutablePointer<Index>,
-    end: UnsafeMutablePointer<Index>,
-    contentsEnd: UnsafeMutablePointer<Index>,
-    for range: Range<Index>
-  ) {
-    _withOptionalOutParameter(start) {
-      start in self._withOptionalOutParameter(end) {
-        end in self._withOptionalOutParameter(contentsEnd) {
-          contentsEnd in self._ns.getParagraphStart(
-            start, end: end,
-            contentsEnd: contentsEnd,
-            for: _toNSRange(range))
-        }
-      }
-    }
-  }
-
-  // - (NSUInteger)hash
-
-  /// An unsigned integer that can be used as a hash table address.
-  public var hash: Int {
-    return _ns.hash
-  }
-
+extension String {
   //===--- Already provided by String's core ------------------------------===//
   // - (instancetype)init
 
@@ -644,13 +187,18 @@
   //     length:(NSUInteger)length
   //     encoding:(NSStringEncoding)encoding
 
-  /// Produces an initialized `NSString` object equivalent to the given
-  /// `bytes` interpreted in the given `encoding`.
+  /// Creates a new string equivalent to the given bytes interpreted in the
+  /// specified encoding.
+  ///
+  /// - Parameters:
+  ///   - bytes: A sequence of bytes to interpret using `encoding`.
+  ///   - encoding: The ecoding to use to interpret `bytes`.
   public init? <S: Sequence>(bytes: S, encoding: Encoding)
     where S.Iterator.Element == UInt8 {
     let byteArray = Array(bytes)
     if let ns = NSString(
       bytes: byteArray, length: byteArray.count, encoding: encoding.rawValue) {
+
       self = String._unconditionallyBridgeFromObjectiveC(ns)
     } else {
       return nil
@@ -663,10 +211,11 @@
   //     encoding:(NSStringEncoding)encoding
   //     freeWhenDone:(BOOL)flag
 
-  /// Produces an initialized `String` object that contains a
-  /// given number of bytes from a given buffer of bytes interpreted
-  /// in a given encoding, and optionally frees the buffer.  WARNING:
-  /// this initializer is not memory-safe!
+  /// Creates a new string that contains the specified number of bytes from the
+  /// given buffer, interpreted in the specified encoding, and optionally
+  /// frees the buffer.
+  ///
+  /// - Warning: This initializer is not memory-safe!
   public init?(
     bytesNoCopy bytes: UnsafeMutableRawPointer, length: Int,
     encoding: Encoding, freeWhenDone flag: Bool
@@ -674,6 +223,7 @@
     if let ns = NSString(
       bytesNoCopy: bytes, length: length, encoding: encoding.rawValue,
       freeWhenDone: flag) {
+
       self = String._unconditionallyBridgeFromObjectiveC(ns)
     } else {
       return nil
@@ -685,9 +235,8 @@
   //     initWithCharacters:(const unichar *)characters
   //     length:(NSUInteger)length
 
-  /// Returns an initialized `String` object that contains a
-  /// given number of characters from a given array of Unicode
-  /// characters.
+  /// Creates a new string that contains the specified number of characters
+  /// from the given C array of Unicode characters.
   public init(
     utf16CodeUnits: UnsafePointer<unichar>,
     count: Int
@@ -700,8 +249,8 @@
   //     length:(NSUInteger)length
   //     freeWhenDone:(BOOL)flag
 
-  /// Returns an initialized `String` object that contains a given
-  /// number of characters from a given array of UTF-16 Code Units
+  /// Creates a new string that contains the specified number of characters
+  /// from the given C array of UTF-16 code units.
   public init(
     utf16CodeUnitsNoCopy: UnsafePointer<unichar>,
     count: Int,
@@ -813,9 +362,9 @@
       return nil
     }
   }
-  
+
   // FIXME: handle optional locale with default arguments
-  
+
   // - (instancetype)
   //     initWithData:(NSData *)data
   //     encoding:(NSStringEncoding)encoding
@@ -826,7 +375,7 @@
     guard let s = NSString(data: data, encoding: encoding.rawValue) else { return nil }
     self = String._unconditionallyBridgeFromObjectiveC(s)
   }
-  
+
   // - (instancetype)initWithFormat:(NSString *)format, ...
 
   /// Returns a `String` object initialized by using a given
@@ -865,83 +414,461 @@
   /// format string as a template into which the remaining argument
   /// values are substituted according to given locale information.
   public init(format: String, locale: Locale?, arguments: [CVarArg]) {
+#if DEPLOYMENT_RUNTIME_SWIFT
     self = withVaList(arguments) {
       String._unconditionallyBridgeFromObjectiveC(
         NSString(format: format, locale: locale?._bridgeToObjectiveC(), arguments: $0)
       )
     }
+#else
+    self = withVaList(arguments) {
+      NSString(format: format, locale: locale, arguments: $0) as String
+    }
+#endif
   }
 
-  //===--- Already provided by core Swift ---------------------------------===//
-  // - (instancetype)initWithString:(NSString *)aString
+}
 
-  //===--- Initializers that can fail dropped for factory functions -------===//
-  // - (instancetype)initWithUTF8String:(const char *)bytes
+extension StringProtocol where Index == String.Index {
+  //===--- Bridging Helpers -----------------------------------------------===//
+  //===--------------------------------------------------------------------===//
 
-  //===--- Omitted for consistency with API review results 5/20/2014 ------===//
-  // @property NSInteger integerValue;
-  // @property Int intValue;
-
-  //===--- Omitted by apparent agreement during API review 5/20/2014 ------===//
-  // @property BOOL absolutePath;
-  // - (BOOL)isEqualToString:(NSString *)aString
-
-  //===--- Kept for consistency with API review results 5/20/2014 ---------===//
-  // We decided to keep pathWithComponents, so keeping this too
-  // @property NSString lastPathComponent;
-
-  /// Returns the last path component of the `String`.
-  @available(*, unavailable, message: "Use lastPathComponent on URL instead.")
-  public var lastPathComponent: String {
-    return _ns.lastPathComponent
+  /// The corresponding `NSString` - a convenience for bridging code.
+  // FIXME(strings): There is probably a better way to bridge Self to NSString
+  var _ns: NSString {
+    return self._ephemeralString._bridgeToObjectiveC()
   }
 
-  //===--- Renamed by agreement during API review 5/20/2014 ---------------===//
-  // @property NSUInteger length;
+  /// Return an `Index` corresponding to the given offset in our UTF-16
+  /// representation.
+  func _index(_ utf16Index: Int) -> Index {
+    return Index(encodedOffset: utf16Index)
+  }
 
-  /// Returns the number of Unicode characters in the `String`.
-  @available(*, unavailable,
-    message: "Take the count of a UTF-16 view instead, i.e. str.utf16.count")
-  public var utf16Count: Int {
-    return _ns.length
+  /// Return a `Range<Index>` corresponding to the given `NSRange` of
+  /// our UTF-16 representation.
+  func _range(_ r: NSRange) -> Range<Index> {
+    return _index(r.location)..<_index(r.location + r.length)
+  }
+
+  /// Return a `Range<Index>?` corresponding to the given `NSRange` of
+  /// our UTF-16 representation.
+  func _optionalRange(_ r: NSRange) -> Range<Index>? {
+    if r.location == NSNotFound {
+      return nil
+    }
+    return _range(r)
+  }
+
+  /// Invoke `body` on an `Int` buffer.  If `index` was converted from
+  /// non-`nil`, convert the buffer to an `Index` and write it into the
+  /// memory referred to by `index`
+  func _withOptionalOutParameter<Result>(
+    _ index: UnsafeMutablePointer<Index>?,
+    _ body: (UnsafeMutablePointer<Int>?) -> Result
+  ) -> Result {
+    var utf16Index: Int = 0
+    let result = (index != nil ? body(&utf16Index) : body(nil))
+    index?.pointee = _index(utf16Index)
+    return result
+  }
+
+  /// Invoke `body` on an `NSRange` buffer.  If `range` was converted
+  /// from non-`nil`, convert the buffer to a `Range<Index>` and write
+  /// it into the memory referred to by `range`
+  func _withOptionalOutParameter<Result>(
+    _ range: UnsafeMutablePointer<Range<Index>>?,
+    _ body: (UnsafeMutablePointer<NSRange>?) -> Result
+  ) -> Result {
+    var nsRange = NSRange(location: 0, length: 0)
+    let result = (range != nil ? body(&nsRange) : body(nil))
+    range?.pointee = self._range(nsRange)
+    return result
+  }
+
+  //===--- Instance Methods/Properties-------------------------------------===//
+  //===--------------------------------------------------------------------===//
+
+  //===--- Omitted by agreement during API review 5/20/2014 ---------------===//
+  // @property BOOL boolValue;
+
+  // - (BOOL)canBeConvertedToEncoding:(NSStringEncoding)encoding
+
+  /// Returns a Boolean value that indicates whether the string can be
+  /// converted to the specified encoding without loss of information.
+  ///
+  /// - Parameter encoding: A string encoding.
+  /// - Returns: `true` if the string can be encoded in `encoding` without loss
+  ///   of information; otherwise, `false`.
+  public func canBeConverted(to encoding: String.Encoding) -> Bool {
+    return _ns.canBeConverted(to: encoding.rawValue)
+  }
+
+  // @property NSString* capitalizedString
+
+  /// A copy of the string with each word changed to its corresponding
+  /// capitalized spelling.
+  ///
+  /// This property performs the canonical (non-localized) mapping. It is
+  /// suitable for programming operations that require stable results not
+  /// depending on the current locale.
+  ///
+  /// A capitalized string is a string with the first character in each word
+  /// changed to its corresponding uppercase value, and all remaining
+  /// characters set to their corresponding lowercase values. A "word" is any
+  /// sequence of characters delimited by spaces, tabs, or line terminators.
+  /// Some common word delimiting punctuation isn't considered, so this
+  /// property may not generally produce the desired results for multiword
+  /// strings. See the `getLineStart(_:end:contentsEnd:for:)` method for
+  /// additional information.
+  ///
+  /// Case transformations aren’t guaranteed to be symmetrical or to produce
+  /// strings of the same lengths as the originals.
+  public var capitalized: String {
+    return _ns.capitalized as String
+  }
+
+  // @property (readonly, copy) NSString *localizedCapitalizedString NS_AVAILABLE(10_11, 9_0);
+
+  /// A capitalized representation of the string that is produced
+  /// using the current locale.
+  @available(OSX 10.11, iOS 9.0, *)
+  public var localizedCapitalized: String {
+    return _ns.localizedCapitalized
+  }
+
+  // - (NSString *)capitalizedStringWithLocale:(Locale *)locale
+
+  /// Returns a capitalized representation of the string
+  /// using the specified locale.
+  public func capitalized(with locale: Locale?) -> String {
+    return _ns.capitalized(with: locale) as String
+  }
+
+  // - (NSComparisonResult)caseInsensitiveCompare:(NSString *)aString
+
+  /// Returns the result of invoking `compare:options:` with
+  /// `NSCaseInsensitiveSearch` as the only option.
+  public func caseInsensitiveCompare<
+    T : StringProtocol
+  >(_ aString: T) -> ComparisonResult {
+    return _ns.caseInsensitiveCompare(aString._ephemeralString)
+  }
+
+  //===--- Omitted by agreement during API review 5/20/2014 ---------------===//
+  // - (unichar)characterAtIndex:(NSUInteger)index
+  //
+  // We have a different meaning for "Character" in Swift, and we are
+  // trying not to expose error-prone UTF-16 integer indexes
+
+  // - (NSString *)
+  //     commonPrefixWithString:(NSString *)aString
+  //     options:(StringCompareOptions)mask
+
+  /// Returns a string containing characters this string and the
+  /// given string have in common, starting from the beginning of each
+  /// up to the first characters that aren't equivalent.
+  public func commonPrefix<
+    T : StringProtocol
+  >(with aString: T, options: String.CompareOptions = []) -> String {
+    return _ns.commonPrefix(with: aString._ephemeralString, options: options)
+  }
+
+  // - (NSComparisonResult)
+  //     compare:(NSString *)aString
+  //
+  // - (NSComparisonResult)
+  //     compare:(NSString *)aString options:(StringCompareOptions)mask
+  //
+  // - (NSComparisonResult)
+  //     compare:(NSString *)aString options:(StringCompareOptions)mask
+  //     range:(NSRange)range
+  //
+  // - (NSComparisonResult)
+  //     compare:(NSString *)aString options:(StringCompareOptions)mask
+  //     range:(NSRange)range locale:(id)locale
+
+  /// Compares the string using the specified options and
+  /// returns the lexical ordering for the range.
+  public func compare<T : StringProtocol>(
+    _ aString: T,
+    options mask: String.CompareOptions = [],
+    range: Range<Index>? = nil,
+    locale: Locale? = nil
+  ) -> ComparisonResult {
+    // According to Ali Ozer, there may be some real advantage to
+    // dispatching to the minimal selector for the supplied options.
+    // So let's do that; the switch should compile away anyhow.
+    let aString = aString._ephemeralString
+    return locale != nil ? _ns.compare(
+      aString,
+      options: mask,
+      range: _toNSRange(
+        range ?? startIndex..<endIndex
+      ),
+      locale: locale?._bridgeToObjectiveC()
+    )
+
+    : range != nil ? _ns.compare(
+      aString,
+      options: mask,
+      range: _toNSRange(range!)
+    )
+
+    : !mask.isEmpty ? _ns.compare(aString, options: mask)
+
+    : _ns.compare(aString)
+  }
+
+  // - (NSUInteger)
+  //     completePathIntoString:(NSString **)outputName
+  //     caseSensitive:(BOOL)flag
+  //     matchesIntoArray:(NSArray **)outputArray
+  //     filterTypes:(NSArray *)filterTypes
+
+  /// Interprets the string as a path in the file system and
+  /// attempts to perform filename completion, returning a numeric
+  /// value that indicates whether a match was possible, and by
+  /// reference the longest path that matches the string.
+  ///
+  /// - Returns: The actual number of matching paths.
+  public func completePath(
+    into outputName: UnsafeMutablePointer<String>? = nil,
+    caseSensitive: Bool,
+    matchesInto outputArray: UnsafeMutablePointer<[String]>? = nil,
+    filterTypes: [String]? = nil
+  ) -> Int {
+#if DEPLOYMENT_RUNTIME_SWIFT
+    var outputNamePlaceholder: String?
+    var outputArrayPlaceholder = [String]()
+    let res = self._ns.completePath(
+        into: &outputNamePlaceholder,
+        caseSensitive: caseSensitive,
+        matchesInto: &outputArrayPlaceholder,
+        filterTypes: filterTypes
+    )
+    if let n = outputNamePlaceholder {
+        outputName?.pointee = n
+    } else {
+        outputName?.pointee = ""
+    }
+    outputArray?.pointee = outputArrayPlaceholder
+    return res
+#else // DEPLOYMENT_RUNTIME_SWIFT
+    var nsMatches: NSArray?
+    var nsOutputName: NSString?
+
+    let result: Int = outputName._withNilOrAddress(of: &nsOutputName) {
+      outputName in outputArray._withNilOrAddress(of: &nsMatches) {
+        outputArray in
+        // FIXME: completePath(...) is incorrectly annotated as requiring
+        // non-optional output parameters. rdar://problem/25494184
+        let outputNonOptionalName = unsafeBitCast(
+          outputName, to: AutoreleasingUnsafeMutablePointer<NSString?>.self)
+        let outputNonOptionalArray = unsafeBitCast(
+          outputArray, to: AutoreleasingUnsafeMutablePointer<NSArray?>.self)
+        return self._ns.completePath(
+          into: outputNonOptionalName,
+          caseSensitive: caseSensitive,
+          matchesInto: outputNonOptionalArray,
+          filterTypes: filterTypes
+        )
+      }
+    }
+
+    if let matches = nsMatches {
+      // Since this function is effectively a bridge thunk, use the
+      // bridge thunk semantics for the NSArray conversion
+      outputArray?.pointee = matches as! [String]
+    }
+
+    if let n = nsOutputName {
+      outputName?.pointee = n as String
+    }
+    return result
+#endif // DEPLOYMENT_RUNTIME_SWIFT
+  }
+
+  // - (NSArray *)
+  //     componentsSeparatedByCharactersInSet:(NSCharacterSet *)separator
+
+  /// Returns an array containing substrings from the string
+  /// that have been divided by characters in the given set.
+  public func components(separatedBy separator: CharacterSet) -> [String] {
+    return _ns.components(separatedBy: separator)
+  }
+
+  // - (NSArray *)componentsSeparatedByString:(NSString *)separator
+
+  /// Returns an array containing substrings from the string that have been
+  /// divided by the given separator.
+  ///
+  /// The substrings in the resulting array appear in the same order as the
+  /// original string. Adjacent occurrences of the separator string produce
+  /// empty strings in the result. Similarly, if the string begins or ends
+  /// with the separator, the first or last substring, respectively, is empty.
+  /// The following example shows this behavior:
+  ///
+  ///     let list1 = "Karin, Carrie, David"
+  ///     let items1 = list1.components(separatedBy: ", ")
+  ///     // ["Karin", "Carrie", "David"]
+  ///
+  ///     // Beginning with the separator:
+  ///     let list2 = ", Norman, Stanley, Fletcher"
+  ///     let items2 = list2.components(separatedBy: ", ")
+  ///     // ["", "Norman", "Stanley", "Fletcher"
+  ///
+  /// If the list has no separators, the array contains only the original
+  /// string itself.
+  ///
+  ///     let name = "Karin"
+  ///     let list = name.components(separatedBy: ", ")
+  ///     // ["Karin"]
+  ///
+  /// - Parameter separator: The separator string.
+  /// - Returns: An array containing substrings that have been divided from the
+  ///   string using `separator`.
+  // FIXME(strings): now when String conforms to Collection, this can be
+  //   replaced by split(separator:maxSplits:omittingEmptySubsequences:)
+  public func components<
+    T : StringProtocol
+  >(separatedBy separator: T) -> [String] {
+    return _ns.components(separatedBy: separator._ephemeralString)
+  }
+
+  // - (const char *)cStringUsingEncoding:(NSStringEncoding)encoding
+
+  /// Returns a representation of the string as a C string
+  /// using a given encoding.
+  public func cString(using encoding: String.Encoding) -> [CChar]? {
+    return withExtendedLifetime(_ns) {
+      (s: NSString) -> [CChar]? in
+      _persistCString(s.cString(using: encoding.rawValue))
+    }
+  }
+
+  // - (NSData *)dataUsingEncoding:(NSStringEncoding)encoding
+  //
+  // - (NSData *)
+  //     dataUsingEncoding:(NSStringEncoding)encoding
+  //     allowLossyConversion:(BOOL)flag
+
+  /// Returns a `Data` containing a representation of
+  /// the `String` encoded using a given encoding.
+  public func data(
+    using encoding: String.Encoding,
+    allowLossyConversion: Bool = false
+  ) -> Data? {
+    return _ns.data(
+      using: encoding.rawValue,
+      allowLossyConversion: allowLossyConversion)
+  }
+
+  // @property NSString* decomposedStringWithCanonicalMapping;
+
+  /// A string created by normalizing the string's contents using Form D.
+  public var decomposedStringWithCanonicalMapping: String {
+    return _ns.decomposedStringWithCanonicalMapping
+  }
+
+  // @property NSString* decomposedStringWithCompatibilityMapping;
+
+  /// A string created by normalizing the string's contents using Form KD.
+  public var decomposedStringWithCompatibilityMapping: String {
+    return _ns.decomposedStringWithCompatibilityMapping
+  }
+
+  //===--- Importing Foundation should not affect String printing ---------===//
+  // Therefore, we're not exposing this:
+  //
+  //   @property NSString* description
+
+
+  //===--- Omitted for consistency with API review results 5/20/2014 -----===//
+  // @property double doubleValue;
+
+  // - (void)
+  //     enumerateLinesUsing:(void (^)(NSString *line, BOOL *stop))block
+
+  /// Enumerates all the lines in a string.
+  public func enumerateLines(
+    invoking body: @escaping (_ line: String, _ stop: inout Bool) -> Void
+  ) {
+    _ns.enumerateLines {
+      (line: String, stop: UnsafeMutablePointer<ObjCBool>)
+    in
+      var stop_ = false
+      body(line, &stop_)
+      if stop_ {
+        stop.pointee = true
+      }
+    }
+  }
+
+  // @property NSStringEncoding fastestEncoding;
+
+  /// The fastest encoding to which the string can be converted without loss
+  /// of information.
+  public var fastestEncoding: String.Encoding {
+    return String.Encoding(rawValue: _ns.fastestEncoding)
+  }
+
+  // - (BOOL)
+  //     getCString:(char *)buffer
+  //     maxLength:(NSUInteger)maxBufferCount
+  //     encoding:(NSStringEncoding)encoding
+
+  /// Converts the `String`'s content to a given encoding and
+  /// stores them in a buffer.
+  /// - Note: will store a maximum of `min(buffer.count, maxLength)` bytes.
+  public func getCString(
+    _ buffer: inout [CChar], maxLength: Int, encoding: String.Encoding
+  ) -> Bool {
+    return _ns.getCString(&buffer,
+                          maxLength: Swift.min(buffer.count, maxLength),
+                          encoding: encoding.rawValue)
+  }
+
+  // - (NSUInteger)hash
+
+  /// An unsigned integer that can be used as a hash table address.
+  public var hash: Int {
+    return _ns.hash
   }
 
   // - (NSUInteger)lengthOfBytesUsingEncoding:(NSStringEncoding)enc
 
   /// Returns the number of bytes required to store the
   /// `String` in a given encoding.
-  public func lengthOfBytes(using encoding: Encoding) -> Int {
+  public func lengthOfBytes(using encoding: String.Encoding) -> Int {
     return _ns.lengthOfBytes(using: encoding.rawValue)
   }
 
-  // - (NSRange)lineRangeForRange:(NSRange)aRange
-
-  /// Returns the range of characters representing the line or lines
-  /// containing a given range.
-  public func lineRange(for aRange: Range<Index>) -> Range<Index> {
-    return _range(_ns.lineRange(for: _toNSRange(aRange)))
-  }
-
   // - (NSComparisonResult)localizedCaseInsensitiveCompare:(NSString *)aString
 
-  /// Compares the string and a given string using a
-  /// case-insensitive, localized, comparison.
+  /// Compares the string and the given string using a case-insensitive,
+  /// localized, comparison.
   public
-  func localizedCaseInsensitiveCompare(_ aString: String) -> ComparisonResult {
-    return _ns.localizedCaseInsensitiveCompare(aString)
+  func localizedCaseInsensitiveCompare<
+    T : StringProtocol
+  >(_ aString: T) -> ComparisonResult {
+    return _ns.localizedCaseInsensitiveCompare(aString._ephemeralString)
   }
 
   // - (NSComparisonResult)localizedCompare:(NSString *)aString
 
-  /// Compares the string and a given string using a localized
-  /// comparison.
-  public func localizedCompare(_ aString: String) -> ComparisonResult {
-    return _ns.localizedCompare(aString)
+  /// Compares the string and the given string using a localized comparison.
+  public func localizedCompare<
+    T : StringProtocol
+  >(_ aString: T) -> ComparisonResult {
+    return _ns.localizedCompare(aString._ephemeralString)
   }
 
-  /// Compares strings as sorted by the Finder.
-  public func localizedStandardCompare(_ string: String) -> ComparisonResult {
-    return _ns.localizedStandardCompare(string)
+  /// Compares the string and the given string as sorted by the Finder.
+  public func localizedStandardCompare<
+    T : StringProtocol
+  >(_ string: T) -> ComparisonResult {
+    return _ns.localizedStandardCompare(string._ephemeralString)
   }
 
   //===--- Omitted for consistency with API review results 5/20/2014 ------===//
@@ -951,6 +878,7 @@
 
   /// A lowercase version of the string that is produced using the current
   /// locale.
+  @available(OSX 10.11, iOS 9.0, *)
   public var localizedLowercase: String {
     return _ns.localizedLowercase
   }
@@ -969,53 +897,25 @@
   /// Returns the maximum number of bytes needed to store the
   /// `String` in a given encoding.
   public
-  func maximumLengthOfBytes(using encoding: Encoding) -> Int {
+  func maximumLengthOfBytes(using encoding: String.Encoding) -> Int {
     return _ns.maximumLengthOfBytes(using: encoding.rawValue)
   }
 
-  // - (NSRange)paragraphRangeForRange:(NSRange)aRange
-
-  /// Returns the range of characters representing the
-  /// paragraph or paragraphs containing a given range.
-  public func paragraphRange(for aRange: Range<Index>) -> Range<Index> {
-    return _range(_ns.paragraphRange(for: _toNSRange(aRange)))
-  }
-
-  // @property NSArray* pathComponents
-
-  /// Returns an array of NSString objects containing, in
-  /// order, each path component of the `String`.
-  @available(*, unavailable, message: "Use pathComponents on URL instead.")
-  public var pathComponents: [String] {
-    return _ns.pathComponents
-  }
-
-  // @property NSString* pathExtension;
-
-  /// Interprets the `String` as a path and returns the
-  /// `String`'s extension, if any.
-  @available(*, unavailable, message: "Use pathExtension on URL instead.")
-  public var pathExtension: String {
-    return _ns.pathExtension
-  }
-
   // @property NSString* precomposedStringWithCanonicalMapping;
 
-  /// Returns a string made by normalizing the `String`'s
-  /// contents using Form C.
+  /// A string created by normalizing the string's contents using Form C.
   public var precomposedStringWithCanonicalMapping: String {
     return _ns.precomposedStringWithCanonicalMapping
   }
 
   // @property NSString * precomposedStringWithCompatibilityMapping;
 
-  /// Returns a string made by normalizing the `String`'s
-  /// contents using Form KC.
+  /// A string created by normalizing the string's contents using Form KC.
   public var precomposedStringWithCompatibilityMapping: String {
     return _ns.precomposedStringWithCompatibilityMapping
   }
 
-#if false
+#if !DEPLOYMENT_RUNTIME_SWIFT
   // - (id)propertyList
 
   /// Parses the `String` as a text representation of a
@@ -1029,151 +929,41 @@
 
   /// Returns a dictionary object initialized with the keys and
   /// values found in the `String`.
-  public
-  func propertyListFromStringsFileFormat() -> [String : String] {
-    return _ns.propertyListFromStringsFileFormat()! as [NSObject : AnyObject]
-      as! [String : String]
+  public func propertyListFromStringsFileFormat() -> [String : String] {
+    return _ns.propertyListFromStringsFileFormat() as! [String : String]? ?? [:]
   }
 #endif
-    
-  // - (NSRange)rangeOfCharacterFromSet:(NSCharacterSet *)aSet
-  //
-  // - (NSRange)
-  //     rangeOfCharacterFromSet:(NSCharacterSet *)aSet
-  //     options:(StringCompareOptions)mask
-  //
-  // - (NSRange)
-  //     rangeOfCharacterFromSet:(NSCharacterSet *)aSet
-  //     options:(StringCompareOptions)mask
-  //     range:(NSRange)aRange
-
-  /// Finds and returns the range in the `String` of the first
-  /// character from a given character set found in a given range with
-  /// given options.
-  public func rangeOfCharacter(
-    from aSet: CharacterSet,
-    options mask: CompareOptions = [],
-    range aRange: Range<Index>? = nil
-  ) -> Range<Index>? {
-    return _optionalRange(
-      _ns.rangeOfCharacter(
-        from: aSet,
-        options: mask,
-        range: _toNSRange(
-          aRange ?? self.startIndex..<self.endIndex
-        )
-      )
-    )
-  }
-
-  // - (NSRange)rangeOfComposedCharacterSequenceAtIndex:(NSUInteger)anIndex
-
-  /// Returns the range in the `String` of the composed
-  /// character sequence located at a given index.
-  public
-  func rangeOfComposedCharacterSequence(at anIndex: Index) -> Range<Index> {
-    return _range(
-      _ns.rangeOfComposedCharacterSequence(at: anIndex.encodedOffset))
-  }
-
-  // - (NSRange)rangeOfComposedCharacterSequencesForRange:(NSRange)range
-
-  /// Returns the range in the string of the composed character
-  /// sequences for a given range.
-  public func rangeOfComposedCharacterSequences(
-    for range: Range<Index>
-  ) -> Range<Index> {
-    // Theoretically, this will be the identity function.  In practice
-    // I think users will be able to observe differences in the input
-    // and output ranges due (if nothing else) to locale changes
-    return _range(
-      _ns.rangeOfComposedCharacterSequences(for: _toNSRange(range)))
-  }
-
-  // - (NSRange)rangeOfString:(NSString *)aString
-  //
-  // - (NSRange)
-  //     rangeOfString:(NSString *)aString options:(StringCompareOptions)mask
-  //
-  // - (NSRange)
-  //     rangeOfString:(NSString *)aString
-  //     options:(StringCompareOptions)mask
-  //     range:(NSRange)aRange
-  //
-  // - (NSRange)
-  //     rangeOfString:(NSString *)aString
-  //     options:(StringCompareOptions)mask
-  //     range:(NSRange)searchRange
-  //     locale:(Locale *)locale
-
-  /// Finds and returns the range of the first occurrence of a
-  /// given string within a given range of the `String`, subject to
-  /// given options, using the specified locale, if any.
-  public func range(
-    of aString: String,
-    options mask: CompareOptions = [],
-    range searchRange: Range<Index>? = nil,
-    locale: Locale? = nil
-  ) -> Range<Index>? {
-    return _optionalRange(
-      locale != nil ? _ns.range(
-        of: aString,
-        options: mask,
-        range: _toNSRange(
-          searchRange ?? self.startIndex..<self.endIndex
-        ),
-        locale: locale
-      )
-      : searchRange != nil ? _ns.range(
-        of: aString, options: mask, range: _toNSRange(searchRange!)
-      )
-      : !mask.isEmpty ? _ns.range(of: aString, options: mask)
-      : _ns.range(of: aString)
-    )
-  }
 
   // - (BOOL)localizedStandardContainsString:(NSString *)str NS_AVAILABLE(10_11, 9_0);
 
-  /// Returns `true` if `self` contains `string`, taking the current locale
-  /// into account.
+  /// Returns a Boolean value indicating whether the string contains the given
+  /// string, taking the current locale into account.
   ///
   /// This is the most appropriate method for doing user-level string searches,
   /// similar to how searches are done generally in the system.  The search is
   /// locale-aware, case and diacritic insensitive.  The exact list of search
   /// options applied may change over time.
-  public func localizedStandardContains(_ string: String) -> Bool {
-    return _ns.localizedStandardContains(string)
-  }
-
-  // - (NSRange)localizedStandardRangeOfString:(NSString *)str NS_AVAILABLE(10_11, 9_0);
-
-  /// Finds and returns the range of the first occurrence of a given string,
-  /// taking the current locale into account.  Returns `nil` if the string was
-  /// not found.
-  ///
-  /// This is the most appropriate method for doing user-level string searches,
-  /// similar to how searches are done generally in the system.  The search is
-  /// locale-aware, case and diacritic insensitive.  The exact list of search
-  /// options applied may change over time.
-  public func localizedStandardRange(of string: String) -> Range<Index>? {
-    return _optionalRange(_ns.localizedStandardRange(of: string))
+  @available(OSX 10.11, iOS 9.0, *)
+  public func localizedStandardContains<
+    T : StringProtocol
+  >(_ string: T) -> Bool {
+    return _ns.localizedStandardContains(string._ephemeralString)
   }
 
   // @property NSStringEncoding smallestEncoding;
 
-  /// Returns the smallest encoding to which the `String` can
-  /// be converted without loss of information.
-  public var smallestEncoding: Encoding {
-    return Encoding(rawValue: _ns.smallestEncoding)
+  /// The smallest encoding to which the string can be converted without
+  /// loss of information.
+  public var smallestEncoding: String.Encoding {
+    return String.Encoding(rawValue: _ns.smallestEncoding)
   }
 
   // - (NSString *)
   //     stringByAddingPercentEncodingWithAllowedCharacters:
   //       (NSCharacterSet *)allowedCharacters
 
-  /// Returns a new string made from the `String` by replacing
-  /// all characters not in the specified set with percent encoded
-  /// characters.
+  /// Returns a new string created by replacing all characters in the string
+  /// not in the specified set with percent encoded characters.
   public func addingPercentEncoding(
     withAllowedCharacters allowedCharacters: CharacterSet
   ) -> String? {
@@ -1193,90 +983,31 @@
 
   // - (NSString *)stringByAppendingFormat:(NSString *)format, ...
 
-  /// Returns a string made by appending to the `String` a
-  /// string constructed from a given format string and the following
-  /// arguments.
-  public func appendingFormat(
-    _ format: String, _ arguments: CVarArg...
+  /// Returns a string created by appending a string constructed from a given
+  /// format string and the following arguments.
+  public func appendingFormat<
+    T : StringProtocol
+  >(
+    _ format: T, _ arguments: CVarArg...
   ) -> String {
     return _ns.appending(
-      String(format: format, arguments: arguments))
-  }
-
-  // - (NSString *)stringByAppendingPathComponent:(NSString *)aString
-
-  /// Returns a new string made by appending to the `String` a given string.
-  @available(*, unavailable, message: "Use appendingPathComponent on URL instead.")
-  public func appendingPathComponent(_ aString: String) -> String {
-    return _ns.appendingPathComponent(aString)
-  }
-
-  // - (NSString *)stringByAppendingPathExtension:(NSString *)ext
-
-  /// Returns a new string made by appending to the `String` an
-  /// extension separator followed by a given extension.
-  @available(*, unavailable, message: "Use appendingPathExtension on URL instead.")
-  public func appendingPathExtension(_ ext: String) -> String? {
-    // FIXME: This method can return nil in practice, for example when self is
-    // an empty string.  OTOH, this is not documented, documentation says that
-    // it always returns a string.
-    //
-    // <rdar://problem/17902469> -[NSString stringByAppendingPathExtension] can
-    // return nil
-    return _ns.appendingPathExtension(ext)
+      String(format: format._ephemeralString, arguments: arguments))
   }
 
   // - (NSString *)stringByAppendingString:(NSString *)aString
 
-  /// Returns a new string made by appending a given string to
-  /// the `String`.
-  public func appending(_ aString: String) -> String {
-    return _ns.appending(aString)
-  }
-
-  // @property NSString* stringByDeletingLastPathComponent;
-
-  /// Returns a new string made by deleting the last path
-  /// component from the `String`, along with any final path
-  /// separator.
-  @available(*, unavailable, message: "Use deletingLastPathComponent on URL instead.")
-  public var deletingLastPathComponent: String {
-    return _ns.deletingLastPathComponent
-  }
-
-  // @property NSString* stringByDeletingPathExtension;
-
-  /// Returns a new string made by deleting the extension (if
-  /// any, and only the last) from the `String`.
-  @available(*, unavailable, message: "Use deletingPathExtension on URL instead.")
-  public var deletingPathExtension: String {
-    return _ns.deletingPathExtension
-  }
-
-  // @property NSString* stringByExpandingTildeInPath;
-
-  /// Returns a new string made by expanding the initial
-  /// component of the `String` to its full path value.
-  @available(*, unavailable, message: "Use expandingTildeInPath on NSString instead.")
-  public var expandingTildeInPath: String {
-    return _ns.expandingTildeInPath
-  }
-
-  // - (NSString *)
-  //     stringByFoldingWithOptions:(StringCompareOptions)options
-  //     locale:(Locale *)locale
-
-  @available(*, unavailable, renamed: "folding(options:locale:)")
-  public func folding(
-    _ options: CompareOptions = [], locale: Locale?
-  ) -> String {
-    return folding(options: options, locale: locale)
+  /// Returns a new string created by appending the given string.
+  // FIXME(strings): shouldn't it be deprecated in favor of `+`?
+  public func appending<
+    T : StringProtocol
+  >(_ aString: T) -> String {
+    return _ns.appending(aString._ephemeralString)
   }
 
   /// Returns a string with the given character folding options
   /// applied.
   public func folding(
-    options: CompareOptions = [], locale: Locale?
+    options: String.CompareOptions = [], locale: Locale?
   ) -> String {
     return _ns.folding(options: options, locale: locale)
   }
@@ -1288,20 +1019,23 @@
   /// Returns a new string formed from the `String` by either
   /// removing characters from the end, or by appending as many
   /// occurrences as necessary of a given pad string.
-  public func padding(
+  public func padding<
+    T : StringProtocol
+  >(
     toLength newLength: Int,
-    withPad padString: String,
+    withPad padString: T,
     startingAt padIndex: Int
   ) -> String {
     return _ns.padding(
-      toLength: newLength, withPad: padString, startingAt: padIndex)
+      toLength: newLength,
+      withPad: padString._ephemeralString,
+      startingAt: padIndex)
   }
 
   // @property NSString* stringByRemovingPercentEncoding;
 
-  /// Returns a new string made from the `String` by replacing
-  /// all percent encoded sequences with the matching UTF-8
-  /// characters.
+  /// A new string made from the string by replacing all percent encoded
+  /// sequences with the matching UTF-8 characters.
   public var removingPercentEncoding: String? {
     return _ns.removingPercentEncoding
   }
@@ -1312,10 +1046,12 @@
 
   /// Returns a new string in which the characters in a
   /// specified range of the `String` are replaced by a given string.
-  public func replacingCharacters(
-    in range: Range<Index>, with replacement: String
-  ) -> String {
-    return _ns.replacingCharacters(in: _toNSRange(range), with: replacement)
+  public func replacingCharacters<
+    T : StringProtocol, R : RangeExpression
+  >(in range: R, with replacement: T) -> String where R.Bound == Index {
+    return _ns.replacingCharacters(
+      in: _toNSRange(range.relative(to: self)),
+      with: replacement._ephemeralString)
   }
 
   // - (NSString *)
@@ -1329,43 +1065,46 @@
   //     range:(NSRange)searchRange
 
   /// Returns a new string in which all occurrences of a target
-  /// string in a specified range of the `String` are replaced by
+  /// string in a specified range of the string are replaced by
   /// another given string.
-  public func replacingOccurrences(
-    of target: String,
-    with replacement: String,
-    options: CompareOptions = [],
+  public func replacingOccurrences<
+    Target : StringProtocol,
+    Replacement : StringProtocol
+  >(
+    of target: Target,
+    with replacement: Replacement,
+    options: String.CompareOptions = [],
     range searchRange: Range<Index>? = nil
   ) -> String {
+    let target = target._ephemeralString
+    let replacement = replacement._ephemeralString
     return (searchRange != nil) || (!options.isEmpty)
     ? _ns.replacingOccurrences(
       of: target,
       with: replacement,
       options: options,
       range: _toNSRange(
-        searchRange ?? self.startIndex..<self.endIndex
+        searchRange ?? startIndex..<endIndex
       )
     )
     : _ns.replacingOccurrences(of: target, with: replacement)
   }
 
-  // @property NSString* stringByResolvingSymlinksInPath;
+#if !DEPLOYMENT_RUNTIME_SWIFT
+  // - (NSString *)
+  //     stringByReplacingPercentEscapesUsingEncoding:(NSStringEncoding)encoding
 
-  /// Returns a new string made from the `String` by resolving
-  /// all symbolic links and standardizing path.
-  @available(*, unavailable, message: "Use resolvingSymlinksInPath on URL instead.")
-  public var resolvingSymlinksInPath: String {
-    return _ns.resolvingSymlinksInPath
+  /// Returns a new string made by replacing in the `String`
+  /// all percent escapes with the matching characters as determined
+  /// by a given encoding.
+  @available(swift, deprecated: 3.0, obsoleted: 4.0,
+    message: "Use removingPercentEncoding instead, which always uses the recommended UTF-8 encoding.")
+  public func replacingPercentEscapes(
+    using encoding: String.Encoding
+  ) -> String? {
+    return _ns.replacingPercentEscapes(using: encoding.rawValue)
   }
-
-  // @property NSString* stringByStandardizingPath;
-
-  /// Returns a new string made by removing extraneous path
-  /// components from the `String`.
-  @available(*, unavailable, message: "Use standardizingPath on URL instead.")
-  public var standardizingPath: String {
-    return _ns.standardizingPath
-  }
+#endif
 
   // - (NSString *)stringByTrimmingCharactersInSet:(NSCharacterSet *)set
 
@@ -1375,43 +1114,11 @@
     return _ns.trimmingCharacters(in: set)
   }
 
-  // - (NSArray *)stringsByAppendingPaths:(NSArray *)paths
-
-  /// Returns an array of strings made by separately appending
-  /// to the `String` each string in a given array.
-  @available(*, unavailable, message: "Map over paths with appendingPathComponent instead.")
-  public func strings(byAppendingPaths paths: [String]) -> [String] {
-    fatalError("This function is not available")
-  }
-
-  // - (NSString *)substringFromIndex:(NSUInteger)anIndex
-
-  /// Returns a new string containing the characters of the
-  /// `String` from the one at a given index to the end.
-  public func substring(from index: Index) -> String {
-    return _ns.substring(from: index.encodedOffset)
-  }
-
-  // - (NSString *)substringToIndex:(NSUInteger)anIndex
-
-  /// Returns a new string containing the characters of the
-  /// `String` up to, but not including, the one at a given index.
-  public func substring(to index: Index) -> String {
-    return _ns.substring(to: index.encodedOffset)
-  }
-
-  // - (NSString *)substringWithRange:(NSRange)aRange
-
-  /// Returns a string object containing the characters of the
-  /// `String` that lie within a given range.
-  public func substring(with aRange: Range<Index>) -> String {
-    return _ns.substring(with: _toNSRange(aRange))
-  }
-
   // @property (readonly, copy) NSString *localizedUppercaseString NS_AVAILABLE(10_11, 9_0);
 
   /// An uppercase version of the string that is produced using the current
   /// locale.
+  @available(OSX 10.11, iOS 9.0, *)
   public var localizedUppercase: String {
     return _ns.localizedUppercase as String
   }
@@ -1436,12 +1143,16 @@
 
   /// Writes the contents of the `String` to a file at a given
   /// path using a given encoding.
-  public func write(
-    toFile path: String, atomically useAuxiliaryFile:Bool,
-    encoding enc: Encoding
+  public func write<
+    T : StringProtocol
+  >(
+    toFile path: T, atomically useAuxiliaryFile: Bool,
+    encoding enc: String.Encoding
   ) throws {
-    try self._ns.write(
-      toFile: path, atomically: useAuxiliaryFile, encoding: enc.rawValue)
+    try _ns.write(
+      toFile: path._ephemeralString,
+      atomically: useAuxiliaryFile,
+      encoding: enc.rawValue)
   }
 
   // - (BOOL)
@@ -1454,23 +1165,458 @@
   /// by url using the specified encoding.
   public func write(
     to url: URL, atomically useAuxiliaryFile: Bool,
-    encoding enc: Encoding
+    encoding enc: String.Encoding
   ) throws {
-    try self._ns.write(
+    try _ns.write(
       to: url, atomically: useAuxiliaryFile, encoding: enc.rawValue)
   }
 
   // - (nullable NSString *)stringByApplyingTransform:(NSString *)transform reverse:(BOOL)reverse NS_AVAILABLE(10_11, 9_0);
 
+#if !DEPLOYMENT_RUNTIME_SWIFT
   /// Perform string transliteration.
-#if false
+  @available(OSX 10.11, iOS 9.0, *)
   public func applyingTransform(
     _ transform: StringTransform, reverse: Bool
   ) -> String? {
     return _ns.applyingTransform(transform, reverse: reverse)
   }
+
+  // - (void)
+  //     enumerateLinguisticTagsInRange:(NSRange)range
+  //     scheme:(NSString *)tagScheme
+  //     options:(LinguisticTaggerOptions)opts
+  //     orthography:(Orthography *)orthography
+  //     usingBlock:(
+  //       void (^)(
+  //         NSString *tag, NSRange tokenRange,
+  //         NSRange sentenceRange, BOOL *stop)
+  //       )block
+
+  /// Performs linguistic analysis on the specified string by
+  /// enumerating the specific range of the string, providing the
+  /// Block with the located tags.
+  public func enumerateLinguisticTags<
+    T : StringProtocol, R : RangeExpression
+  >(
+    in range: R,
+    scheme tagScheme: T,
+    options opts: NSLinguisticTagger.Options = [],
+    orthography: NSOrthography? = nil,
+    invoking body:
+      (String, Range<Index>, Range<Index>, inout Bool) -> Void
+  ) where R.Bound == Index {
+    let range = range.relative(to: self)
+    _ns.enumerateLinguisticTags(
+      in: _toNSRange(range),
+      scheme: tagScheme._ephemeralString,
+      options: opts,
+      orthography: orthography != nil ? orthography! : nil
+    ) {
+      var stop_ = false
+      body($0, self._range($1), self._range($2), &stop_)
+      if stop_ {
+        $3.pointee = true
+      }
+    }
+  }
 #endif
-    
+
+  // - (void)
+  //     enumerateSubstringsInRange:(NSRange)range
+  //     options:(NSStringEnumerationOptions)opts
+  //     usingBlock:(
+  //       void (^)(
+  //         NSString *substring,
+  //         NSRange substringRange,
+  //         NSRange enclosingRange,
+  //         BOOL *stop)
+  //       )block
+
+  /// Enumerates the substrings of the specified type in the specified range of
+  /// the string.
+  ///
+  /// Mutation of a string value while enumerating its substrings is not
+  /// supported. If you need to mutate a string from within `body`, convert
+  /// your string to an `NSMutableString` instance and then call the
+  /// `enumerateSubstrings(in:options:using:)` method.
+  ///
+  /// - Parameters:
+  ///   - range: The range within the string to enumerate substrings.
+  ///   - opts: Options specifying types of substrings and enumeration styles.
+  ///     If `opts` is omitted or empty, `body` is called a single time with
+  ///     the range of the string specified by `range`.
+  ///   - body: The closure executed for each substring in the enumeration. The
+  ///     closure takes four arguments:
+  ///     - The enumerated substring. If `substringNotRequired` is included in
+  ///       `opts`, this parameter is `nil` for every execution of the
+  ///       closure.
+  ///     - The range of the enumerated substring in the string that
+  ///       `enumerate(in:options:_:)` was called on.
+  ///     - The range that includes the substring as well as any separator or
+  ///       filler characters that follow. For instance, for lines,
+  ///       `enclosingRange` contains the line terminators. The enclosing
+  ///       range for the first string enumerated also contains any characters
+  ///       that occur before the string. Consecutive enclosing ranges are
+  ///       guaranteed not to overlap, and every single character in the
+  ///       enumerated range is included in one and only one enclosing range.
+  ///     - An `inout` Boolean value that the closure can use to stop the
+  ///       enumeration by setting `stop = true`.
+  public func enumerateSubstrings<
+    R : RangeExpression
+  >(
+    in range: R,
+    options opts: String.EnumerationOptions = [],
+    _ body: @escaping (
+      _ substring: String?, _ substringRange: Range<Index>,
+      _ enclosingRange: Range<Index>, inout Bool
+    ) -> Void
+  ) where R.Bound == Index {
+    _ns.enumerateSubstrings(
+      in: _toNSRange(range.relative(to: self)), options: opts) {
+      var stop_ = false
+
+      body($0,
+        self._range($1),
+        self._range($2),
+        &stop_)
+
+      if stop_ {
+        UnsafeMutablePointer($3).pointee = true
+      }
+    }
+  }
+
+  //===--- Omitted for consistency with API review results 5/20/2014 ------===//
+  // @property float floatValue;
+
+  // - (BOOL)
+  //     getBytes:(void *)buffer
+  //     maxLength:(NSUInteger)maxBufferCount
+  //     usedLength:(NSUInteger*)usedBufferCount
+  //     encoding:(NSStringEncoding)encoding
+  //     options:(StringEncodingConversionOptions)options
+  //     range:(NSRange)range
+  //     remainingRange:(NSRangePointer)leftover
+
+  /// Writes the given `range` of characters into `buffer` in a given
+  /// `encoding`, without any allocations.  Does not NULL-terminate.
+  ///
+  /// - Parameter buffer: A buffer into which to store the bytes from
+  ///   the receiver. The returned bytes are not NUL-terminated.
+  ///
+  /// - Parameter maxBufferCount: The maximum number of bytes to write
+  ///   to buffer.
+  ///
+  /// - Parameter usedBufferCount: The number of bytes used from
+  ///   buffer. Pass `nil` if you do not need this value.
+  ///
+  /// - Parameter encoding: The encoding to use for the returned bytes.
+  ///
+  /// - Parameter options: A mask to specify options to use for
+  ///   converting the receiver's contents to `encoding` (if conversion
+  ///   is necessary).
+  ///
+  /// - Parameter range: The range of characters in the receiver to get.
+  ///
+  /// - Parameter leftover: The remaining range. Pass `nil` If you do
+  ///   not need this value.
+  ///
+  /// - Returns: `true` iff some characters were converted.
+  ///
+  /// - Note: Conversion stops when the buffer fills or when the
+  ///   conversion isn't possible due to the chosen encoding.
+  ///
+  /// - Note: will get a maximum of `min(buffer.count, maxLength)` bytes.
+  public func getBytes<
+    R : RangeExpression
+  >(
+    _ buffer: inout [UInt8],
+    maxLength maxBufferCount: Int,
+    usedLength usedBufferCount: UnsafeMutablePointer<Int>,
+    encoding: String.Encoding,
+    options: String.EncodingConversionOptions = [],
+    range: R,
+    remaining leftover: UnsafeMutablePointer<Range<Index>>
+  ) -> Bool where R.Bound == Index {
+    return _withOptionalOutParameter(leftover) {
+      self._ns.getBytes(
+        &buffer,
+        maxLength: Swift.min(buffer.count, maxBufferCount),
+        usedLength: usedBufferCount,
+        encoding: encoding.rawValue,
+        options: options,
+        range: _toNSRange(range.relative(to: self)),
+        remaining: $0)
+    }
+  }
+
+  // - (void)
+  //     getLineStart:(NSUInteger *)startIndex
+  //     end:(NSUInteger *)lineEndIndex
+  //     contentsEnd:(NSUInteger *)contentsEndIndex
+  //     forRange:(NSRange)aRange
+
+  /// Returns by reference the beginning of the first line and
+  /// the end of the last line touched by the given range.
+  public func getLineStart<
+    R : RangeExpression
+  >(
+    _ start: UnsafeMutablePointer<Index>,
+    end: UnsafeMutablePointer<Index>,
+    contentsEnd: UnsafeMutablePointer<Index>,
+    for range: R
+  ) where R.Bound == Index {
+    _withOptionalOutParameter(start) {
+      start in self._withOptionalOutParameter(end) {
+        end in self._withOptionalOutParameter(contentsEnd) {
+          contentsEnd in self._ns.getLineStart(
+            start, end: end,
+            contentsEnd: contentsEnd,
+            for: _toNSRange(range.relative(to: self)))
+        }
+      }
+    }
+  }
+
+  // - (void)
+  //     getParagraphStart:(NSUInteger *)startIndex
+  //     end:(NSUInteger *)endIndex
+  //     contentsEnd:(NSUInteger *)contentsEndIndex
+  //     forRange:(NSRange)aRange
+
+  /// Returns by reference the beginning of the first paragraph
+  /// and the end of the last paragraph touched by the given range.
+  public func getParagraphStart<
+    R : RangeExpression
+  >(
+    _ start: UnsafeMutablePointer<Index>,
+    end: UnsafeMutablePointer<Index>,
+    contentsEnd: UnsafeMutablePointer<Index>,
+    for range: R
+  ) where R.Bound == Index {
+    _withOptionalOutParameter(start) {
+      start in self._withOptionalOutParameter(end) {
+        end in self._withOptionalOutParameter(contentsEnd) {
+          contentsEnd in self._ns.getParagraphStart(
+            start, end: end,
+            contentsEnd: contentsEnd,
+            for: _toNSRange(range.relative(to: self)))
+        }
+      }
+    }
+  }
+
+  //===--- Already provided by core Swift ---------------------------------===//
+  // - (instancetype)initWithString:(NSString *)aString
+
+  //===--- Initializers that can fail dropped for factory functions -------===//
+  // - (instancetype)initWithUTF8String:(const char *)bytes
+
+  //===--- Omitted for consistency with API review results 5/20/2014 ------===//
+  // @property NSInteger integerValue;
+  // @property Int intValue;
+
+  //===--- Omitted by apparent agreement during API review 5/20/2014 ------===//
+  // @property BOOL absolutePath;
+  // - (BOOL)isEqualToString:(NSString *)aString
+
+  // - (NSRange)lineRangeForRange:(NSRange)aRange
+
+  /// Returns the range of characters representing the line or lines
+  /// containing a given range.
+  public func lineRange<
+    R : RangeExpression
+  >(for aRange: R) -> Range<Index> where R.Bound == Index {
+    return _range(_ns.lineRange(for: _toNSRange(aRange.relative(to: self))))
+  }
+
+#if !DEPLOYMENT_RUNTIME_SWIFT
+  // - (NSArray *)
+  //     linguisticTagsInRange:(NSRange)range
+  //     scheme:(NSString *)tagScheme
+  //     options:(LinguisticTaggerOptions)opts
+  //     orthography:(Orthography *)orthography
+  //     tokenRanges:(NSArray**)tokenRanges
+
+  /// Returns an array of linguistic tags for the specified
+  /// range and requested tags within the receiving string.
+  public func linguisticTags<
+    T : StringProtocol, R : RangeExpression
+  >(
+    in range: R,
+    scheme tagScheme: T,
+    options opts: NSLinguisticTagger.Options = [],
+    orthography: NSOrthography? = nil,
+    tokenRanges: UnsafeMutablePointer<[Range<Index>]>? = nil // FIXME:Can this be nil?
+  ) -> [String] where R.Bound == Index {
+    var nsTokenRanges: NSArray?
+    let result = tokenRanges._withNilOrAddress(of: &nsTokenRanges) {
+      self._ns.linguisticTags(
+        in: _toNSRange(range.relative(to: self)),
+        scheme: tagScheme._ephemeralString,
+        options: opts,
+        orthography: orthography,
+        tokenRanges: $0) as NSArray
+    }
+
+    if nsTokenRanges != nil {
+      tokenRanges?.pointee = (nsTokenRanges! as [AnyObject]).map {
+        self._range($0.rangeValue)
+      }
+    }
+
+    return result as! [String]
+  }
+
+  // - (NSRange)paragraphRangeForRange:(NSRange)aRange
+
+  /// Returns the range of characters representing the
+  /// paragraph or paragraphs containing a given range.
+  public func paragraphRange<
+    R : RangeExpression
+  >(for aRange: R) -> Range<Index> where R.Bound == Index {
+    return _range(
+      _ns.paragraphRange(for: _toNSRange(aRange.relative(to: self))))
+  }
+#endif
+
+  // - (NSRange)rangeOfCharacterFromSet:(NSCharacterSet *)aSet
+  //
+  // - (NSRange)
+  //     rangeOfCharacterFromSet:(NSCharacterSet *)aSet
+  //     options:(StringCompareOptions)mask
+  //
+  // - (NSRange)
+  //     rangeOfCharacterFromSet:(NSCharacterSet *)aSet
+  //     options:(StringCompareOptions)mask
+  //     range:(NSRange)aRange
+
+  /// Finds and returns the range in the `String` of the first
+  /// character from a given character set found in a given range with
+  /// given options.
+  public func rangeOfCharacter(
+    from aSet: CharacterSet,
+    options mask: String.CompareOptions = [],
+    range aRange: Range<Index>? = nil
+  ) -> Range<Index>? {
+    return _optionalRange(
+      _ns.rangeOfCharacter(
+        from: aSet,
+        options: mask,
+        range: _toNSRange(
+          aRange ?? startIndex..<endIndex
+        )
+      )
+    )
+  }
+
+  // - (NSRange)rangeOfComposedCharacterSequenceAtIndex:(NSUInteger)anIndex
+
+  /// Returns the range in the `String` of the composed
+  /// character sequence located at a given index.
+  public
+  func rangeOfComposedCharacterSequence(at anIndex: Index) -> Range<Index> {
+    return _range(
+      _ns.rangeOfComposedCharacterSequence(at: anIndex.encodedOffset))
+  }
+
+  // - (NSRange)rangeOfComposedCharacterSequencesForRange:(NSRange)range
+
+  /// Returns the range in the string of the composed character
+  /// sequences for a given range.
+  public func rangeOfComposedCharacterSequences<
+    R : RangeExpression
+  >(
+    for range: R
+  ) -> Range<Index> where R.Bound == Index {
+    // Theoretically, this will be the identity function.  In practice
+    // I think users will be able to observe differences in the input
+    // and output ranges due (if nothing else) to locale changes
+    return _range(
+      _ns.rangeOfComposedCharacterSequences(
+        for: _toNSRange(range.relative(to: self))))
+  }
+
+  // - (NSRange)rangeOfString:(NSString *)aString
+  //
+  // - (NSRange)
+  //     rangeOfString:(NSString *)aString options:(StringCompareOptions)mask
+  //
+  // - (NSRange)
+  //     rangeOfString:(NSString *)aString
+  //     options:(StringCompareOptions)mask
+  //     range:(NSRange)aRange
+  //
+  // - (NSRange)
+  //     rangeOfString:(NSString *)aString
+  //     options:(StringCompareOptions)mask
+  //     range:(NSRange)searchRange
+  //     locale:(Locale *)locale
+
+  /// Finds and returns the range of the first occurrence of a
+  /// given string within a given range of the `String`, subject to
+  /// given options, using the specified locale, if any.
+  public func range<
+    T : StringProtocol
+  >(
+    of aString: T,
+    options mask: String.CompareOptions = [],
+    range searchRange: Range<Index>? = nil,
+    locale: Locale? = nil
+  ) -> Range<Index>? {
+    let aString = aString._ephemeralString
+    return _optionalRange(
+      locale != nil ? _ns.range(
+        of: aString,
+        options: mask,
+        range: _toNSRange(
+          searchRange ?? startIndex..<endIndex
+        ),
+        locale: locale
+      )
+      : searchRange != nil ? _ns.range(
+        of: aString, options: mask, range: _toNSRange(searchRange!)
+      )
+      : !mask.isEmpty ? _ns.range(of: aString, options: mask)
+      : _ns.range(of: aString)
+    )
+  }
+
+  // - (NSRange)localizedStandardRangeOfString:(NSString *)str NS_AVAILABLE(10_11, 9_0);
+
+  /// Finds and returns the range of the first occurrence of a given string,
+  /// taking the current locale into account.  Returns `nil` if the string was
+  /// not found.
+  ///
+  /// This is the most appropriate method for doing user-level string searches,
+  /// similar to how searches are done generally in the system.  The search is
+  /// locale-aware, case and diacritic insensitive.  The exact list of search
+  /// options applied may change over time.
+  @available(OSX 10.11, iOS 9.0, *)
+  public func localizedStandardRange<
+    T : StringProtocol
+  >(of string: T) -> Range<Index>? {
+    return _optionalRange(
+      _ns.localizedStandardRange(of: string._ephemeralString))
+  }
+
+#if !DEPLOYMENT_RUNTIME_SWIFT
+  // - (NSString *)
+  //     stringByAddingPercentEscapesUsingEncoding:(NSStringEncoding)encoding
+
+  /// Returns a representation of the `String` using a given
+  /// encoding to determine the percent escapes necessary to convert
+  /// the `String` into a legal URL string.
+  @available(swift, deprecated: 3.0, obsoleted: 4.0,
+    message: "Use addingPercentEncoding(withAllowedCharacters:) instead, which always uses the recommended UTF-8 encoding, and which encodes for a specific URL component or subcomponent since each URL component or subcomponent has different rules for what characters are valid.")
+  public func addingPercentEscapes(
+    using encoding: String.Encoding
+  ) -> String? {
+    return _ns.addingPercentEscapes(using: encoding.rawValue)
+  }
+#endif
+
   //===--- From the 10.10 release notes; not in public documentation ------===//
   // No need to make these unavailable on earlier OSes, since they can
   // forward trivially to rangeOfString.
@@ -1479,44 +1625,233 @@
   /// `self` by case-sensitive, non-literal search.
   ///
   /// Equivalent to `self.rangeOfString(other) != nil`
-  public func contains(_ other: String) -> Bool {
+  public func contains<T : StringProtocol>(_ other: T) -> Bool {
     let r = self.range(of: other) != nil
     if #available(OSX 10.10, iOS 8.0, *) {
-      _sanityCheck(r == _ns.contains(other))
+      _sanityCheck(r == _ns.contains(other._ephemeralString))
     }
     return r
   }
-  
-  /// Returns `true` iff `other` is non-empty and contained within
-  /// `self` by case-insensitive, non-literal search, taking into
-  /// account the current locale.
+
+  /// Returns a Boolean value indicating whether the given string is non-empty
+  /// and contained within this string by case-insensitive, non-literal
+  /// search, taking into account the current locale.
   ///
-  /// Locale-independent case-insensitive operation, and other needs,
-  /// can be achieved by calling
-  /// `rangeOfString(_:options:_, range:_locale:_)`.
+  /// Locale-independent case-insensitive operation, and other needs, can be
+  /// achieved by calling `range(of:options:range:locale:)`.
   ///
-  /// Equivalent to
+  /// Equivalent to:
   ///
-  ///     self.rangeOf(
-  ///       other, options: .CaseInsensitiveSearch,
-  ///       locale: Locale.current) != nil
-  public func localizedCaseInsensitiveContains(_ other: String) -> Bool {
+  ///     range(of: other, options: .caseInsensitiveSearch,
+  ///           locale: Locale.current) != nil
+  public func localizedCaseInsensitiveContains<
+    T : StringProtocol
+  >(_ other: T) -> Bool {
     let r = self.range(
       of: other, options: .caseInsensitive, locale: Locale.current
     ) != nil
     if #available(OSX 10.10, iOS 8.0, *) {
-      _sanityCheck(r == _ns.localizedCaseInsensitiveContains(other))
+      _sanityCheck(r ==
+        _ns.localizedCaseInsensitiveContains(other._ephemeralString))
     }
     return r
   }
 }
 
+// Deprecated slicing
+extension StringProtocol where Index == String.Index {
+  // - (NSString *)substringFromIndex:(NSUInteger)anIndex
+
+  /// Returns a new string containing the characters of the
+  /// `String` from the one at a given index to the end.
+  @available(swift, deprecated: 4.0,
+    message: "Please use String slicing subscript with a 'partial range from' operator.")
+  public func substring(from index: Index) -> String {
+    return _ns.substring(from: index.encodedOffset)
+  }
+
+  // - (NSString *)substringToIndex:(NSUInteger)anIndex
+
+  /// Returns a new string containing the characters of the
+  /// `String` up to, but not including, the one at a given index.
+  @available(swift, deprecated: 4.0,
+    message: "Please use String slicing subscript with a 'partial range upto' operator.")
+  public func substring(to index: Index) -> String {
+    return _ns.substring(to: index.encodedOffset)
+  }
+
+  // - (NSString *)substringWithRange:(NSRange)aRange
+
+  /// Returns a string object containing the characters of the
+  /// `String` that lie within a given range.
+  @available(swift, deprecated: 4.0,
+    message: "Please use String slicing subscript.")
+  public func substring(with aRange: Range<Index>) -> String {
+    return _ns.substring(with: _toNSRange(aRange))
+  }
+}
+
+extension StringProtocol {
+  // - (const char *)fileSystemRepresentation
+
+  /// Returns a file system-specific representation of the `String`.
+  @available(*, unavailable, message: "Use getFileSystemRepresentation on URL instead.")
+  public var fileSystemRepresentation: [CChar] {
+    fatalError("unavailable function can't be called")
+  }
+
+  // - (BOOL)
+  //     getFileSystemRepresentation:(char *)buffer
+  //     maxLength:(NSUInteger)maxLength
+
+  /// Interprets the `String` as a system-independent path and
+  /// fills a buffer with a C-string in a format and encoding suitable
+  /// for use with file-system calls.
+  /// - Note: will store a maximum of `min(buffer.count, maxLength)` bytes.
+  @available(*, unavailable, message: "Use getFileSystemRepresentation on URL instead.")
+  public func getFileSystemRepresentation(
+    _ buffer: inout [CChar], maxLength: Int) -> Bool {
+    fatalError("unavailable function can't be called")
+  }
+
+  //===--- Kept for consistency with API review results 5/20/2014 ---------===//
+  // We decided to keep pathWithComponents, so keeping this too
+  // @property NSString lastPathComponent;
+
+  /// Returns the last path component of the `String`.
+  @available(*, unavailable, message: "Use lastPathComponent on URL instead.")
+  public var lastPathComponent: String {
+    fatalError("unavailable function can't be called")
+  }
+
+  //===--- Renamed by agreement during API review 5/20/2014 ---------------===//
+  // @property NSUInteger length;
+
+  /// Returns the number of Unicode characters in the `String`.
+  @available(*, unavailable,
+    message: "Take the count of a UTF-16 view instead, i.e. str.utf16.count")
+  public var utf16Count: Int {
+    fatalError("unavailable function can't be called")
+  }
+
+  // @property NSArray* pathComponents
+
+  /// Returns an array of NSString objects containing, in
+  /// order, each path component of the `String`.
+  @available(*, unavailable, message: "Use pathComponents on URL instead.")
+  public var pathComponents: [String] {
+    fatalError("unavailable function can't be called")
+  }
+
+  // @property NSString* pathExtension;
+
+  /// Interprets the `String` as a path and returns the
+  /// `String`'s extension, if any.
+  @available(*, unavailable, message: "Use pathExtension on URL instead.")
+  public var pathExtension: String {
+    fatalError("unavailable function can't be called")
+  }
+
+  // @property NSString *stringByAbbreviatingWithTildeInPath;
+
+  /// Returns a new string that replaces the current home
+  /// directory portion of the current path with a tilde (`~`)
+  /// character.
+  @available(*, unavailable, message: "Use abbreviatingWithTildeInPath on NSString instead.")
+  public var abbreviatingWithTildeInPath: String {
+    fatalError("unavailable function can't be called")
+  }
+
+  // - (NSString *)stringByAppendingPathComponent:(NSString *)aString
+
+  /// Returns a new string made by appending to the `String` a given string.
+  @available(*, unavailable, message: "Use appendingPathComponent on URL instead.")
+  public func appendingPathComponent(_ aString: String) -> String {
+    fatalError("unavailable function can't be called")
+  }
+
+  // - (NSString *)stringByAppendingPathExtension:(NSString *)ext
+
+  /// Returns a new string made by appending to the `String` an
+  /// extension separator followed by a given extension.
+  @available(*, unavailable, message: "Use appendingPathExtension on URL instead.")
+  public func appendingPathExtension(_ ext: String) -> String? {
+    fatalError("unavailable function can't be called")
+  }
+
+  // @property NSString* stringByDeletingLastPathComponent;
+
+  /// Returns a new string made by deleting the last path
+  /// component from the `String`, along with any final path
+  /// separator.
+  @available(*, unavailable, message: "Use deletingLastPathComponent on URL instead.")
+  public var deletingLastPathComponent: String {
+    fatalError("unavailable function can't be called")
+  }
+
+  // @property NSString* stringByDeletingPathExtension;
+
+  /// Returns a new string made by deleting the extension (if
+  /// any, and only the last) from the `String`.
+  @available(*, unavailable, message: "Use deletingPathExtension on URL instead.")
+  public var deletingPathExtension: String {
+    fatalError("unavailable function can't be called")
+  }
+
+  // @property NSString* stringByExpandingTildeInPath;
+
+  /// Returns a new string made by expanding the initial
+  /// component of the `String` to its full path value.
+  @available(*, unavailable, message: "Use expandingTildeInPath on NSString instead.")
+  public var expandingTildeInPath: String {
+    fatalError("unavailable function can't be called")
+  }
+
+  // - (NSString *)
+  //     stringByFoldingWithOptions:(StringCompareOptions)options
+  //     locale:(Locale *)locale
+
+  @available(*, unavailable, renamed: "folding(options:locale:)")
+  public func folding(
+    _ options: String.CompareOptions = [], locale: Locale?
+  ) -> String {
+    fatalError("unavailable function can't be called")
+  }
+
+  // @property NSString* stringByResolvingSymlinksInPath;
+
+  /// Returns a new string made from the `String` by resolving
+  /// all symbolic links and standardizing path.
+  @available(*, unavailable, message: "Use resolvingSymlinksInPath on URL instead.")
+  public var resolvingSymlinksInPath: String {
+    fatalError("unavailable property")
+  }
+
+  // @property NSString* stringByStandardizingPath;
+
+  /// Returns a new string made by removing extraneous path
+  /// components from the `String`.
+  @available(*, unavailable, message: "Use standardizingPath on URL instead.")
+  public var standardizingPath: String {
+    fatalError("unavailable function can't be called")
+  }
+
+  // - (NSArray *)stringsByAppendingPaths:(NSArray *)paths
+
+  /// Returns an array of strings made by separately appending
+  /// to the `String` each string in a given array.
+  @available(*, unavailable, message: "Map over paths with appendingPathComponent instead.")
+  public func strings(byAppendingPaths paths: [String]) -> [String] {
+    fatalError("unavailable function can't be called")
+  }
+
+}
+
 // Pre-Swift-3 method names
 extension String {
-
   @available(*, unavailable, renamed: "localizedName(of:)")
   public static func localizedNameOfStringEncoding(
-    _ encoding: Encoding
+    _ encoding: String.Encoding
   ) -> String {
     fatalError("unavailable function can't be called")
   }
@@ -1526,8 +1861,20 @@
     fatalError("unavailable function can't be called")
   }
 
+  // + (NSString *)pathWithComponents:(NSArray *)components
+
+  /// Returns a string built from the strings in a given array
+  /// by concatenating them with a path separator between each pair.
+  @available(*, unavailable, message: "Use fileURL(withPathComponents:) on URL instead.")
+  public static func path(withComponents components: [String]) -> String {
+    fatalError("unavailable function can't be called")
+  }
+}
+
+extension StringProtocol {
+
   @available(*, unavailable, renamed: "canBeConverted(to:)")
-  public func canBeConvertedToEncoding(_ encoding: Encoding) -> Bool {
+  public func canBeConvertedToEncoding(_ encoding: String.Encoding) -> Bool {
     fatalError("unavailable function can't be called")
   }
 
@@ -1538,7 +1885,7 @@
 
   @available(*, unavailable, renamed: "commonPrefix(with:options:)")
   public func commonPrefixWith(
-    _ aString: String, options: CompareOptions) -> String {
+    _ aString: String, options: String.CompareOptions) -> String {
     fatalError("unavailable function can't be called")
   }
 
@@ -1565,22 +1912,36 @@
   }
 
   @available(*, unavailable, renamed: "cString(usingEncoding:)")
-  public func cStringUsingEncoding(_ encoding: Encoding) -> [CChar]? {
+  public func cStringUsingEncoding(_ encoding: String.Encoding) -> [CChar]? {
     fatalError("unavailable function can't be called")
   }
 
   @available(*, unavailable, renamed: "data(usingEncoding:allowLossyConversion:)")
   public func dataUsingEncoding(
-    _ encoding: Encoding,
+    _ encoding: String.Encoding,
     allowLossyConversion: Bool = false
   ) -> Data? {
     fatalError("unavailable function can't be called")
   }
 
+#if !DEPLOYMENT_RUNTIME_SWIFT
+  @available(*, unavailable, renamed: "enumerateLinguisticTags(in:scheme:options:orthography:_:)")
+  public func enumerateLinguisticTagsIn(
+    _ range: Range<Index>,
+    scheme tagScheme: String,
+    options opts: NSLinguisticTagger.Options,
+    orthography: NSOrthography?,
+    _ body:
+      (String, Range<Index>, Range<Index>, inout Bool) -> Void
+  ) {
+    fatalError("unavailable function can't be called")
+  }
+#endif
+
   @available(*, unavailable, renamed: "enumerateSubstrings(in:options:_:)")
   public func enumerateSubstringsIn(
     _ range: Range<Index>,
-    options opts: EnumerationOptions = [],
+    options opts: String.EnumerationOptions = [],
     _ body: (
       _ substring: String?, _ substringRange: Range<Index>,
       _ enclosingRange: Range<Index>, inout Bool
@@ -1594,8 +1955,8 @@
     _ buffer: inout [UInt8],
     maxLength maxBufferCount: Int,
     usedLength usedBufferCount: UnsafeMutablePointer<Int>,
-    encoding: Encoding,
-    options: EncodingConversionOptions = [],
+    encoding: String.Encoding,
+    options: String.EncodingConversionOptions = [],
     range: Range<Index>,
     remainingRange leftover: UnsafeMutablePointer<Range<Index>>
   ) -> Bool {
@@ -1623,7 +1984,7 @@
   }
 
   @available(*, unavailable, renamed: "lengthOfBytes(using:)")
-  public func lengthOfBytesUsingEncoding(_ encoding: Encoding) -> Int {
+  public func lengthOfBytesUsingEncoding(_ encoding: String.Encoding) -> Int {
     fatalError("unavailable function can't be called")
   }
 
@@ -1632,6 +1993,19 @@
     fatalError("unavailable function can't be called")
   }
 
+#if !DEPLOYMENT_RUNTIME_SWIFT
+  @available(*, unavailable, renamed: "linguisticTags(in:scheme:options:orthography:tokenRanges:)")
+  public func linguisticTagsIn(
+    _ range: Range<Index>,
+    scheme tagScheme: String,
+    options opts: NSLinguisticTagger.Options = [],
+    orthography: NSOrthography? = nil,
+    tokenRanges: UnsafeMutablePointer<[Range<Index>]>? = nil
+  ) -> [String] {
+    fatalError("unavailable function can't be called")
+  }
+#endif
+
   @available(*, unavailable, renamed: "lowercased(with:)")
   public func lowercaseStringWith(_ locale: Locale?) -> String {
     fatalError("unavailable function can't be called")
@@ -1639,7 +2013,7 @@
 
   @available(*, unavailable, renamed: "maximumLengthOfBytes(using:)")
   public
-  func maximumLengthOfBytesUsingEncoding(_ encoding: Encoding) -> Int {
+  func maximumLengthOfBytesUsingEncoding(_ encoding: String.Encoding) -> Int {
     fatalError("unavailable function can't be called")
   }
 
@@ -1651,7 +2025,7 @@
   @available(*, unavailable, renamed: "rangeOfCharacter(from:options:range:)")
   public func rangeOfCharacterFrom(
     _ aSet: CharacterSet,
-    options mask: CompareOptions = [],
+    options mask: String.CompareOptions = [],
     range aRange: Range<Index>? = nil
   ) -> Range<Index>? {
     fatalError("unavailable function can't be called")
@@ -1673,7 +2047,7 @@
   @available(*, unavailable, renamed: "range(of:options:range:locale:)")
   public func rangeOf(
     _ aString: String,
-    options mask: CompareOptions = [],
+    options mask: String.CompareOptions = [],
     range searchRange: Range<Index>? = nil,
     locale: Locale? = nil
   ) -> Range<Index>? {
@@ -1694,7 +2068,7 @@
 
   @available(*, unavailable, renamed: "addingPercentEscapes(using:)")
   public func addingPercentEscapesUsingEncoding(
-    _ encoding: Encoding
+    _ encoding: String.Encoding
   ) -> String? {
     fatalError("unavailable function can't be called")
   }
@@ -1712,7 +2086,7 @@
   ) -> String {
     fatalError("unavailable function can't be called")
   }
-  
+
   @available(*, unavailable, renamed: "replacingCharacters(in:with:)")
   public func replacingCharactersIn(
     _ range: Range<Index>, withString replacement: String
@@ -1724,7 +2098,7 @@
   public func replacingOccurrencesOf(
     _ target: String,
     withString replacement: String,
-    options: CompareOptions = [],
+    options: String.CompareOptions = [],
     range searchRange: Range<Index>? = nil
   ) -> String {
     fatalError("unavailable function can't be called")
@@ -1732,7 +2106,7 @@
 
   @available(*, unavailable, renamed: "replacingPercentEscapes(usingEncoding:)")
   public func replacingPercentEscapesUsingEncoding(
-    _ encoding: Encoding
+    _ encoding: String.Encoding
   ) -> String? {
     fatalError("unavailable function can't be called")
   }
@@ -1770,7 +2144,7 @@
   @available(*, unavailable, renamed: "write(toFile:atomically:encoding:)")
   public func writeToFile(
     _ path: String, atomically useAuxiliaryFile:Bool,
-    encoding enc: Encoding
+    encoding enc: String.Encoding
   ) throws {
     fatalError("unavailable function can't be called")
   }
@@ -1778,7 +2152,7 @@
   @available(*, unavailable, renamed: "write(to:atomically:encoding:)")
   public func writeToURL(
     _ url: URL, atomically useAuxiliaryFile: Bool,
-    encoding enc: Encoding
+    encoding enc: String.Encoding
   ) throws {
     fatalError("unavailable function can't be called")
   }
diff --git a/Foundation/NSSwiftRuntime.swift b/Foundation/NSSwiftRuntime.swift
index 58a7174..a37839f 100644
--- a/Foundation/NSSwiftRuntime.swift
+++ b/Foundation/NSSwiftRuntime.swift
@@ -24,7 +24,63 @@
 }
 #endif
 
-public typealias ObjCBool = Bool
+/// The Objective-C BOOL type.
+///
+/// On 64-bit iOS, the Objective-C BOOL type is a typedef of C/C++
+/// bool. Elsewhere, it is "signed char". The Clang importer imports it as
+/// ObjCBool.
+@_fixed_layout
+public struct ObjCBool : ExpressibleByBooleanLiteral {
+    #if os(OSX) || (os(iOS) && (arch(i386) || arch(arm)))
+    // On OS X and 32-bit iOS, Objective-C's BOOL type is a "signed char".
+    var _value: Int8
+
+    init(_ value: Int8) {
+        self._value = value
+    }
+
+    public init(_ value: Bool) {
+        self._value = value ? 1 : 0
+    }
+
+    #else
+    // Everywhere else it is C/C++'s "Bool"
+    var _value: Bool
+
+    public init(_ value: Bool) {
+        self._value = value
+    }
+    #endif
+
+    /// The value of `self`, expressed as a `Bool`.
+    public var boolValue: Bool {
+        #if os(OSX) || (os(iOS) && (arch(i386) || arch(arm)))
+        return _value != 0
+        #else
+        return _value
+        #endif
+    }
+
+    /// Create an instance initialized to `value`.
+    @_transparent
+    public init(booleanLiteral value: Bool) {
+        self.init(value)
+    }
+}
+
+extension ObjCBool : CustomReflectable {
+    /// Returns a mirror that reflects `self`.
+    public var customMirror: Mirror {
+        return Mirror(reflecting: boolValue)
+    }
+}
+
+extension ObjCBool : CustomStringConvertible {
+    /// A textual representation of `self`.
+    public var description: String {
+        return self.boolValue.description
+    }
+}
 
 internal class __NSCFType : NSObject {
     private var _cfinfo : Int32
diff --git a/Foundation/NSTextCheckingResult.swift b/Foundation/NSTextCheckingResult.swift
index caed9a8..74dd8c0 100644
--- a/Foundation/NSTextCheckingResult.swift
+++ b/Foundation/NSTextCheckingResult.swift
@@ -87,7 +87,7 @@
 
 extension NSTextCheckingResult {
     
-    public func resultByAdjustingRangesWithOffset(_ offset: Int) -> NSTextCheckingResult {
+    public func adjustingRanges(offset: Int) -> NSTextCheckingResult {
         let count = self.numberOfRanges
         var newRanges = [NSRange]()
         for idx in 0..<count {
diff --git a/Foundation/NSURL.swift b/Foundation/NSURL.swift
index 697c488..a02f49c 100644
--- a/Foundation/NSURL.swift
+++ b/Foundation/NSURL.swift
@@ -309,7 +309,7 @@
 
         let thePath = _standardizedPath(path)
         
-        var isDir : Bool = false
+        var isDir: ObjCBool = false
         if thePath.hasSuffix("/") {
             isDir = true
         } else {
@@ -323,7 +323,7 @@
             let _ = FileManager.default.fileExists(atPath: absolutePath, isDirectory: &isDir)
         }
 
-        self.init(fileURLWithPath: thePath, isDirectory: isDir, relativeTo: baseURL)
+        self.init(fileURLWithPath: thePath, isDirectory: isDir.boolValue, relativeTo: baseURL)
     }
 
     public convenience init(fileURLWithPath path: String, isDirectory isDir: Bool) {
@@ -339,7 +339,7 @@
             thePath = path
         }
 
-        var isDir : Bool = false
+        var isDir: ObjCBool = false
         if thePath.hasSuffix("/") {
             isDir = true
         } else {
@@ -348,7 +348,7 @@
             }
         }
         super.init()
-        _CFURLInitWithFileSystemPathRelativeToBase(_cfObject, thePath._cfObject, kCFURLPOSIXPathStyle, isDir, nil)
+        _CFURLInitWithFileSystemPathRelativeToBase(_cfObject, thePath._cfObject, kCFURLPOSIXPathStyle, isDir.boolValue, nil)
     }
     
     public convenience init(fileURLWithFileSystemRepresentation path: UnsafePointer<Int8>, isDirectory isDir: Bool, relativeTo baseURL: URL?) {
@@ -779,8 +779,8 @@
         var result : URL? = appendingPathComponent(pathComponent, isDirectory: false)
         if !pathComponent.hasSuffix("/") && isFileURL {
             if let urlWithoutDirectory = result {
-                var isDir : Bool = false
-                if FileManager.default.fileExists(atPath: urlWithoutDirectory.path, isDirectory: &isDir) && isDir {
+                var isDir: ObjCBool = false
+                if FileManager.default.fileExists(atPath: urlWithoutDirectory.path, isDirectory: &isDir) && isDir.boolValue {
                     result = self.appendingPathComponent(pathComponent, isDirectory: true)
                 }
             }
@@ -859,14 +859,14 @@
         }
 
         // It might be a responsibility of NSURL(fileURLWithPath:). Check it.
-        var isExistingDirectory = false
+        var isExistingDirectory: ObjCBool = false
         let _ = FileManager.default.fileExists(atPath: resolvedPath, isDirectory: &isExistingDirectory)
 
         if excludeSystemDirs {
             resolvedPath = resolvedPath._tryToRemovePathPrefix("/private") ?? resolvedPath
         }
 
-        if isExistingDirectory && !resolvedPath.hasSuffix("/") {
+        if isExistingDirectory.boolValue && !resolvedPath.hasSuffix("/") {
             resolvedPath += "/"
         }
         
diff --git a/Foundation/Operation.swift b/Foundation/Operation.swift
index 1c5529f..9c17ad1 100644
--- a/Foundation/Operation.swift
+++ b/Foundation/Operation.swift
@@ -9,13 +9,8 @@
 
 #if DEPLOYMENT_ENABLE_LIBDISPATCH
 import Dispatch
-#if os(Linux) || os(Android)
+#endif
 import CoreFoundation
-private func pthread_main_np() -> Int32 {
-    return _CFIsMainThread() ? 1 : 0
-}
-#endif
-#endif
 
 open class Operation : NSObject {
     let lock = NSLock()
@@ -570,7 +565,7 @@
     open class var current: OperationQueue? {
 #if DEPLOYMENT_ENABLE_LIBDISPATCH
         guard let specific = DispatchQueue.getSpecific(key: OperationQueue.OperationQueueKey) else {
-            if pthread_main_np() == 1 {
+            if _CFIsMainThread() {
                 return OperationQueue.main
             } else {
                 return nil
diff --git a/Foundation/Stream.swift b/Foundation/Stream.swift
index 84dc566..d34949d 100644
--- a/Foundation/Stream.swift
+++ b/Foundation/Stream.swift
@@ -119,7 +119,7 @@
 
     // reads up to length bytes into the supplied buffer, which must be at least of size len. Returns the actual number of bytes read.
     open func read(_ buffer: UnsafeMutablePointer<UInt8>, maxLength len: Int) -> Int {
-        return CFReadStreamRead(_stream, buffer, CFIndex(len._bridgeToObjectiveC()))
+        return CFReadStreamRead(_stream, buffer, len)
     }
     
     // returns in O(1) a pointer to the buffer in 'buffer' and by reference in 'len' how many bytes are available. This buffer is only valid until the next stream operation. Subclassers may return NO for this if it is not appropriate for the stream type. This may return NO if the buffer is not available.
diff --git a/Foundation/Thread.swift b/Foundation/Thread.swift
index 3990db0..402294d 100644
--- a/Foundation/Thread.swift
+++ b/Foundation/Thread.swift
@@ -13,29 +13,23 @@
 #elseif os(Linux) || CYGWIN
 import Glibc
 #endif
-
 import CoreFoundation
 
-// for some reason having this take a generic causes a crash...
-private func _compiler_crash_fix(_ key: _CFThreadSpecificKey, _ value: AnyObject?) {
-    _CThreadSpecificSet(key, value)
-}
-
 internal class NSThreadSpecific<T: NSObject> {
     private var key = _CFThreadSpecificKeyCreate()
-    
+
     internal func get(_ generator: () -> T) -> T {
         if let specific = _CFThreadSpecificGet(key) {
             return specific as! T
         } else {
             let value = generator()
-            _compiler_crash_fix(key, value)
+            _CFThreadSpecificSet(key, value)
             return value
         }
     }
-    
+
     internal func set(_ value: T) {
-        _compiler_crash_fix(key, value)
+        _CFThreadSpecificSet(key, value)
     }
 }
 
@@ -57,18 +51,33 @@
 }
 
 open class Thread : NSObject {
-    
+
     static internal var _currentThread = NSThreadSpecific<Thread>()
     open class var current: Thread {
         return Thread._currentThread.get() {
-            return Thread(thread: pthread_self())
+            if Thread.isMainThread {
+                return mainThread
+            } else {
+                return Thread(thread: pthread_self())
+            }
         }
     }
-    
-    open class var isMainThread: Bool { NSUnimplemented() }
-    
+
+    open class var isMainThread: Bool {
+        return _CFIsMainThread()
+    }
+
     // !!! NSThread's mainThread property is incorrectly exported as "main", which conflicts with its "main" method.
-    open class var mainThread: Thread { NSUnimplemented() }
+    private static let _mainThread: Thread = {
+        var thread = Thread(thread: _CFMainPThread)
+        thread._status = .executing
+        return thread
+    }()
+
+    open class var mainThread: Thread {
+        return _mainThread
+    }
+
 
     /// Alternative API for detached thread creation
     /// - Experiment: This is a draft API currently under consideration for official import into Foundation as a suitable alternative to creation via selector
@@ -77,11 +86,11 @@
         let t = Thread(block: block)
         t.start()
     }
-    
+
     open class func isMultiThreaded() -> Bool {
         return true
     }
-    
+
     open class func sleep(until date: Date) {
         let start_ut = CFGetSystemUptime()
         let start_at = CFAbsoluteTimeGetCurrent()
@@ -127,9 +136,10 @@
     }
 
     open class func exit() {
+        Thread.current._status = .finished
         pthread_exit(nil)
     }
-    
+
     internal var _main: () -> Void = {}
 #if os(OSX) || os(iOS) || CYGWIN
     private var _thread: pthread_t? = nil
@@ -145,12 +155,12 @@
     internal var _cancelled = false
     /// - Note: this differs from the Darwin implementation in that the keys must be Strings
     open var threadDictionary = [String : Any]()
-    
+
     internal init(thread: pthread_t) {
         // Note: even on Darwin this is a non-optional pthread_t; this is only used for valid threads, which are never null pointers.
         _thread = thread
     }
-    
+
     public override init() {
         let _ = withUnsafeMutablePointer(to: &_attr) { attr in
             pthread_attr_init(attr)
@@ -158,7 +168,7 @@
             pthread_attr_setdetachstate(attr, Int32(PTHREAD_CREATE_DETACHED))
         }
     }
-    
+
     public convenience init(block: @escaping () -> Swift.Void) {
         self.init()
         _main = block
@@ -185,11 +195,11 @@
         }
 #endif
     }
-    
+
     open func main() {
         _main()
     }
-    
+
     open var name: String? {
         didSet {
             if _thread == Thread.current._thread {
@@ -227,25 +237,52 @@
     open var isFinished: Bool {
         return _status == .finished
     }
-    
+
     open var isCancelled: Bool {
         return _cancelled
     }
-    
+
     open var isMainThread: Bool {
-        NSUnimplemented()
+        return self === Thread.mainThread
     }
-    
+
     open func cancel() {
         _cancelled = true
     }
 
-    open class var callStackReturnAddresses: [NSNumber] {
-        NSUnimplemented()
+
+    private class func backtraceAddresses<T>(_ body: (UnsafeMutablePointer<UnsafeMutableRawPointer?>, Int) -> [T]) -> [T] {
+        // Same as swift/stdlib/public/runtime/Errors.cpp backtrace
+        let maxSupportedStackDepth = 128;
+        let addrs = UnsafeMutablePointer<UnsafeMutableRawPointer?>.allocate(capacity: maxSupportedStackDepth)
+        defer { addrs.deallocate(capacity: maxSupportedStackDepth) }
+        let count = backtrace(addrs, Int32(maxSupportedStackDepth))
+        let addressCount = max(0, min(Int(count), maxSupportedStackDepth))
+        return body(addrs, addressCount)
     }
-    
+
+    open class var callStackReturnAddresses: [NSNumber] {
+        return backtraceAddresses({ (addrs, count) in
+            UnsafeBufferPointer(start: addrs, count: count).map {
+                NSNumber(value: UInt(bitPattern: $0))
+            }
+        })
+    }
+
     open class var callStackSymbols: [String] {
-        NSUnimplemented()
+        return backtraceAddresses({ (addrs, count) in
+            var symbols: [String] = []
+            if let bs = backtrace_symbols(addrs, Int32(count)) {
+                symbols = UnsafeBufferPointer(start: bs, count: count).map {
+                    guard let symbol = $0 else {
+                        return "<null>"
+                    }
+                    return String(cString: symbol)
+                }
+                free(bs)
+            }
+            return symbols
+        })
     }
 }
 
diff --git a/Foundation/URLSession/URLSession.swift b/Foundation/URLSession/URLSession.swift
index 9dbb84c..8e707b3 100644
--- a/Foundation/URLSession/URLSession.swift
+++ b/Foundation/URLSession/URLSession.swift
@@ -137,11 +137,6 @@
 /// - SeeAlso: https://curl.haxx.se/libcurl/c/threadsafe.html
 /// - SeeAlso: URLSession+libcurl.swift
 ///
-/// The (publicly accessible) attributes of an `URLSessionTask` are made thread
-/// safe by using a concurrent libdispatch queue and only doing writes with a
-/// barrier while allowing concurrent reads. A single queue is shared for all
-/// tasks of a given session for this isolation. C.f. `taskAttributesIsolation`.
-///
 /// ## HTTP and RFC 2616
 ///
 /// Most of HTTP is defined in [RFC 2616](https://tools.ietf.org/html/rfc2616).
@@ -171,12 +166,21 @@
 import CoreFoundation
 import Dispatch
 
+extension URLSession {
+    public enum DelayedRequestDisposition {
+        case cancel
+        case continueLoading
+        case useNewRequest
+    }
+}
 
+fileprivate let globalVarSyncQ = DispatchQueue(label: "org.swift.Foundation.URLSession.GlobalVarSyncQ")
 fileprivate var sessionCounter = Int32(0)
 fileprivate func nextSessionIdentifier() -> Int32 {
-    //TODO: find an alternative for OSAtomicIncrement32Barrier() on Linux
-    sessionCounter += 1
-    return sessionCounter
+    return globalVarSyncQ.sync {
+        sessionCounter += 1
+        return sessionCounter
+    }
 }
 public let NSURLSessionTransferSizeUnknown: Int64 = -1
 
@@ -185,9 +189,6 @@
     fileprivate let multiHandle: _MultiHandle
     fileprivate var nextTaskIdentifier = 1
     internal let workQueue: DispatchQueue 
-    /// This queue is used to make public attributes on `URLSessionTask` instances thread safe.
-    /// - Note: It's a **concurrent** queue.
-    internal let taskAttributesIsolation: DispatchQueue 
     internal let taskRegistry = URLSession._TaskRegistry()
     fileprivate let identifier: Int32
     fileprivate var invalidated = false
@@ -213,7 +214,6 @@
         initializeLibcurl()
         identifier = nextSessionIdentifier()
         self.workQueue = DispatchQueue(label: "URLSession<\(identifier)>")
-        self.taskAttributesIsolation = DispatchQueue(label: "URLSession<\(identifier)>.taskAttributes", attributes: DispatchQueue.Attributes.concurrent)
         self.delegateQueue = OperationQueue()
         self.delegateQueue.maxConcurrentOperationCount = 1
         self.delegate = nil
@@ -236,7 +236,6 @@
         initializeLibcurl()
         identifier = nextSessionIdentifier()
         self.workQueue = DispatchQueue(label: "URLSession<\(identifier)>")
-        self.taskAttributesIsolation = DispatchQueue(label: "URLSession<\(identifier)>.taskAttributes", attributes: DispatchQueue.Attributes.concurrent)
         if let _queue = queue {
            self.delegateQueue = _queue
         } else {
@@ -397,9 +396,11 @@
 
 fileprivate extension URLSession {
     func createNextTaskIdentifier() -> Int {
-        let i = nextTaskIdentifier
-        nextTaskIdentifier += 1
-        return i
+        return workQueue.sync {
+            let i = nextTaskIdentifier
+            nextTaskIdentifier += 1
+            return i
+        }
     }
 }
 
diff --git a/Foundation/URLSession/URLSessionDelegate.swift b/Foundation/URLSession/URLSessionDelegate.swift
index ab9c077..3c65fb9 100644
--- a/Foundation/URLSession/URLSessionDelegate.swift
+++ b/Foundation/URLSession/URLSessionDelegate.swift
@@ -119,6 +119,8 @@
      * nil, which implies that no error occurred and this task is complete.
      */
      func urlSession(_ session: URLSession, task: URLSessionTask, didCompleteWithError error: Error?)
+    
+     func urlSession(_ session: URLSession, task: URLSessionTask, willBeginDelayedRequest request: URLRequest, completionHandler: @escaping (URLSession.DelayedRequestDisposition, URLRequest?) -> Void)
 }
 
 extension URLSessionTaskDelegate {
@@ -137,6 +139,8 @@
     public func urlSession(_ session: URLSession, task: URLSessionTask, didSendBodyData bytesSent: Int64, totalBytesSent: Int64, totalBytesExpectedToSend: Int64) { }
     
     public func urlSession(_ session: URLSession, task: URLSessionTask, didCompleteWithError error: Error?) { }
+    
+    public func urlSession(_ session: URLSession, task: URLSessionTask, willBeginDelayedRequest request: URLRequest, completionHandler: @escaping (URLSession.DelayedRequestDisposition, URLRequest?) -> Void) { }
 }
 
 /*
@@ -194,6 +198,7 @@
      * message to receive the resource data.
      */
      func urlSession(_ session: URLSession, dataTask: URLSessionDataTask, willCacheResponse proposedResponse: CachedURLResponse, completionHandler: @escaping (CachedURLResponse?) -> Void)
+    
 }
 
 extension URLSessionDataDelegate {
diff --git a/Foundation/URLSession/URLSessionTask.swift b/Foundation/URLSession/URLSessionTask.swift
index 1115ef5..98ded2c 100644
--- a/Foundation/URLSession/URLSessionTask.swift
+++ b/Foundation/URLSession/URLSessionTask.swift
@@ -21,22 +21,23 @@
 import CoreFoundation
 import Dispatch
 
-
 /// A cancelable object that refers to the lifetime
 /// of processing a given request.
 open class URLSessionTask : NSObject, NSCopying {
+    
+    public var countOfBytesClientExpectsToReceive: Int64 { NSUnimplemented() }
+    public var countOfBytesClientExpectsToSend: Int64 { NSUnimplemented() }
+    public var earliestBeginDate: Date? { NSUnimplemented() }
+    
     /// How many times the task has been suspended, 0 indicating a running task.
     internal var suspendCount = 1
     internal var session: URLSessionProtocol! //change to nil when task completes
     internal let body: _Body
-    fileprivate var _protocol: URLProtocol! = nil
+    fileprivate var _protocol: URLProtocol? = nil
+    private let syncQ = DispatchQueue(label: "org.swift.URLSessionTask.SyncQ")
     
     /// All operations must run on this queue.
     internal let workQueue: DispatchQueue 
-    /// Using dispatch semaphore to make public attributes thread safe.
-    /// A semaphore is a simpler option against the usage of concurrent queue
-    /// as the critical sections are very short.
-    fileprivate let semaphore = DispatchSemaphore(value: 1)    
     
     public override init() {
         // Darwin Foundation oddly allows calling this initializer, even though
@@ -62,7 +63,8 @@
     }
     internal init(session: URLSession, request: URLRequest, taskIdentifier: Int, body: _Body) {
         self.session = session
-        self.workQueue = session.workQueue
+        /* make sure we're actually having a serial queue as it's used for synchronization */
+        self.workQueue = DispatchQueue.init(label: "org.swift.URLSessionTask.WorkQueue", target: session.workQueue)
         self.taskIdentifier = taskIdentifier
         self.originalRequest = request
         self.body = body
@@ -108,31 +110,19 @@
     /// May differ from originalRequest due to http server redirection
     /*@NSCopying*/ open internal(set) var currentRequest: URLRequest? {
         get {
-            semaphore.wait()
-            defer {
-                semaphore.signal()
-            }
-            return self._currentRequest
+            return self.syncQ.sync { return self._currentRequest }
         }
         set {
-            semaphore.wait()
-            self._currentRequest = newValue
-            semaphore.signal()
+            self.syncQ.sync { self._currentRequest = newValue }
         }
     }
     fileprivate var _currentRequest: URLRequest? = nil
     /*@NSCopying*/ open internal(set) var response: URLResponse? {
         get {
-            semaphore.wait()
-            defer {
-                semaphore.signal()
-            }
-            return self._response
+            return self.syncQ.sync { return self._response }
         }
         set {
-            semaphore.wait()
-            self._response = newValue
-            semaphore.signal()
+            self.syncQ.sync { self._response = newValue }
         }
     }
     fileprivate var _response: URLResponse? = nil
@@ -145,16 +135,10 @@
     /// Number of body bytes already received
     open internal(set) var countOfBytesReceived: Int64 {
         get {
-            semaphore.wait()
-            defer {
-                semaphore.signal()
-            }
-            return self._countOfBytesReceived
+            return self.syncQ.sync { return self._countOfBytesReceived }
         }
         set {
-            semaphore.wait()
-            self._countOfBytesReceived = newValue
-            semaphore.signal()
+            self.syncQ.sync { self._countOfBytesReceived = newValue }
         }
     }
     fileprivate var _countOfBytesReceived: Int64 = 0
@@ -162,16 +146,10 @@
     /// Number of body bytes already sent */
     open internal(set) var countOfBytesSent: Int64 {
         get {
-            semaphore.wait()
-            defer {
-                semaphore.signal()
-            }
-            return self._countOfBytesSent
+            return self.syncQ.sync { return self._countOfBytesSent }
         }
         set {
-            semaphore.wait()
-            self._countOfBytesSent = newValue
-            semaphore.signal()
+            self.syncQ.sync { self._countOfBytesSent = newValue }
         }
     }
     
@@ -200,8 +178,8 @@
             self.workQueue.async {
                 let urlError = URLError(_nsError: NSError(domain: NSURLErrorDomain, code: NSURLErrorCancelled, userInfo: nil))
                 self.error = urlError
-                self._protocol.stopLoading()
-                self._protocol.client?.urlProtocol(self._protocol, didFailWithError: urlError)
+                self._protocol?.stopLoading()
+                self._protocol?.client?.urlProtocol(self._protocol!, didFailWithError: urlError)
             }
         }
     }
@@ -211,16 +189,10 @@
      */
     open var state: URLSessionTask.State {
         get {
-            semaphore.wait()
-            defer {
-                semaphore.signal()
-            }
-            return self._state
+            return self.syncQ.sync { self._state }
         }
         set {
-            semaphore.wait()
-            self._state = newValue
-            semaphore.signal()
+            self.syncQ.sync { self._state = newValue }
         }
     }
     fileprivate var _state: URLSessionTask.State = .suspended
@@ -263,7 +235,7 @@
             
             if self.suspendCount == 1 {
                 self.workQueue.async {
-                    self._protocol.stopLoading()
+                    self._protocol?.stopLoading()
                 }
             }
         }
@@ -278,7 +250,21 @@
             self.updateTaskState()
             if self.suspendCount == 0 {
                 self.workQueue.async {
-                    self._protocol.startLoading()
+                    if let _protocol = self._protocol {
+                        _protocol.startLoading()
+                    }
+                    else if self.error == nil {
+                        var userInfo: [String: Any] = [NSLocalizedDescriptionKey: "unsupported URL"]
+                        if let url = self.originalRequest?.url {
+                            userInfo[NSURLErrorFailingURLErrorKey] = url
+                            userInfo[NSURLErrorFailingURLStringErrorKey] = url.absoluteString
+                        }
+                        let urlError = URLError(_nsError: NSError(domain: NSURLErrorDomain,
+                                                                  code: NSURLErrorUnsupportedURL,
+                                                                  userInfo: userInfo))
+                        self.error = urlError
+                        _ProtocolClient().urlProtocol(task: self, didFailWithError: urlError)
+                    }
                 }
             }
         }
@@ -301,16 +287,10 @@
     /// URLSessionTask.highPriority, but use is not restricted to these.
     open var priority: Float {
         get {
-            semaphore.wait()
-            defer {
-                semaphore.signal()
-            }
-            return self._priority
+            return self.workQueue.sync { return self._priority }
         }
         set {
-            semaphore.wait()
-            self._priority = newValue
-            semaphore.signal()
+            self.workQueue.sync { self._priority = newValue }
         }
     }
     fileprivate var _priority: Float = URLSessionTask.defaultPriority
@@ -328,6 +308,12 @@
     }
 }
 
+extension URLSessionTask : ProgressReporting {
+    public var progress: Progress {
+        NSUnimplemented()
+    }
+}
+
 internal extension URLSessionTask {
     /// Updates the (public) state based on private / internal state.
     ///
@@ -555,7 +541,9 @@
             session.delegateQueue.addOperation {
                 delegate.urlSession(session, task: task, didCompleteWithError: nil)
                 task.state = .completed
-                session.taskRegistry.remove(task)
+                task.workQueue.async {
+                    session.taskRegistry.remove(task)
+                }
             }
         case .noDelegate:
             task.state = .completed
@@ -573,6 +561,7 @@
                 session.taskRegistry.remove(task)
             }
         }
+        task._protocol = nil
     }
 
     func urlProtocol(_ protocol: URLProtocol, didCancel challenge: URLAuthenticationChallenge) {
@@ -600,13 +589,19 @@
 
     func urlProtocol(_ protocol: URLProtocol, didFailWithError error: Error) {
         guard let task = `protocol`.task else { fatalError() }
+        urlProtocol(task: task, didFailWithError: error)
+    }
+
+    func urlProtocol(task: URLSessionTask, didFailWithError error: Error) {
         guard let session = task.session as? URLSession else { fatalError() }
         switch session.behaviour(for: task) {
         case .taskDelegate(let delegate):
             session.delegateQueue.addOperation {
                 delegate.urlSession(session, task: task, didCompleteWithError: error as Error)
                 task.state = .completed
-                session.taskRegistry.remove(task)
+                task.workQueue.async {
+                    session.taskRegistry.remove(task)
+                }
             }
         case .noDelegate:
             task.state = .completed
@@ -615,7 +610,9 @@
             session.delegateQueue.addOperation {
                 completion(nil, nil, error)
                 task.state = .completed
-                session.taskRegistry.remove(task)
+                task.workQueue.async {
+                    session.taskRegistry.remove(task)
+                }
             }
         case .downloadCompletionHandler(let completion):
             session.delegateQueue.addOperation {
@@ -624,6 +621,7 @@
                 session.taskRegistry.remove(task)
             }
         }
+        task._protocol = nil
     }
 
     func urlProtocol(_ protocol: URLProtocol, cachedResponseIsValid cachedResponse: CachedURLResponse) {
diff --git a/Foundation/URLSession/http/HTTPURLProtocol.swift b/Foundation/URLSession/http/HTTPURLProtocol.swift
index 307a64f..78aff84 100644
--- a/Foundation/URLSession/http/HTTPURLProtocol.swift
+++ b/Foundation/URLSession/http/HTTPURLProtocol.swift
@@ -13,13 +13,14 @@
 internal class _HTTPURLProtocol: URLProtocol {
 
     fileprivate var easyHandle: _EasyHandle!
-    fileprivate var tempFileURL: URL
+    fileprivate lazy var tempFileURL: URL = {
+        let fileName = NSTemporaryDirectory() + NSUUID().uuidString + ".tmp"
+        _ = FileManager.default.createFile(atPath: fileName, contents: nil)
+        return URL(fileURLWithPath: fileName)
+    }()
 
     public required init(task: URLSessionTask, cachedResponse: CachedURLResponse?, client: URLProtocolClient?) {
         self.internalState = _InternalState.initial
-        let fileName = NSTemporaryDirectory() + NSUUID().uuidString + ".tmp"
-        _ = FileManager.default.createFile(atPath: fileName, contents: nil)
-        self.tempFileURL = URL(fileURLWithPath: fileName)
         super.init(request: task.originalRequest!, cachedResponse: cachedResponse, client: client)
         self.task = task
         self.easyHandle = _EasyHandle(delegate: self)
@@ -27,9 +28,6 @@
 
     public required init(request: URLRequest, cachedResponse: CachedURLResponse?, client: URLProtocolClient?) {
         self.internalState = _InternalState.initial
-        let fileName = NSTemporaryDirectory() + NSUUID().uuidString + ".tmp"
-        _ = FileManager.default.createFile(atPath: fileName, contents: nil)
-        self.tempFileURL = URL(fileURLWithPath: fileName)
         super.init(request: request, cachedResponse: cachedResponse, client: client)
         self.easyHandle = _EasyHandle(delegate: self)
     }
diff --git a/Foundation/URLSession/http/MultiHandle.swift b/Foundation/URLSession/http/MultiHandle.swift
index bb2acaf..506c9a9 100644
--- a/Foundation/URLSession/http/MultiHandle.swift
+++ b/Foundation/URLSession/http/MultiHandle.swift
@@ -39,11 +39,7 @@
         let group = DispatchGroup()
         fileprivate var easyHandles: [_EasyHandle] = []
         fileprivate var timeoutSource: _TimeoutSource? = nil
-
-        //SR-4567: we need to synchronize the register/unregister commands to the epoll machinery in libdispatch
-        fileprivate let commandQueue: DispatchQueue = DispatchQueue(label: "Register-unregister synchronization")
-        fileprivate var cancelInProgress: DispatchSemaphore? = nil
-
+        
         init(configuration: URLSession._Configuration, workQueue: DispatchQueue) {
             queue = DispatchQueue(label: "MultiHandle.isolation", target: workQueue)
             setupCallbacks()
@@ -103,33 +99,25 @@
         // through libdispatch (DispatchSource) and store the source(s) inside
         // a `SocketSources` which we in turn store inside libcurl's multi handle
         // by means of curl_multi_assign() -- we retain the object fist.
-        commandQueue.async {
-            self.cancelInProgress?.wait()
-            self.cancelInProgress = nil
-
-            let action = _SocketRegisterAction(rawValue: CFURLSessionPoll(value: what))
-            var socketSources = _SocketSources.from(socketSourcePtr: socketSourcePtr)
-            if socketSources == nil && action.needsSource {
-                let s = _SocketSources()
-                let p = Unmanaged.passRetained(s).toOpaque()
-                CFURLSessionMultiHandleAssign(self.rawHandle, socket, UnsafeMutableRawPointer(p))
-                socketSources = s
-            } else if socketSources != nil && action == .unregister {
-                //the beginning of an unregister operation
-                self.cancelInProgress = DispatchSemaphore(value: 0)
-                // We need to release the stored pointer:
-                if let opaque = socketSourcePtr {
-                    Unmanaged<_SocketSources>.fromOpaque(opaque).release()
-                }
-                socketSources?.tearDown(self.cancelInProgress)
-                socketSources = nil
+        let action = _SocketRegisterAction(rawValue: CFURLSessionPoll(value: what))
+        var socketSources = _SocketSources.from(socketSourcePtr: socketSourcePtr)
+        if socketSources == nil && action.needsSource {
+            let s = _SocketSources()
+            let p = Unmanaged.passRetained(s).toOpaque()
+            CFURLSessionMultiHandleAssign(rawHandle, socket, UnsafeMutableRawPointer(p))
+            socketSources = s
+        } else if socketSources != nil && action == .unregister {
+            // We need to release the stored pointer:
+            if let opaque = socketSourcePtr {
+                Unmanaged<_SocketSources>.fromOpaque(opaque).release()
             }
-            if let ss = socketSources {
-                let handler = DispatchWorkItem { [weak self] in
-                    self?.performAction(for: socket)
-                }
-                ss.createSources(with: action, fileDescriptor: Int(socket), queue: self.queue, handler: handler)
+            socketSources = nil
+        }
+        if let ss = socketSources {
+            let handler = DispatchWorkItem { [weak self] in
+                self?.performAction(for: socket)
             }
+            ss.createSources(with: action, fileDescriptor: Int(socket), queue: queue, handler: handler)
         }
         return 0
     }
@@ -411,18 +399,12 @@
         s.resume()
     }
 
-    func tearDown(_ cancelInProgress: DispatchSemaphore?) {
-        let cancelHandler = DispatchWorkItem {
-            //the real end of an unregister operation!
-            cancelInProgress?.signal()
-        }
+    func tearDown() {
         if let s = readSource {
-            s.setCancelHandler(handler: cancelHandler)
             s.cancel()
         }
         readSource = nil
         if let s = writeSource {
-            s.setCancelHandler(handler: cancelHandler)
             s.cancel()
         }
         writeSource = nil
diff --git a/Foundation/Unit.swift b/Foundation/Unit.swift
index 92a9c6a..f43e5ff 100644
--- a/Foundation/Unit.swift
+++ b/Foundation/Unit.swift
@@ -79,6 +79,19 @@
     }
     
     public static var supportsSecureCoding: Bool { return true }
+    
+    open override func isEqual(_ object: Any?) -> Bool {
+        guard let other = object as? UnitConverterLinear else {
+            return false
+        }
+        
+        if self === other {
+            return true
+        }
+        
+        return self.coefficient == other.coefficient
+            && self.constant == other.constant
+    }
 }
 
 private class UnitConverterReciprocal : UnitConverter, NSSecureCoding {
@@ -115,6 +128,18 @@
     }
     
     fileprivate static var supportsSecureCoding: Bool { return true }
+    
+    open override func isEqual(_ object: Any?) -> Bool {
+        guard let other = object as? UnitConverterReciprocal else {
+            return false
+        }
+        
+        if self === other {
+            return true
+        }
+        
+        return self.reciprocal == other.reciprocal
+    }
 }
 
 /*
@@ -127,7 +152,7 @@
     open private(set) var symbol: String
     
     
-    public init(symbol: String) {
+    public required init(symbol: String) {
         self.symbol = symbol
     }
     
@@ -150,8 +175,20 @@
         }
         aCoder.encode(self.symbol._bridgeToObjectiveC(), forKey:"NS.symbol")
     }
-
+    
     public static var supportsSecureCoding: Bool { return true }
+    
+    open override func isEqual(_ object: Any?) -> Bool {
+        guard let other = object as? Unit else {
+            return false
+        }
+        
+        if self === other {
+            return true
+        }
+        
+        return self.symbol == other.symbol
+    }
 }
 
 open class Dimension : Unit {
@@ -159,8 +196,7 @@
     
     open private(set) var converter: UnitConverter
     
-    
-    public init(symbol: String, converter: UnitConverter) {
+    public required init(symbol: String, converter: UnitConverter) {
         self.converter = converter
         super.init(symbol: symbol)
     }
@@ -186,6 +222,11 @@
         super.init(symbol: symbol)
     }
     
+    public required init(symbol: String) {
+        let T = type(of: self)
+        fatalError("\(T) must be initialized with designated initializer \(T).init(symbol: String, converter: UnitConverter)")
+    }
+    
     open override func encode(with aCoder: NSCoder) {
         super.encode(with: aCoder)
         guard aCoder.allowsKeyedCoding else {
@@ -193,6 +234,18 @@
         }
         aCoder.encode(self.converter, forKey:"converter")
     }
+    
+    open override func isEqual(_ object: Any?) -> Bool {
+        guard let other = object as? Dimension else {
+            return false
+        }
+        
+        if self === other {
+            return true
+        }
+        
+        return super.isEqual(object) && self.converter == other.converter
+    }
 }
 
 open class UnitAcceleration : Dimension {
@@ -211,8 +264,8 @@
         static let gravity                  = 9.81
     }
     
-    private init(symbol: String, coefficient: Double) {
-        super.init(symbol: symbol, converter: UnitConverterLinear(coefficient: coefficient))
+    private convenience init(symbol: String, coefficient: Double) {
+        self.init(symbol: symbol, converter: UnitConverterLinear(coefficient: coefficient))
     }
     
     open class var metersPerSecondSquared: UnitAcceleration {
@@ -231,9 +284,17 @@
         return UnitAcceleration.metersPerSecondSquared
     }
     
-    
-    public required init?(coder aDecoder: NSCoder) { super.init(coder: aDecoder) }
-    open override func encode(with aCoder: NSCoder) { super.encode(with: aCoder) }
+    open override func isEqual(_ object: Any?) -> Bool {
+        guard let other = object as? UnitAcceleration else {
+            return false
+        }
+        
+        if self === other {
+            return true
+        }
+        
+        return super.isEqual(object)
+    }
 }
 
 open class UnitAngle : Dimension {
@@ -260,11 +321,10 @@
         static let revolutions  = 360.0
     }
     
-    private init(symbol: String, coefficient: Double) {
-        super.init(symbol: symbol, converter: UnitConverterLinear(coefficient: coefficient))
+    private convenience init(symbol: String, coefficient: Double) {
+        self.init(symbol: symbol, converter: UnitConverterLinear(coefficient: coefficient))
     }
     
-    
     open class var degrees: UnitAngle {
         get {
             return UnitAngle(symbol: Symbol.degrees, coefficient: Coefficient.degrees)
@@ -305,9 +365,17 @@
         return UnitAngle.degrees
     }
     
-    
-    public required init?(coder aDecoder: NSCoder) { super.init(coder: aDecoder) }
-    open override func encode(with aCoder: NSCoder) { super.encode(with: aCoder) }
+    open override func isEqual(_ object: Any?) -> Bool {
+        guard let other = object as? UnitAngle else {
+            return false
+        }
+        
+        if self === other {
+            return true
+        }
+        
+        return super.isEqual(object)
+    }
 }
 
 open class UnitArea : Dimension {
@@ -350,11 +418,10 @@
         static let hectares             = 10000.0
     }
     
-    private init(symbol: String, coefficient: Double) {
-        super.init(symbol: symbol, converter: UnitConverterLinear(coefficient: coefficient))
+    private convenience init(symbol: String, coefficient: Double) {
+        self.init(symbol: symbol, converter: UnitConverterLinear(coefficient: coefficient))
     }
     
-    
     open class var squareMegameters: UnitArea {
         get {
             return UnitArea(symbol: Symbol.squareMegameters, coefficient: Coefficient.squareMegameters)
@@ -443,9 +510,17 @@
         return UnitArea.squareMeters
     }
     
-    
-    public required init?(coder aDecoder: NSCoder) { super.init(coder: aDecoder) }
-    open override func encode(with aCoder: NSCoder) { super.encode(with: aCoder) }
+    open override func isEqual(_ object: Any?) -> Bool {
+        guard let other = object as? UnitArea else {
+            return false
+        }
+        
+        if self === other {
+            return true
+        }
+        
+        return super.isEqual(object)
+    }
 }
 
 open class UnitConcentrationMass : Dimension {
@@ -466,11 +541,10 @@
         static let millimolesPerLiter       = 18.0
     }
     
-    private init(symbol: String, coefficient: Double) {
-        super.init(symbol: symbol, converter: UnitConverterLinear(coefficient: coefficient))
+    private convenience init(symbol: String, coefficient: Double) {
+        self.init(symbol: symbol, converter: UnitConverterLinear(coefficient: coefficient))
     }
     
-    
     open class var gramsPerLiter: UnitConcentrationMass {
         get {
             return UnitConcentrationMass(symbol: Symbol.gramsPerLiter, coefficient: Coefficient.gramsPerLiter)
@@ -491,9 +565,17 @@
         return UnitConcentrationMass.gramsPerLiter
     }
     
-    
-    public required init?(coder aDecoder: NSCoder) { super.init(coder: aDecoder) }
-    open override func encode(with aCoder: NSCoder) { super.encode(with: aCoder) }
+    open override func isEqual(_ object: Any?) -> Bool {
+        guard let other = object as? UnitConcentrationMass else {
+            return false
+        }
+        
+        if self === other {
+            return true
+        }
+        
+        return super.isEqual(object)
+    }
 }
 
 open class UnitDispersion : Dimension {
@@ -510,11 +592,10 @@
         static let partsPerMillion  = 1.0
     }
     
-    private init(symbol: String, coefficient: Double) {
-        super.init(symbol: symbol, converter: UnitConverterLinear(coefficient: coefficient))
+    private convenience init(symbol: String, coefficient: Double) {
+        self.init(symbol: symbol, converter: UnitConverterLinear(coefficient: coefficient))
     }
     
-    
     open class var partsPerMillion: UnitDispersion {
         get {
             return UnitDispersion(symbol: Symbol.partsPerMillion, coefficient: Coefficient.partsPerMillion)
@@ -525,9 +606,17 @@
         return UnitDispersion.partsPerMillion
     }
     
-    
-    public required init?(coder aDecoder: NSCoder) { super.init(coder: aDecoder) }
-    open override func encode(with aCoder: NSCoder) { super.encode(with: aCoder) }
+    open override func isEqual(_ object: Any?) -> Bool {
+        guard let other = object as? UnitDispersion else {
+            return false
+        }
+        
+        if self === other {
+            return true
+        }
+        
+        return super.isEqual(object)
+    }
 }
 
 open class UnitDuration : Dimension {
@@ -548,8 +637,8 @@
         static let hours    = 3600.0
     }
     
-    private init(symbol: String, coefficient: Double) {
-        super.init(symbol: symbol, converter: UnitConverterLinear(coefficient: coefficient))
+    private convenience init(symbol: String, coefficient: Double) {
+        self.init(symbol: symbol, converter: UnitConverterLinear(coefficient: coefficient))
     }
     
     open class var seconds: UnitDuration {
@@ -574,9 +663,17 @@
         return UnitDuration.seconds
     }
     
-    
-    public required init?(coder aDecoder: NSCoder) { super.init(coder: aDecoder) }
-    open override func encode(with aCoder: NSCoder) { super.encode(with: aCoder) }
+    open override func isEqual(_ object: Any?) -> Bool {
+        guard let other = object as? UnitDuration else {
+            return false
+        }
+        
+        if self === other {
+            return true
+        }
+        
+        return super.isEqual(object)
+    }
 }
 
 open class UnitElectricCharge : Dimension {
@@ -602,11 +699,10 @@
         static let microampereHours = 0.0036
     }
     
-    private init(symbol: String, coefficient: Double) {
-        super.init(symbol: symbol, converter: UnitConverterLinear(coefficient: coefficient))
+    private convenience init(symbol: String, coefficient: Double) {
+        self.init(symbol: symbol, converter: UnitConverterLinear(coefficient: coefficient))
     }
     
-    
     open class var coulombs: UnitElectricCharge {
         get {
             return UnitElectricCharge(symbol: Symbol.coulombs, coefficient: Coefficient.coulombs)
@@ -647,9 +743,17 @@
         return UnitElectricCharge.coulombs
     }
     
-    
-    public required init?(coder aDecoder: NSCoder) { super.init(coder: aDecoder) }
-    open override func encode(with aCoder: NSCoder) { super.encode(with: aCoder) }
+    open override func isEqual(_ object: Any?) -> Bool {
+        guard let other = object as? UnitElectricCharge else {
+            return false
+        }
+        
+        if self === other {
+            return true
+        }
+        
+        return super.isEqual(object)
+    }
 }
 
 open class UnitElectricCurrent : Dimension {
@@ -657,6 +761,7 @@
     /*
      Base unit - amperes
      */
+    
     private struct Symbol {
         static let megaamperes  = "MA"
         static let kiloamperes  = "kA"
@@ -674,11 +779,10 @@
         
     }
     
-    private init(symbol: String, coefficient: Double) {
-        super.init(symbol: symbol, converter: UnitConverterLinear(coefficient: coefficient))
+    private convenience init(symbol: String, coefficient: Double) {
+        self.init(symbol: symbol, converter: UnitConverterLinear(coefficient: coefficient))
     }
     
-    
     open class var megaamperes: UnitElectricCurrent {
         get {
             return UnitElectricCurrent(symbol: Symbol.megaamperes, coefficient: Coefficient.megaamperes)
@@ -713,9 +817,17 @@
         return UnitElectricCurrent.amperes
     }
     
-    
-    public required init?(coder aDecoder: NSCoder) { super.init(coder: aDecoder) }
-    open override func encode(with aCoder: NSCoder) { super.encode(with: aCoder) }
+    open override func isEqual(_ object: Any?) -> Bool {
+        guard let other = object as? UnitElectricCurrent else {
+            return false
+        }
+        
+        if self === other {
+            return true
+        }
+        
+        return super.isEqual(object)
+    }
 }
 
 open class UnitElectricPotentialDifference : Dimension {
@@ -741,11 +853,10 @@
         
     }
     
-    private init(symbol: String, coefficient: Double) {
-        super.init(symbol: symbol, converter: UnitConverterLinear(coefficient: coefficient))
+    private convenience init(symbol: String, coefficient: Double) {
+        self.init(symbol: symbol, converter: UnitConverterLinear(coefficient: coefficient))
     }
     
-    
     open class var megavolts: UnitElectricPotentialDifference {
         get {
             return UnitElectricPotentialDifference(symbol: Symbol.megavolts, coefficient: Coefficient.megavolts)
@@ -780,9 +891,17 @@
         return UnitElectricPotentialDifference.volts
     }
     
-    
-    public required init?(coder aDecoder: NSCoder) { super.init(coder: aDecoder) }
-    open override func encode(with aCoder: NSCoder) { super.encode(with: aCoder) }
+    open override func isEqual(_ object: Any?) -> Bool {
+        guard let other = object as? UnitElectricPotentialDifference else {
+            return false
+        }
+        
+        if self === other {
+            return true
+        }
+        
+        return super.isEqual(object)
+    }
 }
 
 open class UnitElectricResistance : Dimension {
@@ -808,8 +927,8 @@
         
     }
     
-    private init(symbol: String, coefficient: Double) {
-        super.init(symbol: symbol, converter: UnitConverterLinear(coefficient: coefficient))
+    private convenience init(symbol: String, coefficient: Double) {
+        self.init(symbol: symbol, converter: UnitConverterLinear(coefficient: coefficient))
     }
     
     open class var megaohms: UnitElectricResistance {
@@ -846,9 +965,17 @@
         return UnitElectricResistance.ohms
     }
     
-    
-    public required init?(coder aDecoder: NSCoder) { super.init(coder: aDecoder) }
-    open override func encode(with aCoder: NSCoder) { super.encode(with: aCoder) }
+    open override func isEqual(_ object: Any?) -> Bool {
+        guard let other = object as? UnitElectricResistance else {
+            return false
+        }
+        
+        if self === other {
+            return true
+        }
+        
+        return super.isEqual(object)
+    }
 }
 
 open class UnitEnergy : Dimension {
@@ -874,8 +1001,8 @@
         
     }
     
-    private init(symbol: String, coefficient: Double) {
-        super.init(symbol: symbol, converter: UnitConverterLinear(coefficient: coefficient))
+    private convenience init(symbol: String, coefficient: Double) {
+        self.init(symbol: symbol, converter: UnitConverterLinear(coefficient: coefficient))
     }
     
     open class var kilojoules: UnitEnergy {
@@ -912,9 +1039,17 @@
         return UnitEnergy.joules
     }
     
-    
-    public required init?(coder aDecoder: NSCoder) { super.init(coder: aDecoder) }
-    open override func encode(with aCoder: NSCoder) { super.encode(with: aCoder) }
+    open override func isEqual(_ object: Any?) -> Bool {
+        guard let other = object as? UnitEnergy else {
+            return false
+        }
+        
+        if self === other {
+            return true
+        }
+        
+        return super.isEqual(object)
+    }
 }
 
 open class UnitFrequency : Dimension {
@@ -945,11 +1080,10 @@
         static let nanohertz    = 1e-9
     }
     
-    private init(symbol: String, coefficient: Double) {
-        super.init(symbol: symbol, converter: UnitConverterLinear(coefficient: coefficient))
+    private convenience init(symbol: String, coefficient: Double) {
+        self.init(symbol: symbol, converter: UnitConverterLinear(coefficient: coefficient))
     }
     
-    
     open class var terahertz: UnitFrequency {
         get {
             return UnitFrequency(symbol: Symbol.terahertz, coefficient: Coefficient.terahertz)
@@ -1002,9 +1136,17 @@
         return UnitFrequency.hertz
     }
     
-    
-    public required init?(coder aDecoder: NSCoder) { super.init(coder: aDecoder) }
-    open override func encode(with aCoder: NSCoder) { super.encode(with: aCoder) }
+    open override func isEqual(_ object: Any?) -> Bool {
+        guard let other = object as? UnitFrequency else {
+            return false
+        }
+        
+        if self === other {
+            return true
+        }
+        
+        return super.isEqual(object)
+    }
 }
 
 open class UnitFuelEfficiency : Dimension {
@@ -1025,11 +1167,10 @@
         static let milesPerGallon           = 235.215
     }
     
-    private init(symbol: String, reciprocal: Double) {
-        super.init(symbol: symbol, converter: UnitConverterReciprocal(reciprocal: reciprocal))
+    private convenience init(symbol: String, reciprocal: Double) {
+        self.init(symbol: symbol, converter: UnitConverterReciprocal(reciprocal: reciprocal))
     }
     
-    
     open class var litersPer100Kilometers: UnitFuelEfficiency {
         get {
             return UnitFuelEfficiency(symbol: Symbol.litersPer100Kilometers, reciprocal: Coefficient.litersPer100Kilometers)
@@ -1052,9 +1193,17 @@
         return UnitFuelEfficiency.litersPer100Kilometers
     }
     
-    
-    public required init?(coder aDecoder: NSCoder) { super.init(coder: aDecoder) }
-    open override func encode(with aCoder: NSCoder) { super.encode(with: aCoder) }
+    open override func isEqual(_ object: Any?) -> Bool {
+        guard let other = object as? UnitFuelEfficiency else {
+            return false
+        }
+        
+        if self === other {
+            return true
+        }
+        
+        return super.isEqual(object)
+    }
 }
 
 open class UnitLength : Dimension {
@@ -1113,8 +1262,8 @@
         static let parsecs              = 3.086e+16
     }
     
-    private init(symbol: String, coefficient: Double) {
-        super.init(symbol: symbol, converter: UnitConverterLinear(coefficient: coefficient))
+    private convenience init(symbol: String, coefficient: Double) {
+        self.init(symbol: symbol, converter: UnitConverterLinear(coefficient: coefficient))
     }
     
     open class var megameters: UnitLength {
@@ -1253,9 +1402,17 @@
         return UnitLength.meters
     }
     
-    
-    public required init?(coder aDecoder: NSCoder) { super.init(coder: aDecoder) }
-    open override func encode(with aCoder: NSCoder) { super.encode(with: aCoder) }
+    open override func isEqual(_ object: Any?) -> Bool {
+        guard let other = object as? UnitLength else {
+            return false
+        }
+        
+        if self === other {
+            return true
+        }
+        
+        return super.isEqual(object)
+    }
 }
 
 open class UnitIlluminance : Dimension {
@@ -1272,8 +1429,8 @@
         static let lux   = 1.0
     }
     
-    private init(symbol: String, coefficient: Double) {
-        super.init(symbol: symbol, converter: UnitConverterLinear(coefficient: coefficient))
+    private convenience init(symbol: String, coefficient: Double) {
+        self.init(symbol: symbol, converter: UnitConverterLinear(coefficient: coefficient))
     }
     
     open class var lux: UnitIlluminance {
@@ -1286,9 +1443,17 @@
         return UnitIlluminance.lux
     }
     
-    
-    public required init?(coder aDecoder: NSCoder) { super.init(coder: aDecoder) }
-    open override func encode(with aCoder: NSCoder) { super.encode(with: aCoder) }
+    open override func isEqual(_ object: Any?) -> Bool {
+        guard let other = object as? UnitIlluminance else {
+            return false
+        }
+        
+        if self === other {
+            return true
+        }
+        
+        return super.isEqual(object)
+    }
 }
 
 open class UnitMass : Dimension {
@@ -1335,8 +1500,8 @@
         static let slugs        = 14.5939
     }
     
-    private init(symbol: String, coefficient: Double) {
-        super.init(symbol: symbol, converter: UnitConverterLinear(coefficient: coefficient))
+    private convenience init(symbol: String, coefficient: Double) {
+        self.init(symbol: symbol, converter: UnitConverterLinear(coefficient: coefficient))
     }
     
     open class var kilograms: UnitMass {
@@ -1439,9 +1604,17 @@
         return UnitMass.kilograms
     }
     
-    
-    public required init?(coder aDecoder: NSCoder) { super.init(coder: aDecoder) }
-    open override func encode(with aCoder: NSCoder) { super.encode(with: aCoder) }
+    open override func isEqual(_ object: Any?) -> Bool {
+        guard let other = object as? UnitMass else {
+            return false
+        }
+        
+        if self === other {
+            return true
+        }
+        
+        return super.isEqual(object)
+    }
 }
 
 open class UnitPower : Dimension {
@@ -1478,8 +1651,8 @@
         static let horsepower = 745.7
     }
     
-    private init(symbol: String, coefficient: Double) {
-        super.init(symbol: symbol, converter: UnitConverterLinear(coefficient: coefficient))
+    private convenience init(symbol: String, coefficient: Double) {
+        self.init(symbol: symbol, converter: UnitConverterLinear(coefficient: coefficient))
     }
     
     open class var terawatts: UnitPower {
@@ -1552,9 +1725,17 @@
         return UnitPower.watts
     }
     
-    
-    public required init?(coder aDecoder: NSCoder) { super.init(coder: aDecoder) }
-    open override func encode(with aCoder: NSCoder) { super.encode(with: aCoder) }
+    open override func isEqual(_ object: Any?) -> Bool {
+        guard let other = object as? UnitPower else {
+            return false
+        }
+        
+        if self === other {
+            return true
+        }
+        
+        return super.isEqual(object)
+    }
 }
 
 open class UnitPressure : Dimension {
@@ -1589,11 +1770,10 @@
         static let poundsForcePerSquareInch = 6894.76
     }
     
-    private init(symbol: String, coefficient: Double) {
-        super.init(symbol: symbol, converter: UnitConverterLinear(coefficient: coefficient))
+    private convenience init(symbol: String, coefficient: Double) {
+        self.init(symbol: symbol, converter: UnitConverterLinear(coefficient: coefficient))
     }
     
-    
     open class var newtonsPerMetersSquared: UnitPressure {
         get {
             return UnitPressure(symbol: Symbol.newtonsPerMetersSquared, coefficient: Coefficient.newtonsPerMetersSquared)
@@ -1658,9 +1838,17 @@
         return UnitPressure.newtonsPerMetersSquared
     }
     
-    
-    public required init?(coder aDecoder: NSCoder) { super.init(coder: aDecoder) }
-    open override func encode(with aCoder: NSCoder) { super.encode(with: aCoder) }
+    open override func isEqual(_ object: Any?) -> Bool {
+        guard let other = object as? UnitPressure else {
+            return false
+        }
+        
+        if self === other {
+            return true
+        }
+        
+        return super.isEqual(object)
+    }
 }
 
 open class UnitSpeed : Dimension {
@@ -1683,11 +1871,10 @@
         static let knots                = 0.514444
     }
     
-    private init(symbol: String, coefficient: Double) {
-        super.init(symbol: symbol, converter: UnitConverterLinear(coefficient: coefficient))
+    private convenience init(symbol: String, coefficient: Double) {
+        self.init(symbol: symbol, converter: UnitConverterLinear(coefficient: coefficient))
     }
     
-    
     open class var metersPerSecond: UnitSpeed {
         get {
             return UnitSpeed(symbol: Symbol.metersPerSecond, coefficient: Coefficient.metersPerSecond)
@@ -1716,9 +1903,17 @@
         return UnitSpeed.metersPerSecond
     }
     
-    
-    public required init?(coder aDecoder: NSCoder) { super.init(coder: aDecoder) }
-    open override func encode(with aCoder: NSCoder) { super.encode(with: aCoder) }
+    open override func isEqual(_ object: Any?) -> Bool {
+        guard let other = object as? UnitSpeed else {
+            return false
+        }
+        
+        if self === other {
+            return true
+        }
+        
+        return super.isEqual(object)
+    }
 }
 
 open class UnitTemperature : Dimension {
@@ -1745,8 +1940,8 @@
         static let fahrenheit = 255.37222222222427
     }
     
-    private init(symbol: String, coefficient: Double, constant: Double) {
-        super.init(symbol: symbol, converter: UnitConverterLinear(coefficient: coefficient, constant: constant))
+    private convenience init(symbol: String, coefficient: Double, constant: Double) {
+        self.init(symbol: symbol, converter: UnitConverterLinear(coefficient: coefficient, constant: constant))
     }
     
     open class var kelvin: UnitTemperature {
@@ -1771,9 +1966,17 @@
         return UnitTemperature.kelvin
     }
     
-    
-    public required init?(coder aDecoder: NSCoder) { super.init(coder: aDecoder) }
-    open override func encode(with aCoder: NSCoder) { super.encode(with: aCoder) }
+    open override func isEqual(_ object: Any?) -> Bool {
+        guard let other = object as? UnitTemperature else {
+            return false
+        }
+        
+        if self === other {
+            return true
+        }
+        
+        return super.isEqual(object)
+    }
 }
 
 open class UnitVolume : Dimension {
@@ -1850,11 +2053,10 @@
         static let metricCups           = 0.25
     }
     
-    private init(symbol: String, coefficient: Double) {
-        super.init(symbol: symbol, converter: UnitConverterLinear(coefficient: coefficient))
+    private convenience init(symbol: String, coefficient: Double) {
+        self.init(symbol: symbol, converter: UnitConverterLinear(coefficient: coefficient))
     }
     
-    
     open class var megaliters: UnitVolume {
         get {
             return UnitVolume(symbol: Symbol.megaliters, coefficient: Coefficient.megaliters)
@@ -2045,6 +2247,15 @@
         return UnitVolume.liters
     }
     
-    public required init?(coder aDecoder: NSCoder) { super.init(coder: aDecoder) }
-    open override func encode(with aCoder: NSCoder) { super.encode(with: aCoder) }
+    open override func isEqual(_ object: Any?) -> Bool {
+        guard let other = object as? UnitVolume else {
+            return false
+        }
+        
+        if self === other {
+            return true
+        }
+        
+        return super.isEqual(object)
+    }
 }
diff --git a/Foundation/UserDefaults.swift b/Foundation/UserDefaults.swift
index 29d36fd..42cbd0d 100644
--- a/Foundation/UserDefaults.swift
+++ b/Foundation/UserDefaults.swift
@@ -45,37 +45,39 @@
         //Force the returned value to an NSObject
         switch CFGetTypeID(anObj) {
         case CFStringGetTypeID():
-            return (anObj as! CFString)._nsObject
+            return unsafeBitCast(anObj, to: NSString.self)
             
         case CFNumberGetTypeID():
-            return (anObj as! CFNumber)._nsObject
+            return unsafeBitCast(anObj, to: NSNumber.self)
             
         case CFURLGetTypeID():
-            return (anObj as! CFURL)._nsObject
+            return unsafeBitCast(anObj, to: NSURL.self)
             
         case CFArrayGetTypeID():
-            return (anObj as! CFArray)._nsObject
+            return unsafeBitCast(anObj, to: NSArray.self)
             
         case CFDictionaryGetTypeID():
-            return (anObj as! CFDictionary)._nsObject
-
+            return unsafeBitCast(anObj, to: NSDictionary.self)
+            
         case CFDataGetTypeID():
-            return (anObj as! CFData)._nsObject
+            return unsafeBitCast(anObj, to: NSData.self)
             
         default:
             return getFromRegistered()
         }
     }
+
     open func set(_ value: Any?, forKey defaultName: String) {
         guard let value = value else {
             CFPreferencesSetAppValue(defaultName._cfObject, nil, suite?._cfObject ?? kCFPreferencesCurrentApplication)
             return
         }
         
-        var cfType: CFTypeRef? = nil
+        let cfType: CFTypeRef
 		
-		//FIXME: is this needed? Am I overcomplicating things?
-        //Foundation types
+		// Convert the input value to the internal representation. All values are
+        // represented as CFTypeRef objects internally because we store the defaults
+        // in a CFPreferences type.
         if let bType = value as? NSNumber {
             cfType = bType._cfObject
         } else if let bType = value as? NSString {
@@ -84,11 +86,26 @@
             cfType = bType._cfObject
         } else if let bType = value as? NSDictionary {
             cfType = bType._cfObject
+        } else if let bType = value as? NSData {
+            cfType = bType._cfObject
+        } else if let bType = value as? NSURL {
+            set(URL(reference: bType), forKey: defaultName)
+            return
+        } else if let bType = value as? String {
+            cfType = bType._cfObject
         } else if let bType = value as? URL {
 			set(bType, forKey: defaultName)
 			return
+        } else if let bType = value as? Int {
+            var cfValue = Int64(bType)
+            cfType = CFNumberCreate(nil, kCFNumberSInt64Type, &cfValue)
+        } else if let bType = value as? Double {
+            var cfValue = bType
+            cfType = CFNumberCreate(nil, kCFNumberDoubleType, &cfValue)
         } else if let bType = value as? Data {
             cfType = bType._cfObject
+        } else {
+            fatalError("The type of 'value' passed to UserDefaults.set(forKey:) is not supported.")
         }
         
         CFPreferencesSetAppValue(defaultName._cfObject, cfType, suite?._cfObject ?? kCFPreferencesCurrentApplication)
@@ -140,10 +157,10 @@
     }
     open func data(forKey defaultName: String) -> Data? {
         guard let aVal = object(forKey: defaultName),
-              let bVal = aVal as? Data else {
+              let bVal = aVal as? NSData else {
             return nil
         }
-        return bVal
+        return Data(referencing: bVal)
     }
     open func stringArray(forKey defaultName: String) -> [String]? {
         guard let aVal = object(forKey: defaultName),
@@ -153,39 +170,61 @@
         return _SwiftValue.fetch(nonOptional: bVal) as? [String]
     }
     open func integer(forKey defaultName: String) -> Int {
-        guard let aVal = object(forKey: defaultName),
-              let bVal = aVal as? NSNumber else {
+        guard let aVal = object(forKey: defaultName) else {
             return 0
         }
-        return bVal.intValue
+        if let bVal = aVal as? NSNumber {
+            return bVal.intValue
+        }
+        if let bVal = aVal as? NSString {
+            return bVal.integerValue
+        }
+        return 0
     }
     open func float(forKey defaultName: String) -> Float {
-        guard let aVal = object(forKey: defaultName),
-              let bVal = aVal as? NSNumber else {
+        guard let aVal = object(forKey: defaultName) else {
             return 0
         }
-        return bVal.floatValue
+        if let bVal = aVal as? NSNumber {
+            return bVal.floatValue
+        }
+        if let bVal = aVal as? NSString {
+            return bVal.floatValue
+        }
+        return 0
     }
     open func double(forKey defaultName: String) -> Double {
-        guard let aVal = object(forKey: defaultName),
-              let bVal = aVal as? NSNumber else {
+        guard let aVal = object(forKey: defaultName) else {
             return 0
         }
-        return bVal.doubleValue
+        if let bVal = aVal as? NSNumber {
+            return bVal.doubleValue
+        }
+        if let bVal = aVal as? NSString {
+            return bVal.doubleValue
+        }
+        return 0
     }
     open func bool(forKey defaultName: String) -> Bool {
-        guard let aVal = object(forKey: defaultName),
-              let bVal = aVal as? NSNumber else {
+        guard let aVal = object(forKey: defaultName) else {
             return false
         }
-        return bVal.boolValue
+        if let bVal = aVal as? NSNumber {
+            return bVal.boolValue
+        }
+        if let bVal = aVal as? NSString {
+            return bVal.boolValue
+        }
+        return false
     }
     open func url(forKey defaultName: String) -> URL? {
         guard let aVal = object(forKey: defaultName) else {
             return nil
         }
         
-        if let bVal = aVal as? NSString {
+        if let bVal = aVal as? NSURL {
+            return URL(reference: bVal)
+        } else if let bVal = aVal as? NSString {
             let cVal = bVal.expandingTildeInPath
             
             return URL(fileURLWithPath: cVal)
@@ -227,10 +266,32 @@
     
     open func register(defaults registrationDictionary: [String : Any]) {
         for (key, value) in registrationDictionary {
-            registeredDefaults[key] = value
+            let nsValue: NSObject
+
+            // Converts a value to the internal representation. Internalized values are
+            // stored as NSObject derived objects in the registration dictionary.
+            if let val = value as? String {
+                nsValue = val._nsObject
+            } else if let val = value as? URL {
+                nsValue = val.path._nsObject
+            } else if let val = value as? Int {
+                nsValue = NSNumber(value: val)
+            } else if let val = value as? Double {
+                nsValue = NSNumber(value: val)
+            } else if let val = value as? Bool {
+                nsValue = NSNumber(value: val)
+            } else if let val = value as? Data {
+                nsValue = val._nsObject
+            } else if let val = value as? NSObject {
+                nsValue = val
+            } else {
+                fatalError("The type of 'value' passed to UserDefaults.register(defaults:) is not supported.")
+            }
+
+            registeredDefaults[key] = nsValue
         }
     }
-    
+
     open func addSuite(named suiteName: String) {
         CFPreferencesAddSuitePreferencesToApp(kCFPreferencesCurrentApplication, suiteName._cfObject)
     }
diff --git a/TestFoundation/HTTPServer.swift b/TestFoundation/HTTPServer.swift
index 39c8b9c..ec2055f 100644
--- a/TestFoundation/HTTPServer.swift
+++ b/TestFoundation/HTTPServer.swift
@@ -16,16 +16,22 @@
 
 #if DEPLOYMENT_RUNTIME_OBJC || os(Linux)
     import Foundation
-    import Glibc
     import XCTest
 #else
-    import CoreFoundation
     import SwiftFoundation
-    import Darwin
     import SwiftXCTest
 #endif
 
+#if os(OSX) || os(iOS)
+    import Darwin
+#elseif os(Linux)
+    import Glibc
+#endif
+
+
 public let globalDispatchQueue = DispatchQueue.global()
+public let dispatchQueueMake: (String) -> DispatchQueue = { DispatchQueue.init(label: $0) }
+public let dispatchGroupMake: () -> DispatchGroup = DispatchGroup.init
 
 struct _HTTPUtils {
     static let CRLF = "\r\n"
@@ -35,6 +41,12 @@
     static let EMPTY = ""
 }
 
+extension UInt16 {
+    public init(networkByteOrder input: UInt16) {
+        self.init(bigEndian: input)
+    }
+}
+
 class _TCPSocket {
   
     private var listenSocket: Int32!
@@ -55,12 +67,15 @@
         return r
     }
 
-    init(port: UInt16) throws {
+    public private(set) var port: UInt16
+
+    init(port: UInt16?) throws {
         #if os(Linux)
             let SOCKSTREAM = Int32(SOCK_STREAM.rawValue)
         #else
             let SOCKSTREAM = SOCK_STREAM
         #endif
+        self.port = port ?? 0
         listenSocket = try attempt("socket", valid: isNotNegative, socket(AF_INET, SOCKSTREAM, Int32(IPPROTO_TCP)))
         var on: Int = 1
         _ = try attempt("setsockopt", valid: isZero, setsockopt(listenSocket, SOL_SOCKET, SO_REUSEADDR, &on, socklen_t(MemoryLayout<Int>.size)))
@@ -70,16 +85,27 @@
             let addr = UnsafePointer<sockaddr>($0)
             _ = try attempt("bind", valid: isZero, bind(listenSocket, addr, socklen_t(MemoryLayout<sockaddr>.size)))
         })
+
+        var actualSA = sockaddr_in()
+        withUnsafeMutablePointer(to: &actualSA) { ptr in
+            ptr.withMemoryRebound(to: sockaddr.self, capacity: 1) { (ptr: UnsafeMutablePointer<sockaddr>) in
+                var len = socklen_t(MemoryLayout<sockaddr>.size)
+                getsockname(listenSocket, ptr, &len)
+            }
+        }
+
+        self.port = UInt16(networkByteOrder: actualSA.sin_port)
     }
 
-    private func createSockaddr(_ port: UInt16) -> sockaddr_in {
+    private func createSockaddr(_ port: UInt16?) -> sockaddr_in {
         // Listen on the loopback address so that OSX doesnt pop up a dialog
         // asking to accept incoming connections if the firewall is enabled.
         let addr = UInt32(INADDR_LOOPBACK).bigEndian
+        let netPort = UInt16(bigEndian: port ?? 0)
         #if os(Linux)
-            return sockaddr_in(sin_family: sa_family_t(AF_INET), sin_port: htons(port), sin_addr: in_addr(s_addr: addr), sin_zero: (0,0,0,0,0,0,0,0))
+            return sockaddr_in(sin_family: sa_family_t(AF_INET), sin_port: netPort, sin_addr: in_addr(s_addr: addr), sin_zero: (0,0,0,0,0,0,0,0))
         #else
-            return sockaddr_in(sin_len: 0, sin_family: sa_family_t(AF_INET), sin_port: CFSwapInt16HostToBig(port), sin_addr: in_addr(s_addr: addr), sin_zero: (0,0,0,0,0,0,0,0))
+            return sockaddr_in(sin_len: 0, sin_family: sa_family_t(AF_INET), sin_port: netPort, sin_addr: in_addr(s_addr: addr), sin_zero: (0,0,0,0,0,0,0,0))
         #endif
     }
 
@@ -133,20 +159,27 @@
     }
 
     func shutdown() {
-        close(connectionSocket)
+        if let connectionSocket = self.connectionSocket {
+            close(connectionSocket)
+        }
         close(listenSocket)
     }
 }
 
 class _HTTPServer {
 
-    let socket: _TCPSocket 
+    let socket: _TCPSocket
+    var port: UInt16 {
+        get {
+            return self.socket.port
+        }
+    }
     
-    init(port: UInt16) throws {
+    init(port: UInt16?) throws {
         socket = try _TCPSocket(port: port)
     }
 
-    public class func create(port: UInt16) throws -> _HTTPServer {
+    public class func create(port: UInt16?) throws -> _HTTPServer {
         return try _HTTPServer(port: port)
     }
 
@@ -159,7 +192,7 @@
     }
    
     public func request() throws -> _HTTPRequest {
-       return _HTTPRequest(request: try socket.readData()) 
+       return try _HTTPRequest(request: socket.readData())
     }
 
     public func respond(with response: _HTTPResponse, startDelay: TimeInterval? = nil, sendDelay: TimeInterval? = nil, bodyChunks: Int? = nil) throws {
@@ -307,8 +340,13 @@
     let startDelay: TimeInterval?
     let sendDelay: TimeInterval?
     let bodyChunks: Int?
+    var port: UInt16 {
+        get {
+            return self.httpServer.port
+        }
+    }
     
-    public init (port: UInt16, startDelay: TimeInterval? = nil, sendDelay: TimeInterval? = nil, bodyChunks: Int? = nil) throws {
+    public init (port: UInt16?, startDelay: TimeInterval? = nil, sendDelay: TimeInterval? = nil, bodyChunks: Int? = nil) throws {
         httpServer = try _HTTPServer.create(port: port)
         self.startDelay = startDelay
         self.sendDelay = sendDelay
@@ -404,23 +442,28 @@
 }
 
 class LoopbackServerTest : XCTestCase {
-    static var serverPort: Int = -1
+    private static let staticSyncQ = DispatchQueue(label: "org.swift.TestFoundation.HTTPServer.StaticSyncQ")
+
+    private static var _serverPort: Int = -1
+    static var serverPort: Int {
+        get {
+            return staticSyncQ.sync { _serverPort }
+        }
+        set {
+            staticSyncQ.sync { _serverPort = newValue }
+        }
+    }
 
     override class func setUp() {
         super.setUp()
         func runServer(with condition: ServerSemaphore, startDelay: TimeInterval? = nil, sendDelay: TimeInterval? = nil, bodyChunks: Int? = nil) throws {
-            let start = 21961
-            for port in start...(start+100) { //we must find at least one port to bind
-                do {
-                    serverPort = port
-                    let test = try TestURLSessionServer(port: UInt16(port), startDelay: startDelay, sendDelay: sendDelay, bodyChunks: bodyChunks)
-                    try test.start(started: condition)
-                    try test.readAndRespond()
-                    test.stop()
-                } catch let e as ServerError {
-                    if e.operation == "bind" { continue }
-                    throw e
-                }
+            while true {
+                let test = try TestURLSessionServer(port: nil, startDelay: startDelay, sendDelay: sendDelay, bodyChunks: bodyChunks)
+                serverPort = Int(test.port)
+                try test.start(started: condition)
+                try test.readAndRespond()
+                serverPort = -2
+                test.stop()
             }
         }
 
diff --git a/TestFoundation/TestAffineTransform.swift b/TestFoundation/TestAffineTransform.swift
index f1d1a51..9a897ad 100644
--- a/TestFoundation/TestAffineTransform.swift
+++ b/TestFoundation/TestAffineTransform.swift
@@ -38,6 +38,9 @@
             ("test_AppendTransform", test_AppendTransform),
             ("test_PrependTransform", test_PrependTransform),
             ("test_TransformComposition", test_TransformComposition),
+            ("test_hashing_identity", test_hashing_identity),
+            ("test_hashing_values", test_hashing_values),
+            ("test_rotation_compose", test_rotation_compose),
             ("test_Equal", test_Equal),
             ("test_NSCoding", test_NSCoding),
         ]
@@ -345,6 +348,16 @@
             XCTAssertEqual(ref.hashValue, val.hashValue)
         }
     }
+
+    func test_rotation_compose() {
+        var t = AffineTransform.identity
+        t.translate(x: 1.0, y: 1.0)
+        t.rotate(byDegrees: 90)
+        t.translate(x: -1.0, y: -1.0)
+        let result = t.transform(NSPoint(x: 1.0, y: 2.0))
+        XCTAssertEqual(0.0, Double(result.x), accuracy: accuracyThreshold)
+        XCTAssertEqual(1.0, Double(result.y), accuracy: accuracyThreshold)
+    }
     
     func test_Equal() {
         let transform = NSAffineTransform()
diff --git a/TestFoundation/TestByteCountFormatter.swift b/TestFoundation/TestByteCountFormatter.swift
index 8046a0f..c077266 100644
--- a/TestFoundation/TestByteCountFormatter.swift
+++ b/TestFoundation/TestByteCountFormatter.swift
@@ -49,7 +49,7 @@
     
     func test_DefaultValues() {
         let formatter = ByteCountFormatter()
-        XCTAssertEqual(formatter.allowedUnits, ByteCountFormatter.Units.useDefault)
+        XCTAssertEqual(formatter.allowedUnits, [])
         XCTAssertEqual(formatter.countStyle, ByteCountFormatter.CountStyle.file)
         XCTAssertEqual(formatter.allowsNonnumericFormatting, true)
         XCTAssertEqual(formatter.includesUnit, true)
@@ -68,7 +68,7 @@
         formatter.allowedUnits = .useGB
         XCTAssertEqual(formatter.string(fromByteCount: 0), "Zero KB")
         
-        formatter.allowedUnits = .useDefault
+        formatter.allowedUnits = []
         formatter.allowsNonnumericFormatting = false
         XCTAssertEqual(formatter.string(fromByteCount: 0), "0 bytes")
         
@@ -91,7 +91,7 @@
         formatter.allowedUnits = .useGB
         XCTAssertEqual(formatter.string(fromByteCount: 1), "0 GB")
         
-        formatter.allowedUnits = .useDefault
+        formatter.allowedUnits = []
         formatter.isAdaptive = false
         XCTAssertEqual(formatter.string(fromByteCount: 1), "1 byte")
         
@@ -365,7 +365,7 @@
         XCTAssertEqual(formatter.string(fromByteCount: 11999), "12.0 KB")
         XCTAssertEqual(formatter.string(fromByteCount: 900000), "900 KB")
         XCTAssertEqual(formatter.string(fromByteCount: 12345678), "12.3 MB")
-        XCTAssertEqual(formatter.string(fromByteCount: 123456789), "123.5 MB")
+        XCTAssertEqual(formatter.string(fromByteCount: 123456789), "123 MB")
         XCTAssertEqual(formatter.string(fromByteCount: 1234567898), "1.23 GB")
         XCTAssertEqual(formatter.string(fromByteCount: 12345678987), "12.3 GB")
     }
diff --git a/TestFoundation/TestCalendar.swift b/TestFoundation/TestCalendar.swift
index 07198f2..0e90ace 100644
--- a/TestFoundation/TestCalendar.swift
+++ b/TestFoundation/TestCalendar.swift
@@ -14,7 +14,6 @@
 import SwiftFoundation
 import SwiftXCTest
 #endif
-import CoreFoundation
 
 class TestCalendar: XCTestCase {
     
diff --git a/TestFoundation/TestCodable.swift b/TestFoundation/TestCodable.swift
index c43becf..f1fb7d6 100644
--- a/TestFoundation/TestCodable.swift
+++ b/TestFoundation/TestCodable.swift
@@ -399,6 +399,13 @@
         let components = calendar.dateComponents(dateComponents, from: Date(timeIntervalSince1970: 1501283776))
         expectRoundTripEqualityThroughJSON(for: components)
     }
+
+    // MARK: - Measurement
+    func test_Measurement_JSON() {
+        expectRoundTripEqualityThroughJSON(for: Measurement(value: 42, unit: UnitAcceleration.metersPerSecondSquared))
+        expectRoundTripEqualityThroughJSON(for: Measurement(value: 42, unit: UnitMass.kilograms))
+        expectRoundTripEqualityThroughJSON(for: Measurement(value: 42, unit: UnitLength.miles))
+    }
 }
 
 extension TestCodable {
@@ -420,6 +427,7 @@
             ("test_TimeZone_JSON", test_TimeZone_JSON),
             ("test_Calendar_JSON", test_Calendar_JSON),
             ("test_DateComponents_JSON", test_DateComponents_JSON),
+            ("test_Measurement_JSON", test_Measurement_JSON),
         ]
     }
 }
diff --git a/TestFoundation/TestDateFormatter.swift b/TestFoundation/TestDateFormatter.swift
index afcebaf..f21ecb1 100644
--- a/TestFoundation/TestDateFormatter.swift
+++ b/TestFoundation/TestDateFormatter.swift
@@ -29,6 +29,7 @@
             ("test_dateStyleFull",     test_dateStyleFull),
             ("test_customDateFormat", test_customDateFormat),
             ("test_setLocalizedDateFormatFromTemplate", test_setLocalizedDateFormatFromTemplate),
+            ("test_dateFormatString", test_dateFormatString),
         ]
     }
     
@@ -295,4 +296,45 @@
         XCTAssertEqual(f.dateFormat, dateFormat)
     }
 
+    func test_dateFormatString() {
+        let f = DateFormatter()
+        f.timeZone = TimeZone(abbreviation: DEFAULT_TIMEZONE)
+        
+        //.full cases have been commented out as they're not working correctly on Linux
+        let formats: [String: (DateFormatter.Style, DateFormatter.Style)] = [
+            "": (.none, .none),
+            "h:mm a": (.none, .short),
+            "h:mm:ss a": (.none, .medium),
+            "h:mm:ss a z": (.none, .long),
+//            "h:mm:ss a zzzz": (.none, .full),
+            "M/d/yy": (.short, .none),
+            "M/d/yy, h:mm a": (.short, .short),
+            "M/d/yy, h:mm:ss a": (.short, .medium),
+            "M/d/yy, h:mm:ss a z": (.short, .long),
+//            "M/d/yy, h:mm:ss a zzzz": (.short, .full),
+            "MMM d, y": (.medium, .none),
+            //These tests currently fail, there seems to be a difference in behavior in the CoreFoundation methods called to construct the format strings.
+//            "MMM d, y 'at' h:mm a": (.medium, .short),
+//            "MMM d, y 'at' h:mm:ss a": (.medium, .medium),
+//            "MMM d, y 'at' h:mm:ss a z": (.medium, .long),
+//            "MMM d, y 'at' h:mm:ss a zzzz": (.medium, .full),
+            "MMMM d, y": (.long, .none),
+            "MMMM d, y 'at' h:mm a": (.long, .short),
+            "MMMM d, y 'at' h:mm:ss a": (.long, .medium),
+            "MMMM d, y 'at' h:mm:ss a z": (.long, .long),
+//            "MMMM d, y 'at' h:mm:ss a zzzz": (.long, .full),
+//            "EEEE, MMMM d, y": (.full, .none),
+//            "EEEE, MMMM d, y 'at' h:mm a": (.full, .short),
+//            "EEEE, MMMM d, y 'at' h:mm:ss a": (.full, .medium),
+//            "EEEE, MMMM d, y 'at' h:mm:ss a z": (.full, .long),
+//            "EEEE, MMMM d, y 'at' h:mm:ss a zzzz": (.full, .full),
+        ]
+        
+        for (dateFormat, styles) in formats {
+            f.dateStyle = styles.0
+            f.timeStyle = styles.1
+            
+            XCTAssertEqual(f.dateFormat, dateFormat)
+        }
+    }
 }
diff --git a/TestFoundation/TestDecimal.swift b/TestFoundation/TestDecimal.swift
index 3839d53..f34d9f7 100644
--- a/TestFoundation/TestDecimal.swift
+++ b/TestFoundation/TestDecimal.swift
@@ -289,6 +289,9 @@
         XCTAssertEqual(.minus, d.sign)
         d.negate()
         XCTAssertEqual(.plus, d.sign)
+        var e = Decimal(0)
+        e.negate()
+        XCTAssertEqual(e, 0)
         XCTAssertTrue(Decimal(3.5).isEqual(to: Decimal(3.5)))
         XCTAssertTrue(Decimal.nan.isEqual(to: Decimal.nan))
         XCTAssertTrue(Decimal(1.28).isLess(than: Decimal(2.24)))
@@ -404,7 +407,7 @@
         XCTAssertNotEqual(.noError, NSDecimalMultiplyByPowerOf10(&result, &NaN, 5, .plain))
         XCTAssertTrue(NSDecimalIsNotANumber(&result), "NaN e5")
 
-        XCTAssertFalse(Double(NSDecimalNumber(decimal:Decimal(0))).isNaN)
+        XCTAssertFalse(Double(truncating: NSDecimalNumber(decimal: Decimal(0))).isNaN)
     }
 
     func test_NegativeAndZeroMultiplication() {
diff --git a/TestFoundation/TestFileManager.swift b/TestFoundation/TestFileManager.swift
index a9cb932..9cc1e3e 100644
--- a/TestFoundation/TestFileManager.swift
+++ b/TestFoundation/TestFileManager.swift
@@ -53,10 +53,10 @@
         // Ensure attempting to create the directory again fails gracefully.
         XCTAssertNil(try? fm.createDirectory(atPath: path, withIntermediateDirectories:false, attributes:nil))
 
-        var isDir = false
+        var isDir: ObjCBool = false
         let exists = fm.fileExists(atPath: path, isDirectory: &isDir)
         XCTAssertTrue(exists)
-        XCTAssertTrue(isDir)
+        XCTAssertTrue(isDir.boolValue)
 
         do {
             try fm.removeItem(atPath: path)
@@ -74,10 +74,10 @@
         
         XCTAssertTrue(fm.createFile(atPath: path, contents: Data(), attributes: nil))
         
-        var isDir = false
+        var isDir: ObjCBool = false
         let exists = fm.fileExists(atPath: path, isDirectory: &isDir)
         XCTAssertTrue(exists)
-        XCTAssertFalse(isDir)
+        XCTAssertFalse(isDir.boolValue)
         
         do {
             try fm.removeItem(atPath: path)
@@ -467,9 +467,9 @@
         }
         
         func directoryExists(atPath path: String) -> Bool {
-            var isDir = false
+            var isDir: ObjCBool = false
             let exists = fm.fileExists(atPath: path, isDirectory: &isDir)
-            return exists && isDir
+            return exists && isDir.boolValue
         }
         
         func createDirectory(atPath path: String) {
diff --git a/TestFoundation/TestHTTPCookieStorage.swift b/TestFoundation/TestHTTPCookieStorage.swift
index 040d6e1..f65a01e 100644
--- a/TestFoundation/TestHTTPCookieStorage.swift
+++ b/TestFoundation/TestHTTPCookieStorage.swift
@@ -253,7 +253,7 @@
         let bundlePath = Bundle.main.bundlePath
         var bundleName = "/" + bundlePath.components(separatedBy: "/").last!
         if let range = bundleName.range(of: ".", options: String.CompareOptions.backwards, range: nil, locale: nil) {
-            bundleName = bundleName.substring(to: range.lowerBound)
+            bundleName = String(bundleName[..<range.lowerBound])
         }
         if let xdg_data_home = getenv("XDG_DATA_HOME") {
             destPath = String(utf8String: xdg_data_home)! + bundleName + "/.cookies.shared"
@@ -261,7 +261,7 @@
             destPath = NSHomeDirectory() + "/.local/share" + bundleName + "/.cookies.shared"
         }
         let fm = FileManager.default
-        var isDir = false
+        var isDir: ObjCBool = false
         let exists = fm.fileExists(atPath: destPath, isDirectory: &isDir)
         XCTAssertTrue(exists)
         //Test by setting the environmental variable
@@ -274,7 +274,7 @@
         let exeName = "/xdgTestHelper/xdgTestHelper"
         #endif
 
-        task.launchPath = bundlePath.substring(to: pathIndex!) + exeName
+        task.launchPath = bundlePath[..<pathIndex!] + exeName
         var environment = ProcessInfo.processInfo.environment
         let testPath = NSHomeDirectory() + "/TestXDG"
         environment["XDG_DATA_HOME"] = testPath
diff --git a/TestFoundation/TestJSONEncoder.swift b/TestFoundation/TestJSONEncoder.swift
index 8631442..76dc81a 100644
--- a/TestFoundation/TestJSONEncoder.swift
+++ b/TestFoundation/TestJSONEncoder.swift
@@ -401,6 +401,34 @@
         test_codingOf(value: URL(string: "https://swift.org")!, toAndFrom: "\"https://swift.org\"")
     }
 
+
+    // UInt and Int
+    func test_codingOfUIntMinMax() {
+
+        struct MyValue: Codable {
+            let int64Min = Int64.min
+            let int64Max = Int64.max
+            let uint64Min = UInt64.min
+            let uint64Max = UInt64.max
+        }
+
+        func compareJSON(_ s1: String, _ s2: String) {
+            let ss1 = s1.trimmingCharacters(in: CharacterSet(charactersIn: "{}")).split(separator: Character(",")).sorted()
+            let ss2 = s2.trimmingCharacters(in: CharacterSet(charactersIn: "{}")).split(separator: Character(",")).sorted()
+            XCTAssertEqual(ss1, ss2)
+        }
+
+        do {
+            let encoder = JSONEncoder()
+            let myValue = MyValue()
+            let result = try encoder.encode(myValue)
+            let r = String(data: result, encoding: .utf8) ?? "nil"
+            compareJSON(r, "{\"uint64Min\":0,\"uint64Max\":18446744073709551615,\"int64Min\":-9223372036854775808,\"int64Max\":9223372036854775807}")
+        } catch {
+            XCTFail(String(describing: error))
+        }
+    }
+
     // MARK: - Helper Functions
     private var _jsonEmptyDictionary: Data {
         return "{}".data(using: .utf8)!
@@ -418,8 +446,8 @@
                                    outputFormatting: JSONEncoder.OutputFormatting = [],
                                    dateEncodingStrategy: JSONEncoder.DateEncodingStrategy = .deferredToDate,
                                    dateDecodingStrategy: JSONDecoder.DateDecodingStrategy = .deferredToDate,
-                                   dataEncodingStrategy: JSONEncoder.DataEncodingStrategy = .base64Encode,
-                                   dataDecodingStrategy: JSONDecoder.DataDecodingStrategy = .base64Decode,
+                                   dataEncodingStrategy: JSONEncoder.DataEncodingStrategy = .base64,
+                                   dataDecodingStrategy: JSONDecoder.DataDecodingStrategy = .base64,
                                    nonConformingFloatEncodingStrategy: JSONEncoder.NonConformingFloatEncodingStrategy = .throw,
                                    nonConformingFloatDecodingStrategy: JSONDecoder.NonConformingFloatDecodingStrategy = .throw) where T : Codable, T : Equatable {
         var payload: Data! = nil
@@ -986,6 +1014,7 @@
             ("test_codingOfUInt64", test_codingOfUInt64),
             ("test_codingOfInt", test_codingOfInt),
             ("test_codingOfUInt", test_codingOfUInt),
+            ("test_codingOfUIntMinMax", test_codingOfUIntMinMax),
             ("test_codingOfFloat", test_codingOfFloat),
             ("test_codingOfDouble", test_codingOfDouble),
             ("test_codingOfString", test_codingOfString),
diff --git a/TestFoundation/TestJSONSerialization.swift b/TestFoundation/TestJSONSerialization.swift
index 61e23c1..dabcf7f 100644
--- a/TestFoundation/TestJSONSerialization.swift
+++ b/TestFoundation/TestJSONSerialization.swift
@@ -829,6 +829,7 @@
         return [
             ("test_isValidJSONObjectTrue", test_isValidJSONObjectTrue),
             ("test_isValidJSONObjectFalse", test_isValidJSONObjectFalse),
+            ("test_validNumericJSONObjects", test_validNumericJSONObjects)
         ]
     }
 
@@ -924,6 +925,36 @@
         }
     }
 
+    func test_validNumericJSONObjects() {
+        // All of the numeric types supported by JSONSerialization
+        XCTAssertTrue(JSONSerialization.isValidJSONObject([nil, NSNull()]))
+        XCTAssertTrue(JSONSerialization.isValidJSONObject([true, false]))
+        XCTAssertTrue(JSONSerialization.isValidJSONObject([Int.min, Int8.min, Int16.min, Int32.min, Int64.min]))
+        XCTAssertTrue(JSONSerialization.isValidJSONObject([UInt.min, UInt8.min, UInt16.min, UInt32.min, UInt64.min]))
+        XCTAssertTrue(JSONSerialization.isValidJSONObject([Float.leastNonzeroMagnitude, Double.leastNonzeroMagnitude]))
+
+        XCTAssertTrue(JSONSerialization.isValidJSONObject([NSNumber(value: true), NSNumber(value: Float.greatestFiniteMagnitude), NSNumber(value: Double.greatestFiniteMagnitude)]))
+        XCTAssertTrue(JSONSerialization.isValidJSONObject([NSNumber(value: Int.max), NSNumber(value: Int8.max), NSNumber(value: Int16.max), NSNumber(value: Int32.max), NSNumber(value: Int64.max)]))
+        XCTAssertTrue(JSONSerialization.isValidJSONObject([NSNumber(value: UInt.max), NSNumber(value: UInt8.max), NSNumber(value: UInt16.max), NSNumber(value: UInt32.max), NSNumber(value: UInt64.max)]))
+        XCTAssertTrue(JSONSerialization.isValidJSONObject([NSDecimalNumber(booleanLiteral: true), NSDecimalNumber(decimal: Decimal.greatestFiniteMagnitude), NSDecimalNumber(floatLiteral: Double.greatestFiniteMagnitude), NSDecimalNumber(integerLiteral: Int.min)]))
+        XCTAssertTrue(JSONSerialization.isValidJSONObject([Decimal(123), Decimal(Double.leastNonzeroMagnitude)]))
+
+        XCTAssertFalse(JSONSerialization.isValidJSONObject(Float.nan))
+        XCTAssertFalse(JSONSerialization.isValidJSONObject(Float.infinity))
+        XCTAssertFalse(JSONSerialization.isValidJSONObject(-Float.infinity))
+        XCTAssertFalse(JSONSerialization.isValidJSONObject(NSNumber(value: Float.nan)))
+        XCTAssertFalse(JSONSerialization.isValidJSONObject(NSNumber(value: Float.infinity)))
+        XCTAssertFalse(JSONSerialization.isValidJSONObject(NSNumber(value: -Float.infinity)))
+
+        XCTAssertFalse(JSONSerialization.isValidJSONObject(Double.nan))
+        XCTAssertFalse(JSONSerialization.isValidJSONObject(Double.infinity))
+        XCTAssertFalse(JSONSerialization.isValidJSONObject(-Double.infinity))
+        XCTAssertFalse(JSONSerialization.isValidJSONObject(NSNumber(value: Double.nan)))
+        XCTAssertFalse(JSONSerialization.isValidJSONObject(NSNumber(value: Double.infinity)))
+        XCTAssertFalse(JSONSerialization.isValidJSONObject(NSNumber(value: -Double.infinity)))
+
+        XCTAssertFalse(JSONSerialization.isValidJSONObject(NSDecimalNumber(decimal: Decimal(floatLiteral: Double.nan))))
+    }
 }
 
 // MARK: - serializationTests
@@ -941,6 +972,14 @@
             ("test_serialize_IntMin", test_serialize_IntMin),
             ("test_serialize_UIntMax", test_serialize_UIntMax),
             ("test_serialize_UIntMin", test_serialize_UIntMin),
+            ("test_serialize_8BitSizes", test_serialize_8BitSizes),
+            ("test_serialize_16BitSizes", test_serialize_16BitSizes),
+            ("test_serialize_32BitSizes", test_serialize_32BitSizes),
+            ("test_serialize_64BitSizes", test_serialize_64BitSizes),
+            ("test_serialize_Float", test_serialize_Float),
+            ("test_serialize_Double", test_serialize_Double),
+            ("test_serialize_Decimal", test_serialize_Decimal),
+            ("test_serialize_NSDecimalNumber", test_serialize_NSDecimalNumber),
             ("test_serialize_stringEscaping", test_serialize_stringEscaping),
             ("test_jsonReadingOffTheEndOfBuffers", test_jsonReadingOffTheEndOfBuffers),
             ("test_jsonObjectToOutputStreamBuffer", test_jsonObjectToOutputStreamBuffer),
@@ -950,6 +989,7 @@
             ("test_serialize_dictionaryWithDecimal", test_serialize_dictionaryWithDecimal),
             ("test_serializeDecimalNumberJSONObject", test_serializeDecimalNumberJSONObject),
             ("test_serializeSortedKeys", test_serializeSortedKeys),
+            ("test_serializePrettyPrinted", test_serializePrettyPrinted),
         ]
     }
 
@@ -1172,7 +1212,80 @@
         let json: [Any] = [UInt.min]
         XCTAssertEqual(try trySerialize(json), "[\(UInt.min)]")
     }
-    
+
+    func test_serialize_8BitSizes() {
+        let json1 = [Int8.min, Int8(-1), Int8(0), Int8(1), Int8.max]
+        XCTAssertEqual(try trySerialize(json1), "[-128,-1,0,1,127]")
+        let json2 = [UInt8.min, UInt8(0), UInt8(1), UInt8.max]
+        XCTAssertEqual(try trySerialize(json2), "[0,0,1,255]")
+    }
+
+    func test_serialize_16BitSizes() {
+        let json1 = [Int16.min, Int16(-1), Int16(0), Int16(1), Int16.max]
+        XCTAssertEqual(try trySerialize(json1), "[-32768,-1,0,1,32767]")
+        let json2 = [UInt16.min, UInt16(0), UInt16(1), UInt16.max]
+        XCTAssertEqual(try trySerialize(json2), "[0,0,1,65535]")
+    }
+
+    func test_serialize_32BitSizes() {
+        let json1 = [Int32.min, Int32(-1), Int32(0), Int32(1), Int32.max]
+        XCTAssertEqual(try trySerialize(json1), "[-2147483648,-1,0,1,2147483647]")
+        let json2 = [UInt32.min, UInt32(0), UInt32(1), UInt32.max]
+        XCTAssertEqual(try trySerialize(json2), "[0,0,1,4294967295]")
+    }
+
+    func test_serialize_64BitSizes() {
+        let json1 = [Int64.min, Int64(-1), Int64(0), Int64(1), Int64.max]
+        XCTAssertEqual(try trySerialize(json1), "[-9223372036854775808,-1,0,1,9223372036854775807]")
+        let json2 = [UInt64.min, UInt64(0), UInt64(1), UInt64.max]
+        XCTAssertEqual(try trySerialize(json2), "[0,0,1,18446744073709551615]")
+    }
+
+    func test_serialize_Float() {
+        XCTAssertEqual(try trySerialize([-Float.leastNonzeroMagnitude, Float.leastNonzeroMagnitude]), "[-0,0]")
+        XCTAssertEqual(try trySerialize([-Float.greatestFiniteMagnitude]), "[-340282346638529000000000000000000000000]")
+        XCTAssertEqual(try trySerialize([Float.greatestFiniteMagnitude]), "[340282346638529000000000000000000000000]")
+        XCTAssertEqual(try trySerialize([Float(-1), Float.leastNonzeroMagnitude, Float(1)]), "[-1,0,1]")
+    }
+
+    func test_serialize_Double() {
+        XCTAssertEqual(try trySerialize([-Double.leastNonzeroMagnitude, Double.leastNonzeroMagnitude]), "[-0,0]")
+        XCTAssertEqual(try trySerialize([-Double.leastNormalMagnitude, Double.leastNormalMagnitude]), "[-0,0]")
+        XCTAssertEqual(try trySerialize([-Double.greatestFiniteMagnitude]), "[-179769313486232000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000]")
+        XCTAssertEqual(try trySerialize([Double.greatestFiniteMagnitude]), "[179769313486232000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000]")
+        XCTAssertEqual(try trySerialize([Double(-1.0),  Double(1.0)]), "[-1,1]")
+    }
+
+    func test_serialize_Decimal() {
+        XCTAssertEqual(try trySerialize([-Decimal.leastFiniteMagnitude]), "[3402823669209384634633746074317682114550000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000]")
+        XCTAssertEqual(try trySerialize([Decimal.leastFiniteMagnitude]), "[-3402823669209384634633746074317682114550000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000]")
+        XCTAssertEqual(try trySerialize([-Decimal.leastNonzeroMagnitude]), "[-0.0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001]")
+        XCTAssertEqual(try trySerialize([Decimal.leastNonzeroMagnitude]), "[0.0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001]")
+        XCTAssertEqual(try trySerialize([-Decimal.greatestFiniteMagnitude]), "[-3402823669209384634633746074317682114550000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000]")
+        XCTAssertEqual(try trySerialize([Decimal.greatestFiniteMagnitude]), "[3402823669209384634633746074317682114550000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000]")
+        XCTAssertEqual(try trySerialize([Decimal(Int8.min), Decimal(Int8(0)), Decimal(Int8.max)]), "[-128,0,127]")
+        XCTAssertEqual(try trySerialize([Decimal(string: "-0.0"), Decimal(string: "0.000"), Decimal(string: "1.0000")]), "[0,0,1]")
+    }
+
+    func test_serialize_NSDecimalNumber() {
+        let dn0: [Any] = [NSDecimalNumber(floatLiteral: -Double.leastNonzeroMagnitude)]
+        let dn1: [Any] = [NSDecimalNumber(floatLiteral: Double.leastNonzeroMagnitude)]
+        let dn2: [Any] = [NSDecimalNumber(floatLiteral: -Double.leastNormalMagnitude)]
+        let dn3: [Any] = [NSDecimalNumber(floatLiteral: Double.leastNormalMagnitude)]
+        let dn4: [Any] = [NSDecimalNumber(floatLiteral: -Double.greatestFiniteMagnitude)]
+        let dn5: [Any] = [NSDecimalNumber(floatLiteral: Double.greatestFiniteMagnitude)]
+
+        XCTAssertEqual(try trySerialize(dn0), "[-0.00000000000000000000000000000000000000000000000000000000000000000004940656458412464128]")
+        XCTAssertEqual(try trySerialize(dn1), "[0.00000000000000000000000000000000000000000000000000000000000000000004940656458412464128]")
+        XCTAssertEqual(try trySerialize(dn2), "[-0.0000000000000000000000000000000000000000000000000002225073858507201792]")
+        XCTAssertEqual(try trySerialize(dn3), "[0.0000000000000000000000000000000000000000000000000002225073858507201792]")
+        XCTAssertEqual(try trySerialize(dn4), "[-17976931348623167488000000000000000000000000000000000]")
+        XCTAssertEqual(try trySerialize(dn5), "[17976931348623167488000000000000000000000000000000000]")
+        XCTAssertEqual(try trySerialize([NSDecimalNumber(string: "0.0001"), NSDecimalNumber(string: "0.00"), NSDecimalNumber(string: "-0.0")]), "[0.0001,0,0]")
+        XCTAssertEqual(try trySerialize([NSDecimalNumber(integerLiteral: Int(Int16.min)), NSDecimalNumber(integerLiteral: 0), NSDecimalNumber(integerLiteral: Int(Int16.max))]), "[-32768,0,32767]")
+        XCTAssertEqual(try trySerialize([NSDecimalNumber(booleanLiteral: true), NSDecimalNumber(booleanLiteral: false)]), "[1,0]")
+    }
+
     func test_serialize_stringEscaping() {
         var json = ["foo"]
         XCTAssertEqual(try trySerialize(json), "[\"foo\"]")
@@ -1367,6 +1480,11 @@
         XCTAssertEqual(try trySerialize(dict, options: .sortedKeys), "{\"a\":{\"a\":1,\"b\":1,\"c\":1},\"b\":{\"a\":1,\"b\":1,\"c\":1},\"c\":{\"a\":1,\"b\":1,\"c\":1}}")
     }
 
+    func test_serializePrettyPrinted() {
+        let dictionary = ["key": 4]
+        XCTAssertEqual(try trySerialize(dictionary, options: .prettyPrinted), "{\n  \"key\" : 4\n}")
+    }
+
     fileprivate func createTestFile(_ path: String,_contents: Data) -> String? {
         let tempDir = NSTemporaryDirectory() + "TestFoundation_Playground_" + NSUUID().uuidString + "/"
         do {
diff --git a/TestFoundation/TestNSData.swift b/TestFoundation/TestNSData.swift
index 020b2c1..3bacd6e 100644
--- a/TestFoundation/TestNSData.swift
+++ b/TestFoundation/TestNSData.swift
@@ -17,7 +17,171 @@
 
 class TestNSData: XCTestCase {
     
-
+    class AllOnesImmutableData : NSData {
+        private var _length : Int
+        var _pointer : UnsafeMutableBufferPointer<UInt8>? {
+            willSet {
+                if let p = _pointer { free(p.baseAddress) }
+            }
+        }
+        
+        init(length : Int) {
+            _length = length
+            super.init(bytes: nil, length: 0, copy: false, deallocator: nil)
+            _length = length
+        }
+        
+        required init?(coder aDecoder: NSCoder) {
+            // Not tested
+            fatalError()
+        }
+        
+        deinit {
+            if let p = _pointer {
+                free(p.baseAddress)
+            }
+        }
+        
+        override var length : Int {
+            get {
+                return _length
+            }
+        }
+        
+        override var bytes : UnsafeRawPointer {
+            if let d = _pointer {
+                return UnsafeRawPointer(d.baseAddress!)
+            } else {
+                // Need to allocate the buffer now.
+                // It doesn't matter if the buffer is uniquely referenced or not here.
+                let buffer = malloc(length)
+                memset(buffer!, 1, length)
+                let bytePtr = buffer!.bindMemory(to: UInt8.self, capacity: length)
+                let result = UnsafeMutableBufferPointer(start: bytePtr, count: length)
+                _pointer = result
+                return UnsafeRawPointer(result.baseAddress!)
+            }
+        }
+        
+        override func getBytes(_ buffer: UnsafeMutableRawPointer, length: Int) {
+            if let d = _pointer {
+                // Get the real data from the buffer
+                memmove(buffer, d.baseAddress!, length)
+            } else {
+                // A more efficient implementation of getBytes in the case where no one has asked for our backing bytes
+                memset(buffer, 1, length)
+            }
+        }
+        
+        override func copy(with zone: NSZone? = nil) -> Any {
+            return self
+        }
+        
+        override func mutableCopy(with zone: NSZone? = nil) -> Any {
+            return AllOnesData(length: _length)
+        }
+    }
+    
+    
+    class AllOnesData : NSMutableData {
+        
+        private var _length : Int
+        var _pointer : UnsafeMutableBufferPointer<UInt8>? {
+            willSet {
+                if let p = _pointer { free(p.baseAddress) }
+            }
+        }
+        
+        /*override*/ init(length : Int) {
+            _length = length
+            super.init(bytes: nil, length: 0, copy: false, deallocator: nil)
+            _length = length
+        }
+        
+        required init?(coder aDecoder: NSCoder) {
+            // Not tested
+            fatalError()
+        }
+        
+        deinit {
+            if let p = _pointer {
+                free(p.baseAddress)
+            }
+        }
+        
+        override var length : Int {
+            get {
+                return _length
+            }
+            set {
+                if let ptr = _pointer {
+                    // Copy the data to our new length buffer
+                    let newBuffer = malloc(newValue)!
+                    if newValue <= _length {
+                        memmove(newBuffer, ptr.baseAddress!, newValue)
+                    } else if newValue > _length {
+                        memmove(newBuffer, ptr.baseAddress!, _length)
+                        memset(newBuffer + _length, 1, newValue - _length)
+                    }
+                    let bytePtr = newBuffer.bindMemory(to: UInt8.self, capacity: newValue)
+                    _pointer = UnsafeMutableBufferPointer(start: bytePtr, count: newValue)
+                }
+                _length = newValue
+            }
+        }
+        
+        override var bytes : UnsafeRawPointer {
+            if let d = _pointer {
+                return UnsafeRawPointer(d.baseAddress!)
+            } else {
+                // Need to allocate the buffer now.
+                // It doesn't matter if the buffer is uniquely referenced or not here.
+                let buffer = malloc(length)
+                memset(buffer!, 1, length)
+                let bytePtr = buffer!.bindMemory(to: UInt8.self, capacity: length)
+                let result = UnsafeMutableBufferPointer(start: bytePtr, count: length)
+                _pointer = result
+                return UnsafeRawPointer(result.baseAddress!)
+            }
+        }
+        
+        override var mutableBytes: UnsafeMutableRawPointer {
+            let newBufferLength = _length
+            let newBuffer = malloc(newBufferLength)
+            if let ptr = _pointer {
+                // Copy the existing data to the new box, then return its pointer
+                memmove(newBuffer!, ptr.baseAddress!, newBufferLength)
+            } else {
+                // Set new data to 1s
+                memset(newBuffer!, 1, newBufferLength)
+            }
+            let bytePtr = newBuffer!.bindMemory(to: UInt8.self, capacity: newBufferLength)
+            let result = UnsafeMutableBufferPointer(start: bytePtr, count: newBufferLength)
+            _pointer = result
+            _length = newBufferLength
+            return UnsafeMutableRawPointer(result.baseAddress!)
+        }
+        
+        override func getBytes(_ buffer: UnsafeMutableRawPointer, length: Int) {
+            if let d = _pointer {
+                // Get the real data from the buffer
+                memmove(buffer, d.baseAddress!, length)
+            } else {
+                // A more efficient implementation of getBytes in the case where no one has asked for our backing bytes
+                memset(buffer, 1, length)
+            }
+        }
+    }
+    
+    var heldData: Data?
+    
+    // this holds a reference while applying the function which forces the internal ref type to become non-uniquely referenced
+    func holdReference(_ data: Data, apply: () -> Void) {
+        heldData = data
+        apply()
+        heldData = nil
+    }
+    
     // MARK: -
     
     // String of course has its own way to get data, but this way tests our own data struct
@@ -37,6 +201,8 @@
             ("test_base64Data_medium", test_base64Data_medium),
             ("test_base64Data_small", test_base64Data_small),
             ("test_openingNonExistentFile", test_openingNonExistentFile),
+            ("test_contentsOfFile", test_contentsOfFile),
+            ("test_contentsOfZeroFile", test_contentsOfZeroFile),
             ("test_basicReadWrite", test_basicReadWrite),
             ("test_bufferSizeCalculation", test_bufferSizeCalculation),
             // ("test_dataHash", test_dataHash),   Disabled due to lack of brdiging in swift runtime -- infinite loops
@@ -98,6 +264,250 @@
             ("test_replaceSubrange", test_replaceSubrange),
             ("test_sliceWithUnsafeBytes", test_sliceWithUnsafeBytes),
             ("test_sliceIteration", test_sliceIteration),
+
+            ("test_validateMutation_withUnsafeMutableBytes", test_validateMutation_withUnsafeMutableBytes),
+            ("test_validateMutation_appendBytes", test_validateMutation_appendBytes),
+            ("test_validateMutation_appendData", test_validateMutation_appendData),
+            ("test_validateMutation_appendBuffer", test_validateMutation_appendBuffer),
+            ("test_validateMutation_appendSequence", test_validateMutation_appendSequence),
+            ("test_validateMutation_appendContentsOf", test_validateMutation_appendContentsOf),
+            ("test_validateMutation_resetBytes", test_validateMutation_resetBytes),
+            ("test_validateMutation_replaceSubrange", test_validateMutation_replaceSubrange),
+            ("test_validateMutation_replaceSubrangeCountableRange", test_validateMutation_replaceSubrangeCountableRange),
+            ("test_validateMutation_replaceSubrangeWithBuffer", test_validateMutation_replaceSubrangeWithBuffer),
+            ("test_validateMutation_replaceSubrangeWithCollection", test_validateMutation_replaceSubrangeWithCollection),
+            ("test_validateMutation_replaceSubrangeWithBytes", test_validateMutation_replaceSubrangeWithBytes),
+            ("test_validateMutation_slice_withUnsafeMutableBytes", test_validateMutation_slice_withUnsafeMutableBytes),
+            ("test_validateMutation_slice_appendBytes", test_validateMutation_slice_appendBytes),
+            ("test_validateMutation_slice_appendData", test_validateMutation_slice_appendData),
+            ("test_validateMutation_slice_appendBuffer", test_validateMutation_slice_appendBuffer),
+            ("test_validateMutation_slice_appendSequence", test_validateMutation_slice_appendSequence),
+            ("test_validateMutation_slice_appendContentsOf", test_validateMutation_slice_appendContentsOf),
+            ("test_validateMutation_slice_resetBytes", test_validateMutation_slice_resetBytes),
+            ("test_validateMutation_slice_replaceSubrange", test_validateMutation_slice_replaceSubrange),
+            ("test_validateMutation_slice_replaceSubrangeCountableRange", test_validateMutation_slice_replaceSubrangeCountableRange),
+            ("test_validateMutation_slice_replaceSubrangeWithBuffer", test_validateMutation_slice_replaceSubrangeWithBuffer),
+            ("test_validateMutation_slice_replaceSubrangeWithCollection", test_validateMutation_slice_replaceSubrangeWithCollection),
+            ("test_validateMutation_slice_replaceSubrangeWithBytes", test_validateMutation_slice_replaceSubrangeWithBytes),
+            ("test_validateMutation_cow_withUnsafeMutableBytes", test_validateMutation_cow_withUnsafeMutableBytes),
+            ("test_validateMutation_cow_appendBytes", test_validateMutation_cow_appendBytes),
+            ("test_validateMutation_cow_appendData", test_validateMutation_cow_appendData),
+            ("test_validateMutation_cow_appendBuffer", test_validateMutation_cow_appendBuffer),
+            ("test_validateMutation_cow_appendSequence", test_validateMutation_cow_appendSequence),
+            ("test_validateMutation_cow_appendContentsOf", test_validateMutation_cow_appendContentsOf),
+            ("test_validateMutation_cow_resetBytes", test_validateMutation_cow_resetBytes),
+            ("test_validateMutation_cow_replaceSubrange", test_validateMutation_cow_replaceSubrange),
+            ("test_validateMutation_cow_replaceSubrangeCountableRange", test_validateMutation_cow_replaceSubrangeCountableRange),
+            ("test_validateMutation_cow_replaceSubrangeWithBuffer", test_validateMutation_cow_replaceSubrangeWithBuffer),
+            ("test_validateMutation_cow_replaceSubrangeWithCollection", test_validateMutation_cow_replaceSubrangeWithCollection),
+            ("test_validateMutation_cow_replaceSubrangeWithBytes", test_validateMutation_cow_replaceSubrangeWithBytes),
+            ("test_validateMutation_slice_cow_withUnsafeMutableBytes", test_validateMutation_slice_cow_withUnsafeMutableBytes),
+            ("test_validateMutation_slice_cow_appendBytes", test_validateMutation_slice_cow_appendBytes),
+            ("test_validateMutation_slice_cow_appendData", test_validateMutation_slice_cow_appendData),
+            ("test_validateMutation_slice_cow_appendBuffer", test_validateMutation_slice_cow_appendBuffer),
+            ("test_validateMutation_slice_cow_appendSequence", test_validateMutation_slice_cow_appendSequence),
+            ("test_validateMutation_slice_cow_appendContentsOf", test_validateMutation_slice_cow_appendContentsOf),
+            ("test_validateMutation_slice_cow_resetBytes", test_validateMutation_slice_cow_resetBytes),
+            ("test_validateMutation_slice_cow_replaceSubrange", test_validateMutation_slice_cow_replaceSubrange),
+            ("test_validateMutation_slice_cow_replaceSubrangeCountableRange", test_validateMutation_slice_cow_replaceSubrangeCountableRange),
+            ("test_validateMutation_slice_cow_replaceSubrangeWithBuffer", test_validateMutation_slice_cow_replaceSubrangeWithBuffer),
+            ("test_validateMutation_slice_cow_replaceSubrangeWithCollection", test_validateMutation_slice_cow_replaceSubrangeWithCollection),
+            ("test_validateMutation_slice_cow_replaceSubrangeWithBytes", test_validateMutation_slice_cow_replaceSubrangeWithBytes),
+            ("test_validateMutation_immutableBacking_withUnsafeMutableBytes", test_validateMutation_immutableBacking_withUnsafeMutableBytes),
+            ("test_validateMutation_immutableBacking_appendBytes", test_validateMutation_immutableBacking_appendBytes),
+            ("test_validateMutation_immutableBacking_appendData", test_validateMutation_immutableBacking_appendData),
+            ("test_validateMutation_immutableBacking_appendBuffer", test_validateMutation_immutableBacking_appendBuffer),
+            ("test_validateMutation_immutableBacking_appendSequence", test_validateMutation_immutableBacking_appendSequence),
+            ("test_validateMutation_immutableBacking_appendContentsOf", test_validateMutation_immutableBacking_appendContentsOf),
+            ("test_validateMutation_immutableBacking_resetBytes", test_validateMutation_immutableBacking_resetBytes),
+            ("test_validateMutation_immutableBacking_replaceSubrange", test_validateMutation_immutableBacking_replaceSubrange),
+            ("test_validateMutation_immutableBacking_replaceSubrangeCountableRange", test_validateMutation_immutableBacking_replaceSubrangeCountableRange),
+            ("test_validateMutation_immutableBacking_replaceSubrangeWithBuffer", test_validateMutation_immutableBacking_replaceSubrangeWithBuffer),
+            ("test_validateMutation_immutableBacking_replaceSubrangeWithCollection", test_validateMutation_immutableBacking_replaceSubrangeWithCollection),
+            ("test_validateMutation_immutableBacking_replaceSubrangeWithBytes", test_validateMutation_immutableBacking_replaceSubrangeWithBytes),
+            ("test_validateMutation_slice_immutableBacking_withUnsafeMutableBytes", test_validateMutation_slice_immutableBacking_withUnsafeMutableBytes),
+            ("test_validateMutation_slice_immutableBacking_appendBytes", test_validateMutation_slice_immutableBacking_appendBytes),
+            ("test_validateMutation_slice_immutableBacking_appendData", test_validateMutation_slice_immutableBacking_appendData),
+            ("test_validateMutation_slice_immutableBacking_appendBuffer", test_validateMutation_slice_immutableBacking_appendBuffer),
+            ("test_validateMutation_slice_immutableBacking_appendSequence", test_validateMutation_slice_immutableBacking_appendSequence),
+            ("test_validateMutation_slice_immutableBacking_appendContentsOf", test_validateMutation_slice_immutableBacking_appendContentsOf),
+            ("test_validateMutation_slice_immutableBacking_resetBytes", test_validateMutation_slice_immutableBacking_resetBytes),
+            ("test_validateMutation_slice_immutableBacking_replaceSubrange", test_validateMutation_slice_immutableBacking_replaceSubrange),
+            ("test_validateMutation_slice_immutableBacking_replaceSubrangeCountableRange", test_validateMutation_slice_immutableBacking_replaceSubrangeCountableRange),
+            ("test_validateMutation_slice_immutableBacking_replaceSubrangeWithBuffer", test_validateMutation_slice_immutableBacking_replaceSubrangeWithBuffer),
+            ("test_validateMutation_slice_immutableBacking_replaceSubrangeWithCollection", test_validateMutation_slice_immutableBacking_replaceSubrangeWithCollection),
+            ("test_validateMutation_slice_immutableBacking_replaceSubrangeWithBytes", test_validateMutation_slice_immutableBacking_replaceSubrangeWithBytes),
+            ("test_validateMutation_cow_immutableBacking_withUnsafeMutableBytes", test_validateMutation_cow_immutableBacking_withUnsafeMutableBytes),
+            ("test_validateMutation_cow_immutableBacking_appendBytes", test_validateMutation_cow_immutableBacking_appendBytes),
+            ("test_validateMutation_cow_immutableBacking_appendData", test_validateMutation_cow_immutableBacking_appendData),
+            ("test_validateMutation_cow_immutableBacking_appendBuffer", test_validateMutation_cow_immutableBacking_appendBuffer),
+            ("test_validateMutation_cow_immutableBacking_appendSequence", test_validateMutation_cow_immutableBacking_appendSequence),
+            ("test_validateMutation_cow_immutableBacking_appendContentsOf", test_validateMutation_cow_immutableBacking_appendContentsOf),
+            ("test_validateMutation_cow_immutableBacking_resetBytes", test_validateMutation_cow_immutableBacking_resetBytes),
+            ("test_validateMutation_cow_immutableBacking_replaceSubrange", test_validateMutation_cow_immutableBacking_replaceSubrange),
+            ("test_validateMutation_cow_immutableBacking_replaceSubrangeCountableRange", test_validateMutation_cow_immutableBacking_replaceSubrangeCountableRange),
+            ("test_validateMutation_cow_immutableBacking_replaceSubrangeWithBuffer", test_validateMutation_cow_immutableBacking_replaceSubrangeWithBuffer),
+            ("test_validateMutation_cow_immutableBacking_replaceSubrangeWithCollection", test_validateMutation_cow_immutableBacking_replaceSubrangeWithCollection),
+            ("test_validateMutation_cow_immutableBacking_replaceSubrangeWithBytes", test_validateMutation_cow_immutableBacking_replaceSubrangeWithBytes),
+            ("test_validateMutation_slice_cow_immutableBacking_withUnsafeMutableBytes", test_validateMutation_slice_cow_immutableBacking_withUnsafeMutableBytes),
+            ("test_validateMutation_slice_cow_immutableBacking_appendBytes", test_validateMutation_slice_cow_immutableBacking_appendBytes),
+            ("test_validateMutation_slice_cow_immutableBacking_appendData", test_validateMutation_slice_cow_immutableBacking_appendData),
+            ("test_validateMutation_slice_cow_immutableBacking_appendBuffer", test_validateMutation_slice_cow_immutableBacking_appendBuffer),
+            ("test_validateMutation_slice_cow_immutableBacking_appendSequence", test_validateMutation_slice_cow_immutableBacking_appendSequence),
+            ("test_validateMutation_slice_cow_immutableBacking_appendContentsOf", test_validateMutation_slice_cow_immutableBacking_appendContentsOf),
+            ("test_validateMutation_slice_cow_immutableBacking_resetBytes", test_validateMutation_slice_cow_immutableBacking_resetBytes),
+            ("test_validateMutation_slice_cow_immutableBacking_replaceSubrange", test_validateMutation_slice_cow_immutableBacking_replaceSubrange),
+            ("test_validateMutation_slice_cow_immutableBacking_replaceSubrangeCountableRange", test_validateMutation_slice_cow_immutableBacking_replaceSubrangeCountableRange),
+            ("test_validateMutation_slice_cow_immutableBacking_replaceSubrangeWithBuffer", test_validateMutation_slice_cow_immutableBacking_replaceSubrangeWithBuffer),
+            ("test_validateMutation_slice_cow_immutableBacking_replaceSubrangeWithCollection", test_validateMutation_slice_cow_immutableBacking_replaceSubrangeWithCollection),
+            ("test_validateMutation_slice_cow_immutableBacking_replaceSubrangeWithBytes", test_validateMutation_slice_cow_immutableBacking_replaceSubrangeWithBytes),
+            ("test_validateMutation_mutableBacking_withUnsafeMutableBytes", test_validateMutation_mutableBacking_withUnsafeMutableBytes),
+            ("test_validateMutation_mutableBacking_appendBytes", test_validateMutation_mutableBacking_appendBytes),
+            ("test_validateMutation_mutableBacking_appendData", test_validateMutation_mutableBacking_appendData),
+            ("test_validateMutation_mutableBacking_appendBuffer", test_validateMutation_mutableBacking_appendBuffer),
+            ("test_validateMutation_mutableBacking_appendSequence", test_validateMutation_mutableBacking_appendSequence),
+            ("test_validateMutation_mutableBacking_appendContentsOf", test_validateMutation_mutableBacking_appendContentsOf),
+            ("test_validateMutation_mutableBacking_resetBytes", test_validateMutation_mutableBacking_resetBytes),
+            ("test_validateMutation_mutableBacking_replaceSubrange", test_validateMutation_mutableBacking_replaceSubrange),
+            ("test_validateMutation_mutableBacking_replaceSubrangeCountableRange", test_validateMutation_mutableBacking_replaceSubrangeCountableRange),
+            ("test_validateMutation_mutableBacking_replaceSubrangeWithBuffer", test_validateMutation_mutableBacking_replaceSubrangeWithBuffer),
+            ("test_validateMutation_mutableBacking_replaceSubrangeWithCollection", test_validateMutation_mutableBacking_replaceSubrangeWithCollection),
+            ("test_validateMutation_mutableBacking_replaceSubrangeWithBytes", test_validateMutation_mutableBacking_replaceSubrangeWithBytes),
+            ("test_validateMutation_slice_mutableBacking_withUnsafeMutableBytes", test_validateMutation_slice_mutableBacking_withUnsafeMutableBytes),
+            ("test_validateMutation_slice_mutableBacking_appendBytes", test_validateMutation_slice_mutableBacking_appendBytes),
+            ("test_validateMutation_slice_mutableBacking_appendData", test_validateMutation_slice_mutableBacking_appendData),
+            ("test_validateMutation_slice_mutableBacking_appendBuffer", test_validateMutation_slice_mutableBacking_appendBuffer),
+            ("test_validateMutation_slice_mutableBacking_appendSequence", test_validateMutation_slice_mutableBacking_appendSequence),
+            ("test_validateMutation_slice_mutableBacking_appendContentsOf", test_validateMutation_slice_mutableBacking_appendContentsOf),
+            ("test_validateMutation_slice_mutableBacking_resetBytes", test_validateMutation_slice_mutableBacking_resetBytes),
+            ("test_validateMutation_slice_mutableBacking_replaceSubrange", test_validateMutation_slice_mutableBacking_replaceSubrange),
+            ("test_validateMutation_slice_mutableBacking_replaceSubrangeCountableRange", test_validateMutation_slice_mutableBacking_replaceSubrangeCountableRange),
+            ("test_validateMutation_slice_mutableBacking_replaceSubrangeWithBuffer", test_validateMutation_slice_mutableBacking_replaceSubrangeWithBuffer),
+            ("test_validateMutation_slice_mutableBacking_replaceSubrangeWithCollection", test_validateMutation_slice_mutableBacking_replaceSubrangeWithCollection),
+            ("test_validateMutation_slice_mutableBacking_replaceSubrangeWithBytes", test_validateMutation_slice_mutableBacking_replaceSubrangeWithBytes),
+            ("test_validateMutation_cow_mutableBacking_withUnsafeMutableBytes", test_validateMutation_cow_mutableBacking_withUnsafeMutableBytes),
+            ("test_validateMutation_cow_mutableBacking_appendBytes", test_validateMutation_cow_mutableBacking_appendBytes),
+            ("test_validateMutation_cow_mutableBacking_appendData", test_validateMutation_cow_mutableBacking_appendData),
+            ("test_validateMutation_cow_mutableBacking_appendBuffer", test_validateMutation_cow_mutableBacking_appendBuffer),
+            ("test_validateMutation_cow_mutableBacking_appendSequence", test_validateMutation_cow_mutableBacking_appendSequence),
+            ("test_validateMutation_cow_mutableBacking_appendContentsOf", test_validateMutation_cow_mutableBacking_appendContentsOf),
+            ("test_validateMutation_cow_mutableBacking_resetBytes", test_validateMutation_cow_mutableBacking_resetBytes),
+            ("test_validateMutation_cow_mutableBacking_replaceSubrange", test_validateMutation_cow_mutableBacking_replaceSubrange),
+            ("test_validateMutation_cow_mutableBacking_replaceSubrangeCountableRange", test_validateMutation_cow_mutableBacking_replaceSubrangeCountableRange),
+            ("test_validateMutation_cow_mutableBacking_replaceSubrangeWithBuffer", test_validateMutation_cow_mutableBacking_replaceSubrangeWithBuffer),
+            ("test_validateMutation_cow_mutableBacking_replaceSubrangeWithCollection", test_validateMutation_cow_mutableBacking_replaceSubrangeWithCollection),
+            ("test_validateMutation_cow_mutableBacking_replaceSubrangeWithBytes", test_validateMutation_cow_mutableBacking_replaceSubrangeWithBytes),
+            ("test_validateMutation_slice_cow_mutableBacking_withUnsafeMutableBytes", test_validateMutation_slice_cow_mutableBacking_withUnsafeMutableBytes),
+            ("test_validateMutation_slice_cow_mutableBacking_appendBytes", test_validateMutation_slice_cow_mutableBacking_appendBytes),
+            ("test_validateMutation_slice_cow_mutableBacking_appendData", test_validateMutation_slice_cow_mutableBacking_appendData),
+            ("test_validateMutation_slice_cow_mutableBacking_appendBuffer", test_validateMutation_slice_cow_mutableBacking_appendBuffer),
+            ("test_validateMutation_slice_cow_mutableBacking_appendSequence", test_validateMutation_slice_cow_mutableBacking_appendSequence),
+            ("test_validateMutation_slice_cow_mutableBacking_appendContentsOf", test_validateMutation_slice_cow_mutableBacking_appendContentsOf),
+            ("test_validateMutation_slice_cow_mutableBacking_resetBytes", test_validateMutation_slice_cow_mutableBacking_resetBytes),
+            ("test_validateMutation_slice_cow_mutableBacking_replaceSubrange", test_validateMutation_slice_cow_mutableBacking_replaceSubrange),
+            ("test_validateMutation_slice_cow_mutableBacking_replaceSubrangeCountableRange", test_validateMutation_slice_cow_mutableBacking_replaceSubrangeCountableRange),
+            ("test_validateMutation_slice_cow_mutableBacking_replaceSubrangeWithBuffer", test_validateMutation_slice_cow_mutableBacking_replaceSubrangeWithBuffer),
+            ("test_validateMutation_slice_cow_mutableBacking_replaceSubrangeWithCollection", test_validateMutation_slice_cow_mutableBacking_replaceSubrangeWithCollection),
+            ("test_validateMutation_slice_cow_mutableBacking_replaceSubrangeWithBytes", test_validateMutation_slice_cow_mutableBacking_replaceSubrangeWithBytes),
+            ("test_validateMutation_customBacking_withUnsafeMutableBytes", test_validateMutation_customBacking_withUnsafeMutableBytes),
+//            ("test_validateMutation_customBacking_appendBytes", test_validateMutation_customBacking_appendBytes),
+//            ("test_validateMutation_customBacking_appendData", test_validateMutation_customBacking_appendData),
+//            ("test_validateMutation_customBacking_appendBuffer", test_validateMutation_customBacking_appendBuffer),
+//            ("test_validateMutation_customBacking_appendSequence", test_validateMutation_customBacking_appendSequence),
+//            ("test_validateMutation_customBacking_appendContentsOf", test_validateMutation_customBacking_appendContentsOf),
+//            ("test_validateMutation_customBacking_resetBytes", test_validateMutation_customBacking_resetBytes),
+//            ("test_validateMutation_customBacking_replaceSubrange", test_validateMutation_customBacking_replaceSubrange),
+//            ("test_validateMutation_customBacking_replaceSubrangeCountableRange", test_validateMutation_customBacking_replaceSubrangeCountableRange),
+//            ("test_validateMutation_customBacking_replaceSubrangeWithBuffer", test_validateMutation_customBacking_replaceSubrangeWithBuffer),
+//            ("test_validateMutation_customBacking_replaceSubrangeWithCollection", test_validateMutation_customBacking_replaceSubrangeWithCollection),
+//            ("test_validateMutation_customBacking_replaceSubrangeWithBytes", test_validateMutation_customBacking_replaceSubrangeWithBytes),
+//            ("test_validateMutation_slice_customBacking_withUnsafeMutableBytes", test_validateMutation_slice_customBacking_withUnsafeMutableBytes),
+//            ("test_validateMutation_slice_customBacking_appendBytes", test_validateMutation_slice_customBacking_appendBytes),
+//            ("test_validateMutation_slice_customBacking_appendData", test_validateMutation_slice_customBacking_appendData),
+//            ("test_validateMutation_slice_customBacking_appendBuffer", test_validateMutation_slice_customBacking_appendBuffer),
+//            ("test_validateMutation_slice_customBacking_appendSequence", test_validateMutation_slice_customBacking_appendSequence),
+//            ("test_validateMutation_slice_customBacking_appendContentsOf", test_validateMutation_slice_customBacking_appendContentsOf),
+//            ("test_validateMutation_slice_customBacking_resetBytes", test_validateMutation_slice_customBacking_resetBytes),
+//            ("test_validateMutation_slice_customBacking_replaceSubrange", test_validateMutation_slice_customBacking_replaceSubrange),
+//            ("test_validateMutation_slice_customBacking_replaceSubrangeCountableRange", test_validateMutation_slice_customBacking_replaceSubrangeCountableRange),
+//            ("test_validateMutation_slice_customBacking_replaceSubrangeWithBuffer", test_validateMutation_slice_customBacking_replaceSubrangeWithBuffer),
+//            ("test_validateMutation_slice_customBacking_replaceSubrangeWithCollection", test_validateMutation_slice_customBacking_replaceSubrangeWithCollection),
+//            ("test_validateMutation_slice_customBacking_replaceSubrangeWithBytes", test_validateMutation_slice_customBacking_replaceSubrangeWithBytes),
+//            ("test_validateMutation_cow_customBacking_withUnsafeMutableBytes", test_validateMutation_cow_customBacking_withUnsafeMutableBytes),
+//            ("test_validateMutation_cow_customBacking_appendBytes", test_validateMutation_cow_customBacking_appendBytes),
+//            ("test_validateMutation_cow_customBacking_appendData", test_validateMutation_cow_customBacking_appendData),
+//            ("test_validateMutation_cow_customBacking_appendBuffer", test_validateMutation_cow_customBacking_appendBuffer),
+//            ("test_validateMutation_cow_customBacking_appendSequence", test_validateMutation_cow_customBacking_appendSequence),
+//            ("test_validateMutation_cow_customBacking_appendContentsOf", test_validateMutation_cow_customBacking_appendContentsOf),
+//            ("test_validateMutation_cow_customBacking_resetBytes", test_validateMutation_cow_customBacking_resetBytes),
+//            ("test_validateMutation_cow_customBacking_replaceSubrange", test_validateMutation_cow_customBacking_replaceSubrange),
+//            ("test_validateMutation_cow_customBacking_replaceSubrangeCountableRange", test_validateMutation_cow_customBacking_replaceSubrangeCountableRange),
+//            ("test_validateMutation_cow_customBacking_replaceSubrangeWithBuffer", test_validateMutation_cow_customBacking_replaceSubrangeWithBuffer),
+//            ("test_validateMutation_cow_customBacking_replaceSubrangeWithCollection", test_validateMutation_cow_customBacking_replaceSubrangeWithCollection),
+//            ("test_validateMutation_cow_customBacking_replaceSubrangeWithBytes", test_validateMutation_cow_customBacking_replaceSubrangeWithBytes),
+//            ("test_validateMutation_slice_cow_customBacking_withUnsafeMutableBytes", test_validateMutation_slice_cow_customBacking_withUnsafeMutableBytes),
+//            ("test_validateMutation_slice_cow_customBacking_appendBytes", test_validateMutation_slice_cow_customBacking_appendBytes),
+//            ("test_validateMutation_slice_cow_customBacking_appendData", test_validateMutation_slice_cow_customBacking_appendData),
+//            ("test_validateMutation_slice_cow_customBacking_appendBuffer", test_validateMutation_slice_cow_customBacking_appendBuffer),
+//            ("test_validateMutation_slice_cow_customBacking_appendSequence", test_validateMutation_slice_cow_customBacking_appendSequence),
+//            ("test_validateMutation_slice_cow_customBacking_appendContentsOf", test_validateMutation_slice_cow_customBacking_appendContentsOf),
+//            ("test_validateMutation_slice_cow_customBacking_resetBytes", test_validateMutation_slice_cow_customBacking_resetBytes),
+//            ("test_validateMutation_slice_cow_customBacking_replaceSubrange", test_validateMutation_slice_cow_customBacking_replaceSubrange),
+//            ("test_validateMutation_slice_cow_customBacking_replaceSubrangeCountableRange", test_validateMutation_slice_cow_customBacking_replaceSubrangeCountableRange),
+//            ("test_validateMutation_slice_cow_customBacking_replaceSubrangeWithBuffer", test_validateMutation_slice_cow_customBacking_replaceSubrangeWithBuffer),
+//            ("test_validateMutation_slice_cow_customBacking_replaceSubrangeWithCollection", test_validateMutation_slice_cow_customBacking_replaceSubrangeWithCollection),
+//            ("test_validateMutation_slice_cow_customBacking_replaceSubrangeWithBytes", test_validateMutation_slice_cow_customBacking_replaceSubrangeWithBytes),
+//            ("test_validateMutation_customMutableBacking_withUnsafeMutableBytes", test_validateMutation_customMutableBacking_withUnsafeMutableBytes),
+//            ("test_validateMutation_customMutableBacking_appendBytes", test_validateMutation_customMutableBacking_appendBytes),
+//            ("test_validateMutation_customMutableBacking_appendData", test_validateMutation_customMutableBacking_appendData),
+//            ("test_validateMutation_customMutableBacking_appendBuffer", test_validateMutation_customMutableBacking_appendBuffer),
+//            ("test_validateMutation_customMutableBacking_appendSequence", test_validateMutation_customMutableBacking_appendSequence),
+//            ("test_validateMutation_customMutableBacking_appendContentsOf", test_validateMutation_customMutableBacking_appendContentsOf),
+//            ("test_validateMutation_customMutableBacking_resetBytes", test_validateMutation_customMutableBacking_resetBytes),
+//            ("test_validateMutation_customMutableBacking_replaceSubrange", test_validateMutation_customMutableBacking_replaceSubrange),
+//            ("test_validateMutation_customMutableBacking_replaceSubrangeCountableRange", test_validateMutation_customMutableBacking_replaceSubrangeCountableRange),
+//            ("test_validateMutation_customMutableBacking_replaceSubrangeWithBuffer", test_validateMutation_customMutableBacking_replaceSubrangeWithBuffer),
+//            ("test_validateMutation_customMutableBacking_replaceSubrangeWithCollection", test_validateMutation_customMutableBacking_replaceSubrangeWithCollection),
+//            ("test_validateMutation_customMutableBacking_replaceSubrangeWithBytes", test_validateMutation_customMutableBacking_replaceSubrangeWithBytes),
+//            ("test_validateMutation_slice_customMutableBacking_withUnsafeMutableBytes", test_validateMutation_slice_customMutableBacking_withUnsafeMutableBytes),
+//            ("test_validateMutation_slice_customMutableBacking_appendBytes", test_validateMutation_slice_customMutableBacking_appendBytes),
+//            ("test_validateMutation_slice_customMutableBacking_appendData", test_validateMutation_slice_customMutableBacking_appendData),
+//            ("test_validateMutation_slice_customMutableBacking_appendBuffer", test_validateMutation_slice_customMutableBacking_appendBuffer),
+//            ("test_validateMutation_slice_customMutableBacking_appendSequence", test_validateMutation_slice_customMutableBacking_appendSequence),
+//            ("test_validateMutation_slice_customMutableBacking_appendContentsOf", test_validateMutation_slice_customMutableBacking_appendContentsOf),
+//            ("test_validateMutation_slice_customMutableBacking_resetBytes", test_validateMutation_slice_customMutableBacking_resetBytes),
+//            ("test_validateMutation_slice_customMutableBacking_replaceSubrange", test_validateMutation_slice_customMutableBacking_replaceSubrange),
+//            ("test_validateMutation_slice_customMutableBacking_replaceSubrangeCountableRange", test_validateMutation_slice_customMutableBacking_replaceSubrangeCountableRange),
+//            ("test_validateMutation_slice_customMutableBacking_replaceSubrangeWithBuffer", test_validateMutation_slice_customMutableBacking_replaceSubrangeWithBuffer),
+//            ("test_validateMutation_slice_customMutableBacking_replaceSubrangeWithCollection", test_validateMutation_slice_customMutableBacking_replaceSubrangeWithCollection),
+//            ("test_validateMutation_slice_customMutableBacking_replaceSubrangeWithBytes", test_validateMutation_slice_customMutableBacking_replaceSubrangeWithBytes),
+//            ("test_validateMutation_cow_customMutableBacking_withUnsafeMutableBytes", test_validateMutation_cow_customMutableBacking_withUnsafeMutableBytes),
+//            ("test_validateMutation_cow_customMutableBacking_appendBytes", test_validateMutation_cow_customMutableBacking_appendBytes),
+//            ("test_validateMutation_cow_customMutableBacking_appendData", test_validateMutation_cow_customMutableBacking_appendData),
+//            ("test_validateMutation_cow_customMutableBacking_appendBuffer", test_validateMutation_cow_customMutableBacking_appendBuffer),
+//            ("test_validateMutation_cow_customMutableBacking_appendSequence", test_validateMutation_cow_customMutableBacking_appendSequence),
+//            ("test_validateMutation_cow_customMutableBacking_appendContentsOf", test_validateMutation_cow_customMutableBacking_appendContentsOf),
+//            ("test_validateMutation_cow_customMutableBacking_resetBytes", test_validateMutation_cow_customMutableBacking_resetBytes),
+//            ("test_validateMutation_cow_customMutableBacking_replaceSubrange", test_validateMutation_cow_customMutableBacking_replaceSubrange),
+//            ("test_validateMutation_cow_customMutableBacking_replaceSubrangeCountableRange", test_validateMutation_cow_customMutableBacking_replaceSubrangeCountableRange),
+//            ("test_validateMutation_cow_customMutableBacking_replaceSubrangeWithBuffer", test_validateMutation_cow_customMutableBacking_replaceSubrangeWithBuffer),
+//            ("test_validateMutation_cow_customMutableBacking_replaceSubrangeWithCollection", test_validateMutation_cow_customMutableBacking_replaceSubrangeWithCollection),
+//            ("test_validateMutation_cow_customMutableBacking_replaceSubrangeWithBytes", test_validateMutation_cow_customMutableBacking_replaceSubrangeWithBytes),
+//            ("test_validateMutation_slice_cow_customMutableBacking_withUnsafeMutableBytes", test_validateMutation_slice_cow_customMutableBacking_withUnsafeMutableBytes),
+//            ("test_validateMutation_slice_cow_customMutableBacking_appendBytes", test_validateMutation_slice_cow_customMutableBacking_appendBytes),
+//            ("test_validateMutation_slice_cow_customMutableBacking_appendData", test_validateMutation_slice_cow_customMutableBacking_appendData),
+//            ("test_validateMutation_slice_cow_customMutableBacking_appendBuffer", test_validateMutation_slice_cow_customMutableBacking_appendBuffer),
+//            ("test_validateMutation_slice_cow_customMutableBacking_appendSequence", test_validateMutation_slice_cow_customMutableBacking_appendSequence),
+//            ("test_validateMutation_slice_cow_customMutableBacking_appendContentsOf", test_validateMutation_slice_cow_customMutableBacking_appendContentsOf),
+//            ("test_validateMutation_slice_cow_customMutableBacking_resetBytes", test_validateMutation_slice_cow_customMutableBacking_resetBytes),
+//            ("test_validateMutation_slice_cow_customMutableBacking_replaceSubrange", test_validateMutation_slice_cow_customMutableBacking_replaceSubrange),
+//            ("test_validateMutation_slice_cow_customMutableBacking_replaceSubrangeCountableRange", test_validateMutation_slice_cow_customMutableBacking_replaceSubrangeCountableRange),
+//            ("test_validateMutation_slice_cow_customMutableBacking_replaceSubrangeWithBuffer", test_validateMutation_slice_cow_customMutableBacking_replaceSubrangeWithBuffer),
+//            ("test_validateMutation_slice_cow_customMutableBacking_replaceSubrangeWithCollection", test_validateMutation_slice_cow_customMutableBacking_replaceSubrangeWithCollection),
+//            ("test_validateMutation_slice_cow_customMutableBacking_replaceSubrangeWithBytes", test_validateMutation_slice_cow_customMutableBacking_replaceSubrangeWithBytes),
+            ("test_sliceHash", test_sliceHash),
+            ("test_slice_resize_growth", test_slice_resize_growth),
+//            ("test_sliceEnumeration", test_sliceEnumeration),
         ]
     }
     
@@ -908,6 +1318,47 @@
         XCTAssertTrue(didCatchError)
     }
 
+    func test_contentsOfFile() {
+        let testDir = testBundle().resourcePath
+        let filename = testDir!.appending("/NSStringTestData.txt")
+
+        let contents = NSData(contentsOfFile: filename)
+        XCTAssertNotNil(contents)
+        if let contents = contents {
+            let ptr =  UnsafeMutableRawPointer(mutating: contents.bytes)
+            let str = String(bytesNoCopy: ptr, length: contents.length,
+                         encoding: .ascii, freeWhenDone: false)
+            XCTAssertEqual(str, "swift-corelibs-foundation")
+        }
+    }
+
+    func test_contentsOfZeroFile() {
+#if os(Linux)
+        guard FileManager.default.fileExists(atPath: "/proc/self") else {
+            return
+        }
+        let contents = NSData(contentsOfFile: "/proc/self/cmdline")
+        XCTAssertNotNil(contents)
+        if let contents = contents {
+            XCTAssertTrue(contents.length > 0)
+            let ptr = UnsafeMutableRawPointer(mutating: contents.bytes)
+            let str = String(bytesNoCopy: ptr, length: contents.length,
+                             encoding: .ascii, freeWhenDone: false)
+            XCTAssertNotNil(str)
+            if let str = str {
+                XCTAssertTrue(str.hasSuffix("TestFoundation"))
+            }
+        }
+
+        do {
+            let maps = try String(contentsOfFile: "/proc/self/maps", encoding: .utf8)
+            XCTAssertTrue(maps.count > 0)
+        } catch {
+            XCTFail("Cannot read /proc/self/maps: \(String(describing: error))")
+        }
+#endif
+    }
+
     func test_basicReadWrite() {
         let url = URL(fileURLWithPath: NSTemporaryDirectory(), isDirectory: true).appendingPathComponent("testfile")
         let count = 1 << 24
@@ -1121,5 +1572,2385 @@
         XCTAssertEqual(found[0], 2)
         XCTAssertEqual(found[1], 3)
     }
+
+        func test_validateMutation_withUnsafeMutableBytes() {
+        var data = Data(bytes: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9])
+        data.withUnsafeMutableBytes { (ptr: UnsafeMutablePointer<UInt8>) in
+            ptr.advanced(by: 5).pointee = 0xFF
+        }
+        XCTAssertEqual(data, Data(bytes: [0, 1, 2, 3, 4, 0xFF, 6, 7, 8, 9]))
+    }
+    
+    func test_validateMutation_appendBytes() {
+        var data = Data(bytes: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9])
+        data.append("hello", count: 5)
+        XCTAssertEqual(data[data.startIndex.advanced(by: 5)], 0x5)
+    }
+    
+    func test_validateMutation_appendData() {
+        var data = Data(bytes: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9])
+        let other = Data(bytes: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9])
+        data.append(other)
+        XCTAssertEqual(data[data.startIndex.advanced(by: 9)], 9)
+        XCTAssertEqual(data[data.startIndex.advanced(by: 10)], 0)
+    }
+    
+    func test_validateMutation_appendBuffer() {
+        var data = Data(bytes: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9])
+        let bytes: [UInt8] = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
+        bytes.withUnsafeBufferPointer { data.append($0) }
+        XCTAssertEqual(data[data.startIndex.advanced(by: 9)], 9)
+        XCTAssertEqual(data[data.startIndex.advanced(by: 10)], 0)
+    }
+    
+    func test_validateMutation_appendSequence() {
+        var data = Data(bytes: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9])
+        let seq = repeatElement(UInt8(1), count: 10)
+        data.append(contentsOf: seq)
+        XCTAssertEqual(data[data.startIndex.advanced(by: 9)], 9)
+        XCTAssertEqual(data[data.startIndex.advanced(by: 10)], 1)
+    }
+    
+    func test_validateMutation_appendContentsOf() {
+        var data = Data(bytes: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9])
+        let bytes: [UInt8] = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
+        data.append(contentsOf: bytes)
+        XCTAssertEqual(data[data.startIndex.advanced(by: 9)], 9)
+        XCTAssertEqual(data[data.startIndex.advanced(by: 10)], 0)
+    }
+    
+    func test_validateMutation_resetBytes() {
+        var data = Data(bytes: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9])
+        data.resetBytes(in: 5..<8)
+        XCTAssertEqual(data, Data(bytes: [0, 1, 2, 3, 4, 0, 0, 0, 8, 9]))
+    }
+    
+    func test_validateMutation_replaceSubrange() {
+        var data = Data(bytes: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9])
+        let range: Range<Data.Index> = data.startIndex.advanced(by: 4)..<data.startIndex.advanced(by: 9)
+        let replacement = Data(bytes: [0xFF, 0xFF])
+        data.replaceSubrange(range, with: replacement)
+        XCTAssertEqual(data, Data(bytes: [0, 1, 2, 3, 0xFF, 0xFF, 9]))
+    }
+    
+    func test_validateMutation_replaceSubrangeCountableRange() {
+        var data = Data(bytes: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9])
+        let range: CountableRange<Data.Index> = data.startIndex.advanced(by: 4)..<data.startIndex.advanced(by: 9)
+        let replacement = Data(bytes: [0xFF, 0xFF])
+        data.replaceSubrange(range, with: replacement)
+        XCTAssertEqual(data, Data(bytes: [0, 1, 2, 3, 0xFF, 0xFF, 9]))
+    }
+    
+    func test_validateMutation_replaceSubrangeWithBuffer() {
+        var data = Data(bytes: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9])
+        let range: Range<Data.Index> = data.startIndex.advanced(by: 4)..<data.startIndex.advanced(by: 9)
+        let bytes: [UInt8] = [0xFF, 0xFF]
+        bytes.withUnsafeBufferPointer {
+            data.replaceSubrange(range, with: $0)
+        }
+        XCTAssertEqual(data, Data(bytes: [0, 1, 2, 3, 0xFF, 0xFF, 9]))
+    }
+    
+    func test_validateMutation_replaceSubrangeWithCollection() {
+        var data = Data(bytes: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9])
+        let range: Range<Data.Index> = data.startIndex.advanced(by: 4)..<data.startIndex.advanced(by: 9)
+        let bytes: [UInt8] = [0xFF, 0xFF]
+        data.replaceSubrange(range, with: bytes)
+        XCTAssertEqual(data, Data(bytes: [0, 1, 2, 3, 0xFF, 0xFF, 9]))
+    }
+    
+    func test_validateMutation_replaceSubrangeWithBytes() {
+        var data = Data(bytes: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9])
+        let range: Range<Data.Index> = data.startIndex.advanced(by: 4)..<data.startIndex.advanced(by: 9)
+        let bytes: [UInt8] = [0xFF, 0xFF]
+        bytes.withUnsafeBytes {
+            data.replaceSubrange(range, with: $0.baseAddress!, count: 2)
+        }
+        XCTAssertEqual(data, Data(bytes: [0, 1, 2, 3, 0xFF, 0xFF, 9]))
+    }
+    
+    func test_validateMutation_slice_withUnsafeMutableBytes() {
+        var data = Data(bytes: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9])[4..<9]
+        data.withUnsafeMutableBytes { (ptr: UnsafeMutablePointer<UInt8>) in
+            ptr.advanced(by: 1).pointee = 0xFF
+        }
+        XCTAssertEqual(data, Data(bytes: [4, 0xFF, 6, 7, 8]))
+    }
+    
+    func test_validateMutation_slice_appendBytes() {
+        var data = Data(bytes: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9])[4..<9]
+        let bytes: [UInt8] = [0xFF, 0xFF]
+        bytes.withUnsafeBufferPointer { data.append($0.baseAddress!, count: $0.count) }
+        XCTAssertEqual(data, Data(bytes: [4, 5, 6, 7, 8, 0xFF, 0xFF]))
+    }
+    
+    func test_validateMutation_slice_appendData() {
+        var data = Data(bytes: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9])[4..<9]
+        let other = Data(bytes: [0xFF, 0xFF])
+        data.append(other)
+        XCTAssertEqual(data, Data(bytes: [4, 5, 6, 7, 8, 0xFF, 0xFF]))
+    }
+    
+    func test_validateMutation_slice_appendBuffer() {
+        var data = Data(bytes: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9])[4..<9]
+        let bytes: [UInt8] = [0xFF, 0xFF]
+        bytes.withUnsafeBufferPointer { data.append($0) }
+        XCTAssertEqual(data, Data(bytes: [4, 5, 6, 7, 8, 0xFF, 0xFF]))
+    }
+    
+    func test_validateMutation_slice_appendSequence() {
+        var data = Data(bytes: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9])[4..<9]
+        let seq = repeatElement(UInt8(0xFF), count: 2)
+        data.append(contentsOf: seq)
+        XCTAssertEqual(data, Data(bytes: [4, 5, 6, 7, 8, 0xFF, 0xFF]))
+    }
+    
+    func test_validateMutation_slice_appendContentsOf() {
+        var data = Data(bytes: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9])[4..<9]
+        let bytes: [UInt8] = [0xFF, 0xFF]
+        data.append(contentsOf: bytes)
+        XCTAssertEqual(data, Data(bytes: [4, 5, 6, 7, 8, 0xFF, 0xFF]))
+    }
+    
+    func test_validateMutation_slice_resetBytes() {
+        var data = Data(bytes: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9])[4..<9]
+        data.resetBytes(in: 5..<8)
+        XCTAssertEqual(data, Data(bytes: [4, 0, 0, 0, 8]))
+    }
+    
+    func test_validateMutation_slice_replaceSubrange() {
+        var data = Data(bytes: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9])[4..<9]
+        let range: Range<Data.Index> = data.startIndex.advanced(by: 1)..<data.endIndex.advanced(by: -1)
+        let replacement = Data(bytes: [0xFF, 0xFF])
+        data.replaceSubrange(range, with: replacement)
+        XCTAssertEqual(data, Data(bytes: [4, 0xFF, 0xFF, 8]))
+    }
+    
+    func test_validateMutation_slice_replaceSubrangeCountableRange() {
+        var data = Data(bytes: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9])[4..<9]
+        let range: CountableRange<Data.Index> = data.startIndex.advanced(by: 1)..<data.endIndex.advanced(by: -1)
+        let replacement = Data(bytes: [0xFF, 0xFF])
+        data.replaceSubrange(range, with: replacement)
+        XCTAssertEqual(data, Data(bytes: [4, 0xFF, 0xFF, 8]))
+    }
+    
+    func test_validateMutation_slice_replaceSubrangeWithBuffer() {
+        var data = Data(bytes: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9])[4..<9]
+        let range: Range<Data.Index> = data.startIndex.advanced(by: 1)..<data.endIndex.advanced(by: -1)
+        let bytes: [UInt8] = [0xFF, 0xFF]
+        bytes.withUnsafeBufferPointer {
+            data.replaceSubrange(range, with: $0)
+        }
+        XCTAssertEqual(data, Data(bytes: [4, 0xFF, 0xFF, 8]))
+    }
+    
+    func test_validateMutation_slice_replaceSubrangeWithCollection() {
+        var data = Data(bytes: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9])[4..<9]
+        let range: Range<Data.Index> = data.startIndex.advanced(by: 1)..<data.endIndex.advanced(by: -1)
+        let bytes: [UInt8] = [0xFF, 0xFF]
+        data.replaceSubrange(range, with: bytes)
+        XCTAssertEqual(data, Data(bytes: [4, 0xFF, 0xFF, 8]))
+    }
+    
+    func test_validateMutation_slice_replaceSubrangeWithBytes() {
+        var data = Data(bytes: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9])[4..<9]
+        let range: Range<Data.Index> = data.startIndex.advanced(by: 1)..<data.endIndex.advanced(by: -1)
+        let bytes: [UInt8] = [0xFF, 0xFF]
+        bytes.withUnsafeBytes {
+            data.replaceSubrange(range, with: $0.baseAddress!, count: 2)
+        }
+        XCTAssertEqual(data, Data(bytes: [4, 0xFF, 0xFF, 8]))
+    }
+    
+    func test_validateMutation_cow_withUnsafeMutableBytes() {
+        var data = Data(bytes: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9])
+        holdReference(data) {
+            data.withUnsafeMutableBytes { (ptr: UnsafeMutablePointer<UInt8>) in
+                ptr.advanced(by: 5).pointee = 0xFF
+            }
+            XCTAssertEqual(data, Data(bytes: [0, 1, 2, 3, 4, 0xFF, 6, 7, 8, 9]))
+        }
+    }
+    
+    func test_validateMutation_cow_appendBytes() {
+        var data = Data(bytes: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9])
+        holdReference(data) {
+            data.append("hello", count: 5)
+            XCTAssertEqual(data[data.startIndex.advanced(by: 9)], 0x9)
+            XCTAssertEqual(data[data.startIndex.advanced(by: 10)], 0x68)
+        }
+    }
+    
+    func test_validateMutation_cow_appendData() {
+        var data = Data(bytes: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9])
+        holdReference(data) {
+            let other = Data(bytes: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9])
+            data.append(other)
+            XCTAssertEqual(data[data.startIndex.advanced(by: 9)], 9)
+            XCTAssertEqual(data[data.startIndex.advanced(by: 10)], 0)
+        }
+    }
+    
+    func test_validateMutation_cow_appendBuffer() {
+        var data = Data(bytes: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9])
+        holdReference(data) {
+            let bytes: [UInt8] = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
+            bytes.withUnsafeBufferPointer { data.append($0) }
+            XCTAssertEqual(data[data.startIndex.advanced(by: 9)], 9)
+            XCTAssertEqual(data[data.startIndex.advanced(by: 10)], 0)
+        }
+    }
+    
+    func test_validateMutation_cow_appendSequence() {
+        var data = Data(bytes: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9])
+        holdReference(data) {
+            let seq = repeatElement(UInt8(1), count: 10)
+            data.append(contentsOf: seq)
+            XCTAssertEqual(data[data.startIndex.advanced(by: 9)], 9)
+            XCTAssertEqual(data[data.startIndex.advanced(by: 10)], 1)
+        }
+    }
+    
+    func test_validateMutation_cow_appendContentsOf() {
+        var data = Data(bytes: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9])
+        holdReference(data) {
+            let bytes: [UInt8] = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
+            data.append(contentsOf: bytes)
+            XCTAssertEqual(data[data.startIndex.advanced(by: 9)], 9)
+            XCTAssertEqual(data[data.startIndex.advanced(by: 10)], 0)
+        }
+    }
+    
+    func test_validateMutation_cow_resetBytes() {
+        var data = Data(bytes: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9])
+        holdReference(data) {
+            data.resetBytes(in: 5..<8)
+            XCTAssertEqual(data, Data(bytes: [0, 1, 2, 3, 4, 0, 0, 0, 8, 9]))
+        }
+    }
+    
+    func test_validateMutation_cow_replaceSubrange() {
+        var data = Data(bytes: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9])
+        holdReference(data) {
+            let range: Range<Data.Index> = data.startIndex.advanced(by: 4)..<data.startIndex.advanced(by: 9)
+            let replacement = Data(bytes: [0xFF, 0xFF])
+            data.replaceSubrange(range, with: replacement)
+            XCTAssertEqual(data, Data(bytes: [0, 1, 2, 3, 0xFF, 0xFF, 9]))
+        }
+    }
+    
+    func test_validateMutation_cow_replaceSubrangeCountableRange() {
+        var data = Data(bytes: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9])
+        holdReference(data) {
+            let range: CountableRange<Data.Index> = data.startIndex.advanced(by: 4)..<data.startIndex.advanced(by: 9)
+            let replacement = Data(bytes: [0xFF, 0xFF])
+            data.replaceSubrange(range, with: replacement)
+            XCTAssertEqual(data, Data(bytes: [0, 1, 2, 3, 0xFF, 0xFF, 9]))
+        }
+    }
+    
+    func test_validateMutation_cow_replaceSubrangeWithBuffer() {
+        var data = Data(bytes: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9])
+        holdReference(data) {
+            let range: Range<Data.Index> = data.startIndex.advanced(by: 4)..<data.startIndex.advanced(by: 9)
+            let bytes: [UInt8] = [0xFF, 0xFF]
+            bytes.withUnsafeBufferPointer {
+                data.replaceSubrange(range, with: $0)
+            }
+            XCTAssertEqual(data, Data(bytes: [0, 1, 2, 3, 0xFF, 0xFF, 9]))
+        }
+    }
+    
+    func test_validateMutation_cow_replaceSubrangeWithCollection() {
+        var data = Data(bytes: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9])
+        holdReference(data) {
+            let range: Range<Data.Index> = data.startIndex.advanced(by: 4)..<data.startIndex.advanced(by: 9)
+            let bytes: [UInt8] = [0xFF, 0xFF]
+            data.replaceSubrange(range, with: bytes)
+            XCTAssertEqual(data, Data(bytes: [0, 1, 2, 3, 0xFF, 0xFF, 9]))
+        }
+    }
+    
+    func test_validateMutation_cow_replaceSubrangeWithBytes() {
+        var data = Data(bytes: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9])
+        holdReference(data) {
+            let range: Range<Data.Index> = data.startIndex.advanced(by: 4)..<data.startIndex.advanced(by: 9)
+            let bytes: [UInt8] = [0xFF, 0xFF]
+            bytes.withUnsafeBytes {
+                data.replaceSubrange(range, with: $0.baseAddress!, count: 2)
+            }
+            XCTAssertEqual(data, Data(bytes: [0, 1, 2, 3, 0xFF, 0xFF, 9]))
+        }
+    }
+    
+    func test_validateMutation_slice_cow_withUnsafeMutableBytes() {
+        var data = Data(bytes: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9])[4..<9]
+        holdReference(data) {
+            data.withUnsafeMutableBytes { (ptr: UnsafeMutablePointer<UInt8>) in
+                ptr.advanced(by: 1).pointee = 0xFF
+            }
+            XCTAssertEqual(data, Data(bytes: [4, 0xFF, 6, 7, 8]))
+        }
+    }
+    
+    func test_validateMutation_slice_cow_appendBytes() {
+        var data = Data(bytes: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9])[4..<9]
+        holdReference(data) {
+            data.append("hello", count: 5)
+            XCTAssertEqual(data[data.startIndex.advanced(by: 4)], 0x8)
+            XCTAssertEqual(data[data.startIndex.advanced(by: 5)], 0x68)
+        }
+    }
+    
+    func test_validateMutation_slice_cow_appendData() {
+        var data = Data(bytes: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9])[4..<9]
+        holdReference(data) {
+            let other = Data(bytes: [0xFF, 0xFF])
+            data.append(other)
+            XCTAssertEqual(data, Data(bytes: [4, 5, 6, 7, 8, 0xFF, 0xFF]))
+        }
+    }
+    
+    func test_validateMutation_slice_cow_appendBuffer() {
+        var data = Data(bytes: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9])[4..<9]
+        holdReference(data) {
+            let bytes: [UInt8] = [0xFF, 0xFF]
+            bytes.withUnsafeBufferPointer { data.append($0) }
+            XCTAssertEqual(data, Data(bytes: [4, 5, 6, 7, 8, 0xFF, 0xFF]))
+        }
+    }
+    
+    func test_validateMutation_slice_cow_appendSequence() {
+        var data = Data(bytes: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9])[4..<9]
+        holdReference(data) {
+            let seq = repeatElement(UInt8(0xFF), count: 2)
+            data.append(contentsOf: seq)
+            XCTAssertEqual(data, Data(bytes: [4, 5, 6, 7, 8, 0xFF, 0xFF]))
+        }
+    }
+    
+    func test_validateMutation_slice_cow_appendContentsOf() {
+        var data = Data(bytes: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9])[4..<9]
+        holdReference(data) {
+            let bytes: [UInt8] = [0xFF, 0xFF]
+            data.append(contentsOf: bytes)
+            XCTAssertEqual(data, Data(bytes: [4, 5, 6, 7, 8, 0xFF, 0xFF]))
+        }
+    }
+    
+    func test_validateMutation_slice_cow_resetBytes() {
+        var data = Data(bytes: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9])[4..<9]
+        holdReference(data) {
+            data.resetBytes(in: 5..<8)
+            XCTAssertEqual(data, Data(bytes: [4, 0, 0, 0, 8]))
+        }
+    }
+    
+    func test_validateMutation_slice_cow_replaceSubrange() {
+        var data = Data(bytes: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9])[4..<9]
+        holdReference(data) {
+            let range: Range<Data.Index> = data.startIndex.advanced(by: 1)..<data.endIndex.advanced(by: -1)
+            let replacement = Data(bytes: [0xFF, 0xFF])
+            data.replaceSubrange(range, with: replacement)
+            XCTAssertEqual(data, Data(bytes: [4, 0xFF, 0xFF, 8]))
+        }
+    }
+    
+    func test_validateMutation_slice_cow_replaceSubrangeCountableRange() {
+        var data = Data(bytes: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9])[4..<9]
+        holdReference(data) {
+            let range: CountableRange<Data.Index> = data.startIndex.advanced(by: 1)..<data.endIndex.advanced(by: -1)
+            let replacement = Data(bytes: [0xFF, 0xFF])
+            data.replaceSubrange(range, with: replacement)
+            XCTAssertEqual(data, Data(bytes: [4, 0xFF, 0xFF, 8]))
+        }
+    }
+    
+    func test_validateMutation_slice_cow_replaceSubrangeWithBuffer() {
+        var data = Data(bytes: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9])[4..<9]
+        holdReference(data) {
+            let range: Range<Data.Index> = data.startIndex.advanced(by: 1)..<data.endIndex.advanced(by: -1)
+            let bytes: [UInt8] = [0xFF, 0xFF]
+            bytes.withUnsafeBufferPointer {
+                data.replaceSubrange(range, with: $0)
+            }
+            XCTAssertEqual(data, Data(bytes: [4, 0xFF, 0xFF, 8]))
+        }
+    }
+    
+    func test_validateMutation_slice_cow_replaceSubrangeWithCollection() {
+        var data = Data(bytes: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9])[4..<9]
+        holdReference(data) {
+            let range: Range<Data.Index> = data.startIndex.advanced(by: 1)..<data.endIndex.advanced(by: -1)
+            let bytes: [UInt8] = [0xFF, 0xFF]
+            data.replaceSubrange(range, with: bytes)
+            XCTAssertEqual(data, Data(bytes: [4, 0xFF, 0xFF, 8]))
+        }
+    }
+    
+    func test_validateMutation_slice_cow_replaceSubrangeWithBytes() {
+        var data = Data(bytes: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9])[4..<9]
+        holdReference(data) {
+            let range: Range<Data.Index> = data.startIndex.advanced(by: 1)..<data.endIndex.advanced(by: -1)
+            let bytes: [UInt8] = [0xFF, 0xFF]
+            bytes.withUnsafeBytes {
+                data.replaceSubrange(range, with: $0.baseAddress!, count: 2)
+            }
+            XCTAssertEqual(data, Data(bytes: [4, 0xFF, 0xFF, 8]))
+        }
+    }
+    
+    func test_validateMutation_immutableBacking_withUnsafeMutableBytes() {
+        var data = Data(referencing: NSData(bytes: "hello world", length: 11))
+        data.withUnsafeMutableBytes { (ptr: UnsafeMutablePointer<UInt8>) in
+            ptr.advanced(by: 5).pointee = 0xFF
+        }
+        XCTAssertEqual(data[data.startIndex.advanced(by: 5)], 0xFF)
+    }
+    
+    func test_validateMutation_immutableBacking_appendBytes() {
+        var data = Data(referencing: NSData(bytes: "hello world", length: 11))
+        data.append("hello", count: 5)
+        XCTAssertEqual(data[data.startIndex.advanced(by: 10)], 0x64)
+        XCTAssertEqual(data[data.startIndex.advanced(by: 11)], 0x68)
+    }
+    
+    func test_validateMutation_immutableBacking_appendData() {
+        var data = Data(referencing: NSData(bytes: "hello world", length: 11))
+        let other = Data(bytes: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9])
+        data.append(other)
+        XCTAssertEqual(data[data.startIndex.advanced(by: 10)], 0x64)
+        XCTAssertEqual(data[data.startIndex.advanced(by: 11)], 0)
+    }
+    
+    func test_validateMutation_immutableBacking_appendBuffer() {
+        var data = Data(referencing: NSData(bytes: "hello world", length: 11))
+        let bytes: [UInt8] = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
+        bytes.withUnsafeBufferPointer { data.append($0) }
+        XCTAssertEqual(data[data.startIndex.advanced(by: 10)], 0x64)
+        XCTAssertEqual(data[data.startIndex.advanced(by: 11)], 0)
+    }
+    
+    func test_validateMutation_immutableBacking_appendSequence() {
+        var data = Data(referencing: NSData(bytes: "hello world", length: 11))
+        let seq = repeatElement(UInt8(1), count: 10)
+        data.append(contentsOf: seq)
+        XCTAssertEqual(data[data.startIndex.advanced(by: 10)], 0x64)
+        XCTAssertEqual(data[data.startIndex.advanced(by: 11)], 1)
+    }
+    
+    func test_validateMutation_immutableBacking_appendContentsOf() {
+        var data = Data(referencing: NSData(bytes: "hello world", length: 11))
+        let bytes: [UInt8] = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
+        data.append(contentsOf: bytes)
+        XCTAssertEqual(data[data.startIndex.advanced(by: 10)], 0x64)
+        XCTAssertEqual(data[data.startIndex.advanced(by: 11)], 0)
+    }
+    
+    func test_validateMutation_immutableBacking_resetBytes() {
+        var data = Data(referencing: NSData(bytes: "hello world", length: 11))
+        data.resetBytes(in: 5..<8)
+        XCTAssertEqual(data, Data(bytes: [0x68, 0x65, 0x6c, 0x6c, 0x6f, 0x00, 0x00, 0x00, 0x72, 0x6c, 0x64]))
+    }
+    
+    func test_validateMutation_immutableBacking_replaceSubrange() {
+        var data = Data(referencing: NSData(bytes: "hello world", length: 11))
+        let range: Range<Data.Index> = data.startIndex.advanced(by: 4)..<data.startIndex.advanced(by: 9)
+        let replacement = Data(bytes: [0xFF, 0xFF])
+        data.replaceSubrange(range, with: replacement)
+        XCTAssertEqual(data, Data(bytes: [0x68, 0x65, 0x6c, 0x6c, 0xFF, 0xFF, 0x6c, 0x64]))
+    }
+    
+    func test_validateMutation_immutableBacking_replaceSubrangeCountableRange() {
+        var data = Data(referencing: NSData(bytes: "hello world", length: 11))
+        let range: CountableRange<Data.Index> = data.startIndex.advanced(by: 4)..<data.startIndex.advanced(by: 9)
+        let replacement = Data(bytes: [0xFF, 0xFF])
+        data.replaceSubrange(range, with: replacement)
+        XCTAssertEqual(data, Data(bytes: [0x68, 0x65, 0x6c, 0x6c, 0xFF, 0xFF, 0x6c, 0x64]))
+    }
+    
+    func test_validateMutation_immutableBacking_replaceSubrangeWithBuffer() {
+        var data = Data(referencing: NSData(bytes: "hello world", length: 11))
+        let range: Range<Data.Index> = data.startIndex.advanced(by: 4)..<data.startIndex.advanced(by: 9)
+        let bytes: [UInt8] = [0xFF, 0xFF]
+        bytes.withUnsafeBufferPointer {
+            data.replaceSubrange(range, with: $0)
+        }
+        XCTAssertEqual(data, Data(bytes: [0x68, 0x65, 0x6c, 0x6c, 0xFF, 0xFF, 0x6c, 0x64]))
+    }
+    
+    func test_validateMutation_immutableBacking_replaceSubrangeWithCollection() {
+        var data = Data(referencing: NSData(bytes: "hello world", length: 11))
+        let range: Range<Data.Index> = data.startIndex.advanced(by: 4)..<data.startIndex.advanced(by: 9)
+        let bytes: [UInt8] = [0xFF, 0xFF]
+        data.replaceSubrange(range, with: bytes)
+        XCTAssertEqual(data, Data(bytes: [0x68, 0x65, 0x6c, 0x6c, 0xFF, 0xFF, 0x6c, 0x64]))
+    }
+    
+    func test_validateMutation_immutableBacking_replaceSubrangeWithBytes() {
+        var data = Data(referencing: NSData(bytes: "hello world", length: 11))
+        let range: Range<Data.Index> = data.startIndex.advanced(by: 4)..<data.startIndex.advanced(by: 9)
+        let bytes: [UInt8] = [0xFF, 0xFF]
+        data.replaceSubrange(range, with: bytes)
+        XCTAssertEqual(data, Data(bytes: [0x68, 0x65, 0x6c, 0x6c, 0xFF, 0xFF, 0x6c, 0x64]))
+    }
+    
+    func test_validateMutation_slice_immutableBacking_withUnsafeMutableBytes() {
+        var data = Data(referencing: NSData(bytes: "hello world", length: 11))[4..<9]
+        data.withUnsafeMutableBytes { (ptr: UnsafeMutablePointer<UInt8>) in
+            ptr.advanced(by: 1).pointee = 0xFF
+        }
+        XCTAssertEqual(data[data.startIndex.advanced(by: 1)], 0xFF)
+    }
+    
+    func test_validateMutation_slice_immutableBacking_appendBytes() {
+        let base: [UInt8] = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
+        var data = base.withUnsafeBufferPointer {
+            return Data(referencing: NSData(bytes: $0.baseAddress!, length: $0.count))[4..<9]
+        }
+        let bytes: [UInt8] = [0xFF, 0xFF]
+        bytes.withUnsafeBufferPointer { data.append($0.baseAddress!, count: $0.count) }
+        XCTAssertEqual(data, Data(bytes: [4, 5, 6, 7, 8, 0xFF, 0xFF]))
+    }
+    
+    func test_validateMutation_slice_immutableBacking_appendData() {
+        let base: [UInt8] = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
+        var data = base.withUnsafeBufferPointer {
+            return Data(referencing: NSData(bytes: $0.baseAddress!, length: $0.count))[4..<9]
+        }
+        data.append(Data(bytes: [0xFF, 0xFF]))
+        XCTAssertEqual(data, Data(bytes: [4, 5, 6, 7, 8, 0xFF, 0xFF]))
+    }
+    
+    func test_validateMutation_slice_immutableBacking_appendBuffer() {
+        let base: [UInt8] = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
+        var data = base.withUnsafeBufferPointer {
+            return Data(referencing: NSData(bytes: $0.baseAddress!, length: $0.count))[4..<9]
+        }
+        let bytes: [UInt8] = [0xFF, 0xFF]
+        bytes.withUnsafeBufferPointer { data.append($0) }
+        XCTAssertEqual(data, Data(bytes: [4, 5, 6, 7, 8, 0xFF, 0xFF]))
+    }
+    
+    func test_validateMutation_slice_immutableBacking_appendSequence() {
+        let base: [UInt8] = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
+        var data = base.withUnsafeBufferPointer {
+            return Data(referencing: NSData(bytes: $0.baseAddress!, length: $0.count))[4..<9]
+        }
+        data.append(contentsOf: repeatElement(UInt8(0xFF), count: 2))
+        XCTAssertEqual(data, Data(bytes: [4, 5, 6, 7, 8, 0xFF, 0xFF]))
+    }
+    
+    func test_validateMutation_slice_immutableBacking_appendContentsOf() {
+        let base: [UInt8] = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
+        var data = base.withUnsafeBufferPointer {
+            return Data(referencing: NSData(bytes: $0.baseAddress!, length: $0.count))[4..<9]
+        }
+        data.append(contentsOf: [0xFF, 0xFF])
+        XCTAssertEqual(data, Data(bytes: [4, 5, 6, 7, 8, 0xFF, 0xFF]))
+    }
+    
+    func test_validateMutation_slice_immutableBacking_resetBytes() {
+        let base: [UInt8] = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
+        var data = base.withUnsafeBufferPointer {
+            return Data(referencing: NSData(bytes: $0.baseAddress!, length: $0.count))[4..<9]
+        }
+        data.resetBytes(in: 5..<8)
+        XCTAssertEqual(data, Data(bytes: [4, 0, 0, 0, 8]))
+    }
+    
+    func test_validateMutation_slice_immutableBacking_replaceSubrange() {
+        let base: [UInt8] = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
+        var data = base.withUnsafeBufferPointer {
+            return Data(referencing: NSData(bytes: $0.baseAddress!, length: $0.count))[4..<9]
+        }
+        let range: Range<Data.Index> = data.startIndex.advanced(by: 1)..<data.endIndex.advanced(by: -1)
+        data.replaceSubrange(range, with: Data(bytes: [0xFF, 0xFF]))
+        XCTAssertEqual(data, Data(bytes: [4, 0xFF, 0xFF, 8]))
+    }
+    
+    func test_validateMutation_slice_immutableBacking_replaceSubrangeCountableRange() {
+        let base: [UInt8] = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
+        var data = base.withUnsafeBufferPointer {
+            return Data(referencing: NSData(bytes: $0.baseAddress!, length: $0.count))[4..<9]
+        }
+        let range: CountableRange<Data.Index> = data.startIndex.advanced(by: 1)..<data.endIndex.advanced(by: -1)
+        data.replaceSubrange(range, with: Data(bytes: [0xFF, 0xFF]))
+        XCTAssertEqual(data, Data(bytes: [4, 0xFF, 0xFF, 8]))
+    }
+    
+    func test_validateMutation_slice_immutableBacking_replaceSubrangeWithBuffer() {
+        let base: [UInt8] = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
+        var data = base.withUnsafeBufferPointer {
+            return Data(referencing: NSData(bytes: $0.baseAddress!, length: $0.count))[4..<9]
+        }
+        let replacement: [UInt8] = [0xFF, 0xFF]
+        let range: Range<Data.Index> = data.startIndex.advanced(by: 1)..<data.endIndex.advanced(by: -1)
+        replacement.withUnsafeBufferPointer { (buffer: UnsafeBufferPointer<UInt8>) in
+            data.replaceSubrange(range, with: buffer)
+        }
+        XCTAssertEqual(data, Data(bytes: [4, 0xFF, 0xFF, 8]))
+    }
+    
+    func test_validateMutation_slice_immutableBacking_replaceSubrangeWithCollection() {
+        let base: [UInt8] = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
+        var data = base.withUnsafeBufferPointer {
+            return Data(referencing: NSData(bytes: $0.baseAddress!, length: $0.count))[4..<9]
+        }
+        let range: Range<Data.Index> = data.startIndex.advanced(by: 1)..<data.endIndex.advanced(by: -1)
+        let replacement: [UInt8] = [0xFF, 0xFF]
+        data.replaceSubrange(range, with:replacement)
+        XCTAssertEqual(data, Data(bytes: [4, 0xFF, 0xFF, 8]))
+    }
+    
+    func test_validateMutation_slice_immutableBacking_replaceSubrangeWithBytes() {
+        let base: [UInt8] = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
+        var data = base.withUnsafeBufferPointer {
+            return Data(referencing: NSData(bytes: $0.baseAddress!, length: $0.count))[4..<9]
+        }
+        let replacement: [UInt8] = [0xFF, 0xFF]
+        let range: Range<Data.Index> = data.startIndex.advanced(by: 1)..<data.endIndex.advanced(by: -1)
+        replacement.withUnsafeBytes {
+            data.replaceSubrange(range, with: $0.baseAddress!, count: 2)
+        }
+        XCTAssertEqual(data, Data(bytes: [4, 0xFF, 0xFF, 8]))
+    }
+    
+    func test_validateMutation_cow_immutableBacking_withUnsafeMutableBytes() {
+        var data = Data(referencing: NSData(bytes: "hello world", length: 11))
+        holdReference(data) {
+            data.withUnsafeMutableBytes { (ptr: UnsafeMutablePointer<UInt8>) in
+                ptr.advanced(by: 5).pointee = 0xFF
+            }
+            XCTAssertEqual(data[data.startIndex.advanced(by: 5)], 0xFF)
+        }
+    }
+    
+    func test_validateMutation_cow_immutableBacking_appendBytes() {
+        var data = Data(referencing: NSData(bytes: "hello world", length: 11))
+        holdReference(data) {
+            data.append("hello", count: 5)
+            XCTAssertEqual(data[data.startIndex.advanced(by: 10)], 0x64)
+            XCTAssertEqual(data[data.startIndex.advanced(by: 11)], 0x68)
+        }
+    }
+    
+    func test_validateMutation_cow_immutableBacking_appendData() {
+        var data = Data(referencing: NSData(bytes: "hello world", length: 11))
+        holdReference(data) {
+            let other = Data(bytes: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9])
+            data.append(other)
+            XCTAssertEqual(data[data.startIndex.advanced(by: 10)], 0x64)
+            XCTAssertEqual(data[data.startIndex.advanced(by: 11)], 0)
+        }
+    }
+    
+    func test_validateMutation_cow_immutableBacking_appendBuffer() {
+        var data = Data(referencing: NSData(bytes: "hello world", length: 11))
+        holdReference(data) {
+            let bytes: [UInt8] = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
+            bytes.withUnsafeBufferPointer { data.append($0) }
+            XCTAssertEqual(data[data.startIndex.advanced(by: 10)], 0x64)
+            XCTAssertEqual(data[data.startIndex.advanced(by: 11)], 0)
+        }
+    }
+    
+    func test_validateMutation_cow_immutableBacking_appendSequence() {
+        var data = Data(referencing: NSData(bytes: "hello world", length: 11))
+        holdReference(data) {
+            let seq = repeatElement(UInt8(1), count: 10)
+            data.append(contentsOf: seq)
+            XCTAssertEqual(data[data.startIndex.advanced(by: 10)], 0x64)
+            XCTAssertEqual(data[data.startIndex.advanced(by: 11)], 1)
+        }
+    }
+    
+    func test_validateMutation_cow_immutableBacking_appendContentsOf() {
+        var data = Data(referencing: NSData(bytes: "hello world", length: 11))
+        holdReference(data) {
+            let bytes: [UInt8] = [1, 1, 2, 3, 4, 5, 6, 7, 8, 9]
+            data.append(contentsOf: bytes)
+            XCTAssertEqual(data[data.startIndex.advanced(by: 10)], 0x64)
+            XCTAssertEqual(data[data.startIndex.advanced(by: 11)], 1)
+        }
+    }
+    
+    func test_validateMutation_cow_immutableBacking_resetBytes() {
+        var data = Data(referencing: NSData(bytes: "hello world", length: 11))
+        holdReference(data) {
+            data.resetBytes(in: 5..<8)
+            XCTAssertEqual(data, Data(bytes: [0x68, 0x65, 0x6c, 0x6c, 0x6f, 0x00, 0x00, 0x00, 0x72, 0x6c, 0x64]))
+        }
+    }
+    
+    func test_validateMutation_cow_immutableBacking_replaceSubrange() {
+        var data = Data(referencing: NSData(bytes: "hello world", length: 11))
+        holdReference(data) {
+            let range: Range<Data.Index> = data.startIndex.advanced(by: 4)..<data.startIndex.advanced(by: 9)
+            let replacement = Data(bytes: [0xFF, 0xFF])
+            data.replaceSubrange(range, with: replacement)
+            XCTAssertEqual(data, Data(bytes: [0x68, 0x65, 0x6c, 0x6c, 0xff, 0xff, 0x6c, 0x64]))
+        }
+    }
+    
+    func test_validateMutation_cow_immutableBacking_replaceSubrangeCountableRange() {
+        var data = Data(referencing: NSData(bytes: "hello world", length: 11))
+        holdReference(data) {
+            let range: CountableRange<Data.Index> = data.startIndex.advanced(by: 4)..<data.startIndex.advanced(by: 9)
+            let replacement = Data(bytes: [0xFF, 0xFF])
+            data.replaceSubrange(range, with: replacement)
+            XCTAssertEqual(data, Data(bytes: [0x68, 0x65, 0x6c, 0x6c, 0xff, 0xff, 0x6c, 0x64]))
+        }
+    }
+    
+    func test_validateMutation_cow_immutableBacking_replaceSubrangeWithBuffer() {
+        var data = Data(referencing: NSData(bytes: "hello world", length: 11))
+        holdReference(data) {
+            let replacement: [UInt8] = [0xFF, 0xFF]
+            let range: Range<Data.Index> = data.startIndex.advanced(by: 1)..<data.endIndex.advanced(by: -1)
+            replacement.withUnsafeBufferPointer { (buffer: UnsafeBufferPointer<UInt8>) in
+                data.replaceSubrange(range, with: buffer)
+            }
+            XCTAssertEqual(data, Data(bytes: [0x68, 0xff, 0xff, 0x64]))
+        }
+    }
+    
+    func test_validateMutation_cow_immutableBacking_replaceSubrangeWithCollection() {
+        var data = Data(referencing: NSData(bytes: "hello world", length: 11))
+        holdReference(data) {
+            let replacement: [UInt8] = [0xFF, 0xFF]
+            let range: Range<Data.Index> = data.startIndex.advanced(by: 1)..<data.endIndex.advanced(by: -1)
+            data.replaceSubrange(range, with: replacement)
+            XCTAssertEqual(data, Data(bytes: [0x68, 0xff, 0xff, 0x64]))
+        }
+    }
+    
+    func test_validateMutation_cow_immutableBacking_replaceSubrangeWithBytes() {
+        var data = Data(referencing: NSData(bytes: "hello world", length: 11))
+        holdReference(data) {
+            let replacement: [UInt8] = [0xFF, 0xFF]
+            let range: Range<Data.Index> = data.startIndex.advanced(by: 1)..<data.endIndex.advanced(by: -1)
+            replacement.withUnsafeBytes {
+                data.replaceSubrange(range, with: $0.baseAddress!, count: 2)
+            }
+            XCTAssertEqual(data, Data(bytes: [0x68, 0xff, 0xff, 0x64]))
+        }
+    }
+    
+    func test_validateMutation_slice_cow_immutableBacking_withUnsafeMutableBytes() {
+        var data = Data(referencing: NSData(bytes: "hello world", length: 11))[4..<9]
+        holdReference(data) {
+            data.withUnsafeMutableBytes { (ptr: UnsafeMutablePointer<UInt8>) in
+                ptr.advanced(by: 1).pointee = 0xFF
+            }
+            XCTAssertEqual(data[data.startIndex.advanced(by: 1)], 0xFF)
+        }
+    }
+    
+    func test_validateMutation_slice_cow_immutableBacking_appendBytes() {
+        let baseBytes: [UInt8] = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
+        var data = baseBytes.withUnsafeBufferPointer {
+            return Data(referencing: NSData(bytes: $0.baseAddress!, length: $0.count))[4..<9]
+        }
+        holdReference(data) {
+            let bytes: [UInt8] = [0xFF, 0xFF]
+            bytes.withUnsafeBufferPointer { data.append($0.baseAddress!, count: $0.count) }
+            XCTAssertEqual(data, Data(bytes: [4, 5, 6, 7, 8, 0xFF, 0xFF]))
+        }
+    }
+    
+    func test_validateMutation_slice_cow_immutableBacking_appendData() {
+        let baseBytes: [UInt8] = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
+        var data = baseBytes.withUnsafeBufferPointer {
+            return Data(referencing: NSData(bytes: $0.baseAddress!, length: $0.count))[4..<9]
+        }
+        holdReference(data) {
+            data.append(Data(bytes: [0xFF, 0xFF]))
+            XCTAssertEqual(data, Data(bytes: [4, 5, 6, 7, 8, 0xFF, 0xFF]))
+        }
+    }
+    
+    func test_validateMutation_slice_cow_immutableBacking_appendBuffer() {
+        var data = Data(referencing: NSData(bytes: "hello world", length: 11))[4..<9]
+        holdReference(data) {
+            let bytes: [UInt8] = [0xFF, 0xFF]
+            bytes.withUnsafeBufferPointer{ data.append($0) }
+            XCTAssertEqual(data, Data(bytes: [0x6f, 0x20, 0x77, 0x6f, 0x72, 0xFF, 0xFF]))
+        }
+    }
+    
+    func test_validateMutation_slice_cow_immutableBacking_appendSequence() {
+        let baseBytes: [UInt8] = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
+        var data = baseBytes.withUnsafeBufferPointer {
+            return Data(referencing: NSData(bytes: $0.baseAddress!, length: $0.count))[4..<9]
+        }
+        holdReference(data) {
+            let bytes = repeatElement(UInt8(0xFF), count: 2)
+            data.append(contentsOf: bytes)
+            XCTAssertEqual(data, Data(bytes: [4, 5, 6, 7, 8, 0xFF, 0xFF]))
+        }
+    }
+    
+    func test_validateMutation_slice_cow_immutableBacking_appendContentsOf() {
+        let baseBytes: [UInt8] = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
+        var data = baseBytes.withUnsafeBufferPointer {
+            return Data(referencing: NSData(bytes: $0.baseAddress!, length: $0.count))[4..<9]
+        }
+        holdReference(data) {
+            let bytes: [UInt8] = [0xFF, 0xFF]
+            data.append(contentsOf: bytes)
+            XCTAssertEqual(data, Data(bytes: [4, 5, 6, 7, 8, 0xFF, 0xFF]))
+        }
+    }
+    
+    func test_validateMutation_slice_cow_immutableBacking_resetBytes() {
+        let baseBytes: [UInt8] = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
+        var data = baseBytes.withUnsafeBufferPointer {
+            return Data(referencing: NSData(bytes: $0.baseAddress!, length: $0.count))[4..<9]
+        }
+        holdReference(data) {
+            data.resetBytes(in: 5..<8)
+            XCTAssertEqual(data, Data(bytes: [4, 0, 0, 0, 8]))
+        }
+    }
+    
+    func test_validateMutation_slice_cow_immutableBacking_replaceSubrange() {
+        let baseBytes: [UInt8] = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
+        var data = baseBytes.withUnsafeBufferPointer {
+            return Data(referencing: NSData(bytes: $0.baseAddress!, length: $0.count))[4..<9]
+        }
+        holdReference(data) {
+            let range: Range<Data.Index> = data.startIndex.advanced(by: 1)..<data.endIndex.advanced(by: -1)
+            data.replaceSubrange(range, with: Data(bytes: [0xFF, 0xFF]))
+            XCTAssertEqual(data, Data(bytes: [4, 0xFF, 0xFF, 8]))
+        }
+    }
+    
+    func test_validateMutation_slice_cow_immutableBacking_replaceSubrangeCountableRange() {
+        let baseBytes: [UInt8] = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
+        var data = baseBytes.withUnsafeBufferPointer {
+            return Data(referencing: NSData(bytes: $0.baseAddress!, length: $0.count))[4..<9]
+        }
+        holdReference(data) {
+            let range: CountableRange<Data.Index> = data.startIndex.advanced(by: 1)..<data.endIndex.advanced(by: -1)
+            data.replaceSubrange(range, with: Data(bytes: [0xFF, 0xFF]))
+            XCTAssertEqual(data, Data(bytes: [4, 0xFF, 0xFF, 8]))
+        }
+    }
+    
+    func test_validateMutation_slice_cow_immutableBacking_replaceSubrangeWithBuffer() {
+        let baseBytes: [UInt8] = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
+        var data = baseBytes.withUnsafeBufferPointer {
+            return Data(referencing: NSData(bytes: $0.baseAddress!, length: $0.count))[4..<9]
+        }
+        holdReference(data) {
+            let range: Range<Data.Index> = data.startIndex.advanced(by: 1)..<data.endIndex.advanced(by: -1)
+            let bytes: [UInt8] = [0xFF, 0xFF]
+            bytes.withUnsafeBufferPointer { data.replaceSubrange(range, with: $0) }
+            XCTAssertEqual(data, Data(bytes: [4, 0xFF, 0xFF, 8]))
+        }
+    }
+    
+    func test_validateMutation_slice_cow_immutableBacking_replaceSubrangeWithCollection() {
+        let baseBytes: [UInt8] = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
+        var data = baseBytes.withUnsafeBufferPointer {
+            return Data(referencing: NSData(bytes: $0.baseAddress!, length: $0.count))[4..<9]
+        }
+        holdReference(data) {
+            let range: Range<Data.Index> = data.startIndex.advanced(by: 1)..<data.endIndex.advanced(by: -1)
+            let bytes: [UInt8] = [0xFF, 0xFF]
+            data.replaceSubrange(range, with: bytes)
+            XCTAssertEqual(data, Data(bytes: [4, 0xFF, 0xFF, 8]))
+        }
+    }
+    
+    func test_validateMutation_slice_cow_immutableBacking_replaceSubrangeWithBytes() {
+        let baseBytes: [UInt8] = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
+        var data = baseBytes.withUnsafeBufferPointer {
+            return Data(referencing: NSData(bytes: $0.baseAddress!, length: $0.count))[4..<9]
+        }
+        holdReference(data) {
+            let range: Range<Data.Index> = data.startIndex.advanced(by: 1)..<data.endIndex.advanced(by: -1)
+            let bytes: [UInt8] = [0xFF, 0xFF]
+            bytes.withUnsafeBytes { data.replaceSubrange(range, with: $0.baseAddress!, count: 2) }
+            XCTAssertEqual(data, Data(bytes: [4, 0xFF, 0xFF, 8]))
+        }
+    }
+    
+    func test_validateMutation_mutableBacking_withUnsafeMutableBytes() {
+        let baseBytes: [UInt8] = [0, 1, 2, 3, 4, 5, 6]
+        var data = baseBytes.withUnsafeBufferPointer {
+            return Data(referencing: NSData(bytes: $0.baseAddress!, length: $0.count))
+        }
+        data.append(contentsOf: [7, 8, 9])
+        data.withUnsafeMutableBytes { (ptr: UnsafeMutablePointer<UInt8>) in
+            ptr.advanced(by: 5).pointee = 0xFF
+        }
+        XCTAssertEqual(data[data.startIndex.advanced(by: 5)], 0xFF)
+    }
+    
+    func test_validateMutation_mutableBacking_appendBytes() {
+        let baseBytes: [UInt8] = [0, 1, 2, 3, 4, 5, 6]
+        var data = baseBytes.withUnsafeBufferPointer {
+            return Data(referencing: NSData(bytes: $0.baseAddress!, length: $0.count))
+        }
+        data.append(contentsOf: [7, 8, 9])
+        let bytes: [UInt8] = [0xFF, 0xFF]
+        bytes.withUnsafeBufferPointer { data.append($0.baseAddress!, count: $0.count) }
+        XCTAssertEqual(data, Data(bytes: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0xFF, 0xFF]))
+    }
+    
+    func test_validateMutation_mutableBacking_appendData() {
+        let baseBytes: [UInt8] = [0, 1, 2, 3, 4, 5, 6]
+        var data = baseBytes.withUnsafeBufferPointer {
+            return Data(referencing: NSData(bytes: $0.baseAddress!, length: $0.count))
+        }
+        data.append(contentsOf: [7, 8, 9])
+        data.append(Data(bytes: [0xFF, 0xFF]))
+        XCTAssertEqual(data, Data(bytes: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0xFF, 0xFF]))
+    }
+    
+    func test_validateMutation_mutableBacking_appendBuffer() {
+        let baseBytes: [UInt8] = [0, 1, 2, 3, 4, 5, 6]
+        var data = baseBytes.withUnsafeBufferPointer {
+            return Data(referencing: NSData(bytes: $0.baseAddress!, length: $0.count))
+        }
+        data.append(contentsOf: [7, 8, 9])
+        let bytes: [UInt8] = [0xFF, 0xFF]
+        bytes.withUnsafeBufferPointer { data.append($0) }
+        XCTAssertEqual(data, Data(bytes: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0xFF, 0xFF]))
+    }
+    
+    func test_validateMutation_mutableBacking_appendSequence() {
+        let baseBytes: [UInt8] = [0, 1, 2, 3, 4, 5, 6]
+        var data = baseBytes.withUnsafeBufferPointer {
+            return Data(referencing: NSData(bytes: $0.baseAddress!, length: $0.count))
+        }
+        data.append(contentsOf: [7, 8, 9])
+        data.append(contentsOf: repeatElement(UInt8(0xFF), count: 2))
+        XCTAssertEqual(data, Data(bytes: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0xFF, 0xFF]))
+    }
+    
+    func test_validateMutation_mutableBacking_appendContentsOf() {
+        let baseBytes: [UInt8] = [0, 1, 2, 3, 4, 5, 6]
+        var data = baseBytes.withUnsafeBufferPointer {
+            return Data(referencing: NSData(bytes: $0.baseAddress!, length: $0.count))
+        }
+        data.append(contentsOf: [7, 8, 9])
+        data.append(contentsOf: [0xFF, 0xFF])
+        XCTAssertEqual(data, Data(bytes: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0xFF, 0xFF]))
+    }
+    
+    func test_validateMutation_mutableBacking_resetBytes() {
+        let baseBytes: [UInt8] = [0, 1, 2, 3, 4, 5, 6]
+        var data = baseBytes.withUnsafeBufferPointer {
+            return Data(referencing: NSData(bytes: $0.baseAddress!, length: $0.count))
+        }
+        data.append(contentsOf: [7, 8, 9])
+        data.resetBytes(in: 5..<8)
+        XCTAssertEqual(data, Data(bytes: [0, 1, 2, 3, 4, 0, 0, 0, 8, 9]))
+    }
+    
+    func test_validateMutation_mutableBacking_replaceSubrange() {
+        let baseBytes: [UInt8] = [0, 1, 2, 3, 4, 5, 6]
+        var data = baseBytes.withUnsafeBufferPointer {
+            return Data(referencing: NSData(bytes: $0.baseAddress!, length: $0.count))
+        }
+        data.append(contentsOf: [7, 8, 9])
+        let range: Range<Data.Index> = data.startIndex.advanced(by: 1)..<data.endIndex.advanced(by: -1)
+        let replacement = Data(bytes: [0xFF, 0xFF])
+        data.replaceSubrange(range, with: replacement)
+        XCTAssertEqual(data, Data(bytes: [0, 0xFF, 0xFF, 9]))
+    }
+    
+    func test_validateMutation_mutableBacking_replaceSubrangeCountableRange() {
+        let baseBytes: [UInt8] = [0, 1, 2, 3, 4, 5, 6]
+        var data = baseBytes.withUnsafeBufferPointer {
+            return Data(referencing: NSData(bytes: $0.baseAddress!, length: $0.count))
+        }
+        data.append(contentsOf: [7, 8, 9])
+        let range: CountableRange<Data.Index> = data.startIndex.advanced(by: 1)..<data.endIndex.advanced(by: -1)
+        let replacement = Data(bytes: [0xFF, 0xFF])
+        data.replaceSubrange(range, with: replacement)
+        XCTAssertEqual(data, Data(bytes: [0, 0xFF, 0xFF, 9]))
+    }
+    
+    func test_validateMutation_mutableBacking_replaceSubrangeWithBuffer() {
+        let baseBytes: [UInt8] = [0, 1, 2, 3, 4, 5, 6]
+        var data = baseBytes.withUnsafeBufferPointer {
+            return Data(referencing: NSData(bytes: $0.baseAddress!, length: $0.count))
+        }
+        data.append(contentsOf: [7, 8, 9])
+        let range: Range<Data.Index> = data.startIndex.advanced(by: 1)..<data.endIndex.advanced(by: -1)
+        let bytes: [UInt8] = [0xFF, 0xFF]
+        bytes.withUnsafeBufferPointer {
+            data.replaceSubrange(range, with: $0)
+        }
+        XCTAssertEqual(data, Data(bytes: [0, 0xFF, 0xFF, 9]))
+    }
+    
+    func test_validateMutation_mutableBacking_replaceSubrangeWithCollection() {
+        let baseBytes: [UInt8] = [0, 1, 2, 3, 4, 5, 6]
+        var data = baseBytes.withUnsafeBufferPointer {
+            return Data(referencing: NSData(bytes: $0.baseAddress!, length: $0.count))
+        }
+        data.append(contentsOf: [7, 8, 9])
+        let range: Range<Data.Index> = data.startIndex.advanced(by: 1)..<data.endIndex.advanced(by: -1)
+        data.replaceSubrange(range, with: [0xFF, 0xFF])
+        XCTAssertEqual(data, Data(bytes: [0, 0xFF, 0xFF, 9]))
+    }
+    
+    func test_validateMutation_mutableBacking_replaceSubrangeWithBytes() {
+        let baseBytes: [UInt8] = [0, 1, 2, 3, 4, 5, 6]
+        var data = baseBytes.withUnsafeBufferPointer {
+            return Data(referencing: NSData(bytes: $0.baseAddress!, length: $0.count))
+        }
+        data.append(contentsOf: [7, 8, 9])
+        let range: Range<Data.Index> = data.startIndex.advanced(by: 1)..<data.endIndex.advanced(by: -1)
+        let bytes: [UInt8] = [0xFF, 0xFF]
+        bytes.withUnsafeBytes {
+            data.replaceSubrange(range, with: $0.baseAddress!, count: $0.count)
+        }
+        XCTAssertEqual(data, Data(bytes: [0, 0xFF, 0xFF, 9]))
+    }
+    
+    func test_validateMutation_slice_mutableBacking_withUnsafeMutableBytes() {
+        var base = Data(referencing: NSData(bytes: "hello world", length: 11))
+        base.append(contentsOf: [1, 2, 3, 4, 5, 6])
+        var data = base[4..<9]
+        data.withUnsafeMutableBytes { (ptr: UnsafeMutablePointer<UInt8>) in
+            ptr.advanced(by: 1).pointee = 0xFF
+        }
+        XCTAssertEqual(data[data.startIndex.advanced(by: 1)], 0xFF)
+    }
+    
+    func test_validateMutation_slice_mutableBacking_appendBytes() {
+        let baseBytes: [UInt8] = [0, 1, 2, 3, 4, 5, 6]
+        var base = baseBytes.withUnsafeBufferPointer {
+            return Data(referencing: NSData(bytes: $0.baseAddress!, length: $0.count))
+        }
+        base.append(contentsOf: [7, 8, 9])
+        var data = base[4..<9]
+        let bytes: [UInt8] = [0xFF, 0xFF]
+        bytes.withUnsafeBufferPointer { data.append($0.baseAddress!, count: $0.count) }
+        XCTAssertEqual(data, Data(bytes: [4, 5, 6, 7, 8, 0xFF, 0xFF]))
+    }
+    
+    func test_validateMutation_slice_mutableBacking_appendData() {
+        let baseBytes: [UInt8] = [0, 1, 2, 3, 4, 5, 6]
+        var base = baseBytes.withUnsafeBufferPointer {
+            return Data(referencing: NSData(bytes: $0.baseAddress!, length: $0.count))
+        }
+        base.append(contentsOf: [7, 8, 9])
+        var data = base[4..<9]
+        data.append(Data(bytes: [0xFF, 0xFF]))
+        XCTAssertEqual(data, Data(bytes: [4, 5, 6, 7, 8, 0xFF, 0xFF]))
+    }
+    
+    func test_validateMutation_slice_mutableBacking_appendBuffer() {
+        var base = Data(referencing: NSData(bytes: "hello world", length: 11))
+        base.append(contentsOf: [1, 2, 3, 4, 5, 6])
+        var data = base[4..<9]
+        let bytes: [UInt8] = [1, 2, 3]
+        bytes.withUnsafeBufferPointer { data.append($0) }
+        XCTAssertEqual(data, Data(bytes: [0x6f, 0x20, 0x77, 0x6f, 0x72, 0x1, 0x2, 0x3]))
+    }
+    
+    func test_validateMutation_slice_mutableBacking_appendSequence() {
+        var base = Data(referencing: NSData(bytes: "hello world", length: 11))
+        base.append(contentsOf: [1, 2, 3, 4, 5, 6])
+        var data = base[4..<9]
+        let seq = repeatElement(UInt8(1), count: 3)
+        data.append(contentsOf: seq)
+        XCTAssertEqual(data, Data(bytes: [0x6f, 0x20, 0x77, 0x6f, 0x72, 0x1, 0x1, 0x1]))
+    }
+    
+    func test_validateMutation_slice_mutableBacking_appendContentsOf() {
+        var base = Data(referencing: NSData(bytes: "hello world", length: 11))
+        base.append(contentsOf: [1, 2, 3, 4, 5, 6])
+        var data = base[4..<9]
+        let bytes: [UInt8] = [1, 2, 3]
+        data.append(contentsOf: bytes)
+        XCTAssertEqual(data, Data(bytes: [0x6f, 0x20, 0x77, 0x6f, 0x72, 0x1, 0x2, 0x3]))
+    }
+    
+    func test_validateMutation_slice_mutableBacking_resetBytes() {
+        let baseBytes: [UInt8] = [0, 1, 2, 3, 4, 5, 6]
+        var base = baseBytes.withUnsafeBufferPointer {
+            return Data(referencing: NSData(bytes: $0.baseAddress!, length: $0.count))
+        }
+        base.append(contentsOf: [7, 8, 9])
+        var data = base[4..<9]
+        data.resetBytes(in: 5..<8)
+        XCTAssertEqual(data, Data(bytes: [4, 0, 0, 0, 8]))
+    }
+    
+    func test_validateMutation_slice_mutableBacking_replaceSubrange() {
+        var base = Data(referencing: NSData(bytes: "hello world", length: 11))
+        base.append(contentsOf: [1, 2, 3, 4, 5, 6])
+        var data = base[4..<9]
+        let range: Range<Data.Index> = data.startIndex.advanced(by: 1)..<data.endIndex.advanced(by: -1)
+        data.replaceSubrange(range, with: Data(bytes: [0xFF, 0xFF]))
+        XCTAssertEqual(data, Data(bytes: [0x6f, 0xFF, 0xFF, 0x72]))
+    }
+    
+    func test_validateMutation_slice_mutableBacking_replaceSubrangeCountableRange() {
+        var base = Data(referencing: NSData(bytes: "hello world", length: 11))
+        base.append(contentsOf: [1, 2, 3, 4, 5, 6])
+        var data = base[4..<9]
+        let range: CountableRange<Data.Index> = data.startIndex.advanced(by: 1)..<data.endIndex.advanced(by: -1)
+        data.replaceSubrange(range, with: Data(bytes: [0xFF, 0xFF]))
+        XCTAssertEqual(data, Data(bytes: [0x6f, 0xFF, 0xFF, 0x72]))
+    }
+    
+    func test_validateMutation_slice_mutableBacking_replaceSubrangeWithBuffer() {
+        var base = Data(referencing: NSData(bytes: "hello world", length: 11))
+        base.append(contentsOf: [1, 2, 3, 4, 5, 6])
+        var data = base[4..<9]
+        let replacement: [UInt8] = [0xFF, 0xFF]
+        let range: Range<Data.Index> = data.startIndex.advanced(by: 1)..<data.endIndex.advanced(by: -1)
+        replacement.withUnsafeBufferPointer { (buffer: UnsafeBufferPointer<UInt8>) in
+            data.replaceSubrange(range, with: buffer)
+        }
+        XCTAssertEqual(data, Data(bytes: [0x6f, 0xFF, 0xFF, 0x72]))
+    }
+    
+    func test_validateMutation_slice_mutableBacking_replaceSubrangeWithCollection() {
+        var base = Data(referencing: NSData(bytes: "hello world", length: 11))
+        base.append(contentsOf: [1, 2, 3, 4, 5, 6])
+        var data = base[4..<9]
+        let range: Range<Data.Index> = data.startIndex.advanced(by: 1)..<data.endIndex.advanced(by: -1)
+        let replacement: [UInt8] = [0xFF, 0xFF]
+        data.replaceSubrange(range, with:replacement)
+        XCTAssertEqual(data, Data(bytes: [0x6f, 0xFF, 0xFF, 0x72]))
+    }
+    
+    func test_validateMutation_slice_mutableBacking_replaceSubrangeWithBytes() {
+        var base = Data(referencing: NSData(bytes: "hello world", length: 11))
+        base.append(contentsOf: [1, 2, 3, 4, 5, 6])
+        var data = base[4..<9]
+        let replacement: [UInt8] = [0xFF, 0xFF]
+        let range: Range<Data.Index> = data.startIndex.advanced(by: 1)..<data.endIndex.advanced(by: -1)
+        replacement.withUnsafeBytes {
+            data.replaceSubrange(range, with: $0.baseAddress!, count: 2)
+        }
+        XCTAssertEqual(data, Data(bytes: [0x6f, 0xFF, 0xFF, 0x72]))
+    }
+    
+    func test_validateMutation_cow_mutableBacking_withUnsafeMutableBytes() {
+        var data = Data(referencing: NSData(bytes: "hello world", length: 11))
+        data.append(contentsOf: [1, 2, 3, 4, 5, 6])
+        holdReference(data) {
+            data.withUnsafeMutableBytes { (ptr: UnsafeMutablePointer<UInt8>) in
+                ptr.advanced(by: 5).pointee = 0xFF
+            }
+            XCTAssertEqual(data[data.startIndex.advanced(by: 5)], 0xFF)
+        }
+    }
+    
+    func test_validateMutation_cow_mutableBacking_appendBytes() {
+        var data = Data(referencing: NSData(bytes: "hello world", length: 11))
+        data.append(contentsOf: [1, 2, 3, 4, 5, 6])
+        holdReference(data) {
+            data.append("hello", count: 5)
+            XCTAssertEqual(data[data.startIndex.advanced(by: 16)], 6)
+            XCTAssertEqual(data[data.startIndex.advanced(by: 17)], 0x68)
+        }
+    }
+    
+    func test_validateMutation_cow_mutableBacking_appendData() {
+        var data = Data(referencing: NSData(bytes: "hello world", length: 11))
+        data.append(contentsOf: [1, 2, 3, 4, 5, 6])
+        holdReference(data) {
+            data.append("hello", count: 5)
+            XCTAssertEqual(data[data.startIndex.advanced(by: 16)], 6)
+            XCTAssertEqual(data[data.startIndex.advanced(by: 17)], 0x68)
+        }
+    }
+    
+    func test_validateMutation_cow_mutableBacking_appendBuffer() {
+        var data = Data(referencing: NSData(bytes: "hello world", length: 11))
+        data.append(contentsOf: [1, 2, 3, 4, 5, 6])
+        holdReference(data) {
+            let other = Data(bytes: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9])
+            data.append(other)
+            XCTAssertEqual(data[data.startIndex.advanced(by: 16)], 6)
+            XCTAssertEqual(data[data.startIndex.advanced(by: 17)], 0)
+        }
+    }
+    
+    func test_validateMutation_cow_mutableBacking_appendSequence() {
+        var data = Data(referencing: NSData(bytes: "hello world", length: 11))
+        data.append(contentsOf: [1, 2, 3, 4, 5, 6])
+        holdReference(data) {
+            let seq = repeatElement(UInt8(1), count: 10)
+            data.append(contentsOf: seq)
+            XCTAssertEqual(data[data.startIndex.advanced(by: 16)], 6)
+            XCTAssertEqual(data[data.startIndex.advanced(by: 17)], 1)
+        }
+    }
+    
+    func test_validateMutation_cow_mutableBacking_appendContentsOf() {
+        var data = Data(referencing: NSData(bytes: "hello world", length: 11))
+        data.append(contentsOf: [1, 2, 3, 4, 5, 6])
+        holdReference(data) {
+            let bytes: [UInt8] = [1, 1, 2, 3, 4, 5, 6, 7, 8, 9]
+            data.append(contentsOf: bytes)
+            XCTAssertEqual(data[data.startIndex.advanced(by: 16)], 6)
+            XCTAssertEqual(data[data.startIndex.advanced(by: 17)], 1)
+        }
+    }
+    
+    func test_validateMutation_cow_mutableBacking_resetBytes() {
+        var data = Data(referencing: NSData(bytes: "hello world", length: 11))
+        data.append(contentsOf: [1, 2, 3, 4, 5, 6])
+        holdReference(data) {
+            data.resetBytes(in: 5..<8)
+            XCTAssertEqual(data, Data(bytes: [0x68, 0x65, 0x6c, 0x6c, 0x6f, 0x00, 0x00, 0x00, 0x72, 0x6c, 0x64, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06]))
+        }
+    }
+    
+    func test_validateMutation_cow_mutableBacking_replaceSubrange() {
+        var data = Data(referencing: NSData(bytes: "hello world", length: 11))
+        data.append(contentsOf: [1, 2, 3, 4, 5, 6])
+        holdReference(data) {
+            let range: Range<Data.Index> = data.startIndex.advanced(by: 4)..<data.startIndex.advanced(by: 9)
+            let replacement = Data(bytes: [0xFF, 0xFF])
+            data.replaceSubrange(range, with: replacement)
+            XCTAssertEqual(data, Data(bytes: [0x68, 0x65, 0x6c, 0x6c, 0xff, 0xff, 0x6c, 0x64, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06]))
+        }
+    }
+    
+    func test_validateMutation_cow_mutableBacking_replaceSubrangeCountableRange() {
+        var data = Data(referencing: NSData(bytes: "hello world", length: 11))
+        data.append(contentsOf: [1, 2, 3, 4, 5, 6])
+        holdReference(data) {
+            let range: CountableRange<Data.Index> = data.startIndex.advanced(by: 4)..<data.startIndex.advanced(by: 9)
+            let replacement = Data(bytes: [0xFF, 0xFF])
+            data.replaceSubrange(range, with: replacement)
+            XCTAssertEqual(data, Data(bytes: [0x68, 0x65, 0x6c, 0x6c, 0xff, 0xff, 0x6c, 0x64, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06]))
+        }
+    }
+    
+    func test_validateMutation_cow_mutableBacking_replaceSubrangeWithBuffer() {
+        var data = Data(referencing: NSData(bytes: "hello world", length: 11))
+        data.append(contentsOf: [1, 2, 3, 4, 5, 6])
+        holdReference(data) {
+            let range: Range<Data.Index> = data.startIndex.advanced(by: 4)..<data.startIndex.advanced(by: 9)
+            let replacement: [UInt8] = [0xFF, 0xFF]
+            replacement.withUnsafeBufferPointer { (buffer: UnsafeBufferPointer<UInt8>) in
+                data.replaceSubrange(range, with: buffer)
+            }
+            XCTAssertEqual(data, Data(bytes: [0x68, 0x65, 0x6c, 0x6c, 0xff, 0xff, 0x6c, 0x64, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06]))
+        }
+    }
+    
+    func test_validateMutation_cow_mutableBacking_replaceSubrangeWithCollection() {
+        var data = Data(referencing: NSData(bytes: "hello world", length: 11))
+        data.append(contentsOf: [1, 2, 3, 4, 5, 6])
+        holdReference(data) {
+            let replacement: [UInt8] = [0xFF, 0xFF]
+            let range: Range<Data.Index> = data.startIndex.advanced(by: 4)..<data.startIndex.advanced(by: 9)
+            data.replaceSubrange(range, with: replacement)
+            XCTAssertEqual(data, Data(bytes: [0x68, 0x65, 0x6c, 0x6c, 0xff, 0xff, 0x6c, 0x64, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06]))
+        }
+    }
+    
+    func test_validateMutation_cow_mutableBacking_replaceSubrangeWithBytes() {
+        var data = Data(referencing: NSData(bytes: "hello world", length: 11))
+        data.append(contentsOf: [1, 2, 3, 4, 5, 6])
+        holdReference(data) {
+            let replacement: [UInt8] = [0xFF, 0xFF]
+            let range: Range<Data.Index> = data.startIndex.advanced(by: 4)..<data.startIndex.advanced(by: 9)
+            replacement.withUnsafeBytes {
+                data.replaceSubrange(range, with: $0.baseAddress!, count: 2)
+            }
+            XCTAssertEqual(data, Data(bytes: [0x68, 0x65, 0x6c, 0x6c, 0xff, 0xff, 0x6c, 0x64, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06]))
+        }
+    }
+    
+    func test_validateMutation_slice_cow_mutableBacking_withUnsafeMutableBytes() {
+        var base = Data(referencing: NSData(bytes: "hello world", length: 11))
+        base.append(contentsOf: [1, 2, 3, 4, 5, 6])
+        var data = base[4..<9]
+        holdReference(data) {
+            data.withUnsafeMutableBytes { (ptr: UnsafeMutablePointer<UInt8>) in
+                ptr.advanced(by: 1).pointee = 0xFF
+            }
+            XCTAssertEqual(data[data.startIndex.advanced(by: 1)], 0xFF)
+        }
+    }
+    
+    func test_validateMutation_slice_cow_mutableBacking_appendBytes() {
+        let bytes: [UInt8] = [0, 1, 2]
+        var base = bytes.withUnsafeBytes { (ptr) in
+            return Data(referencing: NSData(bytes: ptr.baseAddress!, length: ptr.count))
+        }
+        base.append(contentsOf: [3, 4, 5])
+        var data = base[1..<4]
+        holdReference(data) {
+            let bytesToAppend: [UInt8] = [6, 7, 8]
+            bytesToAppend.withUnsafeBytes { (ptr) in
+                data.append(ptr.baseAddress!.assumingMemoryBound(to: UInt8.self), count: ptr.count)
+            }
+            XCTAssertEqual(data, Data(bytes: [1, 2, 3, 6, 7, 8]))
+        }
+    }
+    
+    func test_validateMutation_slice_cow_mutableBacking_appendData() {
+        let baseBytes: [UInt8] = [0, 1, 2, 3, 4, 5, 6]
+        var base = baseBytes.withUnsafeBufferPointer {
+            return Data(referencing: NSData(bytes: $0.baseAddress!, length: $0.count))
+        }
+        base.append(contentsOf: [7, 8, 9])
+        var data = base[4..<9]
+        holdReference(data) {
+            data.append(Data(bytes: [0xFF, 0xFF]))
+            XCTAssertEqual(data, Data(bytes: [4, 5, 6, 7, 8, 0xFF, 0xFF]))
+        }
+    }
+    
+    func test_validateMutation_slice_cow_mutableBacking_appendBuffer() {
+        let baseBytes: [UInt8] = [0, 1, 2, 3, 4, 5, 6]
+        var base = baseBytes.withUnsafeBufferPointer {
+            return Data(referencing: NSData(bytes: $0.baseAddress!, length: $0.count))
+        }
+        base.append(contentsOf: [7, 8, 9])
+        var data = base[4..<9]
+        holdReference(data) {
+            let bytes: [UInt8] = [0xFF, 0xFF]
+            bytes.withUnsafeBufferPointer{ data.append($0) }
+            XCTAssertEqual(data, Data(bytes: [4, 5, 6, 7, 8, 0xFF, 0xFF]))
+        }
+    }
+    
+    func test_validateMutation_slice_cow_mutableBacking_appendSequence() {
+        let baseBytes: [UInt8] = [0, 1, 2, 3, 4, 5, 6]
+        var base = baseBytes.withUnsafeBufferPointer {
+            return Data(referencing: NSData(bytes: $0.baseAddress!, length: $0.count))
+        }
+        base.append(contentsOf: [7, 8, 9])
+        var data = base[4..<9]
+        holdReference(data) {
+            let bytes = repeatElement(UInt8(0xFF), count: 2)
+            data.append(contentsOf: bytes)
+            XCTAssertEqual(data, Data(bytes: [4, 5, 6, 7, 8, 0xFF, 0xFF]))
+        }
+    }
+    
+    func test_validateMutation_slice_cow_mutableBacking_appendContentsOf() {
+        let baseBytes: [UInt8] = [0, 1, 2, 3, 4, 5, 6]
+        var base = baseBytes.withUnsafeBufferPointer {
+            return Data(referencing: NSData(bytes: $0.baseAddress!, length: $0.count))
+        }
+        base.append(contentsOf: [7, 8, 9])
+        var data = base[4..<9]
+        holdReference(data) {
+            let bytes: [UInt8] = [0xFF, 0xFF]
+            data.append(contentsOf: bytes)
+            XCTAssertEqual(data, Data(bytes: [4, 5, 6, 7, 8, 0xFF, 0xFF]))
+        }
+    }
+    
+    func test_validateMutation_slice_cow_mutableBacking_resetBytes() {
+        let baseBytes: [UInt8] = [0, 1, 2, 3, 4, 5, 6]
+        var base = baseBytes.withUnsafeBufferPointer {
+            return Data(referencing: NSData(bytes: $0.baseAddress!, length: $0.count))
+        }
+        base.append(contentsOf: [7, 8, 9])
+        var data = base[4..<9]
+        holdReference(data) {
+            data.resetBytes(in: 5..<8)
+            XCTAssertEqual(data, Data(bytes: [4, 0, 0, 0, 8]))
+        }
+    }
+    
+    func test_validateMutation_slice_cow_mutableBacking_replaceSubrange() {
+        let baseBytes: [UInt8] = [0, 1, 2, 3, 4, 5, 6]
+        var base = baseBytes.withUnsafeBufferPointer {
+            return Data(referencing: NSData(bytes: $0.baseAddress!, length: $0.count))
+        }
+        base.append(contentsOf: [7, 8, 9])
+        var data = base[4..<9]
+        holdReference(data) {
+            let range: Range<Data.Index> = data.startIndex.advanced(by: 1)..<data.endIndex.advanced(by: -1)
+            data.replaceSubrange(range, with: Data(bytes: [0xFF, 0xFF]))
+            XCTAssertEqual(data, Data(bytes: [4, 0xFF, 0xFF, 8]))
+        }
+    }
+    
+    func test_validateMutation_slice_cow_mutableBacking_replaceSubrangeCountableRange() {
+        let baseBytes: [UInt8] = [0, 1, 2, 3, 4, 5, 6]
+        var base = baseBytes.withUnsafeBufferPointer {
+            return Data(referencing: NSData(bytes: $0.baseAddress!, length: $0.count))
+        }
+        base.append(contentsOf: [7, 8, 9])
+        var data = base[4..<9]
+        holdReference(data) {
+            let range: CountableRange<Data.Index> = data.startIndex.advanced(by: 1)..<data.endIndex.advanced(by: -1)
+            data.replaceSubrange(range, with: Data(bytes: [0xFF, 0xFF]))
+            XCTAssertEqual(data, Data(bytes: [4, 0xFF, 0xFF, 8]))
+        }
+    }
+    
+    func test_validateMutation_slice_cow_mutableBacking_replaceSubrangeWithBuffer() {
+        let baseBytes: [UInt8] = [0, 1, 2, 3, 4, 5, 6]
+        var base = baseBytes.withUnsafeBufferPointer {
+            return Data(referencing: NSData(bytes: $0.baseAddress!, length: $0.count))
+        }
+        base.append(contentsOf: [7, 8, 9])
+        var data = base[4..<9]
+        holdReference(data) {
+            let range: Range<Data.Index> = data.startIndex.advanced(by: 1)..<data.endIndex.advanced(by: -1)
+            let bytes: [UInt8] = [0xFF, 0xFF]
+            bytes.withUnsafeBufferPointer { data.replaceSubrange(range, with: $0) }
+            XCTAssertEqual(data, Data(bytes: [4, 0xFF, 0xFF, 8]))
+        }
+    }
+    
+    func test_validateMutation_slice_cow_mutableBacking_replaceSubrangeWithCollection() {
+        let baseBytes: [UInt8] = [0, 1, 2, 3, 4, 5, 6]
+        var base = baseBytes.withUnsafeBufferPointer {
+            return Data(referencing: NSData(bytes: $0.baseAddress!, length: $0.count))
+        }
+        base.append(contentsOf: [7, 8, 9])
+        var data = base[4..<9]
+        holdReference(data) {
+            let range: Range<Data.Index> = data.startIndex.advanced(by: 1)..<data.endIndex.advanced(by: -1)
+            let bytes: [UInt8] = [0xFF, 0xFF]
+            data.replaceSubrange(range, with: bytes)
+            XCTAssertEqual(data, Data(bytes: [4, 0xFF, 0xFF, 8]))
+        }
+    }
+    
+    func test_validateMutation_slice_cow_mutableBacking_replaceSubrangeWithBytes() {
+        let baseBytes: [UInt8] = [0, 1, 2, 3, 4, 5, 6]
+        var base = baseBytes.withUnsafeBufferPointer {
+            return Data(referencing: NSData(bytes: $0.baseAddress!, length: $0.count))
+        }
+        base.append(contentsOf: [7, 8, 9])
+        var data = base[4..<9]
+        holdReference(data) {
+            let range: Range<Data.Index> = data.startIndex.advanced(by: 1)..<data.endIndex.advanced(by: -1)
+            let bytes: [UInt8] = [0xFF, 0xFF]
+            bytes.withUnsafeBytes { data.replaceSubrange(range, with: $0.baseAddress!, count: 2) }
+            XCTAssertEqual(data, Data(bytes: [4, 0xFF, 0xFF, 8]))
+        }
+    }
+    
+    func test_validateMutation_customBacking_withUnsafeMutableBytes() {
+        var data = Data(referencing: AllOnesImmutableData(length: 10))
+        data.withUnsafeMutableBytes { (ptr: UnsafeMutablePointer<UInt8>) in
+            ptr.advanced(by: 5).pointee = 0xFF
+        }
+        XCTAssertEqual(data, Data(bytes: [1, 1, 1, 1, 1, 0xFF, 1, 1, 1, 1]))
+    }
+    
+#if false // this requires factory patterns
+    func test_validateMutation_customBacking_appendBytes() {
+        var data = Data(referencing: AllOnesImmutableData(length: 10))
+        let bytes: [UInt8] = [0xFF, 0xFF]
+        bytes.withUnsafeBufferPointer { data.append($0.baseAddress!, count: $0.count) }
+        XCTAssertEqual(data, Data(bytes: [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0xFF, 0xFF]))
+    }
+    
+    func test_validateMutation_customBacking_appendData() {
+        var data = Data(referencing: AllOnesImmutableData(length: 10))
+        data.append(Data(bytes: [0xFF, 0xFF]))
+        XCTAssertEqual(data, Data(bytes: [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0xFF, 0xFF]))
+    }
+    
+    func test_validateMutation_customBacking_appendBuffer() {
+        var data = Data(referencing: AllOnesImmutableData(length: 10))
+        let bytes: [UInt8] = [0xFF, 0xFF]
+        bytes.withUnsafeBufferPointer { (buffer) in
+            data.append(buffer)
+        }
+        XCTAssertEqual(data, Data(bytes: [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0xFF, 0xFF]))
+        
+    }
+    
+    func test_validateMutation_customBacking_appendSequence() {
+        var data = Data(referencing: AllOnesImmutableData(length: 10))
+        data.append(contentsOf: repeatElement(UInt8(0xFF), count: 2))
+        XCTAssertEqual(data, Data(bytes: [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0xFF, 0xFF]))
+    }
+    
+    func test_validateMutation_customBacking_appendContentsOf() {
+        var data = Data(referencing: AllOnesImmutableData(length: 10))
+        data.append(contentsOf: [0xFF, 0xFF])
+        XCTAssertEqual(data, Data(bytes: [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0xFF, 0xFF]))
+    }
+    
+    func test_validateMutation_customBacking_resetBytes() {
+        var data = Data(referencing: AllOnesImmutableData(length: 10))
+        data.resetBytes(in: 5..<8)
+        XCTAssertEqual(data, Data(bytes: [1, 1, 1, 1, 1, 0, 0, 0, 1, 1]))
+    }
+    
+    func test_validateMutation_customBacking_replaceSubrange() {
+        var data = Data(referencing: AllOnesImmutableData(length: 10))
+        let range: Range<Int> = 1..<4
+        data.replaceSubrange(range, with: Data(bytes: [0xFF, 0xFF]))
+        XCTAssertEqual(data, Data(bytes: [1, 0xFF, 0xFF, 1, 1, 1, 1, 1, 1]))
+    }
+    
+    func test_validateMutation_customBacking_replaceSubrangeCountableRange() {
+        var data = Data(referencing: AllOnesImmutableData(length: 10))
+        let range: CountableRange<Int> = 1..<4
+        data.replaceSubrange(range, with: Data(bytes: [0xFF, 0xFF]))
+        XCTAssertEqual(data, Data(bytes: [1, 0xFF, 0xFF, 1, 1, 1, 1, 1, 1]))
+    }
+    
+    func test_validateMutation_customBacking_replaceSubrangeWithBuffer() {
+        var data = Data(referencing: AllOnesImmutableData(length: 10))
+        let bytes: [UInt8] = [0xFF, 0xFF]
+        let range: Range<Int> = 1..<4
+        bytes.withUnsafeBufferPointer { (buffer) in
+            data.replaceSubrange(range, with: buffer)
+        }
+        XCTAssertEqual(data, Data(bytes: [1, 0xFF, 0xFF, 1, 1, 1, 1, 1, 1]))
+    }
+    
+    func test_validateMutation_customBacking_replaceSubrangeWithCollection() {
+        var data = Data(referencing: AllOnesImmutableData(length: 10))
+        let range: Range<Int> = 1..<4
+        data.replaceSubrange(range, with: [0xFF, 0xFF])
+        XCTAssertEqual(data, Data(bytes: [1, 0xFF, 0xFF, 1, 1, 1, 1, 1, 1]))
+    }
+    
+    func test_validateMutation_customBacking_replaceSubrangeWithBytes() {
+        var data = Data(referencing: AllOnesImmutableData(length: 10))
+        let bytes: [UInt8] = [0xFF, 0xFF]
+        let range: Range<Int> = 1..<5
+        bytes.withUnsafeBufferPointer { (buffer) in
+            data.replaceSubrange(range, with: buffer.baseAddress!, count: buffer.count)
+        }
+        XCTAssertEqual(data, Data(bytes: [1, 0xFF, 0xFF, 1, 1, 1, 1, 1]))
+    }
+    
+    func test_validateMutation_slice_customBacking_withUnsafeMutableBytes() {
+        var data = Data(referencing: AllOnesImmutableData(length: 10))[4..<9]
+        data.withUnsafeMutableBytes { (ptr: UnsafeMutablePointer<UInt8>) in
+            ptr.advanced(by: 1).pointee = 0xFF
+        }
+        XCTAssertEqual(data[data.startIndex.advanced(by: 1)], 0xFF)
+    }
+    
+    func test_validateMutation_slice_customBacking_appendBytes() {
+        var data = Data(referencing: AllOnesImmutableData(length: 10))[4..<9]
+        let bytes: [UInt8] = [0xFF, 0xFF]
+        bytes.withUnsafeBytes { ptr in
+            data.append(ptr.baseAddress!.assumingMemoryBound(to: UInt8.self), count: ptr.count)
+        }
+        XCTAssertEqual(data, Data(bytes: [1, 1, 1, 1, 1, 0xFF, 0xFF]))
+    }
+    
+    func test_validateMutation_slice_customBacking_appendData() {
+        var data = Data(referencing: AllOnesImmutableData(length: 10))[4..<9]
+        data.append(Data(bytes: [0xFF, 0xFF]))
+        XCTAssertEqual(data, Data(bytes: [1, 1, 1, 1, 1, 0xFF, 0xFF]))
+    }
+    
+    func test_validateMutation_slice_customBacking_appendBuffer() {
+        var data = Data(referencing: AllOnesImmutableData(length: 10))[4..<9]
+        let bytes: [UInt8] = [0xFF, 0xFF]
+        bytes.withUnsafeBufferPointer { (buffer) in
+            data.append(buffer)
+        }
+        XCTAssertEqual(data, Data(bytes: [1, 1, 1, 1, 1, 0xFF, 0xFF]))
+    }
+    
+    func test_validateMutation_slice_customBacking_appendSequence() {
+        var data = Data(referencing: AllOnesImmutableData(length: 10))[4..<9]
+        let seq = repeatElement(UInt8(0xFF), count: 2)
+        data.append(contentsOf: seq)
+        XCTAssertEqual(data, Data(bytes: [1, 1, 1, 1, 1, 0xFF, 0xFF]))
+    }
+    
+    func test_validateMutation_slice_customBacking_appendContentsOf() {
+        var data = Data(referencing: AllOnesImmutableData(length: 10))[4..<9]
+        data.append(contentsOf: [0xFF, 0xFF])
+        XCTAssertEqual(data, Data(bytes: [1, 1, 1, 1, 1, 0xFF, 0xFF]))
+    }
+    
+    func test_validateMutation_slice_customBacking_resetBytes() {
+        var data = Data(referencing: AllOnesImmutableData(length: 10))[4..<9]
+        data.resetBytes(in: 5..<8)
+        XCTAssertEqual(data, Data(bytes: [1, 0, 0, 0, 1]))
+    }
+    
+    func test_validateMutation_slice_customBacking_replaceSubrange() {
+        var data = Data(referencing: AllOnesImmutableData(length: 10))[4..<9]
+        let range: Range<Int> = data.startIndex.advanced(by: 1)..<data.endIndex.advanced(by: -1)
+        data.replaceSubrange(range, with: Data(bytes: [0xFF, 0xFF]))
+        XCTAssertEqual(data, Data(bytes: [1, 0xFF, 0xFF, 1]))
+    }
+    
+    func test_validateMutation_slice_customBacking_replaceSubrangeCountableRange() {
+        var data = Data(referencing: AllOnesImmutableData(length: 10))[4..<9]
+        let range: CountableRange<Int> = data.startIndex.advanced(by: 1)..<data.endIndex.advanced(by: -1)
+        data.replaceSubrange(range, with: Data(bytes: [0xFF, 0xFF]))
+        XCTAssertEqual(data, Data(bytes: [1, 0xFF, 0xFF, 1]))
+    }
+    
+    func test_validateMutation_slice_customBacking_replaceSubrangeWithBuffer() {
+        var data = Data(referencing: AllOnesImmutableData(length: 10))[4..<9]
+        let range: Range<Int> = data.startIndex.advanced(by: 1)..<data.endIndex.advanced(by: -1)
+        let bytes: [UInt8] = [0xFF, 0xFF]
+        bytes.withUnsafeBufferPointer { (buffer) in
+            data.replaceSubrange(range, with: buffer)
+        }
+        XCTAssertEqual(data, Data(bytes: [1, 0xFF, 0xFF, 1]))
+    }
+    
+    func test_validateMutation_slice_customBacking_replaceSubrangeWithCollection() {
+        var data = Data(referencing: AllOnesImmutableData(length: 10))[4..<9]
+        let range: Range<Int> = data.startIndex.advanced(by: 1)..<data.endIndex.advanced(by: -1)
+        data.replaceSubrange(range, with: [0xFF, 0xFF])
+        XCTAssertEqual(data, Data(bytes: [1, 0xFF, 0xFF, 1]))
+    }
+    
+    func test_validateMutation_slice_customBacking_replaceSubrangeWithBytes() {
+        var data = Data(referencing: AllOnesImmutableData(length: 10))[4..<9]
+        let range: Range<Int> = data.startIndex.advanced(by: 1)..<data.endIndex.advanced(by: -1)
+        let bytes: [UInt8] = [0xFF, 0xFF]
+        bytes.withUnsafeBytes { buffer in
+            data.replaceSubrange(range, with: buffer.baseAddress!, count: 2)
+        }
+        XCTAssertEqual(data, Data(bytes: [1, 0xFF, 0xFF, 1]))
+    }
+    
+    func test_validateMutation_cow_customBacking_withUnsafeMutableBytes() {
+        var data = Data(referencing: AllOnesImmutableData(length: 10))
+        holdReference(data) {
+            data.withUnsafeMutableBytes { (ptr: UnsafeMutablePointer<UInt8>) in
+                ptr.advanced(by: 5).pointee = 0xFF
+            }
+            XCTAssertEqual(data[data.startIndex.advanced(by: 5)], 0xFF)
+        }
+    }
+    
+    func test_validateMutation_cow_customBacking_appendBytes() {
+        var data = Data(referencing: AllOnesImmutableData(length: 10))
+        holdReference(data) {
+            let bytes: [UInt8] = [0xFF, 0xFF]
+            bytes.withUnsafeBufferPointer { (buffer) in
+                data.append(buffer.baseAddress!, count: buffer.count)
+            }
+            XCTAssertEqual(data, Data(bytes: [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0xFF, 0xFF]))
+        }
+    }
+    
+    func test_validateMutation_cow_customBacking_appendData() {
+        var data = Data(referencing: AllOnesImmutableData(length: 10))
+        holdReference(data) {
+            data.append(Data(bytes: [0xFF, 0xFF]))
+            XCTAssertEqual(data, Data(bytes: [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0xFF, 0xFF]))
+        }
+    }
+    
+    func test_validateMutation_cow_customBacking_appendBuffer() {
+        var data = Data(referencing: AllOnesImmutableData(length: 10))
+        holdReference(data) {
+            let bytes: [UInt8] = [0xFF, 0xFF]
+            bytes.withUnsafeBufferPointer { data.append($0) }
+            XCTAssertEqual(data, Data(bytes: [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0xFF, 0xFF]))
+        }
+    }
+    
+    func test_validateMutation_cow_customBacking_appendSequence() {
+        var data = Data(referencing: AllOnesImmutableData(length: 10))
+        holdReference(data) {
+            data.append(contentsOf: repeatElement(UInt8(0xFF), count: 2))
+            XCTAssertEqual(data, Data(bytes: [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0xFF, 0xFF]))
+        }
+    }
+    
+    func test_validateMutation_cow_customBacking_appendContentsOf() {
+        var data = Data(referencing: AllOnesImmutableData(length: 10))
+        holdReference(data) {
+            data.append(contentsOf: [0xFF, 0xFF])
+            XCTAssertEqual(data, Data(bytes: [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0xFF, 0xFF]))
+        }
+    }
+    
+    func test_validateMutation_cow_customBacking_resetBytes() {
+        var data = Data(referencing: AllOnesImmutableData(length: 10))
+        holdReference(data) {
+            data.resetBytes(in: 5..<8)
+            XCTAssertEqual(data, Data(bytes: [1, 1, 1, 1, 1, 0, 0, 0, 1, 1]))
+        }
+    }
+    
+    func test_validateMutation_cow_customBacking_replaceSubrange() {
+        var data = Data(referencing: AllOnesImmutableData(length: 10))
+        holdReference(data) {
+            let range: Range<Int> = data.startIndex.advanced(by: 1)..<data.endIndex.advanced(by: -1)
+            data.replaceSubrange(range, with: Data(bytes: [0xFF, 0xFF]))
+            XCTAssertEqual(data, Data(bytes: [1, 0xFF, 0xFF, 1]))
+        }
+    }
+    
+    func test_validateMutation_cow_customBacking_replaceSubrangeCountableRange() {
+        var data = Data(referencing: AllOnesImmutableData(length: 10))
+        holdReference(data) {
+            let range: CountableRange<Int> = data.startIndex.advanced(by: 1)..<data.endIndex.advanced(by: -1)
+            data.replaceSubrange(range, with: Data(bytes: [0xFF, 0xFF]))
+            XCTAssertEqual(data, Data(bytes: [1, 0xFF, 0xFF, 1]))
+        }
+    }
+    
+    func test_validateMutation_cow_customBacking_replaceSubrangeWithBuffer() {
+        var data = Data(referencing: AllOnesImmutableData(length: 10))
+        holdReference(data) {
+            let bytes: [UInt8] = [0xFF, 0xFF]
+            let range: Range<Int> = data.startIndex.advanced(by: 1)..<data.endIndex.advanced(by: -1)
+            bytes.withUnsafeBufferPointer { data.replaceSubrange(range, with: $0) }
+            XCTAssertEqual(data, Data(bytes: [1, 0xFF, 0xFF, 1]))
+        }
+    }
+    
+    func test_validateMutation_cow_customBacking_replaceSubrangeWithCollection() {
+        var data = Data(referencing: AllOnesImmutableData(length: 10))
+        holdReference(data) {
+            let range: Range<Int> = data.startIndex.advanced(by: 1)..<data.endIndex.advanced(by: -1)
+            data.replaceSubrange(range, with: [0xFF, 0xFF])
+            XCTAssertEqual(data, Data(bytes: [1, 0xFF, 0xFF, 1]))
+        }
+    }
+    
+    func test_validateMutation_cow_customBacking_replaceSubrangeWithBytes() {
+        var data = Data(referencing: AllOnesImmutableData(length: 10))
+        holdReference(data) {
+            let bytes: [UInt8] = [0xFF, 0xFF]
+            let range: Range<Int> = data.startIndex.advanced(by: 1)..<data.endIndex.advanced(by: -1)
+            bytes.withUnsafeBytes {
+                data.replaceSubrange(range, with: $0.baseAddress!, count: $0.count)
+            }
+            XCTAssertEqual(data, Data(bytes: [1, 0xFF, 0xFF, 1]))
+        }
+    }
+    
+    func test_validateMutation_slice_cow_customBacking_withUnsafeMutableBytes() {
+        var data = Data(referencing: AllOnesImmutableData(length: 10))[4..<9]
+        holdReference(data) {
+            data.withUnsafeMutableBytes { (ptr: UnsafeMutablePointer<UInt8>) in
+                ptr.advanced(by: 1).pointee = 0xFF
+            }
+            XCTAssertEqual(data[data.startIndex.advanced(by: 1)], 0xFF)
+        }
+    }
+    
+    func test_validateMutation_slice_cow_customBacking_appendBytes() {
+        var data = Data(referencing: AllOnesImmutableData(length: 10))[4..<9]
+        holdReference(data) {
+            let bytes: [UInt8] = [0xFF, 0xFF]
+            bytes.withUnsafeBufferPointer { (buffer) in
+                data.append(buffer.baseAddress!, count: buffer.count)
+            }
+            XCTAssertEqual(data, Data(bytes: [1, 1, 1, 1, 1, 0xFF, 0xFF]))
+        }
+    }
+    
+    func test_validateMutation_slice_cow_customBacking_appendData() {
+        var data = Data(referencing: AllOnesImmutableData(length: 10))[4..<9]
+        holdReference(data) {
+            data.append(Data(bytes: [0xFF, 0xFF]))
+            XCTAssertEqual(data, Data(bytes: [1, 1, 1, 1, 1, 0xFF, 0xFF]))
+        }
+    }
+    
+    func test_validateMutation_slice_cow_customBacking_appendBuffer() {
+        var data = Data(referencing: AllOnesImmutableData(length: 10))[4..<9]
+        holdReference(data) {
+            let bytes: [UInt8] = [0xFF, 0xFF]
+            bytes.withUnsafeBufferPointer { data.append($0) }
+            XCTAssertEqual(data, Data(bytes: [1, 1, 1, 1, 1, 0xFF, 0xFF]))
+        }
+    }
+    
+    func test_validateMutation_slice_cow_customBacking_appendSequence() {
+        var data = Data(referencing: AllOnesImmutableData(length: 10))[4..<9]
+        holdReference(data) {
+            data.append(contentsOf: repeatElement(UInt8(0xFF), count: 2))
+            XCTAssertEqual(data, Data(bytes: [1, 1, 1, 1, 1, 0xFF, 0xFF]))
+        }
+    }
+    
+    func test_validateMutation_slice_cow_customBacking_appendContentsOf() {
+        var data = Data(referencing: AllOnesImmutableData(length: 10))[4..<9]
+        holdReference(data) {
+            data.append(contentsOf: [0xFF, 0xFF])
+            XCTAssertEqual(data, Data(bytes: [1, 1, 1, 1, 1, 0xFF, 0xFF]))
+        }
+    }
+    
+    func test_validateMutation_slice_cow_customBacking_resetBytes() {
+        var data = Data(referencing: AllOnesImmutableData(length: 10))[4..<9]
+        holdReference(data) {
+            data.resetBytes(in: 5..<8)
+            XCTAssertEqual(data, Data(bytes: [1, 0, 0, 0, 1]))
+        }
+    }
+    
+    func test_validateMutation_slice_cow_customBacking_replaceSubrange() {
+        var data = Data(referencing: AllOnesImmutableData(length: 10))[4..<9]
+        holdReference(data) {
+            let range: Range<Int> = data.startIndex.advanced(by: 1)..<data.endIndex.advanced(by: -1)
+            data.replaceSubrange(range, with: Data(bytes: [0xFF, 0xFF]))
+            XCTAssertEqual(data, Data(bytes: [1, 0xFF, 0xFF, 1]))
+        }
+    }
+    
+    func test_validateMutation_slice_cow_customBacking_replaceSubrangeCountableRange() {
+        var data = Data(referencing: AllOnesImmutableData(length: 10))[4..<9]
+        holdReference(data) {
+            let range: CountableRange<Int> = data.startIndex.advanced(by: 1)..<data.endIndex.advanced(by: -1)
+            data.replaceSubrange(range, with: Data(bytes: [0xFF, 0xFF]))
+            XCTAssertEqual(data, Data(bytes: [1, 0xFF, 0xFF, 1]))
+        }
+    }
+    
+    func test_validateMutation_slice_cow_customBacking_replaceSubrangeWithBuffer() {
+        var data = Data(referencing: AllOnesImmutableData(length: 10))[4..<9]
+        holdReference(data) {
+            let range: Range<Int> = data.startIndex.advanced(by: 1)..<data.endIndex.advanced(by: -1)
+            let bytes: [UInt8] = [0xFF, 0xFF]
+            bytes.withUnsafeBufferPointer { data.replaceSubrange(range, with: $0) }
+            XCTAssertEqual(data, Data(bytes: [1, 0xFF, 0xFF, 1]))
+        }
+    }
+    
+    func test_validateMutation_slice_cow_customBacking_replaceSubrangeWithCollection() {
+        var data = Data(referencing: AllOnesImmutableData(length: 10))[4..<9]
+        holdReference(data) {
+            let range: Range<Int> = data.startIndex.advanced(by: 1)..<data.endIndex.advanced(by: -1)
+            data.replaceSubrange(range, with: [0xFF, 0xFF])
+            XCTAssertEqual(data, Data(bytes: [1, 0xFF, 0xFF, 1]))
+        }
+    }
+    
+    func test_validateMutation_slice_cow_customBacking_replaceSubrangeWithBytes() {
+        var data = Data(referencing: AllOnesImmutableData(length: 10))[4..<9]
+        holdReference(data) {
+            let range: Range<Int> = data.startIndex.advanced(by: 1)..<data.endIndex.advanced(by: -1)
+            let bytes: [UInt8] = [0xFF, 0xFF]
+            bytes.withUnsafeBytes {
+                data.replaceSubrange(range, with: $0.baseAddress!, count: $0.count)
+            }
+            XCTAssertEqual(data, Data(bytes: [1, 0xFF, 0xFF, 1]))
+        }
+    }
+    
+    func test_validateMutation_customMutableBacking_withUnsafeMutableBytes() {
+        var data = Data(referencing: AllOnesData(length: 1))
+        data.count = 10
+        data.withUnsafeMutableBytes { (ptr: UnsafeMutablePointer<UInt8>) in
+            ptr.advanced(by: 5).pointee = 0xFF
+        }
+        XCTAssertEqual(data[data.startIndex.advanced(by: 5)], 0xFF)
+    }
+    
+    func test_validateMutation_customMutableBacking_appendBytes() {
+        var data = Data(referencing: AllOnesData(length: 1))
+        data.count = 10
+        let bytes: [UInt8] = [0xFF, 0xFF]
+        bytes.withUnsafeBufferPointer { data.append($0.baseAddress!, count: $0.count) }
+        XCTAssertEqual(data, Data(bytes: [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xFF, 0xFF]))
+    }
+    
+    func test_validateMutation_customMutableBacking_appendData() {
+        var data = Data(referencing: AllOnesData(length: 1))
+        data.count = 10
+        data.append(Data(bytes: [0xFF, 0xFF]))
+        XCTAssertEqual(data, Data(bytes: [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xFF, 0xFF]))
+    }
+    
+    func test_validateMutation_customMutableBacking_appendBuffer() {
+        var data = Data(referencing: AllOnesData(length: 1))
+        data.count = 10
+        let bytes: [UInt8] = [0xFF, 0xFF]
+        bytes.withUnsafeBufferPointer { data.append($0) }
+        XCTAssertEqual(data, Data(bytes: [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xFF, 0xFF]))
+    }
+    
+    func test_validateMutation_customMutableBacking_appendSequence() {
+        var data = Data(referencing: AllOnesData(length: 1))
+        data.count = 10
+        data.append(contentsOf: repeatElement(UInt8(0xFF), count: 2))
+        XCTAssertEqual(data, Data(bytes: [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xFF, 0xFF]))
+    }
+    
+    func test_validateMutation_customMutableBacking_appendContentsOf() {
+        var data = Data(referencing: AllOnesData(length: 1))
+        data.count = 10
+        data.append(contentsOf: [0xFF, 0xFF])
+        XCTAssertEqual(data, Data(bytes: [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xFF, 0xFF]))
+    }
+    
+    func test_validateMutation_customMutableBacking_resetBytes() {
+        var data = Data(referencing: AllOnesData(length: 1))
+        data.count = 10
+        data.resetBytes(in: 5..<8)
+        XCTAssertEqual(data.count, 10)
+        XCTAssertEqual(data[data.startIndex.advanced(by: 0)], 1)
+        XCTAssertEqual(data[data.startIndex.advanced(by: 5)], 0)
+        XCTAssertEqual(data[data.startIndex.advanced(by: 6)], 0)
+        XCTAssertEqual(data[data.startIndex.advanced(by: 7)], 0)
+    }
+    
+    func test_validateMutation_customMutableBacking_replaceSubrange() {
+        var data = Data(referencing: AllOnesData(length: 1))
+        data.count = 10
+        let range: Range<Int> = data.startIndex.advanced(by: 1)..<data.endIndex.advanced(by: -1)
+        data.replaceSubrange(range, with: Data(bytes: [0xFF, 0xFF]))
+        XCTAssertEqual(data, Data(bytes: [1, 0xFF, 0xFF, 0]))
+    }
+    
+    func test_validateMutation_customMutableBacking_replaceSubrangeCountableRange() {
+        var data = Data(referencing: AllOnesData(length: 1))
+        data.count = 10
+        let range: CountableRange<Int> = data.startIndex.advanced(by: 1)..<data.endIndex.advanced(by: -1)
+        data.replaceSubrange(range, with: Data(bytes: [0xFF, 0xFF]))
+        XCTAssertEqual(data, Data(bytes: [1, 0xFF, 0xFF, 0]))
+    }
+    
+    func test_validateMutation_customMutableBacking_replaceSubrangeWithBuffer() {
+        var data = Data(referencing: AllOnesData(length: 1))
+        data.count = 10
+        let range: Range<Int> = data.startIndex.advanced(by: 1)..<data.endIndex.advanced(by: -1)
+        let bytes: [UInt8] = [0xFF, 0xFF]
+        bytes.withUnsafeBufferPointer { data.replaceSubrange(range, with: $0) }
+        XCTAssertEqual(data, Data(bytes: [1, 0xFF, 0xFF, 0]))
+    }
+    
+    func test_validateMutation_customMutableBacking_replaceSubrangeWithCollection() {
+        var data = Data(referencing: AllOnesData(length: 1))
+        data.count = 10
+        let range: Range<Int> = data.startIndex.advanced(by: 1)..<data.endIndex.advanced(by: -1)
+        data.replaceSubrange(range, with: [0xFF, 0xFF])
+        XCTAssertEqual(data, Data(bytes: [1, 0xFF, 0xFF, 0]))
+    }
+    
+    func test_validateMutation_customMutableBacking_replaceSubrangeWithBytes() {
+        var data = Data(referencing: AllOnesData(length: 1))
+        data.count = 10
+        let range: Range<Int> = data.startIndex.advanced(by: 1)..<data.endIndex.advanced(by: -1)
+        let bytes: [UInt8] = [0xFF, 0xFF]
+        bytes.withUnsafeBufferPointer { data.replaceSubrange(range, with: $0.baseAddress!, count: $0.count) }
+        XCTAssertEqual(data, Data(bytes: [1, 0xFF, 0xFF, 0]))
+    }
+    
+    func test_validateMutation_slice_customMutableBacking_withUnsafeMutableBytes() {
+        var base = Data(referencing: AllOnesData(length: 1))
+        base.count = 10
+        var data = base[4..<9]
+        data.withUnsafeMutableBytes { (ptr: UnsafeMutablePointer<UInt8>) in
+            ptr.advanced(by: 1).pointee = 0xFF
+        }
+        XCTAssertEqual(data[data.startIndex.advanced(by: 1)], 0xFF)
+    }
+    
+    func test_validateMutation_slice_customMutableBacking_appendBytes() {
+        var base = Data(referencing: AllOnesData(length: 1))
+        base.count = 10
+        var data = base[4..<9]
+        let bytes: [UInt8] = [0xFF, 0xFF]
+        bytes.withUnsafeBufferPointer { data.append($0.baseAddress!, count: $0.count) }
+        XCTAssertEqual(data, Data(bytes: [0, 0, 0, 0, 0, 0xFF, 0xFF]))
+    }
+    
+    func test_validateMutation_slice_customMutableBacking_appendData() {
+        var base = Data(referencing: AllOnesData(length: 1))
+        base.count = 10
+        var data = base[4..<9]
+        data.append(Data(bytes: [0xFF, 0xFF]))
+        XCTAssertEqual(data, Data(bytes: [0, 0, 0, 0, 0, 0xFF, 0xFF]))
+    }
+    
+    func test_validateMutation_slice_customMutableBacking_appendBuffer() {
+        var base = Data(referencing: AllOnesData(length: 1))
+        base.count = 10
+        var data = base[4..<9]
+        let bytes: [UInt8] = [0xFF, 0xFF]
+        bytes.withUnsafeBufferPointer { data.append($0) }
+        XCTAssertEqual(data, Data(bytes: [0, 0, 0, 0, 0, 0xFF, 0xFF]))
+    }
+    
+    func test_validateMutation_slice_customMutableBacking_appendSequence() {
+        var base = Data(referencing: AllOnesData(length: 1))
+        base.count = 10
+        var data = base[4..<9]
+        let bytes: [UInt8] = [0xFF, 0xFF]
+        bytes.withUnsafeBufferPointer { data.append($0) }
+        XCTAssertEqual(data, Data(bytes: [0, 0, 0, 0, 0, 0xFF, 0xFF]))
+    }
+    
+    func test_validateMutation_slice_customMutableBacking_appendContentsOf() {
+        var base = Data(referencing: AllOnesData(length: 1))
+        base.count = 10
+        var data = base[4..<9]
+        data.append(contentsOf: [0xFF, 0xFF])
+        XCTAssertEqual(data, Data(bytes: [0, 0, 0, 0, 0, 0xFF, 0xFF]))
+    }
+    
+    func test_validateMutation_slice_customMutableBacking_resetBytes() {
+        var base = Data(referencing: AllOnesData(length: 1))
+        base.count = 10
+        var data = base[4..<9]
+        data.resetBytes(in: 5..<8)
+        
+        XCTAssertEqual(data[data.startIndex.advanced(by: 1)], 0)
+        XCTAssertEqual(data[data.startIndex.advanced(by: 2)], 0)
+        XCTAssertEqual(data[data.startIndex.advanced(by: 3)], 0)
+    }
+    
+    func test_validateMutation_slice_customMutableBacking_replaceSubrange() {
+        var base = Data(referencing: AllOnesData(length: 1))
+        base.count = 10
+        var data = base[4..<9]
+        let range: Range<Int> = data.startIndex.advanced(by: 1)..<data.endIndex.advanced(by: -1)
+        data.replaceSubrange(range, with: Data(bytes: [0xFF, 0xFF]))
+        XCTAssertEqual(data, Data(bytes: [0, 0xFF, 0xFF, 0]))
+    }
+    
+    func test_validateMutation_slice_customMutableBacking_replaceSubrangeCountableRange() {
+        var base = Data(referencing: AllOnesData(length: 1))
+        base.count = 10
+        var data = base[4..<9]
+        let range: CountableRange<Int> = data.startIndex.advanced(by: 1)..<data.endIndex.advanced(by: -1)
+        data.replaceSubrange(range, with: Data(bytes: [0xFF, 0xFF]))
+        XCTAssertEqual(data, Data(bytes: [0, 0xFF, 0xFF, 0]))
+    }
+    
+    func test_validateMutation_slice_customMutableBacking_replaceSubrangeWithBuffer() {
+        var base = Data(referencing: AllOnesData(length: 1))
+        base.count = 10
+        var data = base[4..<9]
+        let range: Range<Int> = data.startIndex.advanced(by: 1)..<data.endIndex.advanced(by: -1)
+        let bytes: [UInt8] = [0xFF, 0xFF]
+        bytes.withUnsafeBufferPointer { data.replaceSubrange(range, with: $0) }
+        XCTAssertEqual(data, Data(bytes: [0, 0xFF, 0xFF, 0]))
+    }
+    
+    func test_validateMutation_slice_customMutableBacking_replaceSubrangeWithCollection() {
+        var base = Data(referencing: AllOnesData(length: 1))
+        base.count = 10
+        var data = base[4..<9]
+        let range: Range<Int> = data.startIndex.advanced(by: 1)..<data.endIndex.advanced(by: -1)
+        data.replaceSubrange(range, with: [0xFF, 0xFF])
+        XCTAssertEqual(data, Data(bytes: [0, 0xFF, 0xFF, 0]))
+    }
+    
+    func test_validateMutation_slice_customMutableBacking_replaceSubrangeWithBytes() {
+        var base = Data(referencing: AllOnesData(length: 1))
+        base.count = 10
+        var data = base[4..<9]
+        let range: Range<Int> = data.startIndex.advanced(by: 1)..<data.endIndex.advanced(by: -1)
+        let bytes: [UInt8] = [0xFF, 0xFF]
+        bytes.withUnsafeBufferPointer { data.replaceSubrange(range, with: $0.baseAddress!, count: $0.count) }
+        XCTAssertEqual(data, Data(bytes: [0, 0xFF, 0xFF, 0]))
+    }
+    
+    func test_validateMutation_cow_customMutableBacking_withUnsafeMutableBytes() {
+        var data = Data(referencing: AllOnesData(length: 1))
+        data.count = 10
+        holdReference(data) {
+            data.withUnsafeMutableBytes { (ptr: UnsafeMutablePointer<UInt8>) in
+                ptr.advanced(by: 5).pointee = 0xFF
+            }
+            XCTAssertEqual(data[data.startIndex.advanced(by: 5)], 0xFF)
+        }
+    }
+    
+    func test_validateMutation_cow_customMutableBacking_appendBytes() {
+        var data = Data(referencing: AllOnesData(length: 1))
+        data.count = 10
+        holdReference(data) {
+            let bytes: [UInt8] = [0xFF, 0xFF]
+            bytes.withUnsafeBufferPointer { data.append($0.baseAddress!, count: $0.count) }
+            XCTAssertEqual(data, Data(bytes: [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xFF, 0xFF]))
+        }
+    }
+    
+    func test_validateMutation_cow_customMutableBacking_appendData() {
+        var data = Data(referencing: AllOnesData(length: 1))
+        data.count = 10
+        holdReference(data) {
+            data.append(Data(bytes: [0xFF, 0xFF]))
+            XCTAssertEqual(data, Data(bytes: [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xFF, 0xFF]))
+        }
+    }
+    
+    func test_validateMutation_cow_customMutableBacking_appendBuffer() {
+        var data = Data(referencing: AllOnesData(length: 1))
+        data.count = 10
+        holdReference(data) {
+            let bytes: [UInt8] = [0xFF, 0xFF]
+            bytes.withUnsafeBufferPointer { data.append($0) }
+            XCTAssertEqual(data, Data(bytes: [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xFF, 0xFF]))
+        }
+    }
+    
+    func test_validateMutation_cow_customMutableBacking_appendSequence() {
+        var data = Data(referencing: AllOnesData(length: 1))
+        data.count = 10
+        holdReference(data) {
+            data.append(contentsOf: repeatElement(UInt8(0xFF), count: 2))
+            XCTAssertEqual(data, Data(bytes: [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xFF, 0xFF]))
+        }
+    }
+    
+    func test_validateMutation_cow_customMutableBacking_appendContentsOf() {
+        var data = Data(referencing: AllOnesData(length: 1))
+        data.count = 10
+        holdReference(data) {
+            data.append(contentsOf: [0xFF, 0xFF])
+            XCTAssertEqual(data, Data(bytes: [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xFF, 0xFF]))
+        }
+    }
+    
+    func test_validateMutation_cow_customMutableBacking_resetBytes() {
+        var data = Data(referencing: AllOnesData(length: 10))
+        holdReference(data) {
+            data.resetBytes(in: 5..<8)
+            XCTAssertEqual(data.count, 10)
+            XCTAssertEqual(data[data.startIndex.advanced(by: 0)], 1)
+            XCTAssertEqual(data[data.startIndex.advanced(by: 5)], 0)
+            XCTAssertEqual(data[data.startIndex.advanced(by: 6)], 0)
+            XCTAssertEqual(data[data.startIndex.advanced(by: 7)], 0)
+        }
+    }
+    
+    func test_validateMutation_cow_customMutableBacking_replaceSubrange() {
+        var data = Data(referencing: AllOnesData(length: 1))
+        data.count = 10
+        holdReference(data) {
+            let range: Range<Int> = data.startIndex.advanced(by: 1)..<data.endIndex.advanced(by: -1)
+            data.replaceSubrange(range, with: Data(bytes: [0xFF, 0xFF]))
+            XCTAssertEqual(data, Data(bytes: [1, 0xFF, 0xFF, 0])) 
+        }
+    }
+    
+    func test_validateMutation_cow_customMutableBacking_replaceSubrangeCountableRange() {
+        var data = Data(referencing: AllOnesData(length: 1))
+        data.count = 10
+        holdReference(data) {
+            let range: CountableRange<Int> = data.startIndex.advanced(by: 1)..<data.endIndex.advanced(by: -1)
+            data.replaceSubrange(range, with: Data(bytes: [0xFF, 0xFF]))
+            XCTAssertEqual(data, Data(bytes: [1, 0xFF, 0xFF, 0])) 
+        }
+    }
+    
+    func test_validateMutation_cow_customMutableBacking_replaceSubrangeWithBuffer() {
+        var data = Data(referencing: AllOnesData(length: 1))
+        data.count = 10
+        holdReference(data) {
+            let range: Range<Int> = data.startIndex.advanced(by: 1)..<data.endIndex.advanced(by: -1)
+            let bytes: [UInt8] = [0xFF, 0xFF]
+            bytes.withUnsafeBufferPointer { data.replaceSubrange(range, with: $0) }
+            XCTAssertEqual(data, Data(bytes: [1, 0xFF, 0xFF, 0])) 
+        }
+    }
+    
+    func test_validateMutation_cow_customMutableBacking_replaceSubrangeWithCollection() {
+        var data = Data(referencing: AllOnesData(length: 1))
+        data.count = 10
+        holdReference(data) {
+            let range: Range<Int> = data.startIndex.advanced(by: 1)..<data.endIndex.advanced(by: -1)
+            data.replaceSubrange(range, with: [0xFF, 0xFF])
+            XCTAssertEqual(data, Data(bytes: [1, 0xFF, 0xFF, 0])) 
+        }
+    }
+    
+    func test_validateMutation_cow_customMutableBacking_replaceSubrangeWithBytes() {
+        var data = Data(referencing: AllOnesData(length: 1))
+        data.count = 10
+        holdReference(data) {
+            let range: Range<Int> = data.startIndex.advanced(by: 1)..<data.endIndex.advanced(by: -1)
+            let bytes: [UInt8] = [0xFF, 0xFF]
+            bytes.withUnsafeBufferPointer { data.replaceSubrange(range, with: $0.baseAddress!, count: $0.count) }
+            XCTAssertEqual(data, Data(bytes: [1, 0xFF, 0xFF, 0])) 
+        }
+    }
+    
+    func test_validateMutation_slice_cow_customMutableBacking_withUnsafeMutableBytes() {
+        var base = Data(referencing: AllOnesData(length: 1))
+        base.count = 10
+        var data = base[4..<9]
+        holdReference(data) {
+            data.withUnsafeMutableBytes { (ptr: UnsafeMutablePointer<UInt8>) in
+                ptr.advanced(by: 1).pointee = 0xFF
+            }
+            XCTAssertEqual(data[data.startIndex.advanced(by: 1)], 0xFF)
+        }
+    }
+    
+    func test_validateMutation_slice_cow_customMutableBacking_appendBytes() {
+        var base = Data(referencing: AllOnesData(length: 1))
+        base.count = 10
+        var data = base[4..<9]
+        holdReference(data) {
+            let bytes: [UInt8] = [0xFF, 0xFF]
+            bytes.withUnsafeBufferPointer { data.append($0.baseAddress!, count: $0.count) }
+            XCTAssertEqual(data, Data(bytes: [0, 0, 0, 0, 0, 0xFF, 0xFF]))
+        }
+    }
+    
+    func test_validateMutation_slice_cow_customMutableBacking_appendData() {
+        var base = Data(referencing: AllOnesData(length: 1))
+        base.count = 10
+        var data = base[4..<9]
+        holdReference(data) {
+            data.append(Data(bytes: [0xFF, 0xFF]))
+            XCTAssertEqual(data, Data(bytes: [0, 0, 0, 0, 0, 0xFF, 0xFF]))
+        }
+    }
+    
+    func test_validateMutation_slice_cow_customMutableBacking_appendBuffer() {
+        var base = Data(referencing: AllOnesData(length: 1))
+        base.count = 10
+        var data = base[4..<9]
+        holdReference(data) {
+            let bytes: [UInt8] = [0xFF, 0xFF]
+            bytes.withUnsafeBufferPointer { data.append($0) }
+            XCTAssertEqual(data, Data(bytes: [0, 0, 0, 0, 0, 0xFF, 0xFF]))
+        }
+    }
+    
+    func test_validateMutation_slice_cow_customMutableBacking_appendSequence() {
+        var base = Data(referencing: AllOnesData(length: 1))
+        base.count = 10
+        var data = base[4..<9]
+        holdReference(data) {
+            data.append(contentsOf: repeatElement(UInt8(0xFF), count: 2))
+            XCTAssertEqual(data, Data(bytes: [0, 0, 0, 0, 0, 0xFF, 0xFF]))
+        }
+    }
+    
+    func test_validateMutation_slice_cow_customMutableBacking_appendContentsOf() {
+        var base = Data(referencing: AllOnesData(length: 1))
+        base.count = 10
+        var data = base[4..<9]
+        holdReference(data) {
+            data.append(contentsOf: [0xFF, 0xFF])
+            XCTAssertEqual(data, Data(bytes: [0, 0, 0, 0, 0, 0xFF, 0xFF]))
+        }
+    }
+    
+    func test_validateMutation_slice_cow_customMutableBacking_resetBytes() {
+        var base = Data(referencing: AllOnesData(length: 1))
+        base.count = 10
+        var data = base[4..<9]
+        holdReference(data) {
+            data.resetBytes(in: 5..<8)
+            XCTAssertEqual(data[data.startIndex.advanced(by: 1)], 0)
+            XCTAssertEqual(data[data.startIndex.advanced(by: 2)], 0)
+            XCTAssertEqual(data[data.startIndex.advanced(by: 3)], 0)
+        }
+    }
+    
+    func test_validateMutation_slice_cow_customMutableBacking_replaceSubrange() {
+        var base = Data(referencing: AllOnesData(length: 1))
+        base.count = 10
+        var data = base[4..<9]
+        holdReference(data) {
+            let range: Range<Int> = data.startIndex.advanced(by: 1)..<data.endIndex.advanced(by: -1)
+            data.replaceSubrange(range, with: Data(bytes: [0xFF, 0xFF]))
+            XCTAssertEqual(data, Data(bytes: [0, 0xFF, 0xFF, 0]))
+        }
+    }
+    
+    func test_validateMutation_slice_cow_customMutableBacking_replaceSubrangeCountableRange() {
+        var base = Data(referencing: AllOnesData(length: 1))
+        base.count = 10
+        var data = base[4..<9]
+        holdReference(data) {
+            let range: CountableRange<Int> = data.startIndex.advanced(by: 1)..<data.endIndex.advanced(by: -1)
+            data.replaceSubrange(range, with: Data(bytes: [0xFF, 0xFF]))
+            XCTAssertEqual(data, Data(bytes: [0, 0xFF, 0xFF, 0]))
+        }
+    }
+    
+    func test_validateMutation_slice_cow_customMutableBacking_replaceSubrangeWithBuffer() {
+        var base = Data(referencing: AllOnesData(length: 1))
+        base.count = 10
+        var data = base[4..<9]
+        holdReference(data) {
+            let range: Range<Int> = data.startIndex.advanced(by: 1)..<data.endIndex.advanced(by: -1)
+            let bytes: [UInt8] = [0xFF, 0xFF]
+            bytes.withUnsafeBufferPointer { data.replaceSubrange(range, with: $0) }
+            XCTAssertEqual(data, Data(bytes: [0, 0xFF, 0xFF, 0]))
+        }
+    }
+    
+    func test_validateMutation_slice_cow_customMutableBacking_replaceSubrangeWithCollection() {
+        var base = Data(referencing: AllOnesData(length: 1))
+        base.count = 10
+        var data = base[4..<9]
+        holdReference(data) {
+            let range: Range<Int> = data.startIndex.advanced(by: 1)..<data.endIndex.advanced(by: -1)
+            data.replaceSubrange(range, with: [0xFF, 0xFF])
+            XCTAssertEqual(data, Data(bytes: [0, 0xFF, 0xFF, 0]))
+        }
+    }
+    
+    func test_validateMutation_slice_cow_customMutableBacking_replaceSubrangeWithBytes() {
+        var base = Data(referencing: AllOnesData(length: 1))
+        base.count = 10
+        var data = base[4..<9]
+        holdReference(data) {
+            let range: Range<Int> = data.startIndex.advanced(by: 1)..<data.endIndex.advanced(by: -1)
+            let bytes: [UInt8] = [0xFF, 0xFF]
+            bytes.withUnsafeBufferPointer { data.replaceSubrange(range, with: $0.baseAddress!, count: $0.count) }
+            XCTAssertEqual(data, Data(bytes: [0, 0xFF, 0xFF, 0]))
+        }
+    }
+#endif
+    
+    func test_sliceHash() {
+        let base1 = Data(bytes: [0, 0xFF, 0xFF, 0])
+        let base2 = Data(bytes: [0, 0xFF, 0xFF, 0])
+        let base3 = Data(bytes: [0xFF, 0xFF, 0xFF, 0])
+        let sliceEmulation = Data(bytes: [0xFF, 0xFF])
+        XCTAssertEqual(base1.hashValue, base2.hashValue)
+        let slice1 = base1[base1.startIndex.advanced(by: 1)..<base1.endIndex.advanced(by: -1)]
+        let slice2 = base2[base2.startIndex.advanced(by: 1)..<base2.endIndex.advanced(by: -1)]
+        let slice3 = base3[base3.startIndex.advanced(by: 1)..<base3.endIndex.advanced(by: -1)]
+        XCTAssertEqual(slice1.hashValue, sliceEmulation.hashValue)
+        XCTAssertEqual(slice1.hashValue, slice2.hashValue)
+        XCTAssertEqual(slice2.hashValue, slice3.hashValue)
+    }
+
+    func test_slice_resize_growth() {
+        var data = Data(bytes: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9])[4..<9]
+        data.resetBytes(in: data.endIndex.advanced(by: -1)..<data.endIndex.advanced(by: 1))
+        XCTAssertEqual(data, Data(bytes: [4, 5, 6, 7, 0, 0]))
+    }
+    
+    /*
+    func test_sliceEnumeration() {
+        var base = DispatchData.empty
+        let bytes: [UInt8] = [0, 1, 2, 3, 4]
+        base.append(bytes.withUnsafeBytes { DispatchData(bytes: $0) })
+        base.append(bytes.withUnsafeBytes { DispatchData(bytes: $0) })
+        base.append(bytes.withUnsafeBytes { DispatchData(bytes: $0) })
+        let data = ((base as AnyObject) as! Data)[3..<11]
+        var regionRanges: [Range<Int>] = []
+        var regionData: [Data] = []
+        data.enumerateBytes { (buffer, index, _) in
+            regionData.append(Data(bytes: buffer.baseAddress!, count: buffer.count))
+            regionRanges.append(index..<index + buffer.count)
+        }
+        XCTAssertEqual(regionRanges.count, 3)
+        XCTAssertEqual(Range<Data.Index>(3..<5), regionRanges[0])
+        XCTAssertEqual(Range<Data.Index>(5..<10), regionRanges[1])
+        XCTAssertEqual(Range<Data.Index>(10..<11), regionRanges[2])
+        XCTAssertEqual(Data(bytes: [3, 4]), regionData[0]) //fails
+        XCTAssertEqual(Data(bytes: [0, 1, 2, 3, 4]), regionData[1]) //passes
+        XCTAssertEqual(Data(bytes: [0]), regionData[2]) //fails
+    }
+ */
 }
 
diff --git a/TestFoundation/TestNSGeometry.swift b/TestFoundation/TestNSGeometry.swift
index 9367431..953bdd8 100644
--- a/TestFoundation/TestNSGeometry.swift
+++ b/TestFoundation/TestNSGeometry.swift
@@ -11,7 +11,6 @@
 #if DEPLOYMENT_RUNTIME_OBJC || os(Linux)
     import Foundation
     import XCTest
-    import CoreFoundation
 #else
     import SwiftFoundation
     import SwiftXCTest
diff --git a/TestFoundation/TestNSKeyedArchiver.swift b/TestFoundation/TestNSKeyedArchiver.swift
index 32fd2b6..1a03419 100644
--- a/TestFoundation/TestNSKeyedArchiver.swift
+++ b/TestFoundation/TestNSKeyedArchiver.swift
@@ -118,7 +118,7 @@
         XCTAssertTrue(encode(archiver))
         archiver.finishEncoding()
         
-        let unarchiver = NSKeyedUnarchiver(forReadingWithData: Data._unconditionallyBridgeFromObjectiveC(data))
+        let unarchiver = NSKeyedUnarchiver(forReadingWith: Data._unconditionallyBridgeFromObjectiveC(data))
         XCTAssertTrue(decode(unarchiver))
         
         // Archiving using the default initializer
@@ -127,10 +127,10 @@
         XCTAssertTrue(encode(archiver1))
         let archivedData = archiver1.encodedData
         
-        let unarchiver1 = NSKeyedUnarchiver(forReadingWithData: archivedData)
+        let unarchiver1 = NSKeyedUnarchiver(forReadingWith: archivedData)
         XCTAssertTrue(decode(unarchiver1))
     }
-    
+
     private func test_archive(_ object: Any, classes: [AnyClass], allowsSecureCoding: Bool = true, outputFormat: PropertyListSerialization.PropertyListFormat) {
         test_archive({ archiver -> Bool in
                 archiver.requiresSecureCoding = allowsSecureCoding
diff --git a/TestFoundation/TestNSNumber.swift b/TestFoundation/TestNSNumber.swift
index d3ddde8..9d2ac9c 100644
--- a/TestFoundation/TestNSNumber.swift
+++ b/TestFoundation/TestNSNumber.swift
@@ -43,6 +43,8 @@
             ("test_description", test_description ),
             ("test_descriptionWithLocale", test_descriptionWithLocale ),
             ("test_objCType", test_objCType ),
+            ("test_stringValue", test_stringValue),
+            ("test_Equals", test_Equals),
         ]
     }
     
@@ -1019,4 +1021,141 @@
         XCTAssertEqual("f" /* 0x66 */, objCType(NSNumber(value: Float.greatestFiniteMagnitude)))
         XCTAssertEqual("d" /* 0x64 */, objCType(NSNumber(value: Double.greatestFiniteMagnitude)))
     }
+
+    func test_stringValue() {
+
+        if UInt.max == UInt32.max {
+            XCTAssertEqual(NSNumber(value: UInt.min).stringValue, "0")
+            XCTAssertEqual(NSNumber(value: UInt.min + 1).stringValue, "1")
+            XCTAssertEqual(NSNumber(value: UInt.max).stringValue, "4294967295")
+            XCTAssertEqual(NSNumber(value: UInt.max - 1).stringValue, "4294967294")
+        } else if UInt.max == UInt64.max {
+            XCTAssertEqual(NSNumber(value: UInt.min).stringValue, "0")
+            XCTAssertEqual(NSNumber(value: UInt.min + 1).stringValue, "1")
+            XCTAssertEqual(NSNumber(value: UInt.max).stringValue, "18446744073709551615")
+            XCTAssertEqual(NSNumber(value: UInt.max - 1).stringValue, "18446744073709551614")
+        }
+
+        XCTAssertEqual(NSNumber(value: UInt8.min).stringValue, "0")
+        XCTAssertEqual(NSNumber(value: UInt8.min + 1).stringValue, "1")
+        XCTAssertEqual(NSNumber(value: UInt8.max).stringValue, "255")
+        XCTAssertEqual(NSNumber(value: UInt8.max - 1).stringValue, "254")
+
+        XCTAssertEqual(NSNumber(value: UInt16.min).stringValue, "0")
+        XCTAssertEqual(NSNumber(value: UInt16.min + 1).stringValue, "1")
+        XCTAssertEqual(NSNumber(value: UInt16.max).stringValue, "65535")
+        XCTAssertEqual(NSNumber(value: UInt16.max - 1).stringValue, "65534")
+
+        XCTAssertEqual(NSNumber(value: UInt32.min).stringValue, "0")
+        XCTAssertEqual(NSNumber(value: UInt32.min + 1).stringValue, "1")
+        XCTAssertEqual(NSNumber(value: UInt32.max).stringValue, "4294967295")
+        XCTAssertEqual(NSNumber(value: UInt32.max - 1).stringValue, "4294967294")
+
+        XCTAssertEqual(NSNumber(value: UInt64.min).stringValue, "0")
+        XCTAssertEqual(NSNumber(value: UInt64.min + 1).stringValue, "1")
+        XCTAssertEqual(NSNumber(value: UInt64.max).stringValue, "18446744073709551615")
+        XCTAssertEqual(NSNumber(value: UInt64.max - 1).stringValue, "18446744073709551614")
+
+        if Int.max == Int32.max {
+            XCTAssertEqual(NSNumber(value: Int.min).stringValue, "-2147483648")
+            XCTAssertEqual(NSNumber(value: Int.min + 1).stringValue, "-2147483647")
+            XCTAssertEqual(NSNumber(value: Int.max).stringValue, "2147483647")
+            XCTAssertEqual(NSNumber(value: Int.max - 1).stringValue, "2147483646")
+        } else if Int.max == Int64.max {
+            XCTAssertEqual(NSNumber(value: Int.min).stringValue, "-9223372036854775808")
+            XCTAssertEqual(NSNumber(value: Int.min + 1).stringValue, "-9223372036854775807")
+            XCTAssertEqual(NSNumber(value: Int.max).stringValue, "9223372036854775807")
+            XCTAssertEqual(NSNumber(value: Int.max - 1).stringValue, "9223372036854775806")
+        }
+
+        XCTAssertEqual(NSNumber(value: Int8.min).stringValue, "-128")
+        XCTAssertEqual(NSNumber(value: Int8.min + 1).stringValue, "-127")
+        XCTAssertEqual(NSNumber(value: Int8.max).stringValue, "127")
+        XCTAssertEqual(NSNumber(value: Int8.max - 1).stringValue, "126")
+
+        XCTAssertEqual(NSNumber(value: Int16.min).stringValue, "-32768")
+        XCTAssertEqual(NSNumber(value: Int16.min + 1).stringValue, "-32767")
+        XCTAssertEqual(NSNumber(value: Int16.max).stringValue, "32767")
+        XCTAssertEqual(NSNumber(value: Int16.max - 1).stringValue, "32766")
+
+        XCTAssertEqual(NSNumber(value: Int32.min).stringValue, "-2147483648")
+        XCTAssertEqual(NSNumber(value: Int32.min + 1).stringValue, "-2147483647")
+        XCTAssertEqual(NSNumber(value: Int32.max).stringValue, "2147483647")
+        XCTAssertEqual(NSNumber(value: Int32.max - 1).stringValue, "2147483646")
+
+        XCTAssertEqual(NSNumber(value: Int64.min).stringValue, "-9223372036854775808")
+        XCTAssertEqual(NSNumber(value: Int64.min + 1).stringValue, "-9223372036854775807")
+        XCTAssertEqual(NSNumber(value: Int64.max).stringValue, "9223372036854775807")
+        XCTAssertEqual(NSNumber(value: Int64.max - 1).stringValue, "9223372036854775806")
+    }
+
+    func test_Equals() {
+        // Booleans: false only equals 0, true only equals 1
+        XCTAssertTrue(NSNumber(value: true) == NSNumber(value: Bool(true)))
+        XCTAssertTrue(NSNumber(value: true) == NSNumber(value: Int(1)))
+        XCTAssertTrue(NSNumber(value: true) == NSNumber(value: Float(1)))
+        XCTAssertTrue(NSNumber(value: true) == NSNumber(value: Double(1)))
+        XCTAssertTrue(NSNumber(value: true) == NSNumber(value: Int8(1)))
+        XCTAssertTrue(NSNumber(value: true) != NSNumber(value: false))
+        XCTAssertTrue(NSNumber(value: true) != NSNumber(value: Int8(-1)))
+        XCTAssertTrue(NSNumber(value: true) != NSNumber(value: Float(1.01)))
+        XCTAssertTrue(NSNumber(value: true) != NSNumber(value: Double(1234.56)))
+        XCTAssertTrue(NSNumber(value: true) != NSNumber(value: 2))
+        XCTAssertTrue(NSNumber(value: true) != NSNumber(value: Int.max))
+        XCTAssertTrue(NSNumber(value: false) == NSNumber(value: Bool(false)))
+        XCTAssertTrue(NSNumber(value: false) == NSNumber(value: Int(0)))
+        XCTAssertTrue(NSNumber(value: false) == NSNumber(value: Float(0)))
+        XCTAssertTrue(NSNumber(value: false) == NSNumber(value: Double(0)))
+        XCTAssertTrue(NSNumber(value: false) == NSNumber(value: Int8(0)))
+        XCTAssertTrue(NSNumber(value: false) == NSNumber(value: UInt64(0)))
+        XCTAssertTrue(NSNumber(value: false) != NSNumber(value: 1))
+        XCTAssertTrue(NSNumber(value: false) != NSNumber(value: 2))
+        XCTAssertTrue(NSNumber(value: false) != NSNumber(value: Int.max))
+
+        XCTAssertTrue(NSNumber(value: Int8(-1)) == NSNumber(value: Int16(-1)))
+        XCTAssertTrue(NSNumber(value: Int16(-1)) == NSNumber(value: Int32(-1)))
+        XCTAssertTrue(NSNumber(value: Int32(-1)) == NSNumber(value: Int64(-1)))
+        XCTAssertTrue(NSNumber(value: Int8.max) != NSNumber(value: Int16.max))
+        XCTAssertTrue(NSNumber(value: Int16.max) != NSNumber(value: Int32.max))
+        XCTAssertTrue(NSNumber(value: Int32.max) != NSNumber(value: Int64.max))
+        XCTAssertTrue(NSNumber(value: UInt8.min) == NSNumber(value: UInt16.min))
+        XCTAssertTrue(NSNumber(value: UInt16.min) == NSNumber(value: UInt32.min))
+        XCTAssertTrue(NSNumber(value: UInt32.min) == NSNumber(value: UInt64.min))
+        XCTAssertTrue(NSNumber(value: UInt8.max) != NSNumber(value: UInt16.max))
+        XCTAssertTrue(NSNumber(value: UInt16.max) != NSNumber(value: UInt32.max))
+        XCTAssertTrue(NSNumber(value: UInt32.max) != NSNumber(value: UInt64.max))
+        XCTAssertTrue(NSNumber(value: Int8(0)) == NSNumber(value: UInt16(0)))
+        XCTAssertTrue(NSNumber(value: UInt16(0)) == NSNumber(value: Int32(0)))
+        XCTAssertTrue(NSNumber(value: Int32(0)) == NSNumber(value: UInt64(0)))
+        XCTAssertTrue(NSNumber(value: Int(0)) == NSNumber(value: UInt(0)))
+        XCTAssertTrue(NSNumber(value: Int8.min) == NSNumber(value: Float(-128)))
+        XCTAssertTrue(NSNumber(value: Int8.max) == NSNumber(value: Double(127)))
+        XCTAssertTrue(NSNumber(value: UInt16.min) == NSNumber(value: Float(0)))
+        XCTAssertTrue(NSNumber(value: UInt16.max) == NSNumber(value: Double(65535)))
+        XCTAssertTrue(NSNumber(value: 1.1) != NSNumber(value: Int64(1)))
+        let num = NSNumber(value: Int8.min)
+        XCTAssertFalse(num == NSNumber(value: num.uint64Value))
+
+        let num1 = NSNumber(value: Float.nan)
+        XCTAssertEqual(num1.compare(num1), ComparisonResult.orderedSame)
+
+        let num2 = NSNumber(value: num1.uint8Value) // 0
+        XCTAssertFalse(num1 == num2)
+        XCTAssertFalse(num2 == num1)
+        XCTAssertEqual(num1.compare(num2), ComparisonResult.orderedAscending)
+        XCTAssertEqual(num2.compare(num1), ComparisonResult.orderedDescending)
+
+        let num3 = NSNumber(value: Double.nan)
+        XCTAssertEqual(num3.compare(num3), ComparisonResult.orderedSame)
+
+        let num4 = NSNumber(value: num3.intValue) // 0
+        XCTAssertFalse(num3 == num2)
+        XCTAssertFalse(num4 == num3)
+        XCTAssertEqual(num3.compare(num4), ComparisonResult.orderedAscending)
+        XCTAssertEqual(num4.compare(num3), ComparisonResult.orderedDescending)
+
+        XCTAssertEqual(NSNumber(value: Double.leastNonzeroMagnitude).compare(NSNumber(value: 0)), ComparisonResult.orderedDescending)
+        XCTAssertEqual(NSNumber(value: Double.greatestFiniteMagnitude).compare(NSNumber(value: 0)), ComparisonResult.orderedDescending)
+        XCTAssertTrue(NSNumber(value: Double(-0.0)) == NSNumber(value: Double(0.0)))
+    }
 }
diff --git a/TestFoundation/TestNSNumberBridging.swift b/TestFoundation/TestNSNumberBridging.swift
new file mode 100644
index 0000000..3edcbaf
--- /dev/null
+++ b/TestFoundation/TestNSNumberBridging.swift
@@ -0,0 +1,866 @@
+// This source file is part of the Swift.org open source project
+//
+// Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors
+// Licensed under Apache License v2.0 with Runtime Library Exception
+//
+// See http://swift.org/LICENSE.txt for license information
+// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
+//
+
+
+#if DEPLOYMENT_RUNTIME_OBJC || os(Linux)
+import Foundation
+import XCTest
+#else
+import SwiftFoundation
+import SwiftXCTest
+#endif
+
+class TestNSNumberBridging : XCTestCase {
+    static var allTests: [(String, (TestNSNumberBridging) -> () throws -> Void)] {
+        return [
+            ("testNSNumberBridgeFromInt8", testNSNumberBridgeFromInt8),
+            ("testNSNumberBridgeFromUInt8", testNSNumberBridgeFromUInt8),
+            ("testNSNumberBridgeFromInt16", testNSNumberBridgeFromInt16),
+            ("testNSNumberBridgeFromUInt16", testNSNumberBridgeFromUInt16),
+            ("testNSNumberBridgeFromInt32", testNSNumberBridgeFromInt32),
+            ("testNSNumberBridgeFromUInt32", testNSNumberBridgeFromUInt32),
+            ("testNSNumberBridgeFromInt64", testNSNumberBridgeFromInt64),
+            ("testNSNumberBridgeFromUInt64", testNSNumberBridgeFromUInt64),
+            ("testNSNumberBridgeFromInt", testNSNumberBridgeFromInt),
+            ("testNSNumberBridgeFromUInt", testNSNumberBridgeFromUInt),
+            ("testNSNumberBridgeFromFloat", testNSNumberBridgeFromFloat),
+            ("testNSNumberBridgeFromDouble", testNSNumberBridgeFromDouble),
+            ("test_numericBitPatterns_to_floatingPointTypes", test_numericBitPatterns_to_floatingPointTypes),
+            ("testNSNumberBridgeAnyHashable", testNSNumberBridgeAnyHashable),
+        ]
+    }
+
+    func testFloat(_ lhs: Float?, _ rhs: Float?, file: String = #file, line: UInt = #line) {
+        let message = "\(file):\(line) \(String(describing: lhs)) != \(String(describing: rhs)) Float"
+        if let lhsValue = lhs {
+            if let rhsValue = rhs {
+                if lhsValue.isNaN != rhsValue.isNaN {
+                    XCTFail(message)
+                } else if lhsValue != rhsValue && !lhsValue.isNaN {
+                    XCTFail(message)
+                }
+            } else {
+                XCTFail(message)
+            }
+        } else {
+            if rhs != nil {
+                XCTFail(message)
+            }
+        }
+    }
+
+    func testDouble(_ lhs: Double?, _ rhs: Double?, file: String = #file, line: UInt = #line) {
+        let message = "\(file):\(line) \(String(describing: lhs)) != \(String(describing: rhs)) Double"
+        if let lhsValue = lhs {
+            if let rhsValue = rhs {
+                if lhsValue.isNaN != rhsValue.isNaN {
+                    XCTFail(message)
+                } else if lhsValue != rhsValue && !lhsValue.isNaN {
+                    XCTFail(message)
+                }
+            } else {
+                XCTFail(message)
+            }
+        } else {
+            if rhs != nil {
+                XCTFail(message)
+            }
+        }
+    }
+
+    func testNSNumberBridgeFromInt8() {
+        for interestingValue in Int8._interestingValues {
+            func testNumber(_ number: NSNumber?) {
+                XCTAssertNotNil(number)
+                let int8 = Int8(exactly: number!)
+                XCTAssertEqual(Int8(exactly: interestingValue), int8)
+                let uint8 = UInt8(exactly: number!)
+                XCTAssertEqual(UInt8(exactly: interestingValue), uint8)
+                let int16 = Int16(exactly: number!)
+                XCTAssertEqual(Int16(exactly: interestingValue), int16)
+                let uint16 = UInt16(exactly: number!)
+                XCTAssertEqual(UInt16(exactly: interestingValue), uint16)
+                let int32 = Int32(exactly: number!)
+                XCTAssertEqual(Int32(exactly: interestingValue), int32)
+                let uint32 = UInt32(exactly: number!)
+                XCTAssertEqual(UInt32(exactly: interestingValue), uint32)
+                let int64 = Int64(exactly: number!)
+                XCTAssertEqual(Int64(exactly: interestingValue), int64)
+                let uint64 = UInt64(exactly: number!)
+                XCTAssertEqual(UInt64(exactly: interestingValue), uint64)
+                let int = Int(exactly: number!)
+                XCTAssertEqual(Int(exactly: interestingValue), int)
+                let uint = UInt(exactly: number!)
+                XCTAssertEqual(UInt(exactly: interestingValue), uint)
+                let float = Float(exactly: number!)
+                XCTAssertEqual(Float(interestingValue), float)
+                let double = Double(exactly: number!)
+                XCTAssertEqual(Double(interestingValue), double)
+            }
+            let bridged = interestingValue._bridgeToObjectiveC()
+            testNumber(bridged)
+            let created = NSNumber(value: interestingValue)
+            testNumber(created)
+        }
+    }
+
+    func testNSNumberBridgeFromUInt8() {
+        for interestingValue in UInt8._interestingValues {
+            func testNumber(_ number: NSNumber?) {
+                XCTAssertNotNil(number)
+                let int8 = Int8(exactly: number!)
+                XCTAssertEqual(Int8(exactly: interestingValue), int8)
+                let uint8 = UInt8(exactly: number!)
+                XCTAssertEqual(UInt8(exactly: interestingValue), uint8)
+                let int16 = Int16(exactly: number!)
+                XCTAssertEqual(Int16(exactly: interestingValue), int16)
+                let uint16 = UInt16(exactly: number!)
+                XCTAssertEqual(UInt16(exactly: interestingValue), uint16)
+                let int32 = Int32(exactly: number!)
+                XCTAssertEqual(Int32(exactly: interestingValue), int32)
+                let uint32 = UInt32(exactly: number!)
+                XCTAssertEqual(UInt32(exactly: interestingValue), uint32)
+                let int64 = Int64(exactly: number!)
+                XCTAssertEqual(Int64(exactly: interestingValue), int64)
+                let uint64 = UInt64(exactly: number!)
+                XCTAssertEqual(UInt64(exactly: interestingValue), uint64)
+                let int = Int(exactly: number!)
+                XCTAssertEqual(Int(exactly: interestingValue), int)
+                let uint = UInt(exactly: number!)
+                XCTAssertEqual(UInt(exactly: interestingValue), uint)
+                let float = Float(exactly: number!)
+                XCTAssertEqual(Float(interestingValue), float)
+                let double = Double(exactly: number!)
+                XCTAssertEqual(Double(interestingValue), double)
+            }
+            let bridged = interestingValue._bridgeToObjectiveC()
+            testNumber(bridged)
+            let created = NSNumber(value: interestingValue)
+            testNumber(created)
+        }
+    }
+
+    func testNSNumberBridgeFromInt16() {
+        for interestingValue in Int16._interestingValues {
+            func testNumber(_ number: NSNumber?) {
+                XCTAssertNotNil(number)
+                let int8 = Int8(exactly: number!)
+                XCTAssertEqual(Int8(exactly: interestingValue), int8)
+                let uint8 = UInt8(exactly: number!)
+                XCTAssertEqual(UInt8(exactly: interestingValue), uint8)
+                let int16 = Int16(exactly: number!)
+                XCTAssertEqual(Int16(exactly: interestingValue), int16)
+                let uint16 = UInt16(exactly: number!)
+                XCTAssertEqual(UInt16(exactly: interestingValue), uint16)
+                let int32 = Int32(exactly: number!)
+                XCTAssertEqual(Int32(exactly: interestingValue), int32)
+                let uint32 = UInt32(exactly: number!)
+                XCTAssertEqual(UInt32(exactly: interestingValue), uint32)
+                let int64 = Int64(exactly: number!)
+                XCTAssertEqual(Int64(exactly: interestingValue), int64)
+                let uint64 = UInt64(exactly: number!)
+                XCTAssertEqual(UInt64(exactly: interestingValue), uint64)
+                let int = Int(exactly: number!)
+                XCTAssertEqual(Int(exactly: interestingValue), int)
+                let uint = UInt(exactly: number!)
+                XCTAssertEqual(UInt(exactly: interestingValue), uint)
+                let float = Float(exactly: number!)
+                XCTAssertEqual(Float(interestingValue), float)
+                let double = Double(exactly: number!)
+                XCTAssertEqual(Double(interestingValue), double)
+            }
+            let bridged = interestingValue._bridgeToObjectiveC()
+            testNumber(bridged)
+            let created = NSNumber(value: interestingValue)
+            testNumber(created)
+        }
+    }
+
+    func testNSNumberBridgeFromUInt16() {
+        for interestingValue in UInt8._interestingValues {
+            func testNumber(_ number: NSNumber?) {
+                XCTAssertNotNil(number)
+                let int8 = Int8(exactly: number!)
+                XCTAssertEqual(Int8(exactly: interestingValue), int8)
+                let uint8 = UInt8(exactly: number!)
+                XCTAssertEqual(UInt8(exactly: interestingValue), uint8)
+                let int16 = Int16(exactly: number!)
+                XCTAssertEqual(Int16(exactly: interestingValue), int16)
+                let uint16 = UInt16(exactly: number!)
+                XCTAssertEqual(UInt16(exactly: interestingValue), uint16)
+                let int32 = Int32(exactly: number!)
+                XCTAssertEqual(Int32(exactly: interestingValue), int32)
+                let uint32 = UInt32(exactly: number!)
+                XCTAssertEqual(UInt32(exactly: interestingValue), uint32)
+                let int64 = Int64(exactly: number!)
+                XCTAssertEqual(Int64(exactly: interestingValue), int64)
+                let uint64 = UInt64(exactly: number!)
+                XCTAssertEqual(UInt64(exactly: interestingValue), uint64)
+                let int = Int(exactly: number!)
+                XCTAssertEqual(Int(exactly: interestingValue), int)
+                let uint = UInt(exactly: number!)
+                XCTAssertEqual(UInt(exactly: interestingValue), uint)
+                let float = Float(exactly: number!)
+                XCTAssertEqual(Float(interestingValue), float)
+                let double = Double(exactly: number!)
+                XCTAssertEqual(Double(interestingValue), double)
+            }
+            let bridged = interestingValue._bridgeToObjectiveC()
+            testNumber(bridged)
+            let created = NSNumber(value: interestingValue)
+            testNumber(created)
+        }
+    }
+
+    func testNSNumberBridgeFromInt32() {
+        for interestingValue in Int32._interestingValues {
+            func testNumber(_ number: NSNumber?) {
+                XCTAssertNotNil(number)
+                let int8 = Int8(exactly: number!)
+                XCTAssertEqual(Int8(exactly: interestingValue), int8)
+                let uint8 = UInt8(exactly: number!)
+                XCTAssertEqual(UInt8(exactly: interestingValue), uint8)
+                let int16 = Int16(exactly: number!)
+                XCTAssertEqual(Int16(exactly: interestingValue), int16)
+                let uint16 = UInt16(exactly: number!)
+                XCTAssertEqual(UInt16(exactly: interestingValue), uint16)
+                let int32 = Int32(exactly: number!)
+                XCTAssertEqual(Int32(exactly: interestingValue), int32)
+                let uint32 = UInt32(exactly: number!)
+                XCTAssertEqual(UInt32(exactly: interestingValue), uint32)
+                let int64 = Int64(exactly: number!)
+                XCTAssertEqual(Int64(exactly: interestingValue), int64)
+                let uint64 = UInt64(exactly: number!)
+                XCTAssertEqual(UInt64(exactly: interestingValue), uint64)
+                let int = Int(exactly: number!)
+                XCTAssertEqual(Int(exactly: interestingValue), int)
+                let uint = UInt(exactly: number!)
+                XCTAssertEqual(UInt(exactly: interestingValue), uint)
+                let float = Float(exactly: number!)
+                let expectedFloat = Float(exactly: int32!)
+                // these are disabled because of https://bugs.swift.org/browse/SR-4634
+                if (int32! != Int32.min && int32! != Int32.max &&
+                    int32! != Int32.min + 1 && int32! != Int32.max - 1) {
+                    testFloat(expectedFloat, float)
+                }
+                let double = Double(exactly: number!)
+                let expectedDouble = Double(exactly: int32!)
+                testDouble(expectedDouble, double)
+            }
+            let bridged = interestingValue._bridgeToObjectiveC()
+            testNumber(bridged)
+            let created = NSNumber(value: interestingValue)
+            testNumber(created)
+        }
+    }
+
+    func testNSNumberBridgeFromUInt32() {
+        for interestingValue in UInt32._interestingValues {
+            func testNumber(_ number: NSNumber?) {
+                XCTAssertNotNil(number)
+                let int8 = Int8(exactly: number!)
+                XCTAssertEqual(Int8(exactly: interestingValue), int8)
+                let uint8 = UInt8(exactly: number!)
+                XCTAssertEqual(UInt8(exactly: interestingValue), uint8)
+                let int16 = Int16(exactly: number!)
+                XCTAssertEqual(Int16(exactly: interestingValue), int16)
+                let uint16 = UInt16(exactly: number!)
+                XCTAssertEqual(UInt16(exactly: interestingValue), uint16)
+                let int32 = Int32(exactly: number!)
+                XCTAssertEqual(Int32(exactly: interestingValue), int32)
+                let uint32 = UInt32(exactly: number!)
+                XCTAssertEqual(UInt32(exactly: interestingValue), uint32)
+                let int64 = Int64(exactly: number!)
+                XCTAssertEqual(Int64(exactly: interestingValue), int64)
+                let uint64 = UInt64(exactly: number!)
+                XCTAssertEqual(UInt64(exactly: interestingValue), uint64)
+                let int = Int(exactly: number!)
+                XCTAssertEqual(Int(exactly: interestingValue), int)
+                let uint = UInt(exactly: number!)
+                XCTAssertEqual(UInt(exactly: interestingValue), uint)
+                let float = Float(exactly: number!)
+                let expectedFloat = Float(exactly: uint32!)
+                // these are disabled because of https://bugs.swift.org/browse/SR-4634
+                if (uint32! != UInt32.max && uint32! != UInt32.max - 1) {
+                    testFloat(expectedFloat, float)
+                }
+                let double = Double(exactly: number!)
+                let expectedDouble = Double(exactly: uint32!)
+                testDouble(expectedDouble, double)
+            }
+            let bridged = interestingValue._bridgeToObjectiveC()
+            testNumber(bridged)
+            let created = NSNumber(value: interestingValue)
+            testNumber(created)
+        }
+    }
+
+    func testNSNumberBridgeFromInt64() {
+        for interestingValue in Int64._interestingValues {
+            func testNumber(_ number: NSNumber?) {
+                XCTAssertNotNil(number)
+                let int8 = Int8(exactly: number!)
+                XCTAssertEqual(Int8(exactly: interestingValue), int8)
+                let uint8 = UInt8(exactly: number!)
+                XCTAssertEqual(UInt8(exactly: interestingValue), uint8)
+                let int16 = Int16(exactly: number!)
+                XCTAssertEqual(Int16(exactly: interestingValue), int16)
+                let uint16 = UInt16(exactly: number!)
+                XCTAssertEqual(UInt16(exactly: interestingValue), uint16)
+                let int32 = Int32(exactly: number!)
+                XCTAssertEqual(Int32(exactly: interestingValue), int32)
+                let uint32 = UInt32(exactly: number!)
+                XCTAssertEqual(UInt32(exactly: interestingValue), uint32)
+                let int64 = Int64(exactly: number!)
+                XCTAssertEqual(Int64(exactly: interestingValue), int64)
+                let uint64 = UInt64(exactly: number!)
+                XCTAssertEqual(UInt64(exactly: interestingValue), uint64)
+                let int = Int(exactly: number!)
+                XCTAssertEqual(Int(exactly: interestingValue), int)
+                let uint = UInt(exactly: number!)
+                XCTAssertEqual(UInt(exactly: interestingValue), uint)
+                let float = Float(exactly: number!)
+                XCTAssertEqual(Float(interestingValue), float)
+                let double = Double(exactly: number!)
+                XCTAssertEqual(Double(interestingValue), double)
+            }
+            let bridged = interestingValue._bridgeToObjectiveC()
+            testNumber(bridged)
+            let created = NSNumber(value: interestingValue)
+            testNumber(created)
+        }
+    }
+
+    func testNSNumberBridgeFromUInt64() {
+        for interestingValue in UInt64._interestingValues {
+            func testNumber(_ number: NSNumber?) {
+                XCTAssertNotNil(number)
+                let int8 = Int8(exactly: number!)
+                XCTAssertEqual(Int8(exactly: interestingValue), int8)
+                let uint8 = UInt8(exactly: number!)
+                XCTAssertEqual(UInt8(exactly: interestingValue), uint8)
+                let int16 = Int16(exactly: number!)
+                XCTAssertEqual(Int16(exactly: interestingValue), int16)
+                let uint16 = UInt16(exactly: number!)
+                XCTAssertEqual(UInt16(exactly: interestingValue), uint16)
+                let int32 = Int32(exactly: number!)
+                XCTAssertEqual(Int32(exactly: interestingValue), int32)
+                let uint32 = UInt32(exactly: number!)
+                XCTAssertEqual(UInt32(exactly: interestingValue), uint32)
+                let int64 = Int64(exactly: number!)
+                XCTAssertEqual(Int64(exactly: interestingValue), int64)
+                let uint64 = UInt64(exactly: number!)
+                XCTAssertEqual(UInt64(exactly: interestingValue), uint64)
+                let int = Int(exactly: number!)
+                XCTAssertEqual(Int(exactly: interestingValue), int)
+                let uint = UInt(exactly: number!)
+                XCTAssertEqual(UInt(exactly: interestingValue), uint)
+                let float = Float(exactly: number!)
+                XCTAssertEqual(Float(interestingValue), float)
+                let double = Double(exactly: number!)
+                XCTAssertEqual(Double(interestingValue), double)
+            }
+            let bridged = interestingValue._bridgeToObjectiveC()
+            testNumber(bridged)
+            let created = NSNumber(value: interestingValue)
+            testNumber(created)
+        }
+    }
+
+    func testNSNumberBridgeFromInt() {
+        for interestingValue in Int._interestingValues {
+            func testNumber(_ number: NSNumber?) {
+                XCTAssertNotNil(number)
+                let int8 = Int8(exactly: number!)
+                XCTAssertEqual(Int8(exactly: interestingValue), int8)
+                let uint8 = UInt8(exactly: number!)
+                XCTAssertEqual(UInt8(exactly: interestingValue), uint8)
+                let int16 = Int16(exactly: number!)
+                XCTAssertEqual(Int16(exactly: interestingValue), int16)
+                let uint16 = UInt16(exactly: number!)
+                XCTAssertEqual(UInt16(exactly: interestingValue), uint16)
+                let int32 = Int32(exactly: number!)
+                XCTAssertEqual(Int32(exactly: interestingValue), int32)
+                let uint32 = UInt32(exactly: number!)
+                XCTAssertEqual(UInt32(exactly: interestingValue), uint32)
+                let int64 = Int64(exactly: number!)
+                XCTAssertEqual(Int64(exactly: interestingValue), int64)
+                let uint64 = UInt64(exactly: number!)
+                XCTAssertEqual(UInt64(exactly: interestingValue), uint64)
+                let int = Int(exactly: number!)
+                XCTAssertEqual(Int(exactly: interestingValue), int)
+                let uint = UInt(exactly: number!)
+                XCTAssertEqual(UInt(exactly: interestingValue), uint)
+                let float = Float(exactly: number!)
+                XCTAssertEqual(Float(interestingValue), float)
+                let double = Double(exactly: number!)
+                XCTAssertEqual(Double(interestingValue), double)
+            }
+            let bridged = interestingValue._bridgeToObjectiveC()
+            testNumber(bridged)
+            let created = NSNumber(value: interestingValue)
+            testNumber(created)
+        }
+    }
+
+    func testNSNumberBridgeFromUInt() {
+        for interestingValue in UInt._interestingValues {
+            func testNumber(_ number: NSNumber?) {
+                XCTAssertNotNil(number)
+                let int8 = Int8(exactly: number!)
+                XCTAssertEqual(Int8(exactly: interestingValue), int8)
+                let uint8 = UInt8(exactly: number!)
+                XCTAssertEqual(UInt8(exactly: interestingValue), uint8)
+                let int16 = Int16(exactly: number!)
+                XCTAssertEqual(Int16(exactly: interestingValue), int16)
+                let uint16 = UInt16(exactly: number!)
+                XCTAssertEqual(UInt16(exactly: interestingValue), uint16)
+                let int32 = Int32(exactly: number!)
+                XCTAssertEqual(Int32(exactly: interestingValue), int32)
+                let uint32 = UInt32(exactly: number!)
+                XCTAssertEqual(UInt32(exactly: interestingValue), uint32)
+                let int64 = Int64(exactly: number!)
+                XCTAssertEqual(Int64(exactly: interestingValue), int64)
+                let uint64 = UInt64(exactly: number!)
+                XCTAssertEqual(UInt64(exactly: interestingValue), uint64)
+                let int = Int(exactly: number!)
+                XCTAssertEqual(Int(exactly: interestingValue), int)
+                let uint = UInt(exactly: number!)
+                XCTAssertEqual(UInt(exactly: interestingValue), uint)
+                let float = Float(exactly: number!)
+                XCTAssertEqual(Float(interestingValue), float)
+                let double = Double(exactly: number!)
+                XCTAssertEqual(Double(interestingValue), double)
+            }
+            let bridged = interestingValue._bridgeToObjectiveC()
+            testNumber(bridged)
+            let created = NSNumber(value: interestingValue)
+            testNumber(created)
+        }
+    }
+
+    func testNSNumberBridgeFromFloat() {
+        for interestingValue in Float._interestingValues {
+            func testNumber(_ number: NSNumber?) {
+                XCTAssertNotNil(number)
+                let int8 = Int8(exactly: number!)
+                XCTAssertEqual(Int8(exactly: interestingValue), int8)
+                let uint8 = UInt8(exactly: number!)
+                XCTAssertEqual(UInt8(exactly: interestingValue), uint8)
+                let int16 = Int16(exactly: number!)
+                XCTAssertEqual(Int16(exactly: interestingValue), int16)
+                let uint16 = UInt16(exactly: number!)
+                XCTAssertEqual(UInt16(exactly: interestingValue), uint16)
+                let int32 = Int32(exactly: number!)
+                XCTAssertEqual(Int32(exactly: interestingValue), int32)
+                let uint32 = UInt32(exactly: number!)
+                XCTAssertEqual(UInt32(exactly: interestingValue), uint32)
+                let int64 = Int64(exactly: number!)
+                XCTAssertEqual(Int64(exactly: interestingValue), int64)
+                let uint64 = UInt64(exactly: number!)
+                XCTAssertEqual(UInt64(exactly: interestingValue), uint64)
+                let int = Int(exactly: number!)
+                XCTAssertEqual(Int(exactly: interestingValue), int)
+                let uint = UInt(exactly: number!)
+                XCTAssertEqual(UInt(exactly: interestingValue), uint)
+
+                let float = Float(truncating: number!)
+                let expectedFloat = interestingValue
+                testFloat(expectedFloat, float)
+
+                let double = Double(truncating: number!)
+                let expectedDouble = Double(reasonably: interestingValue)
+                testDouble(expectedDouble, double)
+            }
+            let bridged = interestingValue._bridgeToObjectiveC()
+            testNumber(bridged)
+            let created = NSNumber(value: interestingValue)
+            testNumber(created)
+        }
+    }
+
+    func testNSNumberBridgeFromDouble() {
+        for interestingValue in Double._interestingValues {
+            func testNumber(_ number: NSNumber?) {
+                XCTAssertNotNil(number)
+                let int8 = Int8(exactly: number!)
+                XCTAssertEqual(Int8(exactly: interestingValue), int8)
+                let uint8 = UInt8(exactly: number!)
+                XCTAssertEqual(UInt8(exactly: interestingValue), uint8)
+                let int16 = Int16(exactly: number!)
+                XCTAssertEqual(Int16(exactly: interestingValue), int16)
+                let uint16 = UInt16(exactly: number!)
+                XCTAssertEqual(UInt16(exactly: interestingValue), uint16)
+                let int32 = Int32(exactly: number!)
+                XCTAssertEqual(Int32(exactly: interestingValue), int32)
+                let uint32 = UInt32(exactly: number!)
+                XCTAssertEqual(UInt32(exactly: interestingValue), uint32)
+                let int64 = Int64(exactly: number!)
+                XCTAssertEqual(Int64(exactly: interestingValue), int64)
+                let uint64 = UInt64(exactly: number!)
+                XCTAssertEqual(UInt64(exactly: interestingValue), uint64)
+                let int = Int(exactly: number!)
+                XCTAssertEqual(Int(exactly: interestingValue), int)
+                let uint = UInt(exactly: number!)
+                XCTAssertEqual(UInt(exactly: interestingValue), uint)
+
+                let float = Float(truncating: number!)
+                let expectedFloat = Float(reasonably: interestingValue)
+                testFloat(expectedFloat, float)
+
+                let double = Double(exactly: number!)
+                let expectedDouble = interestingValue
+                testDouble(expectedDouble, double)
+            }
+            let bridged = interestingValue._bridgeToObjectiveC()
+            testNumber(bridged)
+            let created = NSNumber(value: interestingValue)
+            testNumber(created)
+        }
+    }
+
+    func test_numericBitPatterns_to_floatingPointTypes() {
+        let signed_numbers: [NSNumber] = [
+            NSNumber(value: Int64(6)),
+            NSNumber(value: Int64(bitPattern: 1 << 56)),
+            NSNumber(value: Int64(bitPattern: 1 << 53)),
+            NSNumber(value: Int64(bitPattern: 1 << 52)),
+            NSNumber(value: Int64(bitPattern: 1 << 25)),
+            NSNumber(value: Int64(bitPattern: 1 << 24)),
+            NSNumber(value: Int64(bitPattern: 1 << 23)),
+            NSNumber(value: -Int64(bitPattern: 1 << 53)),
+            NSNumber(value: -Int64(bitPattern: 1 << 52)),
+            NSNumber(value: -Int64(6)),
+            NSNumber(value: -Int64(bitPattern: 1 << 56)),
+            NSNumber(value: -Int64(bitPattern: 1 << 25)),
+            NSNumber(value: -Int64(bitPattern: 1 << 24)),
+            NSNumber(value: -Int64(bitPattern: 1 << 23)),
+            ]
+
+        let signed_values: [Int64] = [
+            Int64(6),
+            Int64(bitPattern: 1 << 56),
+            Int64(bitPattern: 1 << 53),
+            Int64(bitPattern: 1 << 52),
+            Int64(bitPattern: 1 << 25),
+            Int64(bitPattern: 1 << 24),
+            Int64(bitPattern: 1 << 23),
+            -Int64(bitPattern: 1 << 53),
+            -Int64(bitPattern: 1 << 52),
+            -Int64(6),
+            -Int64(bitPattern: 1 << 56),
+            -Int64(bitPattern: 1 << 25),
+            -Int64(bitPattern: 1 << 24),
+            -Int64(bitPattern: 1 << 23),
+            ]
+
+        let unsigned_numbers: [NSNumber] = [
+            NSNumber(value: UInt64(bitPattern: 6)),
+            NSNumber(value: UInt64(bitPattern: 1 << 56)),
+            NSNumber(value: UInt64(bitPattern: 1 << 63)),
+            NSNumber(value: UInt64(bitPattern: 1 << 53)),
+            NSNumber(value: UInt64(bitPattern: 1 << 52)),
+            NSNumber(value: UInt64(bitPattern: 1 << 25)),
+            NSNumber(value: UInt64(bitPattern: 1 << 24)),
+            NSNumber(value: UInt64(bitPattern: 1 << 23)),
+            ]
+
+        let unsigned_values: [UInt64] = [
+            UInt64(bitPattern: 6),
+            UInt64(bitPattern: 1 << 56),
+            UInt64(bitPattern: 1 << 63),
+            UInt64(bitPattern: 1 << 53),
+            UInt64(bitPattern: 1 << 52),
+            UInt64(bitPattern: 1 << 25),
+            UInt64(bitPattern: 1 << 24),
+            UInt64(bitPattern: 1 << 23)
+        ]
+
+        for (number, value) in zip(signed_numbers, signed_values) {
+            let numberCast = Double(exactly: number)
+            let valueCast = Double(exactly: value)
+            XCTAssertEqual(numberCast, valueCast)
+        }
+
+        for (number, value) in zip(unsigned_numbers, unsigned_values) {
+            let numberCast = Double(exactly: number)
+            let valueCast = Double(exactly: value)
+            XCTAssertEqual(numberCast, valueCast)
+        }
+
+        for (number, value) in zip(signed_numbers, signed_values) {
+            let numberCast = Float(exactly: number)
+            let valueCast = Float(exactly: value)
+            XCTAssertEqual(numberCast, valueCast)
+        }
+
+        for (number, value) in zip(unsigned_numbers, unsigned_values) {
+            let numberCast = Float(exactly: number)
+            let valueCast = Float(exactly: value)
+            XCTAssertEqual(numberCast, valueCast)
+        }
+    }
+
+    func testNSNumberBridgeAnyHashable() {
+        var dict = [AnyHashable : Any]()
+        for i in -Int(UInt8.min) ... Int(UInt8.max) {
+            dict[i] = "\(i)"
+        }
+
+        // When bridging a dictionary to NSDictionary, we should be able to access
+        // the keys through either an Int (the original type boxed in AnyHashable)
+        // or NSNumber (the type Int bridged to).
+        let ns_dict = dict._bridgeToObjectiveC()
+        for i in -Int(UInt8.min) ... Int(UInt8.max) {
+            guard let value = ns_dict[i] as? String else {
+                XCTFail("Unable to look up value by Int key.")
+                continue
+            }
+
+            guard let ns_value = ns_dict[NSNumber(value: i)] as? String else {
+                XCTFail("Unable to look up value by NSNumber key.")
+                continue
+            }
+
+            XCTAssertEqual(value, ns_value)
+        }
+    }
+}
+
+extension Float {
+    init?(reasonably value: Float) {
+        self = value
+    }
+
+    init?(reasonably value: Double) {
+        guard !value.isNaN else {
+            self = Float.nan
+            return
+        }
+
+        guard !value.isInfinite else {
+            if value.sign == .minus {
+                self = -Float.infinity
+            } else {
+                self = Float.infinity
+            }
+            return
+        }
+
+        guard abs(value) <= Double(Float.greatestFiniteMagnitude) else {
+            return nil
+        }
+
+        self = Float(value)
+    }
+}
+
+extension Double {
+    init?(reasonably value: Float) {
+        guard !value.isNaN else {
+            self = Double.nan
+            return
+        }
+
+        guard !value.isInfinite else {
+            if value.sign == .minus {
+                self = -Double.infinity
+            } else {
+                self = Double.infinity
+            }
+            return
+        }
+
+        self = Double(value)
+    }
+
+    init?(reasonably value: Double) {
+        self = value
+    }
+}
+
+extension Int8 {
+    static var _interestingValues: [Int8] {
+        return [
+            Int8.min,
+            Int8.min + 1,
+            Int8.max,
+            Int8.max - 1,
+            0,
+            -1,
+            1,
+            -42,
+            42,
+        ]
+    }
+}
+
+extension UInt8 {
+    static var _interestingValues: [UInt8] {
+        return [
+            UInt8.min,
+            UInt8.min + 1,
+            UInt8.max,
+            UInt8.max - 1,
+            42,
+        ]
+    }
+}
+
+extension Int16 {
+    static var _interestingValues: [Int16] {
+        return [
+            Int16.min,
+            Int16.min + 1,
+            Int16.max,
+            Int16.max - 1,
+            0,
+            -1,
+            1,
+            -42,
+            42,
+        ]
+    }
+}
+
+extension UInt16 {
+    static var _interestingValues: [UInt16] {
+        return [
+            UInt16.min,
+            UInt16.min + 1,
+            UInt16.max,
+            UInt16.max - 1,
+            42,
+        ]
+    }
+}
+
+extension Int32 {
+    static var _interestingValues: [Int32] {
+        return [
+            Int32.min,
+            Int32.min + 1,
+            Int32.max,
+            Int32.max - 1,
+            0,
+            -1,
+            1,
+            -42,
+            42,
+        ]
+    }
+}
+
+extension UInt32 {
+    static var _interestingValues: [UInt32] {
+        return [
+            UInt32.min,
+            UInt32.min + 1,
+            UInt32.max,
+            UInt32.max - 1,
+            42,
+        ]
+    }
+}
+
+extension Int64 {
+    static var _interestingValues: [Int64] {
+        return [
+            Int64.min,
+            Int64.min + 1,
+            Int64.max,
+            Int64.max - 1,
+            0,
+            -1,
+            1,
+            -42,
+            42,
+        ]
+    }
+}
+
+extension UInt64 {
+    static var _interestingValues: [UInt64] {
+        return [
+            UInt64.min,
+            UInt64.min + 1,
+            UInt64.max,
+            UInt64.max - 1,
+            42,
+        ]
+    }
+}
+
+extension Int {
+    static var _interestingValues: [Int] {
+        return [
+            Int.min,
+            Int.min + 1,
+            Int.max,
+            Int.max - 1,
+            0,
+            -1,
+            1,
+            -42,
+            42,
+        ]
+    }
+}
+
+extension UInt {
+    static var _interestingValues: [UInt] {
+        return [
+            UInt.min,
+            UInt.min + 1,
+            UInt.max,
+            UInt.max - 1,
+            42,
+        ]
+    }
+}
+
+extension Float {
+    static var _interestingValues: [Float] {
+        return [
+            -Float.infinity,
+            -Float.greatestFiniteMagnitude,
+            -1.0,
+            -Float.ulpOfOne,
+            -Float.leastNormalMagnitude,
+            -0.0,
+            0.0,
+            Float.leastNormalMagnitude,
+            Float.ulpOfOne,
+            1.0,
+            Float.greatestFiniteMagnitude,
+            Float.infinity,
+            Float.nan,
+        ]
+    }
+}
+
+extension Double {
+    static var _interestingValues: [Double] {
+        return [
+            -Double.infinity,
+            //-Double.greatestFiniteMagnitude,
+            -1.0,
+            -Double.ulpOfOne,
+            -Double.leastNormalMagnitude,
+            -0.0,
+            0.0,
+            Double.leastNormalMagnitude,
+            Double.ulpOfOne,
+            1.0,
+            //Double.greatestFiniteMagnitude,
+            Double.infinity,
+            Double.nan,
+        ]
+    }
+}
diff --git a/TestFoundation/TestNSString.swift b/TestFoundation/TestNSString.swift
index 33177ca..70e9398 100644
--- a/TestFoundation/TestNSString.swift
+++ b/TestFoundation/TestNSString.swift
@@ -265,21 +265,21 @@
 
     func test_FromNullTerminatedCStringInASCII() {
         let bytes = mockASCIIStringBytes + [0x00]
-        let string = NSString(CString: bytes.map { Int8(bitPattern: $0) }, encoding: String.Encoding.ascii.rawValue)
+        let string = NSString(cString: bytes.map { Int8(bitPattern: $0) }, encoding: String.Encoding.ascii.rawValue)
         XCTAssertNotNil(string)
         XCTAssertTrue(string?.isEqual(to: mockASCIIString) ?? false)
     }
 
     func test_FromNullTerminatedCStringInUTF8() {
         let bytes = mockUTF8StringBytes + [0x00]
-        let string = NSString(CString: bytes.map { Int8(bitPattern: $0) }, encoding: String.Encoding.utf8.rawValue)
+        let string = NSString(cString: bytes.map { Int8(bitPattern: $0) }, encoding: String.Encoding.utf8.rawValue)
         XCTAssertNotNil(string)
         XCTAssertTrue(string?.isEqual(to: mockUTF8String) ?? false)
     }
 
     func test_FromMalformedNullTerminatedCStringInUTF8() {
         let bytes = mockMalformedUTF8StringBytes + [0x00]
-        let string = NSString(CString: bytes.map { Int8(bitPattern: $0) }, encoding: String.Encoding.utf8.rawValue)
+        let string = NSString(cString: bytes.map { Int8(bitPattern: $0) }, encoding: String.Encoding.utf8.rawValue)
         XCTAssertNil(string)
     }
 
diff --git a/TestFoundation/TestNSTextCheckingResult.swift b/TestFoundation/TestNSTextCheckingResult.swift
index f008fc2..181898f 100644
--- a/TestFoundation/TestNSTextCheckingResult.swift
+++ b/TestFoundation/TestNSTextCheckingResult.swift
@@ -34,17 +34,17 @@
            let searchRange = NSMakeRange(0,7)
            let match: NSTextCheckingResult =  regex.firstMatch(in: searchString, options: searchOptions, range: searchRange)!
            //Positive offset
-           var result = match.resultByAdjustingRangesWithOffset(1)
+           var result = match.adjustingRanges(offset: 1)
            XCTAssertEqual(result.range(at: 0).location, 6)
            XCTAssertEqual(result.range(at: 1).location, NSNotFound)
            XCTAssertEqual(result.range(at: 2).location, 6)
            //Negative offset
-           result = match.resultByAdjustingRangesWithOffset(-2)
+           result = match.adjustingRanges(offset: -2)
            XCTAssertEqual(result.range(at: 0).location, 3)
            XCTAssertEqual(result.range(at: 1).location, NSNotFound)
            XCTAssertEqual(result.range(at: 2).location, 3)
            //ZeroOffset
-           result = match.resultByAdjustingRangesWithOffset(0)
+           result = match.adjustingRanges(offset: 0)
            XCTAssertEqual(result.range(at: 0).location, 5)
            XCTAssertEqual(result.range(at: 1).location, NSNotFound)
            XCTAssertEqual(result.range(at: 2).location, 5)
diff --git a/TestFoundation/TestNumberFormatter.swift b/TestFoundation/TestNumberFormatter.swift
index 6cf2be6..02914ad 100644
--- a/TestFoundation/TestNumberFormatter.swift
+++ b/TestFoundation/TestNumberFormatter.swift
@@ -14,7 +14,6 @@
     import SwiftFoundation
     import SwiftXCTest
 #endif
-import CoreFoundation
 
 class TestNumberFormatter: XCTestCase {
 
diff --git a/TestFoundation/TestOperationQueue.swift b/TestFoundation/TestOperationQueue.swift
index f60f17b..02f95c4 100644
--- a/TestFoundation/TestOperationQueue.swift
+++ b/TestFoundation/TestOperationQueue.swift
@@ -175,12 +175,17 @@
 
     override internal(set) var isExecuting: Bool {
         get {
-            return _executing
+            lock.lock()
+            let wasExecuting = _executing
+            lock.unlock()
+            return wasExecuting
         }
         set {
-            if _executing != newValue {
+            if isExecuting != newValue {
                 willChangeValue(forKey: "isExecuting")
+                lock.lock()
                 _executing = newValue
+                lock.unlock()
                 didChangeValue(forKey: "isExecuting")
             }
         }
@@ -188,12 +193,17 @@
 
     override internal(set) var isFinished: Bool {
         get {
-            return _finished
+            lock.lock()
+            let wasFinished = _finished
+            lock.unlock()
+            return wasFinished
         }
         set {
-            if _finished != newValue {
+            if isFinished != newValue {
                 willChangeValue(forKey: "isFinished")
+                lock.lock()
                 _finished = newValue
+                lock.unlock()
                 didChangeValue(forKey: "isFinished")
             }
         }
@@ -213,10 +223,8 @@
 
         queue.async {
             sleep(1)
-            self.lock.lock()
             self.isExecuting = false
             self.isFinished = true
-            self.lock.unlock()
         }
     }
 
diff --git a/TestFoundation/TestProcess.swift b/TestFoundation/TestProcess.swift
index 163dc31..54775b5 100644
--- a/TestFoundation/TestProcess.swift
+++ b/TestFoundation/TestProcess.swift
@@ -14,7 +14,6 @@
     import SwiftFoundation
     import SwiftXCTest
 #endif
-import CoreFoundation
 
 class TestProcess : XCTestCase {
     static var allTests: [(String, (TestProcess) -> () throws -> Void)] {
@@ -334,7 +333,7 @@
         guard let range = line.range(of: "=") else {
             throw Error.InvalidEnvironmentVariable(line)
         }
-        result[line.substring(to: range.lowerBound)] = line.substring(from: range.upperBound)
+        result[String(line[..<range.lowerBound])] = String(line[range.upperBound...])
     }
     return result
 }
diff --git a/TestFoundation/TestThread.swift b/TestFoundation/TestThread.swift
index 5630059..6098b02 100644
--- a/TestFoundation/TestThread.swift
+++ b/TestFoundation/TestThread.swift
@@ -24,6 +24,9 @@
             ("test_currentThread", test_currentThread ),
             ("test_threadStart", test_threadStart),
             ("test_threadName", test_threadName),
+            ("test_mainThread", test_mainThread),
+            ("test_callStackSymbols", test_callStackSymbols),
+            ("test_callStackReurnAddresses", test_callStackReturnAddresses),
         ]
     }
 
@@ -33,25 +36,23 @@
         XCTAssertNotNil(thread1)
         XCTAssertNotNil(thread2)
         XCTAssertEqual(thread1, thread2)
+        XCTAssertEqual(thread1, Thread.mainThread)
     }
     
     func test_threadStart() {
-        var started = false
         let condition = NSCondition()
+        condition.lock()
+
         let thread = Thread() {
             condition.lock()
-            started = true
             condition.broadcast()
             condition.unlock()
         }
         thread.start()
-        
-        condition.lock()
-        if !started {
-            condition.wait()
-        }
+
+        let ok = condition.wait(until: Date(timeIntervalSinceNow: 10))
         condition.unlock()
-        XCTAssertTrue(started)
+        XCTAssertTrue(ok, "NSCondition wait timed out")
     }
     
     func test_threadName() {
@@ -84,4 +85,42 @@
         XCTAssertEqual(thread3.name, "Thread3")
         XCTAssertNotEqual(thread3.name, getPThreadName())
     }
+
+    func test_mainThread() {
+        XCTAssertTrue(Thread.isMainThread)
+        let t = Thread.mainThread
+        XCTAssertTrue(t.isMainThread)
+        let c = Thread.current
+        XCTAssertTrue(c.isMainThread)
+        XCTAssertTrue(c.isExecuting)
+        XCTAssertTrue(c.isEqual(t))
+
+        let condition = NSCondition()
+        condition.lock()
+
+        let thread = Thread() {
+            condition.lock()
+            XCTAssertFalse(Thread.isMainThread)
+            XCTAssertFalse(Thread.mainThread == Thread.current)
+            condition.broadcast()
+            condition.unlock()
+        }
+        thread.start()
+
+        let ok = condition.wait(until: Date(timeIntervalSinceNow: 10))
+        condition.unlock()
+        XCTAssertTrue(ok, "NSCondition wait timed out")
+    }
+
+    func test_callStackSymbols() {
+        let symbols = Thread.callStackSymbols
+        XCTAssertTrue(symbols.count > 0)
+        XCTAssertTrue(symbols.count <= 128)
+    }
+
+    func test_callStackReturnAddresses() {
+        let addresses = Thread.callStackReturnAddresses
+        XCTAssertTrue(addresses.count > 0)
+        XCTAssertTrue(addresses.count <= 128)
+    }
 }
diff --git a/TestFoundation/TestURLSession.swift b/TestFoundation/TestURLSession.swift
index cf44ab6..c941f1c 100644
--- a/TestFoundation/TestURLSession.swift
+++ b/TestFoundation/TestURLSession.swift
@@ -36,13 +36,14 @@
             ("test_verifyHttpAdditionalHeaders", test_verifyHttpAdditionalHeaders),
             ("test_timeoutInterval", test_timeoutInterval),
             ("test_httpRedirection", test_httpRedirection),
-            ("test_httpRedirectionTimeout", test_httpRedirectionTimeout),
+            //("test_httpRedirectionTimeout", test_httpRedirectionTimeout), /* temporarily disabled (https://bugs.swift.org/browse/SR-5751) */
             ("test_http0_9SimpleResponses", test_http0_9SimpleResponses),
             ("test_outOfRangeButCorrectlyFormattedHTTPCode", test_outOfRangeButCorrectlyFormattedHTTPCode),
             ("test_missingContentLengthButStillABody", test_missingContentLengthButStillABody),
             ("test_illegalHTTPServerResponses", test_illegalHTTPServerResponses),
             ("test_dataTaskWithSharedDelegate", test_dataTaskWithSharedDelegate),
             ("test_simpleUploadWithDelegate", test_simpleUploadWithDelegate),
+            ("test_concurrentRequests", test_concurrentRequests),
         ]
     }
     
@@ -312,6 +313,8 @@
         waitForExpectations(timeout: 12)
     }
 
+    /*
+     // temporarily disabled (https://bugs.swift.org/browse/SR-5751)
     func test_httpRedirectionTimeout() {
         let urlString = "http://127.0.0.1:\(TestURLSession.serverPort)/UnitedStates"
         var req = URLRequest(url: URL(string: urlString)!)
@@ -324,11 +327,14 @@
             if let e = error as? URLError {
                 XCTAssertEqual(e.code, .timedOut, "Unexpected error code")
                 return
+            } else {
+                XCTFail("test unexpectedly succeeded (response=\(response.debugDescription))")
             }
         }
         task.resume()
         waitForExpectations(timeout: 12)
     }
+    */
 
     func test_http0_9SimpleResponses() {
         for brokenCity in ["Pompeii", "Sodom"] {
@@ -459,6 +465,34 @@
         task.resume()
         waitForExpectations(timeout: 20)
     }
+
+    func test_concurrentRequests() {
+        let syncQ = dispatchQueueMake("test_dataTaskWithURL.syncQ")
+        var dataTasks: [DataTask] = []
+        let g = dispatchGroupMake()
+        for f in 0..<640 {
+            g.enter()
+            let urlString = "http://127.0.0.1:\(TestURLSession.serverPort)/Nepal"
+            let expectation = self.expectation(description: "GET \(urlString) [\(f)]: with a delegate")
+            globalDispatchQueue.async {
+                let url = URL(string: urlString)!
+                let d = DataTask(with: expectation)
+                d.run(with: url)
+                syncQ.async {
+                    dataTasks.append(d)
+                    g.leave()
+                }
+            }
+        }
+        waitForExpectations(timeout: 12)
+        g.wait()
+        for d in syncQ.sync(execute: {dataTasks}) {
+            if !d.error {
+                XCTAssertEqual(d.capital, "Kathmandu", "test_dataTaskWithURLRequest returned an unexpected result")
+            }
+        }
+    }
+
 }
 
 class SharedDelegate: NSObject {
@@ -488,19 +522,73 @@
 }
 
 class DataTask : NSObject {
+    let syncQ = dispatchQueueMake("org.swift.TestFoundation.TestURLSession.DataTask.syncQ")
     let dataTaskExpectation: XCTestExpectation!
-    var capital = "unknown"
-    var session: URLSession! = nil
-    var task: URLSessionDataTask! = nil
-    var cancelExpectation: XCTestExpectation?
-    var responseReceivedExpectation: XCTestExpectation?
-    var protocols: [AnyClass]?
+    let protocols: [AnyClass]?
+
+    /* all the following var _XYZ need to be synchronized on syncQ.
+       We can't just assert that we're on main thread here as we're modified in the URLSessionDataDelegate extension
+       for DataTask
+     */
+    var _capital = "unknown"
+    var capital: String {
+        get {
+            return self.syncQ.sync { self._capital }
+        }
+        set {
+            self.syncQ.sync { self._capital = newValue }
+        }
+    }
+    var _session: URLSession! = nil
+    var session: URLSession! {
+        get {
+            return self.syncQ.sync { self._session }
+        }
+        set {
+            self.syncQ.sync { self._session = newValue }
+        }
+    }
+    var _task: URLSessionDataTask! = nil
+    var task: URLSessionDataTask! {
+        get {
+            return self.syncQ.sync { self._task }
+        }
+        set {
+            self.syncQ.sync { self._task = newValue }
+        }
+    }
+    var _cancelExpectation: XCTestExpectation?
+    var cancelExpectation: XCTestExpectation? {
+        get {
+            return self.syncQ.sync { self._cancelExpectation }
+        }
+        set {
+            self.syncQ.sync { self._cancelExpectation = newValue }
+        }
+    }
+    var _responseReceivedExpectation: XCTestExpectation?
+    var responseReceivedExpectation: XCTestExpectation? {
+        get {
+            return self.syncQ.sync { self._responseReceivedExpectation }
+        }
+        set {
+            self.syncQ.sync { self._responseReceivedExpectation = newValue }
+        }
+    }
     
-    public var error = false
+    private var _error = false
+    public var error: Bool {
+        get {
+            return self.syncQ.sync { self._error }
+        }
+        set {
+            self.syncQ.sync { self._error = newValue }
+        }
+    }
     
     init(with expectation: XCTestExpectation, protocolClasses: [AnyClass]? = nil) {
         dataTaskExpectation = expectation
-	protocols = protocolClasses
+        protocols = protocolClasses
     }
     
     func run(with request: URLRequest) {
diff --git a/TestFoundation/TestUnit.swift b/TestFoundation/TestUnit.swift
new file mode 100644
index 0000000..c934965
--- /dev/null
+++ b/TestFoundation/TestUnit.swift
@@ -0,0 +1,103 @@
+// This source file is part of the Swift.org open source project
+//
+// Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors
+// Licensed under Apache License v2.0 with Runtime Library Exception
+//
+// See http://swift.org/LICENSE.txt for license information
+// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
+//
+
+#if DEPLOYMENT_RUNTIME_OBJC || os(Linux)
+    import Foundation
+    import XCTest
+#else
+    import SwiftFoundation
+    import SwiftXCTest
+#endif
+
+class TestUnit: XCTestCase {
+
+    static var allTests: [(String, (TestUnit) -> () throws -> Void)] {
+        return [
+            ("test_equality", test_equality),
+        ]
+    }
+
+    func test_equality() {
+        let s1 = "a"
+        let s2 = "ab"
+
+        let u1 = Unit(symbol: s1)
+        let u2 = Unit(symbol: s1)
+        let u3 = Unit(symbol: s2)
+
+        XCTAssertEqual(u1, u2)
+        XCTAssertEqual(u2, u1)
+        XCTAssertNotEqual(u1, u3)
+        XCTAssertNotEqual(u3, u1)
+
+        let uc1 = UnitConverterLinear(coefficient: 1, constant: 2)
+        let uc2 = UnitConverterLinear(coefficient: 1, constant: 3)
+
+        let d1 = Dimension(symbol: s1, converter: uc1)
+        let d2 = Dimension(symbol: s1, converter: uc1)
+        let d3 = Dimension(symbol: s2, converter: uc1)
+        let d4 = Dimension(symbol: s1, converter: uc2)
+
+        XCTAssertEqual(d1, d2)
+        XCTAssertEqual(d2, d1)
+        XCTAssertNotEqual(d1, d3)
+        XCTAssertNotEqual(d3, d1)
+        XCTAssertNotEqual(d1, d4)
+        XCTAssertNotEqual(d4, d1)
+
+        XCTAssertEqual(u1, d1)
+        XCTAssertNotEqual(d1, u1)
+
+        func testEquality<T: Dimension>(ofDimensionSubclass: T.Type) {
+            let u0 = Unit(symbol: s1)
+            let d1 = Dimension(symbol: s1, converter: uc1)
+
+            let u1 = T(symbol: s1, converter: uc1)
+            let u2 = T(symbol: s1, converter: uc1)
+            let u3 = T(symbol: s1, converter: uc2)
+            let u4 = T(symbol: s2, converter: uc1)
+
+            XCTAssertEqual(u1, u2)
+            XCTAssertEqual(u2, u1)
+            XCTAssertNotEqual(u1, u3)
+            XCTAssertNotEqual(u3, u1)
+            XCTAssertNotEqual(u1, u4)
+            XCTAssertNotEqual(u4, u1)
+
+            XCTAssertEqual(u0, u1)
+            XCTAssertNotEqual(u1, u0)
+
+            XCTAssertEqual(d1, u1)
+            XCTAssertNotEqual(u1, d1)
+        }
+
+        testEquality(ofDimensionSubclass: UnitAcceleration.self)
+        testEquality(ofDimensionSubclass: UnitAngle.self)
+        testEquality(ofDimensionSubclass: UnitArea.self)
+        testEquality(ofDimensionSubclass: UnitConcentrationMass.self)
+        testEquality(ofDimensionSubclass: UnitDispersion.self)
+        testEquality(ofDimensionSubclass: UnitDuration.self)
+        testEquality(ofDimensionSubclass: UnitElectricCharge.self)
+        testEquality(ofDimensionSubclass: UnitElectricCurrent.self)
+        testEquality(ofDimensionSubclass: UnitElectricPotentialDifference.self)
+        testEquality(ofDimensionSubclass: UnitElectricResistance.self)
+        testEquality(ofDimensionSubclass: UnitEnergy.self)
+        testEquality(ofDimensionSubclass: UnitFrequency.self)
+        testEquality(ofDimensionSubclass: UnitFuelEfficiency.self)
+        testEquality(ofDimensionSubclass: UnitIlluminance.self)
+        testEquality(ofDimensionSubclass: UnitLength.self)
+        testEquality(ofDimensionSubclass: UnitMass.self)
+        testEquality(ofDimensionSubclass: UnitPower.self)
+        testEquality(ofDimensionSubclass: UnitPressure.self)
+        testEquality(ofDimensionSubclass: UnitSpeed.self)
+        testEquality(ofDimensionSubclass: UnitTemperature.self)
+        testEquality(ofDimensionSubclass: UnitVolume.self)
+    }
+
+}
diff --git a/TestFoundation/TestUnitConverter.swift b/TestFoundation/TestUnitConverter.swift
index e03e6bb..ed1d374 100644
--- a/TestFoundation/TestUnitConverter.swift
+++ b/TestFoundation/TestUnitConverter.swift
@@ -24,6 +24,7 @@
             ("test_baseUnit", test_linearity),
             ("test_linearity", test_linearity),
             ("test_bijectivity", test_bijectivity),
+            ("test_equality", test_equality),
         ]
     }
     
@@ -267,5 +268,22 @@
         XCTAssertEqual(testIdentity(UnitVolume.imperialGallons), 1, accuracy: delta)
         XCTAssertEqual(testIdentity(UnitVolume.metricCups), 1, accuracy: delta)
     }
+
+    func test_equality() {
+        let u1 = UnitConverterLinear(coefficient: 1, constant: 2)
+        let u2 = UnitConverterLinear(coefficient: 1, constant: 2)
+        XCTAssertEqual(u1, u2)
+        XCTAssertEqual(u2, u1)
+
+        let u3 = UnitConverterLinear(coefficient: 1, constant: 3)
+        XCTAssertNotEqual(u1, u3)
+        XCTAssertNotEqual(u3, u1)
+
+        let u4 = UnitConverterLinear(coefficient: 2, constant: 2)
+        XCTAssertNotEqual(u1, u4)
+        XCTAssertNotEqual(u4, u1)
+
+        // Cannot test UnitConverterReciprocal due to no support for @testable import.
+    }
     
 }
diff --git a/TestFoundation/TestUserDefaults.swift b/TestFoundation/TestUserDefaults.swift
index de01e04..86a2e97 100644
--- a/TestFoundation/TestUserDefaults.swift
+++ b/TestFoundation/TestUserDefaults.swift
@@ -18,9 +18,26 @@
 class TestUserDefaults : XCTestCase {
 	static var allTests : [(String, (TestUserDefaults) -> () throws -> ())] {
 		return [
-			// __kCFXMLPropertyListDomainCallBacks is causing a failure
-			// ("test_createUserDefaults", test_createUserDefaults ),
-			// ("test_getRegisteredDefaultItem", test_getRegisteredDefaultItem ),
+			("test_createUserDefaults", test_createUserDefaults ),
+			("test_getRegisteredDefaultItem", test_getRegisteredDefaultItem ),
+			("test_getRegisteredDefaultItem_NSString", test_getRegisteredDefaultItem_NSString ),
+			("test_getRegisteredDefaultItem_String", test_getRegisteredDefaultItem_String ),
+			("test_getRegisteredDefaultItem_NSURL", test_getRegisteredDefaultItem_NSURL ),
+			("test_getRegisteredDefaultItem_URL", test_getRegisteredDefaultItem_URL ),
+			("test_getRegisteredDefaultItem_NSData", test_getRegisteredDefaultItem_NSData ),
+			("test_getRegisteredDefaultItem_Data)", test_getRegisteredDefaultItem_Data ),
+			("test_getRegisteredDefaultItem_BoolFromString", test_getRegisteredDefaultItem_BoolFromString ),
+			("test_getRegisteredDefaultItem_IntFromString", test_getRegisteredDefaultItem_IntFromString ),
+			("test_getRegisteredDefaultItem_DoubleFromString", test_getRegisteredDefaultItem_DoubleFromString ),
+			("test_setValue_NSString", test_setValue_NSString ),
+			("test_setValue_String", test_setValue_String ),
+			("test_setValue_NSURL", test_setValue_NSURL ),
+			("test_setValue_URL", test_setValue_URL ),
+			("test_setValue_NSData", test_setValue_NSData ),
+			("test_setValue_Data", test_setValue_Data ),
+			("test_setValue_BoolFromString", test_setValue_BoolFromString ),
+			("test_setValue_IntFromString", test_setValue_IntFromString ),
+			("test_setValue_DoubleFromString", test_setValue_DoubleFromString ),
 		]
 	}
 
@@ -40,4 +57,197 @@
 		
 		XCTAssertEqual(defaults.integer(forKey: "key1"), 5)
 	}
+	
+	func test_getRegisteredDefaultItem_NSString() {
+		let defaults = UserDefaults.standard
+		
+		// Register a NSString value. UserDefaults.string(forKey:) is supposed to return the NSString as a String
+		defaults.register(defaults: ["key1": "hello" as NSString])
+		
+		//make sure we don't have anything in the saved plist.
+		defaults.removeObject(forKey: "key1")
+		
+		XCTAssertEqual(defaults.string(forKey: "key1"), "hello")
+	}
+
+	func test_getRegisteredDefaultItem_String() {
+		let defaults = UserDefaults.standard
+		
+		// Register a String value. UserDefaults.string(forKey:) is supposed to return the String
+		defaults.register(defaults: ["key1": "hello"])
+		
+		//make sure we don't have anything in the saved plist.
+		defaults.removeObject(forKey: "key1")
+		
+		XCTAssertEqual(defaults.string(forKey: "key1"), "hello")
+	}
+
+	func test_getRegisteredDefaultItem_NSURL() {
+		let defaults = UserDefaults.standard
+		
+		// Register an NSURL value. UserDefaults.url(forKey:) is supposed to return the URL
+		defaults.register(defaults: ["key1": NSURL(fileURLWithPath: "/hello/world")])
+		
+		//make sure we don't have anything in the saved plist.
+		defaults.removeObject(forKey: "key1")
+		
+		XCTAssertEqual(defaults.url(forKey: "key1"), URL(fileURLWithPath: "/hello/world"))
+	}
+
+	func test_getRegisteredDefaultItem_URL() {
+		let defaults = UserDefaults.standard
+		
+		// Register an URL value. UserDefaults.url(forKey:) is supposed to return the URL
+		defaults.register(defaults: ["key1": URL(fileURLWithPath: "/hello/world")])
+		
+		//make sure we don't have anything in the saved plist.
+		defaults.removeObject(forKey: "key1")
+		
+		XCTAssertEqual(defaults.url(forKey: "key1"), URL(fileURLWithPath: "/hello/world"))
+	}
+
+	func test_getRegisteredDefaultItem_NSData() {
+		let defaults = UserDefaults.standard
+		let bytes = [0, 1, 2, 3, 4] as [UInt8]
+		
+		// Register an NSData value. UserDefaults.data(forKey:) is supposed to return the Data
+		defaults.register(defaults: ["key1": NSData(bytes: bytes, length: bytes.count)])
+		
+		//make sure we don't have anything in the saved plist.
+		defaults.removeObject(forKey: "key1")
+		
+		XCTAssertEqual(defaults.data(forKey: "key1"), Data(bytes: bytes))
+	}
+	
+	func test_getRegisteredDefaultItem_Data() {
+		let defaults = UserDefaults.standard
+		let bytes = [0, 1, 2, 3, 4] as [UInt8]
+		
+		// Register a Data value. UserDefaults.data(forKey:) is supposed to return the Data
+		defaults.register(defaults: ["key1": Data(bytes: bytes)])
+		
+		//make sure we don't have anything in the saved plist.
+		defaults.removeObject(forKey: "key1")
+		
+		XCTAssertEqual(defaults.data(forKey: "key1"), Data(bytes: bytes))
+	}
+
+	func test_getRegisteredDefaultItem_BoolFromString() {
+		let defaults = UserDefaults.standard
+		
+		// Register a boolean default value as a string. UserDefaults.bool(forKey:) is supposed to return the parsed Bool value
+		defaults.register(defaults: ["key1": "YES"])
+		
+		//make sure we don't have anything in the saved plist.
+		defaults.removeObject(forKey: "key1")
+		
+		XCTAssertEqual(defaults.bool(forKey: "key1"), true)
+	}
+	
+	func test_getRegisteredDefaultItem_IntFromString() {
+		let defaults = UserDefaults.standard
+		
+		// Register an int default value as a string. UserDefaults.integer(forKey:) is supposed to return the parsed Int value
+		defaults.register(defaults: ["key1": "1234"])
+		
+		//make sure we don't have anything in the saved plist.
+		defaults.removeObject(forKey: "key1")
+		
+		XCTAssertEqual(defaults.integer(forKey: "key1"), 1234)
+	}
+	
+	func test_getRegisteredDefaultItem_DoubleFromString() {
+		let defaults = UserDefaults.standard
+		
+		// Register a double default value as a string. UserDefaults.double(forKey:) is supposed to return the parsed Double value
+		defaults.register(defaults: ["key1": "12.34"])
+		
+		//make sure we don't have anything in the saved plist.
+		defaults.removeObject(forKey: "key1")
+		
+		XCTAssertEqual(defaults.double(forKey: "key1"), 12.34)
+	}
+	
+	func test_setValue_NSString() {
+		let defaults = UserDefaults.standard
+		
+		// Set a NSString value. UserDefaults.string(forKey:) is supposed to return the NSString as a String
+		defaults.set("hello" as NSString, forKey: "key1")
+		
+		XCTAssertEqual(defaults.string(forKey: "key1"), "hello")
+	}
+	
+	func test_setValue_String() {
+		let defaults = UserDefaults.standard
+		
+		// Register a String value. UserDefaults.string(forKey:) is supposed to return the String
+		defaults.set("hello", forKey: "key1")
+		
+		XCTAssertEqual(defaults.string(forKey: "key1"), "hello")
+	}
+
+	func test_setValue_NSURL() {
+		let defaults = UserDefaults.standard
+		
+		// Set a NSURL value. UserDefaults.url(forKey:) is supposed to return the NSURL as a URL
+		defaults.set(NSURL(fileURLWithPath: "/hello/world"), forKey: "key1")
+		
+		XCTAssertEqual(defaults.url(forKey: "key1"), URL(fileURLWithPath: "/hello/world"))
+	}
+
+	func test_setValue_URL() {
+		let defaults = UserDefaults.standard
+		
+		// Set a URL value. UserDefaults.url(forKey:) is supposed to return the URL
+		defaults.set(URL(fileURLWithPath: "/hello/world"), forKey: "key1")
+		
+		XCTAssertEqual(defaults.url(forKey: "key1"), URL(fileURLWithPath: "/hello/world"))
+	}
+
+	func test_setValue_NSData() {
+		let defaults = UserDefaults.standard
+		let bytes = [0, 1, 2, 3, 4] as [UInt8]
+		
+		// Set a NSData value. UserDefaults.data(forKey:) is supposed to return the Data
+		defaults.set(NSData(bytes: bytes, length: bytes.count), forKey: "key1")
+		
+		XCTAssertEqual(defaults.data(forKey: "key1"), Data(bytes: bytes))
+	}
+	
+	func test_setValue_Data() {
+		let defaults = UserDefaults.standard
+		let bytes = [0, 1, 2, 3, 4] as [UInt8]
+		
+		// Set a Data value. UserDefaults.data(forKey:) is supposed to return the Data
+		defaults.set(Data(bytes: bytes), forKey: "key1")
+		
+		XCTAssertEqual(defaults.data(forKey: "key1"), Data(bytes: bytes))
+	}
+
+	func test_setValue_BoolFromString() {
+		let defaults = UserDefaults.standard
+		
+		// Register a boolean default value as a string. UserDefaults.bool(forKey:) is supposed to return the parsed Bool value
+		defaults.set("YES", forKey: "key1")
+		
+		XCTAssertEqual(defaults.bool(forKey: "key1"), true)
+	}
+	
+	func test_setValue_IntFromString() {
+		let defaults = UserDefaults.standard
+		
+		// Register an int default value as a string. UserDefaults.integer(forKey:) is supposed to return the parsed Int value
+		defaults.set("1234", forKey: "key1")
+		
+		XCTAssertEqual(defaults.integer(forKey: "key1"), 1234)
+	}
+	
+	func test_setValue_DoubleFromString() {
+		let defaults = UserDefaults.standard
+		
+		// Register a double default value as a string. UserDefaults.double(forKey:) is supposed to return the parsed Double value
+		defaults.set("12.34", forKey: "key1")
+		
+		XCTAssertEqual(defaults.double(forKey: "key1"), 12.34)
+	}
 }
diff --git a/TestFoundation/TestUtils.swift b/TestFoundation/TestUtils.swift
index b587b36..860e129 100644
--- a/TestFoundation/TestUtils.swift
+++ b/TestFoundation/TestUtils.swift
@@ -41,7 +41,7 @@
                     print(err)
                     return false
                 }
-            } else if !isDir {
+            } else if !isDir.boolValue {
                 return false
             }
             
diff --git a/TestFoundation/TestXMLDocument.swift b/TestFoundation/TestXMLDocument.swift
index d02ef9f..00bbbf4 100644
--- a/TestFoundation/TestXMLDocument.swift
+++ b/TestFoundation/TestXMLDocument.swift
@@ -17,7 +17,6 @@
     import SwiftXCTest
 #endif
 
-import CoreFoundation
 
 class TestXMLDocument : XCTestCase {
 
diff --git a/TestFoundation/TestXMLParser.swift b/TestFoundation/TestXMLParser.swift
index 84e5782..b08f0b3 100644
--- a/TestFoundation/TestXMLParser.swift
+++ b/TestFoundation/TestXMLParser.swift
@@ -86,10 +86,10 @@
             return xmlUnderTest
         }
         if let open = encoding.range(of: "(") {
-            encoding = encoding.substring(from: open.upperBound)
+            encoding = String(encoding[open.upperBound...])
         }
         if let close = encoding.range(of: ")") {
-            encoding = encoding.substring(to: close.lowerBound)
+            encoding = String(encoding[..<close.lowerBound])
         }
         return "<?xml version='1.0' encoding='\(encoding.uppercased())' standalone='no'?>\n\(xmlUnderTest)\n"
     }
diff --git a/TestFoundation/XDGTestHelper.swift b/TestFoundation/XDGTestHelper.swift
index bdf58a0..9692199 100644
--- a/TestFoundation/XDGTestHelper.swift
+++ b/TestFoundation/XDGTestHelper.swift
@@ -35,7 +35,7 @@
         storage.setCookie(simpleCookie!)
         let fm = FileManager.default
         let destPath = xdg_data_home! + "/xdgTestHelper/.cookies.shared"
-        var isDir = false
+        var isDir: ObjCBool = false
         let exists = fm.fileExists(atPath: destPath, isDirectory: &isDir) 
         if (!exists) {
             print("Expected cookie path: ", destPath)
diff --git a/TestFoundation/main.swift b/TestFoundation/main.swift
index 6e288ac..a1f6bf9 100644
--- a/TestFoundation/main.swift
+++ b/TestFoundation/main.swift
@@ -10,13 +10,18 @@
 #if DEPLOYMENT_RUNTIME_OBJC || os(Linux)
 import Foundation
 import XCTest
-import Glibc
 #else
 import SwiftFoundation
 import SwiftXCTest
-import Darwin
 #endif
 
+#if os(OSX) || os(iOS)
+    import Darwin
+#elseif os(Linux)
+    import Glibc
+#endif
+
+
 internal func testBundle() -> Bundle {
     return Bundle.main
 }
@@ -58,6 +63,7 @@
     testCase(TestNotificationQueue.allTests),
     testCase(TestNSNull.allTests),
     testCase(TestNSNumber.allTests),
+    testCase(TestNSNumberBridging.allTests),
     testCase(TestNumberFormatter.allTests),
     testCase(TestOperationQueue.allTests),
     testCase(TestNSOrderedSet.allTests),
@@ -73,7 +79,7 @@
     testCase(TestNSSet.allTests),
     testCase(TestStream.allTests),
     testCase(TestNSString.allTests),
-//    testCase(TestThread.allTests),
+    testCase(TestThread.allTests),
     testCase(TestProcess.allTests),
     testCase(TestNSTextCheckingResult.allTests),
     testCase(TestTimer.allTests),
@@ -104,4 +110,5 @@
     testCase(TestMassFormatter.allTests),
     testCase(TestJSONEncoder.allTests),
     testCase(TestCodable.allTests),
+    testCase(TestUnit.allTests),
 ])
diff --git a/build.py b/build.py
index 00d8588..efe0ce1 100755
--- a/build.py
+++ b/build.py
@@ -282,6 +282,7 @@
 	'CoreFoundation/PlugIn.subproj/CFPlugIn_PlugIn.c',
 	'CoreFoundation/Preferences.subproj/CFApplicationPreferences.c',
 	'CoreFoundation/Preferences.subproj/CFPreferences.c',
+    'CoreFoundation/Preferences.subproj/CFXMLPreferencesDomain.c',
 	# 'CoreFoundation/RunLoop.subproj/CFMachPort.c',
 	# 'CoreFoundation/RunLoop.subproj/CFMessagePort.c',
 	'CoreFoundation/RunLoop.subproj/CFRunLoop.c',