Merge pull request #1193 from spevans/pr_nslock
diff --git a/CoreFoundation/Base.subproj/ForSwiftFoundationOnly.h b/CoreFoundation/Base.subproj/ForSwiftFoundationOnly.h
index a3063c2..2d20856 100644
--- a/CoreFoundation/Base.subproj/ForSwiftFoundationOnly.h
+++ b/CoreFoundation/Base.subproj/ForSwiftFoundationOnly.h
@@ -29,6 +29,14 @@
#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
struct __CFSwiftObject {
@@ -345,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/Foundation.xcodeproj/project.pbxproj b/Foundation.xcodeproj/project.pbxproj
index 359dfc8..4fff062 100644
--- a/Foundation.xcodeproj/project.pbxproj
+++ b/Foundation.xcodeproj/project.pbxproj
@@ -21,6 +21,7 @@
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 */; };
@@ -505,6 +506,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>"; };
@@ -1036,6 +1038,7 @@
isa = PBXGroup;
children = (
5B5D886A1BBC948300234F36 /* CFApplicationPreferences.c */,
+ 559451EA1F706BF5002807FB /* CFXMLPreferencesDomain.c */,
5B5D898B1BBDBF6500234F36 /* CFPreferences.c */,
5B5D886C1BBC94C400234F36 /* CFPreferences.h */,
);
@@ -2030,7 +2033,7 @@
TargetAttributes = {
5B5D885C1BBC938800234F36 = {
CreatedOnToolsVersion = 7.1;
- LastSwiftMigration = 0800;
+ LastSwiftMigration = 0900;
LastSwiftUpdateCheck = 0800;
ProvisioningStyle = Manual;
};
@@ -2309,6 +2312,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 */,
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/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/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..e5e2673 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)
}
}
@@ -718,7 +719,11 @@
open var homeDirectoryForCurrentUser: URL {
return homeDirectory(forUser: CFCopyUserName().takeRetainedValue()._swiftObject)!
}
- open var temporaryDirectory: URL { NSUnimplemented() }
+
+ open var temporaryDirectory: URL {
+ return URL(fileURLWithPath: NSTemporaryDirectory())
+ }
+
open func homeDirectory(forUser userName: String) -> URL? {
guard !userName.isEmpty else { return nil }
guard let url = CFCopyHomeDirectoryURLForUser(userName._cfObject) else { return nil }
diff --git a/Foundation/HTTPCookieStorage.swift b/Foundation/HTTPCookieStorage.swift
index 045b69d..2209818 100644
--- a/Foundation/HTTPCookieStorage.swift
+++ b/Foundation/HTTPCookieStorage.swift
@@ -36,14 +36,34 @@
*/
open class HTTPCookieStorage: NSObject {
+ /* both sharedStorage and sharedCookieStorages are synchronized on sharedSyncQ */
private static var sharedStorage: HTTPCookieStorage?
private static var sharedCookieStorages: [String: HTTPCookieStorage] = [:] //for group storage containers
+ private static let sharedSyncQ = DispatchQueue(label: "org.swift.HTTPCookieStorage.sharedSyncQ")
+
+ /* only modified in init */
private var cookieFilePath: String!
- private let workQueue: DispatchQueue = DispatchQueue(label: "HTTPCookieStorage.workqueue")
- var allCookies: [String: HTTPCookie]
+
+ /* synchronized on syncQ, please don't use _allCookies directly outside of init/deinit */
+ private var _allCookies: [String: HTTPCookie]
+ private var allCookies: [String: HTTPCookie] {
+ get {
+ if #available(OSX 10.12, iOS 10.0, tvOS 10.0, watchOS 3.0, *) {
+ dispatchPrecondition(condition: DispatchPredicate.onQueue(self.syncQ))
+ }
+ return self._allCookies
+ }
+ set {
+ if #available(OSX 10.12, iOS 10.0, tvOS 10.0, watchOS 3.0, *) {
+ dispatchPrecondition(condition: DispatchPredicate.onQueue(self.syncQ))
+ }
+ self._allCookies = newValue
+ }
+ }
+ private let syncQ = DispatchQueue(label: "org.swift.HTTPCookieStorage.syncQ")
private init(cookieStorageName: String) {
- allCookies = [:]
+ _allCookies = [:]
cookieAcceptPolicy = .always
super.init()
let bundlePath = Bundle.main.bundlePath
@@ -59,9 +79,11 @@
private func loadPersistedCookies() {
guard let cookies = NSMutableDictionary(contentsOfFile: cookieFilePath) else { return }
var cookies0 = _SwiftValue.fetch(cookies) as? [String: [String: Any]] ?? [:]
- for key in cookies0.keys {
- if let cookie = createCookie(cookies0[key]!) {
- allCookies[key] = cookie
+ self.syncQ.sync {
+ for key in cookies0.keys {
+ if let cookie = createCookie(cookies0[key]!) {
+ allCookies[key] = cookie
+ }
}
}
}
@@ -87,11 +109,7 @@
}
open var cookies: [HTTPCookie]? {
- var theCookies: [HTTPCookie]?
- workQueue.sync {
- theCookies = Array(self.allCookies.values)
- }
- return theCookies
+ return Array(self.syncQ.sync { self.allCookies.values })
}
/*!
@@ -103,10 +121,12 @@
*/
open class var shared: HTTPCookieStorage {
get {
- if sharedStorage == nil {
- sharedStorage = HTTPCookieStorage(cookieStorageName: "shared")
+ return sharedSyncQ.sync {
+ if sharedStorage == nil {
+ sharedStorage = HTTPCookieStorage(cookieStorageName: "shared")
+ }
+ return sharedStorage!
}
- return sharedStorage!
}
}
@@ -122,12 +142,14 @@
method with the same identifier will return the same cookie storage instance.
*/
open class func sharedCookieStorage(forGroupContainerIdentifier identifier: String) -> HTTPCookieStorage {
- guard let cookieStorage = sharedCookieStorages[identifier] else {
- let newCookieStorage = HTTPCookieStorage(cookieStorageName: identifier)
- sharedCookieStorages[identifier] = newCookieStorage
- return newCookieStorage
+ return sharedSyncQ.sync {
+ guard let cookieStorage = sharedCookieStorages[identifier] else {
+ let newCookieStorage = HTTPCookieStorage(cookieStorageName: identifier)
+ sharedCookieStorages[identifier] = newCookieStorage
+ return newCookieStorage
+ }
+ return cookieStorage
}
- return cookieStorage
}
@@ -138,7 +160,7 @@
same name, domain and path, if any.
*/
open func setCookie(_ cookie: HTTPCookie) {
- workQueue.sync {
+ self.syncQ.sync {
guard cookieAcceptPolicy != .never else { return }
//add or override
@@ -173,9 +195,13 @@
}
private func updatePersistentStore() {
+ if #available(OSX 10.12, iOS 10.0, tvOS 10.0, watchOS 3.0, *) {
+ dispatchPrecondition(condition: DispatchPredicate.onQueue(self.syncQ))
+ }
+
//persist cookies
var persistDictionary: [String : [String : Any]] = [:]
- let persistable = allCookies.filter { (_, value) in
+ let persistable = self.allCookies.filter { (_, value) in
value.expiresDate != nil &&
value.isSessionOnly == false &&
value.expiresDate!.timeIntervalSinceNow > 0
@@ -190,14 +216,22 @@
}
/*!
+ @method lockedDeleteCookie:
+ @abstract Delete the specified cookie, for internal callers already on syncQ.
+ */
+ private func lockedDeleteCookie(_ cookie: HTTPCookie) {
+ let key = cookie.domain + cookie.path + cookie.name
+ self.allCookies.removeValue(forKey: key)
+ updatePersistentStore()
+ }
+
+ /*!
@method deleteCookie:
@abstract Delete the specified cookie
*/
open func deleteCookie(_ cookie: HTTPCookie) {
- let key = cookie.domain + cookie.path + cookie.name
- workQueue.sync {
- self.allCookies.removeValue(forKey: key)
- updatePersistentStore()
+ self.syncQ.sync {
+ self.lockedDeleteCookie(cookie)
}
}
@@ -206,13 +240,15 @@
@abstract Delete all cookies from the cookie storage since the provided date.
*/
open func removeCookies(since date: Date) {
- let cookiesSinceDate = allCookies.values.filter {
- $0.properties![.created] as! Double > date.timeIntervalSinceReferenceDate
+ self.syncQ.sync {
+ let cookiesSinceDate = self.allCookies.values.filter {
+ $0.properties![.created] as! Double > date.timeIntervalSinceReferenceDate
+ }
+ for cookie in cookiesSinceDate {
+ lockedDeleteCookie(cookie)
+ }
+ updatePersistentStore()
}
- for cookie in cookiesSinceDate {
- deleteCookie(cookie)
- }
- updatePersistentStore()
}
/*!
@@ -226,12 +262,8 @@
into a set of header fields to add to a request.
*/
open func cookies(for url: URL) -> [HTTPCookie]? {
- var cookies: [HTTPCookie]?
guard let host = url.host else { return nil }
- workQueue.sync {
- cookies = Array(allCookies.values.filter{ $0.domain == host })
- }
- return cookies
+ return Array(self.syncQ.sync(execute: {allCookies}).values.filter{ $0.domain == host })
}
/*!
diff --git a/Foundation/IndexSet.swift b/Foundation/IndexSet.swift
index ea103fa..1b4c7c4 100644
--- a/Foundation/IndexSet.swift
+++ b/Foundation/IndexSet.swift
@@ -407,7 +407,7 @@
public func intersects(integersIn range: CountableClosedRange<Element>) -> Bool { return self.intersects(integersIn: Range(range)) }
// MARK: -
- // Indexable
+ // Collection
public func index(after i: Index) -> Index {
if i.value + 1 == i.extent.upperBound {
diff --git a/Foundation/JSONEncoder.swift b/Foundation/JSONEncoder.swift
index ecafeed..5c36e1f 100644
--- a/Foundation/JSONEncoder.swift
+++ b/Foundation/JSONEncoder.swift
@@ -64,6 +64,9 @@
/// 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 base64
@@ -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,6 +675,11 @@
fileprivate func box(_ data: Data) throws -> NSObject {
switch self.options.dataEncodingStrategy {
+ 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())
@@ -826,6 +834,9 @@
/// 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 base64
@@ -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,6 +2053,12 @@
guard !(value is NSNull) else { return nil }
switch self.options.dataDecodingStrategy {
+ 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/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 97b269d..3066406 100644
--- a/Foundation/NSData.swift
+++ b/Foundation/NSData.swift
@@ -991,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..18392f4 100644
--- a/Foundation/NSDictionary.swift
+++ b/Foundation/NSDictionary.swift
@@ -32,6 +32,10 @@
return nil
}
+ open func value(forKey key: String) -> Any? {
+ NSUnsupported()
+ }
+
open func keyEnumerator() -> NSEnumerator {
guard type(of: self) === NSDictionary.self || type(of: self) === NSMutableDictionary.self else {
NSRequiresConcreteImplementation()
@@ -40,6 +44,23 @@
return NSGeneratorEnumerator(_storage.keys.map { _SwiftValue.fetch(nonOptional: $0) }.makeIterator())
}
+ @available(*, deprecated)
+ public convenience init?(contentsOfFile path: String) {
+ self.init(contentsOf: URL(fileURLWithPath: path))
+ }
+
+ @available(*, deprecated)
+ public convenience init?(contentsOf url: URL) {
+ do {
+ guard let plistDoc = try? Data(contentsOf: url) else { return nil }
+ let plistDict = try PropertyListSerialization.propertyList(from: plistDoc, options: [], format: nil) as? Dictionary<AnyHashable,Any>
+ guard let plistDictionary = plistDict else { return nil }
+ self.init(dictionary: plistDictionary)
+ } catch {
+ return nil
+ }
+ }
+
public override convenience init() {
self.init(objects: [], forKeys: [], count: 0)
}
@@ -467,11 +488,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()
@@ -583,20 +604,6 @@
super.init(objects: objects, forKeys: keys, count: cnt)
}
- public convenience init?(contentsOfFile path: String) {
- self.init(contentsOfURL: URL(fileURLWithPath: path))
- }
-
- public convenience init?(contentsOfURL url: URL) {
- do {
- guard let plistDoc = try? Data(contentsOf: url) else { return nil }
- let plistDict = try PropertyListSerialization.propertyList(from: plistDoc, options: [], format: nil) as? Dictionary<AnyHashable,Any>
- guard let plistDictionary = plistDict else { return nil }
- self.init(dictionary: plistDictionary)
- } catch {
- return nil
- }
- }
}
extension NSMutableDictionary {
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/NSKeyedArchiver.swift b/Foundation/NSKeyedArchiver.swift
index 3790990..6df2ae1 100644
--- a/Foundation/NSKeyedArchiver.swift
+++ b/Foundation/NSKeyedArchiver.swift
@@ -553,9 +553,11 @@
}
// check replacement cache
- objectToEncode = self._replacementMap[object as! AnyHashable]
- if objectToEncode != nil {
- return objectToEncode
+ if let hashable = object as? AnyHashable {
+ objectToEncode = self._replacementMap[hashable]
+ if objectToEncode != nil {
+ return objectToEncode
+ }
}
// object replaced by NSObject.replacementObject(for:)
diff --git a/Foundation/NSNotification.swift b/Foundation/NSNotification.swift
index 3926ee8..b848d6d 100644
--- a/Foundation/NSNotification.swift
+++ b/Foundation/NSNotification.swift
@@ -169,7 +169,7 @@
}
}
- open func post(name aName: Notification.Name, object anObject: Any?, userInfo aUserInfo: [AnyHashable : Any]? = nil) {
+ open func post(name aName: NSNotification.Name, object anObject: Any?, userInfo aUserInfo: [AnyHashable : Any]? = nil) {
let notification = Notification(name: aName, object: anObject, userInfo: aUserInfo)
post(notification)
}
@@ -189,11 +189,11 @@
}
@available(*,obsoleted:4.0,renamed:"addObserver(forName:object:queue:using:)")
- open func addObserver(forName name: Notification.Name?, object obj: Any?, queue: OperationQueue?, usingBlock block: @escaping (Notification) -> Void) -> NSObjectProtocol {
+ open func addObserver(forName name: NSNotification.Name?, object obj: Any?, queue: OperationQueue?, usingBlock block: @escaping (Notification) -> Void) -> NSObjectProtocol {
return addObserver(forName: name, object: obj, queue: queue, using: block)
}
- open func addObserver(forName name: Notification.Name?, object obj: Any?, queue: OperationQueue?, using block: @escaping (Notification) -> Void) -> NSObjectProtocol {
+ open func addObserver(forName name: NSNotification.Name?, object obj: Any?, queue: OperationQueue?, using block: @escaping (Notification) -> Void) -> NSObjectProtocol {
let object = NSObject()
let newObserver = NSNotificationReceiver()
diff --git a/Foundation/NSObject.swift b/Foundation/NSObject.swift
index 2c5956f..bd4fe38 100644
--- a/Foundation/NSObject.swift
+++ b/Foundation/NSObject.swift
@@ -7,6 +7,11 @@
// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
//
+// @_exported import of Dispatch here makes it available to all
+// classes in Foundation and all sources that import Foundation.
+// This brings it into line with Darwin usage for compatbility.
+@_exported import Dispatch
+
import CoreFoundation
/// The `NSObjectProtocol` groups methods that are fundamental to all Foundation objects.
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 26c45b5..b27719a 100644
--- a/Foundation/NSString.swift
+++ b/Foundation/NSString.swift
@@ -1248,33 +1248,37 @@
public convenience init(contentsOf url: URL, usedEncoding enc: UnsafeMutablePointer<UInt>?) throws {
let readResult = try NSData(contentsOf: url, options:[])
- var offset = 0
+ let encoding: UInt
+ let offset: Int
let bytePtr = readResult.bytes.bindMemory(to: UInt8.self, capacity:readResult.length)
if readResult.length >= 4 && bytePtr[0] == 0xFF && bytePtr[1] == 0xFE && bytePtr[2] == 0x00 && bytePtr[3] == 0x00 {
- enc?.pointee = String.Encoding.utf32LittleEndian.rawValue
+ encoding = String.Encoding.utf32LittleEndian.rawValue
offset = 4
}
else if readResult.length >= 2 && bytePtr[0] == 0xFE && bytePtr[1] == 0xFF {
- enc?.pointee = String.Encoding.utf16BigEndian.rawValue
+ encoding = String.Encoding.utf16BigEndian.rawValue
offset = 2
}
else if readResult.length >= 2 && bytePtr[0] == 0xFF && bytePtr[1] == 0xFE {
- enc?.pointee = String.Encoding.utf16LittleEndian.rawValue
+ encoding = String.Encoding.utf16LittleEndian.rawValue
offset = 2
}
else if readResult.length >= 4 && bytePtr[0] == 0x00 && bytePtr[1] == 0x00 && bytePtr[2] == 0xFE && bytePtr[3] == 0xFF {
- enc?.pointee = String.Encoding.utf32BigEndian.rawValue
+ encoding = String.Encoding.utf32BigEndian.rawValue
offset = 4
}
else {
//Need to work on more conditions. This should be the default
- enc?.pointee = String.Encoding.utf8.rawValue
+ encoding = String.Encoding.utf8.rawValue
+ offset = 0
}
+ enc?.pointee = encoding
+
// Since the encoding being passed includes the byte order the BOM wont be checked or skipped, so pass offset to
// manually skip the BOM header.
- guard let enc = enc, let cf = CFStringCreateWithBytes(kCFAllocatorDefault, bytePtr + offset, readResult.length - offset,
- CFStringConvertNSStringEncodingToEncoding(enc.pointee), true) else {
+ guard let cf = CFStringCreateWithBytes(kCFAllocatorDefault, bytePtr + offset, readResult.length - offset,
+ CFStringConvertNSStringEncodingToEncoding(encoding), true) else {
throw NSError(domain: NSCocoaErrorDomain, code: CocoaError.fileReadInapplicableStringEncoding.rawValue, userInfo: [
"NSDebugDescription" : "Unable to create a string using the specified encoding."
])
@@ -1286,11 +1290,11 @@
throw NSError(domain: NSCocoaErrorDomain, code: CocoaError.fileReadInapplicableStringEncoding.rawValue, userInfo: [
"NSDebugDescription" : "Unable to bridge CFString to String."
])
- }
+ }
}
public convenience init(contentsOfFile path: String, usedEncoding enc: UnsafeMutablePointer<UInt>?) throws {
- NSUnimplemented()
+ try self.init(contentsOf: URL(fileURLWithPath: path), usedEncoding: enc)
}
}
diff --git a/Foundation/NSStringAPI.swift b/Foundation/NSStringAPI.swift
index 03ebc30..1b57164 100644
--- a/Foundation/NSStringAPI.swift
+++ b/Foundation/NSStringAPI.swift
@@ -42,12 +42,6 @@
return result
}
-func _toNSRange(_ r: Range<String.Index>) -> NSRange {
- return NSRange(
- location: r.lowerBound.encodedOffset,
- 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.
@@ -439,10 +433,26 @@
return self._ephemeralString._bridgeToObjectiveC()
}
+ // self can be a Substring so we need to subtract/add this offset when
+ // passing _ns to the Foundation APIs. Will be 0 if self is String.
+ @_inlineable
+ @_versioned
+ internal var _substringOffset: Int {
+ return self.startIndex.encodedOffset
+ }
+
/// Return an `Index` corresponding to the given offset in our UTF-16
/// representation.
func _index(_ utf16Index: Int) -> Index {
- return Index(encodedOffset: utf16Index)
+ return Index(encodedOffset: utf16Index + _substringOffset)
+ }
+
+ @_inlineable
+ @_versioned
+ internal func _toRelativeNSRange(_ r: Range<String.Index>) -> NSRange {
+ return NSRange(
+ location: r.lowerBound.encodedOffset - _substringOffset,
+ length: r.upperBound.encodedOffset - r.lowerBound.encodedOffset)
}
/// Return a `Range<Index>` corresponding to the given `NSRange` of
@@ -603,7 +613,7 @@
return locale != nil ? _ns.compare(
aString,
options: mask,
- range: _toNSRange(
+ range: _toRelativeNSRange(
range ?? startIndex..<endIndex
),
locale: locale?._bridgeToObjectiveC()
@@ -612,7 +622,7 @@
: range != nil ? _ns.compare(
aString,
options: mask,
- range: _toNSRange(range!)
+ range: _toRelativeNSRange(range!)
)
: !mask.isEmpty ? _ns.compare(aString, options: mask)
@@ -1050,7 +1060,7 @@
T : StringProtocol, R : RangeExpression
>(in range: R, with replacement: T) -> String where R.Bound == Index {
return _ns.replacingCharacters(
- in: _toNSRange(range.relative(to: self)),
+ in: _toRelativeNSRange(range.relative(to: self)),
with: replacement._ephemeralString)
}
@@ -1083,7 +1093,7 @@
of: target,
with: replacement,
options: options,
- range: _toNSRange(
+ range: _toRelativeNSRange(
searchRange ?? startIndex..<endIndex
)
)
@@ -1208,7 +1218,7 @@
) where R.Bound == Index {
let range = range.relative(to: self)
_ns.enumerateLinguisticTags(
- in: _toNSRange(range),
+ in: _toRelativeNSRange(range),
scheme: tagScheme._ephemeralString,
options: opts,
orthography: orthography != nil ? orthography! : nil
@@ -1273,7 +1283,7 @@
) -> Void
) where R.Bound == Index {
_ns.enumerateSubstrings(
- in: _toNSRange(range.relative(to: self)), options: opts) {
+ in: _toRelativeNSRange(range.relative(to: self)), options: opts) {
var stop_ = false
body($0,
@@ -1346,7 +1356,7 @@
usedLength: usedBufferCount,
encoding: encoding.rawValue,
options: options,
- range: _toNSRange(range.relative(to: self)),
+ range: _toRelativeNSRange(range.relative(to: self)),
remaining: $0)
}
}
@@ -1373,7 +1383,7 @@
contentsEnd in self._ns.getLineStart(
start, end: end,
contentsEnd: contentsEnd,
- for: _toNSRange(range.relative(to: self)))
+ for: _toRelativeNSRange(range.relative(to: self)))
}
}
}
@@ -1401,7 +1411,7 @@
contentsEnd in self._ns.getParagraphStart(
start, end: end,
contentsEnd: contentsEnd,
- for: _toNSRange(range.relative(to: self)))
+ for: _toRelativeNSRange(range.relative(to: self)))
}
}
}
@@ -1428,7 +1438,8 @@
public func lineRange<
R : RangeExpression
>(for aRange: R) -> Range<Index> where R.Bound == Index {
- return _range(_ns.lineRange(for: _toNSRange(aRange.relative(to: self))))
+ return _range(_ns.lineRange(
+ for: _toRelativeNSRange(aRange.relative(to: self))))
}
#if !DEPLOYMENT_RUNTIME_SWIFT
@@ -1453,7 +1464,7 @@
var nsTokenRanges: NSArray?
let result = tokenRanges._withNilOrAddress(of: &nsTokenRanges) {
self._ns.linguisticTags(
- in: _toNSRange(range.relative(to: self)),
+ in: _toRelativeNSRange(range.relative(to: self)),
scheme: tagScheme._ephemeralString,
options: opts,
orthography: orthography,
@@ -1477,7 +1488,7 @@
R : RangeExpression
>(for aRange: R) -> Range<Index> where R.Bound == Index {
return _range(
- _ns.paragraphRange(for: _toNSRange(aRange.relative(to: self))))
+ _ns.paragraphRange(for: _toRelativeNSRange(aRange.relative(to: self))))
}
#endif
@@ -1504,7 +1515,7 @@
_ns.rangeOfCharacter(
from: aSet,
options: mask,
- range: _toNSRange(
+ range: _toRelativeNSRange(
aRange ?? startIndex..<endIndex
)
)
@@ -1535,7 +1546,7 @@
// and output ranges due (if nothing else) to locale changes
return _range(
_ns.rangeOfComposedCharacterSequences(
- for: _toNSRange(range.relative(to: self))))
+ for: _toRelativeNSRange(range.relative(to: self))))
}
// - (NSRange)rangeOfString:(NSString *)aString
@@ -1570,13 +1581,13 @@
locale != nil ? _ns.range(
of: aString,
options: mask,
- range: _toNSRange(
+ range: _toRelativeNSRange(
searchRange ?? startIndex..<endIndex
),
locale: locale
)
: searchRange != nil ? _ns.range(
- of: aString, options: mask, range: _toNSRange(searchRange!)
+ of: aString, options: mask, range: _toRelativeNSRange(searchRange!)
)
: !mask.isEmpty ? _ns.range(of: aString, options: mask)
: _ns.range(of: aString)
@@ -1687,7 +1698,7 @@
@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))
+ return _ns.substring(with: _toRelativeNSRange(aRange))
}
}
diff --git a/Foundation/NSSwiftRuntime.swift b/Foundation/NSSwiftRuntime.swift
index 58a7174..33112a8 100644
--- a/Foundation/NSSwiftRuntime.swift
+++ b/Foundation/NSSwiftRuntime.swift
@@ -18,13 +18,73 @@
@_exported import Glibc
#endif
+@_exported import Dispatch
+
#if os(Android) // shim required for bzero
@_transparent func bzero(_ ptr: UnsafeMutableRawPointer, _ size: size_t) {
memset(ptr, 0, size)
}
#endif
-public typealias ObjCBool = Bool
+#if !_runtime(_ObjC)
+/// 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
+ }
+}
+#endif
internal class __NSCFType : NSObject {
private var _cfinfo : Int32
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 9c17ad1..ab09c1f 100644
--- a/Foundation/Operation.swift
+++ b/Foundation/Operation.swift
@@ -43,13 +43,15 @@
}
open func start() {
- lock.lock()
- _executing = true
- lock.unlock()
- main()
- lock.lock()
- _executing = false
- lock.unlock()
+ if !isCancelled {
+ lock.lock()
+ _executing = true
+ lock.unlock()
+ main()
+ lock.lock()
+ _executing = false
+ lock.unlock()
+ }
finish()
}
@@ -79,9 +81,13 @@
}
open func cancel() {
+ // Note that calling cancel() is advisory. It is up to the main() function to
+ // call isCancelled at appropriate points in its execution flow and to do the
+ // actual canceling work. Eventually main() will invoke finish() and this is
+ // where we then leave the groups and unblock other operations that might
+ // depend on us.
lock.lock()
_cancelled = true
- _leaveGroups()
lock.unlock()
}
diff --git a/Foundation/Stream.swift b/Foundation/Stream.swift
index d34949d..410be23 100644
--- a/Foundation/Stream.swift
+++ b/Foundation/Stream.swift
@@ -241,11 +241,11 @@
#endif
extension StreamDelegate {
- func stream(_ aStream: Stream, handleEvent eventCode: Stream.Event) { }
+ func stream(_ aStream: Stream, handle eventCode: Stream.Event) { }
}
public protocol StreamDelegate : class {
- func stream(_ aStream: Stream, handleEvent eventCode: Stream.Event)
+ func stream(_ aStream: Stream, handle eventCode: Stream.Event)
}
// MARK: -
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/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/TestDecimal.swift b/TestFoundation/TestDecimal.swift
index f626e1e..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)))
diff --git a/TestFoundation/TestFileManager.swift b/TestFoundation/TestFileManager.swift
index a9cb932..90d1597 100644
--- a/TestFoundation/TestFileManager.swift
+++ b/TestFoundation/TestFileManager.swift
@@ -31,6 +31,7 @@
("test_subpathsOfDirectoryAtPath", test_subpathsOfDirectoryAtPath),
("test_copyItemAtPathToPath", test_copyItemAtPathToPath),
("test_homedirectoryForUser", test_homedirectoryForUser),
+ ("test_temporaryDirectoryForUser", test_temporaryDirectoryForUser),
]
}
@@ -53,10 +54,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 +75,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 +468,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) {
@@ -525,4 +526,25 @@
XCTAssertNil(filemanger.homeDirectory(forUser: ""))
XCTAssertNotNil(filemanger.homeDirectoryForCurrentUser)
}
+
+ func test_temporaryDirectoryForUser() {
+ let filemanger = FileManager.default
+ let tmpDir = filemanger.temporaryDirectory
+ XCTAssertNotNil(tmpDir)
+ let tmpFileUrl = tmpDir.appendingPathComponent("test.bin")
+ let tmpFilePath = tmpFileUrl.path
+
+ do {
+ if filemanger.fileExists(atPath: tmpFilePath) {
+ try filemanger.removeItem(at: tmpFileUrl)
+ }
+
+ try "hello world".write(to: tmpFileUrl, atomically: false, encoding: .utf8)
+ XCTAssert(filemanger.fileExists(atPath: tmpFilePath))
+
+ try filemanger.removeItem(at: tmpFileUrl)
+ } catch {
+ XCTFail("Unable to write a file to the temporary directory: \(tmpDir), err: \(error)")
+ }
+ }
}
diff --git a/TestFoundation/TestHTTPCookieStorage.swift b/TestFoundation/TestHTTPCookieStorage.swift
index 472e34a..f65a01e 100644
--- a/TestFoundation/TestHTTPCookieStorage.swift
+++ b/TestFoundation/TestHTTPCookieStorage.swift
@@ -14,6 +14,7 @@
import SwiftFoundation
import SwiftXCTest
#endif
+import Dispatch
class TestHTTPCookieStorage: XCTestCase {
@@ -24,6 +25,7 @@
static var allTests: [(String, (TestHTTPCookieStorage) -> () throws -> Void)] {
return [
+ ("test_sharedCookieStorageAccessedFromMultipleThreads", test_sharedCookieStorageAccessedFromMultipleThreads),
("test_BasicStorageAndRetrieval", test_BasicStorageAndRetrieval),
("test_deleteCookie", test_deleteCookie),
("test_removeCookies", test_removeCookies),
@@ -34,6 +36,27 @@
]
}
+ func test_sharedCookieStorageAccessedFromMultipleThreads() {
+ let q = DispatchQueue.global()
+ let syncQ = DispatchQueue(label: "TestHTTPCookieStorage.syncQ")
+ var allCookieStorages: [HTTPCookieStorage] = []
+ let g = DispatchGroup()
+ for _ in 0..<64 {
+ g.enter()
+ q.async {
+ let mySharedCookieStore = HTTPCookieStorage.shared
+ syncQ.async {
+ allCookieStorages.append(mySharedCookieStore)
+ g.leave()
+ }
+ }
+ }
+ g.wait()
+ let cookieStorages = syncQ.sync { allCookieStorages }
+ let mySharedCookieStore = HTTPCookieStorage.shared
+ XCTAssertTrue(cookieStorages.reduce(true, { $0 && $1 === mySharedCookieStore }), "\(cookieStorages)")
+ }
+
func test_BasicStorageAndRetrieval() {
basicStorageAndRetrieval(with: .shared)
basicStorageAndRetrieval(with: .groupContainer("test"))
@@ -238,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
diff --git a/TestFoundation/TestNSData.swift b/TestFoundation/TestNSData.swift
index df0cd2e..e592268 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
@@ -100,6 +264,252 @@
("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),
+ ("test_sliceInsertion", test_sliceInsertion),
+ ("test_sliceDeletion", test_sliceDeletion),
]
}
@@ -1164,5 +1574,2411 @@
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
+ }
+ */
+
+ func test_sliceInsertion() {
+ // https://bugs.swift.org/browse/SR-5810
+ let baseData = Data([0, 1, 2, 3, 4, 5])
+ var sliceData = baseData[2..<4]
+ let sliceDataEndIndexBeforeInsertion = sliceData.endIndex
+ let elementToInsert: UInt8 = 0x07
+ sliceData.insert(elementToInsert, at: sliceData.startIndex)
+ XCTAssertEqual(sliceData.first, elementToInsert)
+ XCTAssertEqual(sliceData.startIndex, 2)
+ XCTAssertEqual(sliceDataEndIndexBeforeInsertion, 4)
+ XCTAssertEqual(sliceData.endIndex, sliceDataEndIndexBeforeInsertion + 1)
+ }
+
+ func test_sliceDeletion() {
+ // https://bugs.swift.org/browse/SR-5810
+ let baseData = Data([0, 1, 2, 3, 4, 5, 6, 7])
+ let sliceData = baseData[2..<6]
+ var mutableSliceData = sliceData
+ let numberOfElementsToDelete = 2
+ let subrangeToDelete = mutableSliceData.startIndex..<mutableSliceData.startIndex.advanced(by: numberOfElementsToDelete)
+ mutableSliceData.removeSubrange(subrangeToDelete)
+ XCTAssertEqual(sliceData[sliceData.startIndex + numberOfElementsToDelete], mutableSliceData.first)
+ XCTAssertEqual(mutableSliceData.startIndex, 2)
+ XCTAssertEqual(mutableSliceData.endIndex, sliceData.endIndex - numberOfElementsToDelete)
+ }
}
diff --git a/TestFoundation/TestNSDictionary.swift b/TestFoundation/TestNSDictionary.swift
index 096f0a6..fa09cb0 100644
--- a/TestFoundation/TestNSDictionary.swift
+++ b/TestFoundation/TestNSDictionary.swift
@@ -211,7 +211,7 @@
let d1: NSDictionary = ["Hello":["world":"again"]]
let isWritten = d1.write(toFile: testFilePath!, atomically: true)
if(isWritten) {
- let dict = NSMutableDictionary.init(contentsOfFile: testFilePath!)
+ let dict = NSDictionary(contentsOfFile: testFilePath!)
XCTAssert(dict == d1)
} else {
XCTFail("Write to file failed")
diff --git a/TestFoundation/TestNSKeyedArchiver.swift b/TestFoundation/TestNSKeyedArchiver.swift
index 1a03419..4ccc05e 100644
--- a/TestFoundation/TestNSKeyedArchiver.swift
+++ b/TestFoundation/TestNSKeyedArchiver.swift
@@ -106,6 +106,7 @@
("test_archive_user_class", test_archive_user_class),
("test_archive_uuid_bvref", test_archive_uuid_byref),
("test_archive_uuid_byvalue", test_archive_uuid_byvalue),
+ ("test_archive_unhashable", test_archive_unhashable),
]
}
@@ -312,4 +313,30 @@
let uuid = UUID()
return test_archive(uuid, classes: [NSUUID.self])
}
+
+ func test_archive_unhashable() {
+ let data = """
+ {
+ "args": {},
+ "headers": {
+ "Accept": "*/*",
+ "Accept-Encoding": "deflate, gzip",
+ "Accept-Language": "en",
+ "Connection": "close",
+ "Host": "httpbin.org",
+ "User-Agent": "TestFoundation (unknown version) curl/7.54.0"
+ },
+ "origin": "0.0.0.0",
+ "url": "https://httpbin.org/get"
+ }
+ """.data(using: .utf8)!
+ do {
+ let json = try JSONSerialization.jsonObject(with: data)
+ _ = NSKeyedArchiver.archivedData(withRootObject: json)
+ XCTAssert(true, "NSKeyedArchiver.archivedData handles unhashable")
+ }
+ catch {
+ XCTFail("test_archive_unhashable, de-serialization error \(error)")
+ }
+ }
}
diff --git a/TestFoundation/TestNSNumber.swift b/TestFoundation/TestNSNumber.swift
index b34d45c..9d2ac9c 100644
--- a/TestFoundation/TestNSNumber.swift
+++ b/TestFoundation/TestNSNumber.swift
@@ -1091,8 +1091,8 @@
func test_Equals() {
// Booleans: false only equals 0, true only equals 1
- XCTAssertTrue(NSNumber(value: true) == NSNumber(value: true))
- XCTAssertTrue(NSNumber(value: true) == NSNumber(value: 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)))
@@ -1102,8 +1102,8 @@
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: false))
- XCTAssertTrue(NSNumber(value: false) == NSNumber(value: 0))
+ 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)))
diff --git a/TestFoundation/TestNSString.swift b/TestFoundation/TestNSString.swift
index 70e9398..e75bd4f 100644
--- a/TestFoundation/TestNSString.swift
+++ b/TestFoundation/TestNSString.swift
@@ -66,6 +66,8 @@
("test_rangeOfCharacterFromSet", test_rangeOfCharacterFromSet ),
("test_CFStringCreateMutableCopy", test_CFStringCreateMutableCopy),
("test_FromContentsOfURL",test_FromContentsOfURL),
+ ("test_FromContentOfFileUsedEncodingIgnored", test_FromContentOfFileUsedEncodingIgnored),
+ ("test_FromContentOfFileUsedEncodingUTF8", test_FromContentOfFileUsedEncodingUTF8),
("test_FromContentsOfURLUsedEncodingUTF16BE", test_FromContentsOfURLUsedEncodingUTF16BE),
("test_FromContentsOfURLUsedEncodingUTF16LE", test_FromContentsOfURLUsedEncodingUTF16LE),
("test_FromContentsOfURLUsedEncodingUTF32BE", test_FromContentsOfURLUsedEncodingUTF32BE),
@@ -303,6 +305,32 @@
}
}
+ func test_FromContentOfFileUsedEncodingIgnored() {
+ let testFilePath = testBundle().path(forResource: "NSStringTestData", ofType: "txt")
+ XCTAssertNotNil(testFilePath)
+
+ do {
+ let str = try NSString(contentsOfFile: testFilePath!, usedEncoding: nil)
+ XCTAssertEqual(str, "swift-corelibs-foundation")
+ } catch {
+ XCTFail("Unable to init NSString from contentsOfFile:encoding:")
+ }
+ }
+
+ func test_FromContentOfFileUsedEncodingUTF8() {
+ let testFilePath = testBundle().path(forResource: "NSStringTestData", ofType: "txt")
+ XCTAssertNotNil(testFilePath)
+
+ do {
+ var encoding: UInt = 0
+ let str = try NSString(contentsOfFile: testFilePath!, usedEncoding: &encoding)
+ XCTAssertEqual(str, "swift-corelibs-foundation")
+ XCTAssertEqual(encoding, String.Encoding.utf8.rawValue, "Wrong encoding detected from UTF8 file")
+ } catch {
+ XCTFail("Unable to init NSString from contentsOfFile:encoding:")
+ }
+ }
+
func test_FromContentsOfURLUsedEncodingUTF16BE() {
guard let testFileURL = testBundle().url(forResource: "NSString-UTF16-BE-data", withExtension: "txt") else {
XCTFail("URL for NSString-UTF16-BE-data.txt is nil")
diff --git a/TestFoundation/TestOperationQueue.swift b/TestFoundation/TestOperationQueue.swift
index 02f95c4..1dd8c50 100644
--- a/TestFoundation/TestOperationQueue.swift
+++ b/TestFoundation/TestOperationQueue.swift
@@ -28,6 +28,7 @@
("test_MainQueueGetter", test_MainQueueGetter),
("test_CurrentQueueOnMainQueue", test_CurrentQueueOnMainQueue),
("test_CurrentQueueOnBackgroundQueue", test_CurrentQueueOnBackgroundQueue),
+ ("test_CurrentQueueOnBackgroundQueueWithSelfCancel", test_CurrentQueueOnBackgroundQueueWithSelfCancel),
("test_CurrentQueueWithCustomUnderlyingQueue", test_CurrentQueueWithCustomUnderlyingQueue),
("test_CurrentQueueWithUnderlyingQueueResetToNil", test_CurrentQueueWithUnderlyingQueueResetToNil),
]
@@ -135,6 +136,20 @@
waitForExpectations(timeout: 1)
}
+ func test_CurrentQueueOnBackgroundQueueWithSelfCancel() {
+ let operationQueue = OperationQueue()
+ operationQueue.maxConcurrentOperationCount = 1
+ let expectation = self.expectation(description: "Background execution")
+ operationQueue.addOperation {
+ XCTAssertEqual(operationQueue, OperationQueue.current)
+ expectation.fulfill()
+ // Canceling operation X from inside operation X should not cause the app to a crash
+ operationQueue.cancelAllOperations()
+ }
+
+ waitForExpectations(timeout: 1)
+ }
+
func test_CurrentQueueWithCustomUnderlyingQueue() {
let expectation = self.expectation(description: "Background execution")
diff --git a/TestFoundation/TestProcess.swift b/TestFoundation/TestProcess.swift
index 54775b5..d19340b 100644
--- a/TestFoundation/TestProcess.swift
+++ b/TestFoundation/TestProcess.swift
@@ -28,13 +28,11 @@
("test_pipe_stdout", test_pipe_stdout),
("test_pipe_stderr", test_pipe_stderr),
("test_current_working_directory", test_current_working_directory),
- // disabled for now
- // ("test_pipe_stdout_and_stderr_same_pipe", test_pipe_stdout_and_stderr_same_pipe),
+ ("test_pipe_stdout_and_stderr_same_pipe", test_pipe_stdout_and_stderr_same_pipe),
("test_file_stdout", test_file_stdout),
- // disabled for now
- // ("test_passthrough_environment", test_passthrough_environment),
- // ("test_no_environment", test_no_environment),
- // ("test_custom_environment", test_custom_environment),
+ ("test_passthrough_environment", test_passthrough_environment),
+ ("test_no_environment", test_no_environment),
+ ("test_custom_environment", test_custom_environment),
]
}
@@ -183,7 +181,7 @@
XCTFail("Could not read stdout")
return
}
- // testing the return value of an external process is does not port well, and may change.
+ // testing the return value of an external process does not port well, and may change.
// XCTAssertEqual(string, "/bin/cat: invalid_file_name: No such file or directory\n")
}
@@ -197,6 +195,9 @@
process.standardOutput = pipe
process.standardError = pipe
+ // Clear the environment to stop the malloc debug flags used in Xcode debug being
+ // set in the subprocess.
+ process.environment = [:]
process.launch()
process.waitUntilExit()
XCTAssertEqual(process.terminationStatus, 1)
@@ -206,7 +207,12 @@
XCTFail("Could not read stdout")
return
}
- XCTAssertEqual(string, "/bin/cat: invalid_file_name: No such file or directory\n")
+
+ // Remove the leading '/bin/' since on macOS '/bin/cat' just outputs 'cat:'
+ let searchStr = "/bin/"
+ let errMsg = string.replacingOccurrences(of: searchStr, with: "", options: [.literal, .anchored],
+ range: searchStr.startIndex..<searchStr.endIndex)
+ XCTAssertEqual(errMsg, "cat: invalid_file_name: No such file or directory\n")
}
func test_file_stdout() {
@@ -234,7 +240,7 @@
func test_passthrough_environment() {
do {
- let output = try runTask(["/usr/bin/env"], environment: nil)
+ let (output, _) = try runTask(["/usr/bin/env"], environment: nil)
let env = try parseEnv(output)
XCTAssertGreaterThan(env.count, 0)
} catch let error {
@@ -244,7 +250,7 @@
func test_no_environment() {
do {
- let output = try runTask(["/usr/bin/env"], environment: [:])
+ let (output, _) = try runTask(["/usr/bin/env"], environment: [:])
let env = try parseEnv(output)
XCTAssertEqual(env.count, 0)
} catch let error {
@@ -255,7 +261,7 @@
func test_custom_environment() {
do {
let input = ["HELLO": "WORLD", "HOME": "CUPERTINO"]
- let output = try runTask(["/usr/bin/env"], environment: input)
+ let (output, _) = try runTask(["/usr/bin/env"], environment: input)
let env = try parseEnv(output)
XCTAssertEqual(env, input)
} catch let error {
@@ -267,9 +273,9 @@
do {
let previousWorkingDirectory = FileManager.default.currentDirectoryPath
- // `bash` will not be found if the current working directory is not set correctly.
- let _ = try runTask(["bash", "-c", "exit 0"], currentDirectoryPath: "/bin")
-
+ // Darwin Foundation requires the full path to the executable (.launchPath)
+ let (output, _) = try runTask(["/bin/bash", "-c", "pwd"], currentDirectoryPath: "/bin")
+ XCTAssertEqual(output.trimmingCharacters(in: .newlines), "/bin")
XCTAssertEqual(previousWorkingDirectory, FileManager.default.currentDirectoryPath)
} catch let error {
XCTFail("Test failed: \(error)")
@@ -297,21 +303,26 @@
case InvalidEnvironmentVariable(String)
}
-private func runTask(_ arguments: [String], environment: [String: String]? = nil, currentDirectoryPath: String? = nil) throws -> String {
+private func runTask(_ arguments: [String], environment: [String: String]? = nil, currentDirectoryPath: String? = nil) throws -> (String, String) {
let process = Process()
var arguments = arguments
process.launchPath = arguments.removeFirst()
process.arguments = arguments
- process.environment = environment
+ // Darwin Foundation doesnt allow .environment to be set to nil although the documentation
+ // says it is an optional. https://developer.apple.com/documentation/foundation/process/1409412-environment
+ if let e = environment {
+ process.environment = e
+ }
if let directoryPath = currentDirectoryPath {
process.currentDirectoryPath = directoryPath
}
- let pipe = Pipe()
- process.standardOutput = pipe
- process.standardError = pipe
+ let stdoutPipe = Pipe()
+ let stderrPipe = Pipe()
+ process.standardOutput = stdoutPipe
+ process.standardError = stderrPipe
process.launch()
process.waitUntilExit()
@@ -319,12 +330,17 @@
throw Error.TerminationStatus(process.terminationStatus)
}
- let data = pipe.fileHandleForReading.availableData
- guard let output = String(data: data, encoding: .utf8) else {
- throw Error.UnicodeDecodingError(data)
+ let stdoutData = stdoutPipe.fileHandleForReading.availableData
+ guard let stdout = String(data: stdoutData, encoding: .utf8) else {
+ throw Error.UnicodeDecodingError(stdoutData)
}
- return output
+ let stderrData = stderrPipe.fileHandleForReading.availableData
+ guard let stderr = String(data: stderrData, encoding: .utf8) else {
+ throw Error.UnicodeDecodingError(stderrData)
+ }
+
+ return (stdout, stderr)
}
private func parseEnv(_ env: String) throws -> [String: String] {
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/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/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',