Merge pull request #690 from kareman/implement-FileHandle.nullDevice

diff --git a/Docs/Status.md b/Docs/Status.md
index de77b21..6c0eb68 100644
--- a/Docs/Status.md
+++ b/Docs/Status.md
@@ -47,7 +47,7 @@
     |------------------------------|-----------------|---------------|--------------------------------------------------------------------------------------------------------------------|
     | `URLAuthenticationChallenge` | Unimplemented   | None          |                                                                                                                    |
     | `URLCache`                   | Unimplemented   | None          |                                                                                                                    |
-    | `URLCredential`              | Mostly Complete | Incomplete    | `NSCoding` and `NSCopying` remain unimplemented                                                                    |
+    | `URLCredential`              | Mostly Complete | Incomplete    | `NSCopying` remains unimplemented                                                                                  |
     | `URLCredentialStorage`       | Unimplemented   | None          |                                                                                                                    |
     | `NSURLError*`                | Complete        | N/A           |                                                                                                                    |
     | `URLProtectionSpace`         | Unimplemented   | None          |                                                                                                                    |
diff --git a/Foundation.xcodeproj/project.pbxproj b/Foundation.xcodeproj/project.pbxproj
index 45e43e4..2af4035 100755
--- a/Foundation.xcodeproj/project.pbxproj
+++ b/Foundation.xcodeproj/project.pbxproj
@@ -308,6 +308,7 @@
 		7900433B1CACD33E00ECCBF1 /* TestNSCompoundPredicate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 790043391CACD33E00ECCBF1 /* TestNSCompoundPredicate.swift */; };
 		7900433C1CACD33E00ECCBF1 /* TestNSPredicate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7900433A1CACD33E00ECCBF1 /* TestNSPredicate.swift */; };
 		AE35A1861CBAC85E0042DB84 /* SwiftFoundation.h in Headers */ = {isa = PBXBuildFile; fileRef = AE35A1851CBAC85E0042DB84 /* SwiftFoundation.h */; settings = {ATTRIBUTES = (Public, ); }; };
+		BF8E65311DC3B3CB005AB5C3 /* TestNotification.swift in Sources */ = {isa = PBXBuildFile; fileRef = BF8E65301DC3B3CB005AB5C3 /* TestNotification.swift */; };
 		CC5249C01D341D23007CB54D /* TestUnitConverter.swift in Sources */ = {isa = PBXBuildFile; fileRef = CC5249BF1D341D23007CB54D /* TestUnitConverter.swift */; };
 		CE19A88C1C23AA2300B4CB6A /* NSStringTestData.txt in Resources */ = {isa = PBXBuildFile; fileRef = CE19A88B1C23AA2300B4CB6A /* NSStringTestData.txt */; };
 		D31302011C30CEA900295652 /* NSConcreteValue.swift in Sources */ = {isa = PBXBuildFile; fileRef = D31302001C30CEA900295652 /* NSConcreteValue.swift */; };
@@ -744,6 +745,7 @@
 		88D28DE61C13AE9000494606 /* TestNSGeometry.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TestNSGeometry.swift; sourceTree = "<group>"; };
 		A5A34B551C18C85D00FD972B /* TestNSByteCountFormatter.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TestNSByteCountFormatter.swift; sourceTree = "<group>"; };
 		AE35A1851CBAC85E0042DB84 /* SwiftFoundation.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SwiftFoundation.h; sourceTree = "<group>"; };
+		BF8E65301DC3B3CB005AB5C3 /* TestNotification.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TestNotification.swift; sourceTree = "<group>"; };
 		C2A9D75B1C15C08B00993803 /* TestNSUUID.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TestNSUUID.swift; sourceTree = "<group>"; };
 		C93559281C12C49F009FD6A9 /* TestNSAffineTransform.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TestNSAffineTransform.swift; sourceTree = "<group>"; };
 		CC5249BF1D341D23007CB54D /* TestUnitConverter.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TestUnitConverter.swift; sourceTree = "<group>"; };
@@ -1378,6 +1380,7 @@
 				0383A1741D2E558A0052E5D1 /* TestNSStream.swift */,
 				5B1FD9E21D6D17B80080E83C /* TestNSURLSession.swift */,
 				EA54A6FA1DB16D53009E0809 /* TestObjCRuntime.swift */,
+				BF8E65301DC3B3CB005AB5C3 /* TestNotification.swift */,
 			);
 			name = Tests;
 			sourceTree = "<group>";
@@ -2215,6 +2218,7 @@
 				5B13B34D1C582D4C00651CE2 /* TestNSUUID.swift in Sources */,
 				5B13B3281C582D4C00651CE2 /* TestNSBundle.swift in Sources */,
 				5B13B32A1C582D4C00651CE2 /* TestNSCharacterSet.swift in Sources */,
+				BF8E65311DC3B3CB005AB5C3 /* TestNotification.swift in Sources */,
 				EA01AAEC1DA839C4008F4E07 /* TestProgress.swift in Sources */,
 				5B13B3411C582D4C00651CE2 /* TestNSRegularExpression.swift in Sources */,
 				5B13B3491C582D4C00651CE2 /* TestNSTimeZone.swift in Sources */,
diff --git a/Foundation/CGFloat.swift b/Foundation/CGFloat.swift
index bba73b4..3462d8d 100644
--- a/Foundation/CGFloat.swift
+++ b/Foundation/CGFloat.swift
@@ -145,15 +145,17 @@
     public var native: NativeType
 }
 
-@_transparent extension CGFloat : BinaryFloatingPoint {
+extension CGFloat : BinaryFloatingPoint {
     
     public typealias RawSignificand = UInt
     public typealias Exponent = Int
-    
+
+    @_transparent
     public static var exponentBitCount: Int {
         return NativeType.exponentBitCount
     }
     
+    @_transparent
     public static var significandBitCount: Int {
         return NativeType.significandBitCount
     }
@@ -161,10 +163,12 @@
     //  Conversions to/from integer encoding.  These are not part of the
     //  BinaryFloatingPoint prototype because there's no guarantee that an
     //  integer type of the same size actually exists (e.g. Float80).
+    @_transparent
     public var bitPattern: UInt {
         return UInt(native.bitPattern)
     }
-    
+
+    @_transparent
     public init(bitPattern: UInt) {
 #if arch(i386) || arch(arm)
         native = NativeType(bitPattern: UInt32(bitPattern))
@@ -172,19 +176,23 @@
         native = NativeType(bitPattern: UInt64(bitPattern))
 #endif
     }
-    
+
+    @_transparent
     public var sign: FloatingPointSign {
         return native.sign
     }
-    
+
+    @_transparent
     public var exponentBitPattern: UInt {
         return native.exponentBitPattern
     }
-    
+
+    @_transparent
     public var significandBitPattern: UInt {
         return UInt(native.significandBitPattern)
     }
-    
+
+    @_transparent
     public init(sign: FloatingPointSign,
                 exponentBitPattern: UInt,
                 significandBitPattern: UInt) {
@@ -192,177 +200,217 @@
                             exponentBitPattern: exponentBitPattern,
                             significandBitPattern: NativeType.RawSignificand(significandBitPattern))
     }
-    
+
+    @_transparent
     public init(nan payload: RawSignificand, signaling: Bool) {
         native = NativeType(nan: NativeType.RawSignificand(payload),
                             signaling: signaling)
     }
-    
+
+    @_transparent
     public static var infinity: CGFloat {
         return CGFloat(NativeType.infinity)
     }
-    
+
+    @_transparent
     public static var nan: CGFloat {
         return CGFloat(NativeType.nan)
     }
-    
+
+    @_transparent
     public static var signalingNaN: CGFloat {
         return CGFloat(NativeType.signalingNaN)
     }
-    
+
     @available(*, unavailable, renamed: "nan")
     public static var quietNaN: CGFloat {
         fatalError("unavailable")
     }
-    
+
+    @_transparent
     public static var greatestFiniteMagnitude: CGFloat {
         return CGFloat(NativeType.greatestFiniteMagnitude)
     }
-    
+
+    @_transparent
     public static var pi: CGFloat {
         return CGFloat(NativeType.pi)
     }
-    
+
+    @_transparent
     public var ulp: CGFloat {
         return CGFloat(native.ulp)
     }
-    
+
+    @_transparent
     public static var leastNormalMagnitude: CGFloat {
         return CGFloat(NativeType.leastNormalMagnitude)
     }
-    
+
+    @_transparent
     public static var leastNonzeroMagnitude: CGFloat {
         return CGFloat(NativeType.leastNonzeroMagnitude)
     }
-    
+
+    @_transparent
     public var exponent: Int {
         return native.exponent
     }
-    
+
+    @_transparent
     public var significand: CGFloat {
         return CGFloat(native.significand)
     }
-    
+
+    @_transparent
     public init(sign: FloatingPointSign, exponent: Int, significand: CGFloat) {
         native = NativeType(sign: sign,
                             exponent: exponent, significand: significand.native)
     }
-    
+
+    @_transparent
     public mutating func round(_ rule: FloatingPointRoundingRule) {
         native.round(rule)
     }
-    
+
+    @_transparent
     public var nextUp: CGFloat {
         return CGFloat(native.nextUp)
     }
-    
+
+    @_transparent
     public var magnitude: CGFloat {
         return CGFloat(Swift.abs(native))
     }
-    
+
+    @_transparent
     public mutating func negate() {
         native.negate()
     }
-    
+
+    @_transparent
     public mutating func add(_ other: CGFloat) {
         native.add(other.native)
     }
-    
+
+    @_transparent
     public mutating func subtract(_ other: CGFloat) {
         native.subtract(other.native)
     }
-    
+
+    @_transparent
     public mutating func multiply(by other: CGFloat) {
         native.multiply(by: other.native)
     }
-    
+
+    @_transparent
     public mutating func divide(by other: CGFloat) {
         native.divide(by: other.native)
     }
-    
+
+    @_transparent
     public mutating func formTruncatingRemainder(dividingBy other: CGFloat) {
         native.formTruncatingRemainder(dividingBy: other.native)
     }
-    
+
+    @_transparent
     public mutating func formRemainder(dividingBy other: CGFloat) {
         native.formRemainder(dividingBy: other.native)
     }
-    
+
+    @_transparent
     public mutating func formSquareRoot( ) {
         native.formSquareRoot( )
     }
-    
+
+    @_transparent
     public mutating func addProduct(_ lhs: CGFloat, _ rhs: CGFloat) {
         native.addProduct(lhs.native, rhs.native)
     }
-    
+
+    @_transparent
     public func isEqual(to other: CGFloat) -> Bool {
         return self.native.isEqual(to: other.native)
     }
-    
+
+    @_transparent
     public func isLess(than other: CGFloat) -> Bool {
         return self.native.isLess(than: other.native)
     }
-    
+
+    @_transparent
     public func isLessThanOrEqualTo(_ other: CGFloat) -> Bool {
         return self.native.isLessThanOrEqualTo(other.native)
     }
-    
+
+    @_transparent
     public var isNormal:  Bool {
         return native.isNormal
     }
-    
+
+    @_transparent
     public var isFinite:  Bool {
         return native.isFinite
     }
-    
+
+    @_transparent
     public var isZero:  Bool {
         return native.isZero
     }
-    
+
+    @_transparent
     public var isSubnormal:  Bool {
         return native.isSubnormal
     }
-    
+
+    @_transparent
     public var isInfinite:  Bool {
         return native.isInfinite
     }
-    
+
+    @_transparent
     public var isNaN:  Bool {
         return native.isNaN
     }
-    
+
+    @_transparent
     public var isSignalingNaN: Bool {
         return native.isSignalingNaN
     }
-    
+
     @available(*, unavailable, renamed: "isSignalingNaN")
     public var isSignaling: Bool {
         fatalError("unavailable")
     }
-    
+
+    @_transparent
     public var isCanonical: Bool {
         return true
     }
-    
+
+    @_transparent
     public var floatingPointClass: FloatingPointClassification {
         return native.floatingPointClass
     }
-    
+
+    @_transparent
     public var binade: CGFloat {
         return CGFloat(native.binade)
     }
-    
+
+    @_transparent
     public var significandWidth: Int {
         return native.significandWidth
     }
-    
+
     /// Create an instance initialized to `value`.
+    @_transparent
     public init(floatLiteral value: NativeType) {
         native = value
     }
-    
+
     /// Create an instance initialized to `value`.
+    @_transparent
     public init(integerLiteral value: Int) {
         native = NativeType(value)
     }
@@ -402,14 +450,14 @@
     }
 }
 
-@_transparent extension CGFloat : CustomStringConvertible {
+extension CGFloat : CustomStringConvertible {
     /// A textual representation of `self`.
     public var description: String {
         return native.description
     }
 }
 
-@_transparent extension CGFloat : Hashable {
+extension CGFloat : Hashable {
     /// The hash value.
     ///
     /// **Axiom:** `x == y` implies `x.hashValue == y.hashValue`
@@ -417,78 +465,91 @@
     /// - Note: the hash value is not guaranteed to be stable across
     ///   different invocations of the same program.  Do not persist the
     ///   hash value across program runs.
+    @_transparent
     public var hashValue: Int {
         return native.hashValue
     }
 }
 
-@_transparent extension UInt8 {
+extension UInt8 {
+    @_transparent
     public init(_ value: CGFloat) {
         self = UInt8(value.native)
     }
 }
 
-@_transparent extension Int8 {
+extension Int8 {
+    @_transparent
     public init(_ value: CGFloat) {
         self = Int8(value.native)
     }
 }
 
-@_transparent extension UInt16 {
+extension UInt16 {
+    @_transparent
     public init(_ value: CGFloat) {
         self = UInt16(value.native)
     }
 }
 
-@_transparent extension Int16 {
+extension Int16 {
+    @_transparent
     public init(_ value: CGFloat) {
         self = Int16(value.native)
     }
 }
 
-@_transparent extension UInt32 {
+extension UInt32 {
+    @_transparent
     public init(_ value: CGFloat) {
         self = UInt32(value.native)
     }
 }
 
-@_transparent extension Int32 {
+extension Int32 {
+    @_transparent
     public init(_ value: CGFloat) {
         self = Int32(value.native)
     }
 }
 
-@_transparent extension UInt64 {
+extension UInt64 {
+    @_transparent
     public init(_ value: CGFloat) {
         self = UInt64(value.native)
     }
 }
 
-@_transparent extension Int64 {
+extension Int64 {
+    @_transparent
     public init(_ value: CGFloat) {
         self = Int64(value.native)
     }
 }
 
-@_transparent extension UInt {
+extension UInt {
+    @_transparent
     public init(_ value: CGFloat) {
         self = UInt(value.native)
     }
 }
 
-@_transparent extension Int {
+extension Int {
+    @_transparent
     public init(_ value: CGFloat) {
         self = Int(value.native)
     }
 }
 
-@_transparent extension Double {
+extension Double {
+    @_transparent
     public init(_ value: CGFloat) {
         self = Double(value.native)
     }
 }
 
-@_transparent extension Float {
+extension Float {
+    @_transparent
     public init(_ value: CGFloat) {
         self = Float(value.native)
     }
@@ -547,7 +608,7 @@
 // Strideable Conformance
 //===----------------------------------------------------------------------===//
 
-@_transparent extension CGFloat : Strideable {
+extension CGFloat : Strideable {
     /// Returns a stride `x` such that `self.advanced(by: x)` approximates
     /// `other`.
     ///
@@ -571,41 +632,35 @@
 // Deprecated operators
 //===----------------------------------------------------------------------===//
 
-@_transparent
 @available(*, unavailable, message: "use += 1")
 @discardableResult
 public prefix func ++(rhs: inout CGFloat) -> CGFloat {
     fatalError("++ is not available")
 }
 
-@_transparent
 @available(*, unavailable, message: "use -= 1")
 @discardableResult
 public prefix func --(rhs: inout CGFloat) -> CGFloat {
     fatalError("-- is not available")
 }
 
-@_transparent
 @available(*, unavailable, message: "use += 1")
 @discardableResult
 public postfix func ++(lhs: inout CGFloat) -> CGFloat {
     fatalError("++ is not available")
 }
 
-@_transparent
 @available(*, unavailable, message: "use -= 1")
 @discardableResult
 public postfix func --(lhs: inout CGFloat) -> CGFloat {
     fatalError("-- is not available")
 }
 
-@_transparent
 @available(*, unavailable, message: "Use truncatingRemainder instead")
 public func %(lhs: CGFloat, rhs: CGFloat) -> CGFloat {
     fatalError("% is not available.")
 }
 
-@_transparent
 @available(*, unavailable, message: "Use formTruncatingRemainder instead")
 public func %=(lhs: inout CGFloat, rhs: CGFloat) {
     fatalError("%= is not available.")
@@ -880,16 +935,17 @@
     return CGFloat(yn(n, Double(x.native)))
 }
 
-@_transparent
 extension CGFloat : _CVarArgPassedAsDouble, _CVarArgAligned {
     /// Transform `self` into a series of machine words that can be
     /// appropriately interpreted by C varargs
+    @_transparent
     public var _cVarArgEncoding: [Int] {
         return native._cVarArgEncoding
     }
     
     /// Return the required alignment in bytes of 
     /// the value returned by `_cVarArgEncoding`.
+    @_transparent
     public var _cVarArgAlignment: Int { 
         return native._cVarArgAlignment
     }
diff --git a/Foundation/CharacterSet.swift b/Foundation/CharacterSet.swift
index 4babf01..35fbe72 100644
--- a/Foundation/CharacterSet.swift
+++ b/Foundation/CharacterSet.swift
@@ -13,6 +13,10 @@
 private func _utfRangeToNSRange(_ inRange : Range<UnicodeScalar>) -> NSRange {
     return NSMakeRange(Int(inRange.lowerBound.value), Int(inRange.upperBound.value - inRange.lowerBound.value))
 }
+ 
+private func _utfRangeToNSRange(_ inRange : ClosedRange<UnicodeScalar>) -> NSRange {
+    return NSMakeRange(Int(inRange.lowerBound.value), Int(inRange.upperBound.value - inRange.lowerBound.value + 1))
+}
 
 internal final class _SwiftNSCharacterSet : NSCharacterSet, _SwiftNativeFoundationType {
     internal typealias ImmutableType = NSCharacterSet
@@ -129,8 +133,7 @@
     ///
     /// It is the caller's responsibility to ensure that the values represent valid `UnicodeScalar` values, if that is what is desired.
     public init(charactersIn range: ClosedRange<UnicodeScalar>) {
-        let halfOpenRange = range.lowerBound..<UnicodeScalar(range.upperBound.value + 1)!
-        _wrapped = _SwiftNSCharacterSet(immutableObject: NSCharacterSet(range: _utfRangeToNSRange(halfOpenRange)))
+        _wrapped = _SwiftNSCharacterSet(immutableObject: NSCharacterSet(range: _utfRangeToNSRange(range)))
     }
     
     /// Initialize with the characters in the given string.
@@ -320,8 +323,7 @@
     ///
     /// It is the caller's responsibility to ensure that the values represent valid `UnicodeScalar` values, if that is what is desired.
     public mutating func insert(charactersIn range: ClosedRange<UnicodeScalar>) {
-        let halfOpenRange = range.lowerBound..<UnicodeScalar(range.upperBound.value + 1)!
-        let nsRange = _utfRangeToNSRange(halfOpenRange)
+        let nsRange = _utfRangeToNSRange(range)
         _applyUnmanagedMutation {
             $0.addCharacters(in: nsRange)
         }
@@ -337,8 +339,7 @@
     
     /// Remove a closed range of integer values from the `CharacterSet`.
     public mutating func remove(charactersIn range: ClosedRange<UnicodeScalar>) {
-        let halfOpenRange = range.lowerBound..<UnicodeScalar(range.upperBound.value + 1)!
-        let nsRange = _utfRangeToNSRange(halfOpenRange)
+        let nsRange = _utfRangeToNSRange(range)
         _applyUnmanagedMutation {
             $0.removeCharacters(in: nsRange)
         }
diff --git a/Foundation/Locale.swift b/Foundation/Locale.swift
index ffe584a..46642ac 100644
--- a/Foundation/Locale.swift
+++ b/Foundation/Locale.swift
@@ -69,7 +69,7 @@
     
     /// Returns a localized string for a specified identifier.
     ///
-    /// For example, in the "en" locale, the result for `"en"` is `"Spanish"`.
+    /// For example, in the "en" locale, the result for `"es"` is `"Spanish"`.
     public func localizedString(forIdentifier identifier: String) -> String? {
         return _wrapped.displayName(forKey: .identifier, value: identifier)
     }
@@ -83,7 +83,7 @@
     
     /// Returns a localized string for a specified region code.
     ///
-    /// For example, in the "en" locale, the result for `"fr"` is `"French"`.
+    /// For example, in the "en" locale, the result for `"fr"` is `"France"`.
     public func localizedString(forRegionCode regionCode: String) -> String? {
         return _wrapped.displayName(forKey: .countryCode, value: regionCode)
     }
diff --git a/Foundation/NSCFString.swift b/Foundation/NSCFString.swift
index e12e0fa..4558549 100644
--- a/Foundation/NSCFString.swift
+++ b/Foundation/NSCFString.swift
@@ -140,19 +140,18 @@
 }
 
 internal func _CFSwiftStringGetBytes(_ str: AnyObject, encoding: CFStringEncoding, range: CFRange, buffer: UnsafeMutablePointer<UInt8>?, maxBufLen: CFIndex, usedBufLen: UnsafeMutablePointer<CFIndex>?) -> CFIndex {
+    let convertedLength: CFIndex
     switch encoding {
         // TODO: Don't treat many encodings like they are UTF8
     case CFStringEncoding(kCFStringEncodingUTF8), CFStringEncoding(kCFStringEncodingISOLatin1), CFStringEncoding(kCFStringEncodingMacRoman), CFStringEncoding(kCFStringEncodingASCII), CFStringEncoding(kCFStringEncodingNonLossyASCII):
-        let encodingView = (str as! NSString)._swiftObject.utf8
-        let start = encodingView.startIndex
+        let encodingView = (str as! NSString).substring(with: NSRange(range)).utf8
         if let buffer = buffer {
-            for idx in 0..<range.length {
-                let characterIndex = encodingView.index(start, offsetBy: idx + range.location)
-                let character = encodingView[characterIndex]
+            for (idx, character) in encodingView.enumerated() {
                 buffer.advanced(by: idx).initialize(to: character)
             }
         }
-        usedBufLen?.pointee = range.length
+        usedBufLen?.pointee = encodingView.count
+        convertedLength = encodingView.count
         
     case CFStringEncoding(kCFStringEncodingUTF16):
         let encodingView = (str as! NSString)._swiftObject.utf16
@@ -169,13 +168,13 @@
         }
         // Every character was 2 bytes
         usedBufLen?.pointee = range.length * 2
-
+        convertedLength = range.length
 
     default:
         fatalError("Attempted to get bytes of a Swift string using an unsupported encoding")
     }
     
-    return range.length
+    return convertedLength
 }
 
 internal func _CFSwiftStringCreateWithSubstring(_ str: AnyObject, range: CFRange) -> Unmanaged<AnyObject> {
diff --git a/Foundation/NSDecimal.swift b/Foundation/NSDecimal.swift
index c5a999f..dcba6f4 100644
--- a/Foundation/NSDecimal.swift
+++ b/Foundation/NSDecimal.swift
@@ -33,6 +33,9 @@
             return UInt32((__lengthAndFlags & 0b0000_1111))
         }
         set {
+            guard newValue <= maxMantissaLength else {
+                fatalError("Attempt to set a length greater than capacity \(newValue) > \(maxMantissaLength)")
+            }
             __lengthAndFlags =
                 (__lengthAndFlags & 0b1111_0000) |
                 UInt8(newValue & 0b0000_1111)
@@ -88,9 +91,8 @@
     public init(_exponent: Int32, _length: UInt32, _isNegative: UInt32, _isCompact: UInt32, _reserved: UInt32, _mantissa: (UInt16, UInt16, UInt16, UInt16, UInt16, UInt16, UInt16, UInt16)){
         self._mantissa = _mantissa
         self.__exponent = Int8(truncatingBitPattern: _exponent)
-        self.__lengthAndFlags = 0
+        self.__lengthAndFlags = UInt8(_length & 0b1111)
         self.__reserved = 0
-        self._length = _length
         self._isNegative = _isNegative
         self._isCompact = _isCompact
         self._reserved = _reserved
@@ -564,9 +566,7 @@
         d[i] = UInt16(accumulator / UInt32(divisor))
         carry = accumulator % UInt32(divisor)
     }
-    while d._length != 0 && d[d._length - 1] == 0 {
-        d._length -= 1
-    }
+    d.trimTrailingZeros()
     return (UInt16(carry),.noError)
 }
 
@@ -674,7 +674,7 @@
     var previousRemainder: Bool = false
 
     // Divide by 10 as much as possible
-    while big._length >= Decimal.maxSize {
+    while big._length > Decimal.maxSize + 1 {
         if remainder != 0 {
             previousRemainder = true
         }
@@ -727,21 +727,19 @@
     return .lossOfPrecision;
 }
 
-fileprivate func integerMultiply(_ big: inout WideDecimal,
-                                 _ left: WideDecimal,
-                                 _ right: WideDecimal) -> NSDecimalNumber.CalculationError {
+fileprivate func integerMultiply<T:VariableLengthNumber>(_ big: inout T,
+                                 _ left: T,
+                                 _ right: Decimal) -> NSDecimalNumber.CalculationError {
     if left._length == 0 || right._length == 0 {
         big._length = 0
         return .noError
     }
 
-    if big._length > left._length + right._length {
-        big._length = left._length + right._length
+    if big._length == 0 || big._length > left._length + right._length {
+        big._length = min(big.maxMantissaLength,left._length + right._length)
     }
 
-    for i in 0..<big._length {
-        big[i] = 0
-    }
+    big.zeroMantissa()
 
     var carry: UInt16 = 0
 
@@ -769,16 +767,14 @@
         }
     }
 
-    while big._length != 0 && big[big._length - 1] == 0 {
-        big._length -= 1
-    }
+    big.trimTrailingZeros()
 
     return .noError
 }
 
-fileprivate func integerDivide(_ r: inout WideDecimal,
-                               _ cu: WideDecimal,
-                               _ cv: WideDecimal) -> NSDecimalNumber.CalculationError {
+fileprivate func integerDivide<T:VariableLengthNumber>(_ r: inout T,
+                               _ cu: T,
+                               _ cv: Decimal) -> NSDecimalNumber.CalculationError {
     // Calculate result = a / b.
     // Result could NOT be a pointer to same space as a or b.
     // resultLen must be >= aLen - bLen.
@@ -792,17 +788,19 @@
     var u = WideDecimal(true)
     var v = WideDecimal(true) // divisor
 
-    var v1:UInt16, v2:UInt16
-
     // Simple case
     if cv.isZero {
         return .divideByZero;
     }
 
     // If u < v, the result is approximately 0...
-    if cu < cv {
-        r._length = 0
-        return .noError;
+    if cu._length < cv._length {
+        for i in 0..<cv._length {
+            if cu[i] < cv[i] {
+                r._length = 0
+                return .noError;
+            }
+        }
     }
 
     // Fast algorithm
@@ -812,6 +810,9 @@
         return error
     }
 
+    u.copyMantissa(from: cu)
+    v.copyMantissa(from: cv)
+
     u._length = cu._length + 1
     v._length = cv._length + 1
 
@@ -826,9 +827,12 @@
     _ = multiplyByShort(&u, UInt16(d))
     _ = multiplyByShort(&v, UInt16(d))
 
+    u.trimTrailingZeros()
+    v.trimTrailingZeros()
+
     // Set a zero at the leftmost u position if the multiplication
-    // do not have a carry.
-    if(u._length == cu._length) {
+    // does not have a carry.
+    if u._length == cu._length {
         u[u._length] = 0
         u._length += 1
     }
@@ -845,22 +849,20 @@
     // It's used to determine the quotient digit as fast as possible
     // The test vl > 1 is probably useless, since optimizations
     // up there are taking over this case. I'll keep it, just in case.
-    v1 = v[v._length-1]
-    v2 = v._length > 1 ? v[v._length-2] : 0
+    let v1:UInt16 = v[v._length-1]
+    let v2:UInt16 = v._length > 1 ? v[v._length-2] : 0
 
     // D2: initialize j
     // On each pass, build a single value for the quotient.
     for j in 0..<ql {
-        var q: UInt32 // Quotient digit. could be a short.
 
         // D3: calculate q^
         // This formula and test for q gives at most q+1; See Knuth for proof.
 
         let ul = u._length
-        let uu = u // work around compiler bug
-        let tmp: UInt32 = UInt32(uu[ul - UInt32(j) - UInt32(1)] << 16 + uu[ul - UInt32(j) - UInt32(2)])
-        q = tmp / UInt32(v1)
-        var rtmp: UInt32 = tmp % UInt32(v1)
+        let tmp:UInt32 = UInt32(u[ul - UInt32(j) - UInt32(1)]) << 16 + UInt32(u[ul - UInt32(j) - UInt32(2)])
+        var q:UInt32 = tmp / UInt32(v1) // Quotient digit. could be a short.
+        var rtmp:UInt32 = tmp % UInt32(v1)
 
         // This test catches all cases where q is really q+2 and
         // most where it is q+1
@@ -888,8 +890,7 @@
             acc = q * UInt32(v[i]) + mk     // multiply
             mk = acc >> 16                  // multiplication carry
             acc = acc & 0xffff;
-            let uu = u // work around compiler bug
-            acc = 0xffff + UInt32(uu[ul - vl + i - UInt32(j) - UInt32(1)]) - acc + sk; // subtract
+            acc = 0xffff + UInt32(u[ul - vl + i - UInt32(j) - UInt32(1)]) - acc + sk; // subtract
             sk = acc >> 16;
             u[ul - vl + i - UInt32(j) - UInt32(1)] = UInt16(truncatingBitPattern:acc)
         }
@@ -905,9 +906,7 @@
             for i in 0...v._length {
                 let ul = u._length
                 let vl = v._length
-                let vv = v // work around compiler bug
-                let uu = u // work around compiler bug
-                acc = UInt32(vv[i]) + UInt32(uu[UInt32(ul) - UInt32(vl) + UInt32(i) - UInt32(j) - UInt32(1)]) + k
+                acc = UInt32(v[i]) + UInt32(u[UInt32(ul) - UInt32(vl) + UInt32(i) - UInt32(j) - UInt32(1)]) + k
                 k = acc >> 16;
                 u[UInt32(ul) - UInt32(vl) + UInt32(i) - UInt32(j) - UInt32(1)] = UInt16(truncatingBitPattern:acc)
             }
@@ -920,14 +919,12 @@
 
     r._length = UInt32(ql);
 
-    while r._length != 0 && r[r._length - 1] == 0 {
-        r._length -= 1
-    }
+    r.trimTrailingZeros()
 
     return .noError;
 }
 
-fileprivate func integerMultiplyByPowerOf10(_ result: inout WideDecimal, _ left: WideDecimal, _ p: Int) -> NSDecimalNumber.CalculationError {
+fileprivate func integerMultiplyByPowerOf10<T:VariableLengthNumber>(_ result: inout T, _ left: T, _ p: Int) -> NSDecimalNumber.CalculationError {
     var power = p
     if power == 0 {
         result = left
@@ -943,10 +940,10 @@
     var error:NSDecimalNumber.CalculationError = .noError
 
     while power > maxpow10 {
-        var big = WideDecimal()
+        var big = T()
 
         power -= maxpow10
-        let p10 = WideDecimal(pow10[maxpow10])
+        let p10 = pow10[maxpow10]
 
         if !isNegative {
             error = integerMultiply(&big,result,p10)
@@ -965,9 +962,10 @@
         result._length = big._length
     }
 
-    var big = WideDecimal()
+    var big = T()
+
     // Handle the rest of the power (<= maxpow10)
-    let p10 = WideDecimal(pow10[Int(power)])
+    let p10 = pow10[Int(power)]
 
     if !isNegative {
         error = integerMultiply(&big, result, p10)
@@ -994,7 +992,7 @@
 
 public func NSDecimalNormalize(_ a: UnsafeMutablePointer<Decimal>, _ b: UnsafeMutablePointer<Decimal>, _ roundingMode: NSDecimalNumber.RoundingMode) -> NSDecimalNumber.CalculationError {
     var diffexp = a.pointee.__exponent - b.pointee.__exponent
-    var result = WideDecimal()
+    var result = Decimal()
 
     //
     // If the two numbers share the same exponents,
@@ -1030,19 +1028,49 @@
     // Try to multiply aa to reach the same exponent level than bb
     //
 
-    if integerMultiplyByPowerOf10(&result, WideDecimal(aa.pointee), Int(diffexp)) == .noError {
+    if integerMultiplyByPowerOf10(&result, aa.pointee, Int(diffexp)) == .noError {
         // Succeed. Adjust the length/exponent info
         // and return no errorNSDecimalNormalize
-        aa.pointee._length = result._length
-        for i in 0..<result._length {
-            aa.pointee[i] = result[i]
-        }
-        aa.pointee._isCompact = 0
+        aa.pointee.copyMantissa(from: result)
         aa.pointee._exponent = bb.pointee._exponent
         return .noError;
     }
 
-    NSUnimplemented() // work in progress
+    //
+    // Failed, restart from scratch
+    //
+    NSDecimalCopy(aa, &backup);
+
+    //
+    // What is the maximum pow10 we can apply to aa ?
+    //
+    let logBase10of2to16 = 4.81647993
+    let aaLength = aa.pointee._length
+    let maxpow10 = Int8(floor(Double(Decimal.maxSize - aaLength) * logBase10of2to16))
+
+    //
+    // Divide bb by this value
+    //
+    _ = integerMultiplyByPowerOf10(&result, bb.pointee, maxpow10 - diffexp)
+
+    bb.pointee.copyMantissa(from: result)
+    bb.pointee._exponent -= maxpow10 - diffexp;
+
+    //
+    // If bb > 0 multiply aa by the same value
+    //
+    if !bb.pointee.isZero {
+        _ = integerMultiplyByPowerOf10(&result, aa.pointee, Int(maxpow10))
+        aa.pointee.copyMantissa(from: result)
+        aa.pointee._exponent -= Int32(maxpow10)
+    } else {
+        bb.pointee._exponent = aa.pointee._exponent;
+    }
+
+    //
+    // the two exponents are now identical, but we've lost some digits in the operation.
+    //
+    return .lossOfPrecision;
 }
 
 public func NSDecimalAdd(_ result: UnsafeMutablePointer<Decimal>, _ leftOperand: UnsafePointer<Decimal>, _ rightOperand: UnsafePointer<Decimal>, _ roundingMode: NSDecimalNumber.RoundingMode) -> NSDecimalNumber.CalculationError {
@@ -1233,9 +1261,7 @@
     }
     result._length = i;
 
-    while result._length != 0 && result[result._length - 1] == 0 {
-        result._length -= 1
-    }
+    result.trimTrailingZeros()
 
     return .noError;
 }
@@ -1265,7 +1291,7 @@
     var big = WideDecimal()
     var calculationError:NSDecimalNumber.CalculationError = .noError
 
-    calculationError = integerMultiply(&big,WideDecimal(leftOperand.pointee),WideDecimal(rightOperand.pointee))
+    calculationError = integerMultiply(&big,WideDecimal(leftOperand.pointee),rightOperand.pointee)
 
     result.pointee._isNegative = (leftOperand.pointee._isNegative + rightOperand.pointee._isNegative) % 2
 
@@ -1340,7 +1366,7 @@
     }
 
     _ = integerMultiplyByPowerOf10(&big, WideDecimal(a), 38) // Trust me, it's 38 !
-    _ = integerDivide(&big, big, WideDecimal(b))
+    _ = integerDivide(&big, big, b)
     _ = fitMantissa(&big, &exponent, .down)
 
     let length = min(big._length,Decimal.maxSize)
@@ -1386,23 +1412,84 @@
 
 public func NSDecimalString(_ dcm: UnsafePointer<Decimal>, _ locale: AnyObject?) -> String {
     guard locale == nil else {
-        fatalError("Locale not supported: \(locale)")
+        fatalError("Locale not supported: \(locale!)")
     }
     return dcm.pointee.description
 }
 
 fileprivate protocol VariableLengthNumber {
     var _length: UInt32 { get set }
+    init()
     subscript(index:UInt32) -> UInt16 { get set }
     var isZero:Bool { get }
+    mutating func copyMantissa<T:VariableLengthNumber>(from other:T)
+    mutating func zeroMantissa()
+    mutating func trimTrailingZeros()
+    var maxMantissaLength: UInt32 { get }
 }
 
 extension Decimal: VariableLengthNumber {
-
+    var maxMantissaLength:UInt32 {
+        return Decimal.maxSize
+    }
+    fileprivate mutating func zeroMantissa() {
+        for i in 0..<Decimal.maxSize {
+            self[i] = 0
+        }
+    }
+    internal mutating func trimTrailingZeros() {
+        if _length > Decimal.maxSize {
+            _length = Decimal.maxSize
+        }
+        while _length != 0 && self[_length - 1] == 0 {
+            _length -= 1
+        }
+    }
+    fileprivate mutating func copyMantissa<T : VariableLengthNumber>(from other: T) {
+        if other._length > maxMantissaLength {
+            for i in maxMantissaLength..<other._length {
+                guard other[i] == 0 else {
+                    fatalError("Loss of precision during copy other[\(i)] \(other[i]) != 0")
+                }
+            }
+        }
+        let length = min(other._length, maxMantissaLength)
+        for i in 0..<length {
+            self[i] = other[i]
+        }
+        self._length = length
+        self._isCompact = 0
+    }
 }
 
 // Provides a way with dealing with extra-length decimals, used for calculations
 fileprivate struct WideDecimal : VariableLengthNumber {
+    var maxMantissaLength:UInt32 {
+        return _extraWide ? 17 : 16
+    }
+
+    fileprivate mutating func zeroMantissa() {
+        for i in 0..<maxMantissaLength {
+            self[i] = 0
+        }
+    }
+    fileprivate mutating func trimTrailingZeros() {
+        while _length != 0 && self[_length - 1] == 0 {
+            _length -= 1
+        }
+    }
+    init() {
+        self.init(false)
+    }
+
+    fileprivate mutating func copyMantissa<T : VariableLengthNumber>(from other: T) {
+        let length = other is Decimal ? min(other._length,Decimal.maxSize) : other._length
+        for i in 0..<length {
+            self[i] = other[i]
+        }
+        self._length = length
+    }
+
     var isZero: Bool {
         return _length == 0
     }
@@ -1417,14 +1504,14 @@
             return UInt32(__length)
         }
         set {
-            guard newValue <= Decimal.maxSize * 2 + 1 else {
-                fatalError("Cannot set size to \(newValue)")
+            guard newValue <= maxMantissaLength else {
+                fatalError("Attempt to set a length greater than capacity \(newValue) > \(maxMantissaLength)")
             }
             __length = UInt16(newValue)
         }
     }
     init(_ extraWide:Bool = false) {
-        __length = UInt16(Decimal.maxSize * 2)
+        __length = 0
         _mantissa = (UInt16(0),UInt16(0),UInt16(0),UInt16(0),UInt16(0),UInt16(0),UInt16(0),UInt16(0),UInt16(0),UInt16(0),UInt16(0),UInt16(0),UInt16(0),UInt16(0),UInt16(0),UInt16(0),UInt16(0))
         _extraWide = extraWide
     }
@@ -1479,26 +1566,6 @@
             }
         }
     }
-    public func compare(to rhs: WideDecimal) -> ComparisonResult {
-        if self._length > rhs._length {
-            return .orderedDescending
-        }
-        if self._length < rhs._length {
-            return .orderedAscending
-        }
-        for i in (0..<self._length).reversed() {
-            if self[i] > rhs[i] {
-                return .orderedDescending
-            }
-            if self[i] < rhs[i] {
-                return .orderedAscending
-            }
-        }
-        return .orderedSame
-    }
-    public static func <(lhs: WideDecimal, rhs: WideDecimal) -> Bool {
-        return lhs.compare(to:rhs) == .orderedAscending
-    }
     func toDecimal() -> Decimal {
         var result = Decimal()
         result._length = self._length
@@ -1630,7 +1697,7 @@
         _exponent = newExponent;
         self.compact();
     }
-    fileprivate func compare(to other:Decimal) -> ComparisonResult {
+    internal func compare(to other:Decimal) -> ComparisonResult {
         // NaN is a special case and is arbitrary ordered before everything else
         // Conceptually comparing with NaN is bogus anyway but raising or
         // always returning the same answer will confuse the sorting algorithms
diff --git a/Foundation/NSDecimalNumber.swift b/Foundation/NSDecimalNumber.swift
index 759dc28..46b9b20 100644
--- a/Foundation/NSDecimalNumber.swift
+++ b/Foundation/NSDecimalNumber.swift
@@ -75,29 +75,86 @@
 
 // Receiver can raise, return a new value, or return nil to ignore the exception.
 
+fileprivate func handle(_ error: NSDecimalNumber.CalculationError, _ handler: NSDecimalNumberBehaviors) {
+    // handle the error condition, such as throwing an error for over/underflow
+}
 
 /***************	NSDecimalNumber: the class		***********/
 open class NSDecimalNumber : NSNumber {
-    
-    public convenience init(mantissa: UInt64, exponent: Int16, isNegative flag: Bool) { NSUnimplemented() }
-    public init(decimal dcm: Decimal) { NSUnimplemented() }
-    public convenience init(string numberValue: String?) { NSUnimplemented() }
-    public convenience init(string numberValue: String?, locale: AnyObject?) { NSUnimplemented() }
 
-    public required init?(coder aDecoder: NSCoder) {
-        NSUnimplemented()
+    fileprivate let decimal: Decimal
+    public convenience init(mantissa: UInt64, exponent: Int16, isNegative: Bool) {
+        var d = Decimal()
+        d._exponent = Int32(exponent)
+        d._isNegative = isNegative ? 1 : 0
+        var man = mantissa
+        d._mantissa.0 = UInt16(man & 0xffff)
+        man >>= 4
+        d._mantissa.1 = UInt16(man & 0xffff)
+        man >>= 4
+        d._mantissa.2 = UInt16(man & 0xffff)
+        man >>= 4
+        d._mantissa.3 = UInt16(man & 0xffff)
+        d._length = 4
+        d.trimTrailingZeros()
+        // TODO more parts of the mantissa...
+        self.init(decimal: d)
+    }
+    public init(decimal dcm: Decimal) {
+        self.decimal = dcm
+        super.init()
+    }
+    public convenience init(string numberValue: String?) {
+        self.init(decimal: Decimal(string: numberValue ?? "") ?? Decimal.nan)
+    }
+    public convenience init(string numberValue: String?, locale: AnyObject?) {
+        self.init(decimal: Decimal(string: numberValue ?? "", locale: locale as? Locale) ?? Decimal.nan)
+    }
+
+    public required init?(coder: NSCoder) {
+        guard coder.allowsKeyedCoding else {
+            preconditionFailure("Unkeyed coding is unsupported.")
+        }
+        let exponent:Int32 = coder.decodeInt32(forKey: "NS.exponent")
+        let length:UInt32 = UInt32(coder.decodeInt32(forKey: "NS.length"))
+        let isNegative:UInt32 = UInt32(coder.decodeBool(forKey: "NS.negative") ? 1 : 0)
+        let isCompact:UInt32 = UInt32(coder.decodeBool(forKey: "NS.compact") ? 1 : 0)
+        // let byteOrder:UInt32 = UInt32(coder.decodeInt32(forKey: "NS.bo"))
+        guard let mantissaData: Data = coder.decodeObject(forKey: "NS.mantissa") as? Data else {
+            return nil // raise "Critical NSDecimalNumber archived data is missing"
+        }
+        guard mantissaData.count == Int(NSDecimalMaxSize * 2) else {
+            return nil  // raise "Critical NSDecimalNumber archived data is wrong size"
+        }
+        // Byte order?
+        let mantissa:(UInt16, UInt16, UInt16, UInt16, UInt16, UInt16, UInt16, UInt16) = (
+            UInt16(mantissaData[0]) << 8 & UInt16(mantissaData[1]),
+            UInt16(mantissaData[2]) << 8 & UInt16(mantissaData[3]),
+            UInt16(mantissaData[4]) << 8 & UInt16(mantissaData[5]),
+            UInt16(mantissaData[6]) << 8 & UInt16(mantissaData[7]),
+            UInt16(mantissaData[8]) << 8 & UInt16(mantissaData[9]),
+            UInt16(mantissaData[10]) << 8 & UInt16(mantissaData[11]),
+            UInt16(mantissaData[12]) << 8 & UInt16(mantissaData[13]),
+            UInt16(mantissaData[14]) << 8 & UInt16(mantissaData[15])
+        )
+        self.decimal = Decimal(_exponent: exponent, _length: length, _isNegative: isNegative, _isCompact: isCompact, _reserved: 0, _mantissa: mantissa)
+        super.init()
     }
 
     public required convenience init(floatLiteral value: Double) {
-        NSUnimplemented()
+        self.init(decimal:Decimal(value))
     }
 
     public required convenience init(booleanLiteral value: Bool) {
-        NSUnimplemented()
+        if value {
+            self.init(integerLiteral: 1)
+        } else {
+            self.init(integerLiteral: 0)
+        }
     }
 
     public required convenience init(integerLiteral value: Int) {
-        NSUnimplemented()
+        self.init(decimal:Decimal(value))
     }
     
     public required convenience init(bytes buffer: UnsafeRawPointer, objCType type: UnsafePointer<Int8>) {
@@ -105,52 +162,180 @@
     }
     
     open override func description(withLocale locale: Locale?) -> String { NSUnimplemented() }
+
+    open class var zero: NSDecimalNumber {
+        return NSDecimalNumber(integerLiteral: 0)
+    }
+    open class var one: NSDecimalNumber {
+        return NSDecimalNumber(integerLiteral: 1)
+    }
+    open class var minimum: NSDecimalNumber {
+        return NSDecimalNumber(decimal:Decimal.leastFiniteMagnitude)
+    }
+    open class var maximum: NSDecimalNumber {
+        return NSDecimalNumber(decimal:Decimal.greatestFiniteMagnitude)
+
+    }
+    open class var notANumber: NSDecimalNumber {
+        return NSDecimalNumber(decimal: Decimal.nan)
+    }
     
-    // TODO: "declarations from extensions cannot be overridden yet"
-    // Although it's not clear we actually need to redeclare this here when the extension adds it to the superclass of this class
-    // open var decimalValue: Decimal { NSUnimplemented() }
+    open func adding(_ other: NSDecimalNumber) -> NSDecimalNumber {
+        return adding(other, withBehavior: nil)
+    }
+    open func adding(_ other: NSDecimalNumber, withBehavior b: NSDecimalNumberBehaviors?) -> NSDecimalNumber {
+        var result = Decimal()
+        var left = self.decimal
+        var right = other.decimal
+        let behavior = b ?? NSDecimalNumber.defaultBehavior
+        let roundingMode = behavior.roundingMode()
+        let error = NSDecimalAdd(&result, &left, &right, roundingMode)
+        handle(error,behavior)
+        return NSDecimalNumber(decimal: result)
+    }
+
+    open func subtracting(_ other: NSDecimalNumber) -> NSDecimalNumber {
+        return subtracting(other, withBehavior: nil)
+    }
+    open func subtracting(_ other: NSDecimalNumber, withBehavior b: NSDecimalNumberBehaviors?) -> NSDecimalNumber {
+        var result = Decimal()
+        var left = self.decimal
+        var right = other.decimal
+        let behavior = b ?? NSDecimalNumber.defaultBehavior
+        let roundingMode = behavior.roundingMode()
+        let error = NSDecimalSubtract(&result, &left, &right, roundingMode)
+        handle(error,behavior)
+        return NSDecimalNumber(decimal: result)
+    }
+    open func multiplying(by other: NSDecimalNumber) -> NSDecimalNumber {
+        return multiplying(by: other, withBehavior: nil)
+    }
+    open func multiplying(by other: NSDecimalNumber, withBehavior b: NSDecimalNumberBehaviors?) -> NSDecimalNumber {
+        var result = Decimal()
+        var left = self.decimal
+        var right = other.decimal
+        let behavior = b ?? NSDecimalNumber.defaultBehavior
+        let roundingMode = behavior.roundingMode()
+        let error = NSDecimalMultiply(&result, &left, &right, roundingMode)
+        handle(error,behavior)
+        return NSDecimalNumber(decimal: result)
+    }
     
-    open class var zero: NSDecimalNumber { NSUnimplemented() }
-    open class var one: NSDecimalNumber { NSUnimplemented() }
-    open class var minimum: NSDecimalNumber { NSUnimplemented() }
-    open class var maximum: NSDecimalNumber { NSUnimplemented() }
-    open class var notANumber: NSDecimalNumber { NSUnimplemented() }
+    open func dividing(by other: NSDecimalNumber) -> NSDecimalNumber {
+        return dividing(by: other, withBehavior: nil)
+    }
+    open func dividing(by other: NSDecimalNumber, withBehavior b: NSDecimalNumberBehaviors?) -> NSDecimalNumber {
+        var result = Decimal()
+        var left = self.decimal
+        var right = other.decimal
+        let behavior = b ?? NSDecimalNumber.defaultBehavior
+        let roundingMode = behavior.roundingMode()
+        let error = NSDecimalDivide(&result, &left, &right, roundingMode)
+        handle(error,behavior)
+        return NSDecimalNumber(decimal: result)
+    }
     
-    open func adding(_ decimalNumber: NSDecimalNumber) -> NSDecimalNumber { NSUnimplemented() }
-    open func adding(_ decimalNumber: NSDecimalNumber, withBehavior behavior: NSDecimalNumberBehaviors?) -> NSDecimalNumber { NSUnimplemented() }
-    
-    open func subtracting(_ decimalNumber: NSDecimalNumber) -> NSDecimalNumber { NSUnimplemented() }
-    open func subtracting(_ decimalNumber: NSDecimalNumber, withBehavior behavior: NSDecimalNumberBehaviors?) -> NSDecimalNumber { NSUnimplemented() }
-    
-    open func multiplying(by decimalNumber: NSDecimalNumber) -> NSDecimalNumber { NSUnimplemented() }
-    open func multiplying(by decimalNumber: NSDecimalNumber, withBehavior behavior: NSDecimalNumberBehaviors?) -> NSDecimalNumber { NSUnimplemented() }
-    
-    open func dividing(by decimalNumber: NSDecimalNumber) -> NSDecimalNumber { NSUnimplemented() }
-    open func dividing(by decimalNumber: NSDecimalNumber, withBehavior behavior: NSDecimalNumberBehaviors?) -> NSDecimalNumber { NSUnimplemented() }
-    
-    open func raising(toPower power: Int) -> NSDecimalNumber { NSUnimplemented() }
-    open func raising(toPower power: Int, withBehavior behavior: NSDecimalNumberBehaviors?) -> NSDecimalNumber { NSUnimplemented() }
-    
-    open func multiplying(byPowerOf10 power: Int16) -> NSDecimalNumber { NSUnimplemented() }
-    open func multiplying(byPowerOf10 power: Int16, withBehavior behavior: NSDecimalNumberBehaviors?) -> NSDecimalNumber { NSUnimplemented() }
+    open func raising(toPower power: Int) -> NSDecimalNumber {
+        return raising(toPower:power, withBehavior: nil)
+    }
+    open func raising(toPower power: Int, withBehavior b: NSDecimalNumberBehaviors?) -> NSDecimalNumber {
+        var result = Decimal()
+        var input = self.decimal
+        let behavior = b ?? NSDecimalNumber.defaultBehavior
+        let roundingMode = behavior.roundingMode()
+        let error = NSDecimalPower(&result, &input, power, roundingMode)
+        handle(error,behavior)
+        return NSDecimalNumber(decimal: result)
+    }
+
+    open func multiplying(byPowerOf10 power: Int16) -> NSDecimalNumber {
+        return multiplying(byPowerOf10: power, withBehavior: nil)
+    }
+    open func multiplying(byPowerOf10 power: Int16, withBehavior b: NSDecimalNumberBehaviors?) -> NSDecimalNumber {
+        var result = Decimal()
+        var input = self.decimal
+        let behavior = b ?? NSDecimalNumber.defaultBehavior
+        let roundingMode = behavior.roundingMode()
+        let error = NSDecimalPower(&result, &input, Int(power), roundingMode)
+        handle(error,behavior)
+        return NSDecimalNumber(decimal: result)
+    }
     
     open func rounding(accordingToBehavior behavior: NSDecimalNumberBehaviors?) -> NSDecimalNumber { NSUnimplemented() }
     // Round to the scale of the behavior.
     
-    open override func compare(_ decimalNumber: NSNumber) -> ComparisonResult { NSUnimplemented() }
     // compare two NSDecimalNumbers
-    
-    open class var defaultBehavior: NSDecimalNumberBehaviors { NSUnimplemented() }
+    open override func compare(_ decimalNumber: NSNumber) -> ComparisonResult {
+        if let num = decimalNumber as? NSDecimalNumber {
+            return decimal.compare(to:num.decimal)
+        } else {
+            return decimal.compare(to:Decimal(decimalNumber.doubleValue))
+        }
+    }
+
+    open class var defaultBehavior: NSDecimalNumberBehaviors {
+        return NSDecimalNumberHandler.defaultBehavior
+    }
     // One behavior per thread - The default behavior is
     //   rounding mode: NSRoundPlain
     //   scale: No defined scale (full precision)
     //   ignore exactnessException
     //   raise on overflow, underflow and divide by zero.
-    
-    open override var objCType: UnsafePointer<Int8> { NSUnimplemented() }
+    static let OBJC_TYPE = "d".utf8CString
+
+    open override var objCType: UnsafePointer<Int8> {
+        return NSDecimalNumber.OBJC_TYPE.withUnsafeBufferPointer{ $0.baseAddress! }
+    }
     // return 'd' for double
     
-    open override var doubleValue: Double { NSUnimplemented() }
+    open override var int8Value: Int8 {
+        return Int8(decimal.doubleValue)
+    }
+    open override var uint8Value: UInt8 {
+        return UInt8(decimal.doubleValue)
+    }
+    open override var int16Value: Int16 {
+        return Int16(decimal.doubleValue)
+    }
+    open override var uint16Value: UInt16 {
+        return UInt16(decimal.doubleValue)
+    }
+    open override var int32Value: Int32 {
+        return Int32(decimal.doubleValue)
+    }
+    open override var uint32Value: UInt32 {
+        return UInt32(decimal.doubleValue)
+    }
+    open override var int64Value: Int64 {
+        return Int64(decimal.doubleValue)
+    }
+    open override var uint64Value: UInt64 {
+        return UInt64(decimal.doubleValue)
+    }
+    open override var floatValue: Float {
+        return Float(decimal.doubleValue)
+    }
+    open override var doubleValue: Double {
+        return decimal.doubleValue
+    }
+    open override var boolValue: Bool {
+        return !decimal.isZero
+    }
+    open override var intValue: Int {
+        return Int(decimal.doubleValue)
+    }
+    open override var uintValue: UInt {
+        return UInt(decimal.doubleValue)
+    }
+
+    open override func isEqual(_ value: Any?) -> Bool {
+        if let number = value as? NSDecimalNumber {
+            return self.decimal == number.decimal
+        } else {
+            return false
+        }
+    }
+
 }
 
 // return an approximate double value
@@ -158,33 +343,103 @@
 
 /***********	A class for defining common behaviors		*******/
 open class NSDecimalNumberHandler : NSObject, NSDecimalNumberBehaviors, NSCoding {
-    
-    public required init?(coder aDecoder: NSCoder) {
-        NSUnimplemented()
+
+    static let defaultBehavior = NSDecimalNumberHandler()
+
+    let _roundingMode: NSDecimalNumber.RoundingMode
+    let _scale:Int16
+
+    let _raiseOnExactness: Bool
+    let _raiseOnOverflow: Bool
+    let _raiseOnUnderflow: Bool
+    let _raiseOnDivideByZero: Bool
+
+    public override init() {
+        _roundingMode = .plain
+        _scale = Int16(NSDecimalNoScale)
+
+        _raiseOnExactness = false
+        _raiseOnOverflow = true
+        _raiseOnUnderflow = true
+        _raiseOnDivideByZero = true
+    }
+    public required init?(coder: NSCoder) {
+        guard coder.allowsKeyedCoding else {
+            preconditionFailure("Unkeyed coding is unsupported.")
+        }
+        _roundingMode = NSDecimalNumber.RoundingMode(rawValue: UInt(coder.decodeInteger(forKey: "NS.roundingMode")))!
+        if coder.containsValue(forKey: "NS.scale") {
+            _scale = Int16(coder.decodeInteger(forKey: "NS.scale"))
+        } else {
+            _scale = Int16(NSDecimalNoScale)
+        }
+        _raiseOnExactness = coder.decodeBool(forKey: "NS.raise.exactness")
+        _raiseOnOverflow = coder.decodeBool(forKey: "NS.raise.overflow")
+        _raiseOnUnderflow = coder.decodeBool(forKey: "NS.raise.underflow")
+        _raiseOnDivideByZero = coder.decodeBool(forKey: "NS.raise.dividebyzero")
     }
     
-    open func encode(with aCoder: NSCoder) {
-        NSUnimplemented()
+    open func encode(with coder: NSCoder) {
+        guard coder.allowsKeyedCoding else {
+            preconditionFailure("Unkeyed coding is unsupported.")
+        }
+        if _roundingMode != .plain {
+            coder.encode(Int(_roundingMode.rawValue), forKey: "NS.roundingmode")
+        }
+        if _scale != Int16(NSDecimalNoScale) {
+            coder.encode(_scale, forKey:"NS.scale")
+        }
+        if _raiseOnExactness {
+            coder.encode(_raiseOnExactness, forKey:"NS.raise.exactness")
+        }
+        if _raiseOnOverflow {
+            coder.encode(_raiseOnOverflow, forKey:"NS.raise.overflow")
+        }
+        if _raiseOnUnderflow {
+            coder.encode(_raiseOnUnderflow, forKey:"NS.raise.underflow")
+        }
+        if _raiseOnDivideByZero {
+            coder.encode(_raiseOnDivideByZero, forKey:"NS.raise.dividebyzero")
+        }
     }
     
-    open class func `default`() -> NSDecimalNumberHandler { NSUnimplemented() }
+    open class func `default`() -> NSDecimalNumberHandler {
+        return defaultBehavior
+    }
     // rounding mode: NSRoundPlain
     // scale: No defined scale (full precision)
     // ignore exactnessException (return nil)
     // raise on overflow, underflow and divide by zero.
     
-    public init(roundingMode: NSDecimalNumber.RoundingMode, scale: Int16, raiseOnExactness exact: Bool, raiseOnOverflow overflow: Bool, raiseOnUnderflow underflow: Bool, raiseOnDivideByZero divideByZero: Bool) { NSUnimplemented() }
+    public init(roundingMode: NSDecimalNumber.RoundingMode, scale: Int16, raiseOnExactness exact: Bool, raiseOnOverflow overflow: Bool, raiseOnUnderflow underflow: Bool, raiseOnDivideByZero divideByZero: Bool) {
+        _roundingMode = roundingMode
+        _scale = scale
+        _raiseOnExactness = exact
+        _raiseOnOverflow = overflow
+        _raiseOnUnderflow = underflow
+        _raiseOnDivideByZero = divideByZero
+    }
     
-    open func roundingMode() -> NSDecimalNumber.RoundingMode { NSUnimplemented() }
+    open func roundingMode() -> NSDecimalNumber.RoundingMode {
+        return _roundingMode
+    }
     
-    open func scale() -> Int16 { NSUnimplemented() }
-    // The scale could return NO_SCALE for no defined scale.
+    // The scale could return NoScale for no defined scale.
+    open func scale() -> Int16 {
+        return _scale
+    }
 }
 
 
 extension NSNumber {
     
-    public var decimalValue: Decimal { NSUnimplemented() }
+    public var decimalValue: Decimal {
+        if let d = self as? NSDecimalNumber {
+            return d.decimal
+        } else {
+            return Decimal(self.doubleValue)
+        }
+    }
 }
 
 // Could be silently inexact for float and double.
diff --git a/Foundation/NSKeyedArchiver.swift b/Foundation/NSKeyedArchiver.swift
index 003dc15..f9b473b 100644
--- a/Foundation/NSKeyedArchiver.swift
+++ b/Foundation/NSKeyedArchiver.swift
@@ -270,7 +270,9 @@
             return NSKeyedArchiveNullObjectReference
         }
         
-        uid = self._objRefMap[objv as! AnyHashable]
+        let value = _SwiftValue.store(objv)!
+        
+        uid = self._objRefMap[value]
         if uid == nil {
             if conditional {
                 return nil // object has not been unconditionally encoded
@@ -278,7 +280,7 @@
             
             uid = UInt32(self._objects.count)
             
-            self._objRefMap[objv as! AnyHashable] = uid
+            self._objRefMap[value] = uid
             self._objects.insert(NSKeyedArchiveNullObjectReferenceName, at: Int(uid!))
         }
 
@@ -292,7 +294,7 @@
         if objv == nil {
             return true // always have a null reference
         } else {
-            return self._objRefMap[objv as! AnyHashable] != nil
+            return self._objRefMap[_SwiftValue.store(objv)] != nil
         }
     }
     
@@ -361,10 +363,10 @@
      */
     private func replaceObject(_ object: Any, withObject replacement: Any?) {
         if let unwrappedDelegate = self.delegate {
-            unwrappedDelegate.archiver(self, willReplace: object as! AnyHashable, with: replacement)
+            unwrappedDelegate.archiver(self, willReplace: object, with: replacement)
         }
         
-        self._replacementMap[object as! AnyHashable] = replacement
+        self._replacementMap[_SwiftValue.store(object)] = replacement
     }
    
     /**
@@ -476,9 +478,8 @@
         
         // object replaced by NSObject.replacementObjectForKeyedArchiver
         // if it is replaced with nil, it cannot be further replaced
-        if objectToEncode == nil {
-            let ns = object as? NSObject
-            objectToEncode = ns?.replacementObjectForKeyedArchiver(self)
+        if let ns = objectToEncode as? NSObject {
+            objectToEncode = ns.replacementObjectForKeyedArchiver(self)
             if objectToEncode == nil {
                 replaceObject(object!, withObject: nil)
                 return nil
@@ -510,7 +511,12 @@
 
         haveVisited = _haveVisited(objv)
         object = _replacementObject(objv)
-
+        
+        // bridge value types
+        if let bridgedObject = object as? _ObjectBridgeable {
+            object = bridgedObject._bridgeToAnyObject()
+        }
+        
         objectRef = _referenceObject(object, conditional: conditional)
         guard let unwrappedObjectRef = objectRef else {
             // we can return nil if the object is being conditionally encoded
@@ -531,12 +537,9 @@
                 _pushEncodingContext(innerEncodingContext)
                 codable.encode(with: self)
 
-                guard let ns = object as? NSObject else {
-                    fatalError("Attempt to encode non-NSObject");
-                }
-
-                let cls : AnyClass = ns.classForKeyedArchiver ?? type(of: object) as! AnyClass
-
+                let ns = object as? NSObject
+                let cls : AnyClass = ns?.classForKeyedArchiver ?? type(of: object!) as! AnyClass
+                
                 _setObjectInCurrentEncodingContext(_classReference(cls), forKey: "$class", escape: false)
                 _popEncodingContext()
                 encodedObject = innerEncodingContext.dict
diff --git a/Foundation/NSKeyedUnarchiver.swift b/Foundation/NSKeyedUnarchiver.swift
index d9c691e..b3dfc8e 100644
--- a/Foundation/NSKeyedUnarchiver.swift
+++ b/Foundation/NSKeyedUnarchiver.swift
@@ -375,7 +375,7 @@
             unwrappedDelegate.unarchiver(self, willReplace: object, with: replacement)
         }
         
-        self._replacementMap[object as! AnyHashable] = replacement
+        self._replacementMap[_SwiftValue.store(object)] = replacement
     }
     
     private func _decodingError(_ code: CocoaError.Code, withDescription description: String) -> NSError {
@@ -392,7 +392,7 @@
         }
         
         // check replacement cache
-        object = self._replacementMap[decodedObject as! AnyHashable]
+        object = self._replacementMap[_SwiftValue.store(decodedObject)]
         if object != nil {
             return object
         }
@@ -489,9 +489,8 @@
             }
         } else {
             // reference to a non-container object
-            // FIXME remove these special cases
-            if let str = dereferencedObject as? String {
-                object = str._bridgeToObjectiveC()
+            if let bridgedObject = dereferencedObject as? _ObjectBridgeable {
+                object = bridgedObject._bridgeToAnyObject()
             } else {
                 object = dereferencedObject
             }
diff --git a/Foundation/NSLock.swift b/Foundation/NSLock.swift
index c4a9f68..e166b80 100644
--- a/Foundation/NSLock.swift
+++ b/Foundation/NSLock.swift
@@ -115,7 +115,7 @@
 
     open func lock(before limit: Date) -> Bool {
         _cond.lock()
-        while _thread == nil {
+        while _thread != nil {
             if !_cond.wait(until: limit) {
                 _cond.unlock()
                 return false
diff --git a/Foundation/NSNumber.swift b/Foundation/NSNumber.swift
index 724cc02..14bec84 100644
--- a/Foundation/NSNumber.swift
+++ b/Foundation/NSNumber.swift
@@ -290,7 +290,11 @@
         super.init()
         _CFNumberInitBool(_cfObject, value)
     }
-    
+
+    override internal init() {
+        super.init()
+    }
+
     public required convenience init(bytes buffer: UnsafeRawPointer, objCType: UnsafePointer<Int8>) {
         guard let type = _NSSimpleObjCType(UInt8(objCType.pointee)) else {
             fatalError("NSNumber.init: unsupported type encoding spec '\(String(cString: objCType))'")
diff --git a/Foundation/NSString.swift b/Foundation/NSString.swift
index 32455e9..95f5e6c 100644
--- a/Foundation/NSString.swift
+++ b/Foundation/NSString.swift
@@ -817,7 +817,7 @@
 
             return data
         }
-        return nil
+        return Data()
     }
     
     public func data(using encoding: UInt) -> Data? {
@@ -1008,8 +1008,10 @@
     open func trimmingCharacters(in set: CharacterSet) -> String {
         let len = length
         var buf = _NSStringBuffer(string: self, start: 0, end: len)
-        while !buf.isAtEnd && set.contains(UnicodeScalar(buf.currentCharacter)!) {
-            buf.advance()
+        while !buf.isAtEnd,
+            let character = UnicodeScalar(buf.currentCharacter),
+            set.contains(character) {
+                buf.advance()
         }
         
         let startOfNonTrimmedRange = buf.location // This points at the first char not in the set
@@ -1018,8 +1020,10 @@
             return ""
         } else if startOfNonTrimmedRange < len - 1 {
             buf.location = len - 1
-            while set.contains(UnicodeScalar(buf.currentCharacter)!) && buf.location >= startOfNonTrimmedRange {
-                buf.rewind()
+            while let character = UnicodeScalar(buf.currentCharacter),
+                set.contains(character),
+                buf.location >= startOfNonTrimmedRange {
+                    buf.rewind()
             }
             let endOfNonTrimmedRange = buf.location
             return substring(with: NSMakeRange(startOfNonTrimmedRange, endOfNonTrimmedRange + 1 - startOfNonTrimmedRange))
diff --git a/Foundation/NSURLCredential.swift b/Foundation/NSURLCredential.swift
index 300126a..32cd075 100644
--- a/Foundation/NSURLCredential.swift
+++ b/Foundation/NSURLCredential.swift
@@ -65,11 +65,32 @@
      */
     
     public required init?(coder aDecoder: NSCoder) {
-        NSUnimplemented()
+        guard aDecoder.allowsKeyedCoding else {
+            preconditionFailure("Unkeyed coding is unsupported.")
+        }
+        
+        func bridgeString(_ value: NSString) -> String? {
+            return String._unconditionallyBridgeFromObjectiveC(value)
+        }
+        
+        let encodedUser = aDecoder.decodeObject(forKey: "NS._user") as! NSString
+        self._user = bridgeString(encodedUser)!
+        
+        let encodedPassword = aDecoder.decodeObject(forKey: "NS._password") as! NSString
+        self._password = bridgeString(encodedPassword)!
+        
+        let encodedPersistence = aDecoder.decodeObject(forKey: "NS._persistence") as! NSNumber
+        self._persistence = Persistence(rawValue: encodedPersistence.uintValue)!
     }
     
     open func encode(with aCoder: NSCoder) {
-        NSUnimplemented()
+        guard aCoder.allowsKeyedCoding else {
+            preconditionFailure("Unkeyed coding is unsupported.")
+        }
+        
+        aCoder.encode(self._user._bridgeToObjectiveC(), forKey: "NS._user")
+        aCoder.encode(self._password._bridgeToObjectiveC(), forKey: "NS._password")
+        aCoder.encode(self._persistence.rawValue._bridgeToObjectiveC(), forKey: "NS._persistence")
     }
     
     static public var supportsSecureCoding: Bool {
@@ -84,6 +105,17 @@
         return self 
     }
     
+    open override func isEqual(_ object: Any?) -> Bool {
+        if let other = object as? URLCredential {
+            return other === self
+                || (other._user == self._user
+                    && other._password == self._password
+                    && other._persistence == self._persistence)
+        }
+        
+        return false
+    }
+    
     /*!
         @method persistence
         @abstract Determine whether this credential is or should be stored persistently
diff --git a/Foundation/NSURLSession/HTTPMessage.swift b/Foundation/NSURLSession/HTTPMessage.swift
index 4f41eef..6598d06 100644
--- a/Foundation/NSURLSession/HTTPMessage.swift
+++ b/Foundation/NSURLSession/HTTPMessage.swift
@@ -143,7 +143,12 @@
     var headersAsDictionary: [String: String] {
         var result: [String: String] = [:]
         headers.forEach {
-            result[$0.name] = $0.value
+            if result[$0.name] == nil {
+                result[$0.name] = $0.value
+            }
+            else {
+                result[$0.name]! += (", " + $0.value)
+            }
         }
         return result
     }
@@ -287,8 +292,13 @@
         var value: String?
         let line = headView[headView.index(after: nameRange.upperBound)..<headView.endIndex]
         if !line.isEmpty {
-            guard let v = line.trimSPHTPrefix else { return nil }
-            value = String(v)
+            if line.hasSPHTPrefix && line.count == 1 {
+                // to handle empty headers i.e header without value
+                value = String("")
+            } else {
+                guard let v = line.trimSPHTPrefix else { return nil }
+                value = String(v)
+            }
         }
         do {
             var t = tail
diff --git a/Foundation/NSURLSession/NSURLSessionTask.swift b/Foundation/NSURLSession/NSURLSessionTask.swift
index f8b9569..27ad59f 100644
--- a/Foundation/NSURLSession/NSURLSessionTask.swift
+++ b/Foundation/NSURLSession/NSURLSessionTask.swift
@@ -88,7 +88,7 @@
         originalRequest = nil
         body = .none
         workQueue = DispatchQueue(label: "URLSessionTask.notused.0")
-        taskAttributesIsolation = DispatchQueue(label: "URLSessionTask.notused.1")
+        taskAttributesIsolation = DispatchQueue(label: "URLSessionTask.notused.1", attributes: DispatchQueue.Attributes.concurrent)
         let fileName = NSTemporaryDirectory() + NSUUID().uuidString + ".tmp"
         _ = FileManager.default.createFile(atPath: fileName, contents: nil)
         self.tempFileURL = URL(fileURLWithPath: fileName)
@@ -145,7 +145,7 @@
             return r
         }
         //TODO: dispatch_barrier_async
-        set { taskAttributesIsolation.async { self._currentRequest = newValue } }
+        set { taskAttributesIsolation.async(flags: .barrier) { self._currentRequest = newValue } }
     }
     fileprivate var _currentRequest: URLRequest? = nil
     /*@NSCopying*/ open fileprivate(set) var response: URLResponse? {
@@ -154,7 +154,7 @@
             taskAttributesIsolation.sync { r = self._response }
             return r
         }
-        set { taskAttributesIsolation.async { self._response = newValue } }
+        set { taskAttributesIsolation.async(flags: .barrier) { self._response = newValue } }
     }
     fileprivate var _response: URLResponse? = nil
     
@@ -170,7 +170,7 @@
             taskAttributesIsolation.sync { r = self._countOfBytesReceived }
             return r
         }
-        set { taskAttributesIsolation.async { self._countOfBytesReceived = newValue } }
+        set { taskAttributesIsolation.async(flags: .barrier) { self._countOfBytesReceived = newValue } }
     }
     fileprivate var _countOfBytesReceived: Int64 = 0
     
@@ -181,7 +181,7 @@
             taskAttributesIsolation.sync { r = self._countOfBytesSent }
             return r
         }
-        set { taskAttributesIsolation.async { self._countOfBytesSent = newValue } }
+        set { taskAttributesIsolation.async(flags: .barrier) { self._countOfBytesSent = newValue } }
     }
 
     fileprivate var _countOfBytesSent: Int64 = 0
@@ -213,7 +213,7 @@
             taskAttributesIsolation.sync { r = self._state }
             return r
         }
-        set { taskAttributesIsolation.async { self._state = newValue } }
+        set { taskAttributesIsolation.async(flags: .barrier) { self._state = newValue } }
     }
     fileprivate var _state: URLSessionTask.State = .suspended
     
@@ -298,7 +298,7 @@
             return r
         }
         set {
-            taskAttributesIsolation.async { self._priority = newValue }
+            taskAttributesIsolation.async(flags: .barrier) { self._priority = newValue }
         }
     }
     fileprivate var _priority: Float = URLSessionTaskPriorityDefault
@@ -791,7 +791,7 @@
         // to the delegate. But in case of redirects etc. we might send another
         // request.
         guard case .transferInProgress(let ts) = internalState else { fatalError("Transfer completed, but it wasn't in progress.") }
-        guard let request = currentRequest else { fatalError("Transfer completed, but there's no currect request.") }
+        guard let request = currentRequest else { fatalError("Transfer completed, but there's no current request.") }
         guard errorCode == nil else {
             internalState = .transferFailed
             failWith(errorCode: errorCode!, request: request)
diff --git a/Foundation/Notification.swift b/Foundation/Notification.swift
index 2ed74d0..d929dbe 100644
--- a/Foundation/Notification.swift
+++ b/Foundation/Notification.swift
@@ -76,7 +76,17 @@
 
 extension Notification : CustomReflectable {
     public var customMirror: Mirror {
-        NSUnimplemented()
+        var children: [(label: String?, value: Any)] = [(label: "name", self.name.rawValue)]
+
+        if let object = self.object {
+            children.append((label: "object", object))
+        }
+
+        if let info = self.userInfo {
+            children.append((label: "userInfo", info))
+        }
+
+        return Mirror(self, children: children, displayStyle: .class)
     }
 }
 
diff --git a/TestFoundation/TestNSCharacterSet.swift b/TestFoundation/TestNSCharacterSet.swift
index 71ff177..7bd9d62 100644
--- a/TestFoundation/TestNSCharacterSet.swift
+++ b/TestFoundation/TestNSCharacterSet.swift
@@ -28,7 +28,7 @@
             ("testRanges", testRanges),
             ("testInsertAndRemove", testInsertAndRemove),
             ("testBasics", testBasics),
-            
+            ("testClosedRanges_SR_2988", testClosedRanges_SR_2988),
             ("test_Predefines", test_Predefines),
             ("test_Range", test_Range),
             ("test_String", test_String),
@@ -223,6 +223,18 @@
         }
     }
     
+    func testClosedRanges_SR_2988() {
+        // "CharacterSet.insert(charactersIn: ClosedRange) crashes on a closed ClosedRange<UnicodeScalar> containing U+D7FF"
+        let problematicChar = UnicodeScalar(0xD7FF)!
+        let range = capitalA...problematicChar
+        var characters = CharacterSet(charactersIn: range) // this should not crash
+        XCTAssertTrue(characters.contains(problematicChar))
+        characters.remove(charactersIn: range) // this should not crash
+        XCTAssertTrue(!characters.contains(problematicChar))
+        characters.insert(charactersIn: range) // this should not crash
+        XCTAssertTrue(characters.contains(problematicChar))
+    }
+    
     func test_Bitmap() {
         
     }
diff --git a/TestFoundation/TestNSData.swift b/TestFoundation/TestNSData.swift
index 9705c15..44daab7 100644
--- a/TestFoundation/TestNSData.swift
+++ b/TestFoundation/TestNSData.swift
@@ -89,6 +89,7 @@
             ("test_replaceBytes", test_replaceBytes),
             ("test_initDataWithCapacity", test_initDataWithCapacity),
             ("test_initDataWithCount", test_initDataWithCount),
+            ("test_emptyStringToData", test_emptyStringToData),
         ]
     }
     
@@ -438,6 +439,11 @@
             return
         }
     }
+
+    func test_emptyStringToData() {
+        let data = "".data(using: .utf8)!
+        XCTAssertEqual(0, data.count, "data from empty string is empty")
+    }
 }
 
 // Tests from Swift SDK Overlay
diff --git a/TestFoundation/TestNSDecimal.swift b/TestFoundation/TestNSDecimal.swift
index 72f33f4..ffddd40 100644
--- a/TestFoundation/TestNSDecimal.swift
+++ b/TestFoundation/TestNSDecimal.swift
@@ -19,18 +19,92 @@
 
     static var allTests : [(String, (TestNSDecimal) -> () throws -> Void)] {
         return [
+            ("test_AdditionWithNormalization", test_AdditionWithNormalization),
             ("test_BasicConstruction", test_BasicConstruction),
             ("test_Constants", test_Constants),
             ("test_Description", test_Description),
             ("test_ExplicitConstruction", test_ExplicitConstruction),
             ("test_Maths", test_Maths),
             ("test_Misc", test_Misc),
+            ("test_MultiplicationOverflow", test_MultiplicationOverflow),
+            ("test_NaNInput", test_NaNInput),
+            ("test_NegativeAndZeroMultiplication", test_NegativeAndZeroMultiplication),
             ("test_Normalise", test_Normalise),
-            ("test_Round", test_Round),
             ("test_NSDecimal", test_NSDecimal),
+            ("test_PositivePowers", test_PositivePowers),
+            ("test_RepeatingDivision", test_RepeatingDivision),
+            ("test_Round", test_Round),
+            ("test_SimpleMultiplication", test_SimpleMultiplication),
+            ("test_SmallerNumbers", test_SmallerNumbers),
+            ("test_ZeroPower", test_ZeroPower),
         ]
     }
 
+    func test_AdditionWithNormalization() {
+
+        let biggie = Decimal(65536)
+        let smallee = Decimal(65536)
+        let answer = biggie/smallee
+        XCTAssertEqual(Decimal(1),answer)
+
+        var one = Decimal(1)
+        var addend = Decimal(1)
+        var expected = Decimal()
+        var result = Decimal()
+
+        expected._isNegative = 0;
+        expected._isCompact = 0;
+
+        // 2 digits -- certain to work
+        addend._exponent = -1;
+        XCTAssertEqual(.noError, NSDecimalAdd(&result, &one, &addend, .plain), "1 + 0.1")
+        expected._exponent = -1;
+        expected._length = 1;
+        expected._mantissa.0 = 11;
+        XCTAssertEqual(.orderedSame, NSDecimalCompare(&expected, &result), "1.1 == 1 + 0.1")
+
+        // 38 digits -- guaranteed by NSDecimal to work
+        addend._exponent = -37;
+        XCTAssertEqual(.noError, NSDecimalAdd(&result, &one, &addend, .plain), "1 + 1e-37")
+        expected._exponent = -37;
+        expected._length = 8;
+        expected._mantissa.0 = 0x0001;
+        expected._mantissa.1 = 0x0000;
+        expected._mantissa.2 = 0x36a0;
+        expected._mantissa.3 = 0x00f4;
+        expected._mantissa.4 = 0x46d9;
+        expected._mantissa.5 = 0xd5da;
+        expected._mantissa.6 = 0xee10;
+        expected._mantissa.7 = 0x0785;
+        XCTAssertEqual(.orderedSame, NSDecimalCompare(&expected, &result), "1 + 1e-37")
+
+        // 39 digits -- not guaranteed to work but it happens to, so we make the test work either way
+        addend._exponent = -38;
+        let error = NSDecimalAdd(&result, &one, &addend, .plain)
+        XCTAssertTrue(error == .noError || error == .lossOfPrecision, "1 + 1e-38")
+        if error == .noError {
+            expected._exponent = -38;
+            expected._length = 8;
+            expected._mantissa.0 = 0x0001;
+            expected._mantissa.1 = 0x0000;
+            expected._mantissa.2 = 0x2240;
+            expected._mantissa.3 = 0x098a;
+            expected._mantissa.4 = 0xc47a;
+            expected._mantissa.5 = 0x5a86;
+            expected._mantissa.6 = 0x4ca8;
+            expected._mantissa.7 = 0x4b3b;
+            XCTAssertEqual(.orderedSame, NSDecimalCompare(&expected, &result), "1 + 1e-38")
+        } else {
+            XCTAssertEqual(.orderedSame, NSDecimalCompare(&one, &result), "1 + 1e-38")
+        }
+
+        // 40 digits -- doesn't work; need to make sure it's rounding for us
+        addend._exponent = -39;
+        XCTAssertEqual(.lossOfPrecision, NSDecimalAdd(&result, &one, &addend, .plain), "1 + 1e-39")
+        XCTAssertEqual("1", result.description)
+        XCTAssertEqual(.orderedSame, NSDecimalCompare(&one, &result), "1 + 1e-39")
+    }
+
     func test_BasicConstruction() {
         let zero = Decimal()
         XCTAssertEqual(20, MemoryLayout<Decimal>.size)
@@ -39,7 +113,7 @@
         XCTAssertEqual(0, zero._isNegative)
         XCTAssertEqual(0, zero._isCompact)
         XCTAssertEqual(0, zero._reserved)
-        let (m0,m1,m2,m3,m4,m5,m6,m7) = zero._mantissa
+        let (m0, m1, m2, m3, m4, m5, m6, m7) = zero._mantissa
         XCTAssertEqual(0, m0)
         XCTAssertEqual(0, m1)
         XCTAssertEqual(0, m2)
@@ -59,47 +133,47 @@
         XCTAssertFalse(zero.isSignaling)
     }
     func test_Constants() {
-        XCTAssertEqual(8,NSDecimalMaxSize)
-        XCTAssertEqual(32767,NSDecimalNoScale)
+        XCTAssertEqual(8, NSDecimalMaxSize)
+        XCTAssertEqual(32767, NSDecimalNoScale)
         let smallest = Decimal(_exponent: 127, _length: 8, _isNegative: 1, _isCompact: 1, _reserved: 0, _mantissa: (UInt16.max, UInt16.max, UInt16.max, UInt16.max, UInt16.max, UInt16.max, UInt16.max, UInt16.max))
         XCTAssertEqual(smallest, Decimal.leastFiniteMagnitude)
         let biggest = Decimal(_exponent: 127, _length: 8, _isNegative: 0, _isCompact: 1, _reserved: 0, _mantissa: (UInt16.max, UInt16.max, UInt16.max, UInt16.max, UInt16.max, UInt16.max, UInt16.max, UInt16.max))
         XCTAssertEqual(biggest, Decimal.greatestFiniteMagnitude)
-        let leastNormal = Decimal(_exponent: -127, _length: 1, _isNegative: 0, _isCompact: 1, _reserved: 0, _mantissa: (1,0,0,0,0,0,0,0))
+        let leastNormal = Decimal(_exponent: -127, _length: 1, _isNegative: 0, _isCompact: 1, _reserved: 0, _mantissa: (1, 0, 0, 0, 0, 0, 0, 0))
         XCTAssertEqual(leastNormal, Decimal.leastNormalMagnitude)
-        let leastNonzero = Decimal(_exponent: -127, _length: 1, _isNegative: 0, _isCompact: 1, _reserved: 0, _mantissa: (1,0,0,0,0,0,0,0))
+        let leastNonzero = Decimal(_exponent: -127, _length: 1, _isNegative: 0, _isCompact: 1, _reserved: 0, _mantissa: (1, 0, 0, 0, 0, 0, 0, 0))
         XCTAssertEqual(leastNonzero, Decimal.leastNonzeroMagnitude)
         let pi = Decimal(_exponent: -38, _length: 8, _isNegative: 0, _isCompact: 1, _reserved: 0, _mantissa: (0x6623, 0x7d57, 0x16e7, 0xad0d, 0xaf52, 0x4641, 0xdfa7, 0xec58))
-        XCTAssertEqual(pi,Decimal.pi)
-        XCTAssertEqual(10,Decimal.radix)
+        XCTAssertEqual(pi, Decimal.pi)
+        XCTAssertEqual(10, Decimal.radix)
         XCTAssertTrue(Decimal().isCanonical)
         XCTAssertFalse(Decimal().isSignalingNaN)
         XCTAssertFalse(Decimal.nan.isSignalingNaN)
         XCTAssertTrue(Decimal.nan.isNaN)
-        XCTAssertEqual(.quietNaN,Decimal.nan.floatingPointClass)
-        XCTAssertEqual(.positiveZero,Decimal().floatingPointClass)
-        XCTAssertEqual(.negativeNormal,smallest.floatingPointClass)
-        XCTAssertEqual(.positiveNormal,biggest.floatingPointClass)
+        XCTAssertEqual(.quietNaN, Decimal.nan.floatingPointClass)
+        XCTAssertEqual(.positiveZero, Decimal().floatingPointClass)
+        XCTAssertEqual(.negativeNormal, smallest.floatingPointClass)
+        XCTAssertEqual(.positiveNormal, biggest.floatingPointClass)
         XCTAssertFalse(Double.nan.isFinite)
         XCTAssertFalse(Double.nan.isInfinite)
     }
 
     func test_Description() {
-        XCTAssertEqual("0",Decimal().description)
-        XCTAssertEqual("0",Decimal(0).description)
-        XCTAssertEqual("10",Decimal(_exponent: 1, _length: 1, _isNegative: 0, _isCompact: 1, _reserved: 0, _mantissa: (1,0,0,0,0,0,0,0)).description)
-        XCTAssertEqual("10",Decimal(10).description)
-        XCTAssertEqual("123.458",Decimal(_exponent: -3, _length: 2, _isNegative: 0, _isCompact:1, _reserved: 0, _mantissa: (57922,1,0,0,0,0,0,0)).description)
-        XCTAssertEqual("123.458",Decimal(123.458).description)
-        XCTAssertEqual("123",Decimal(UInt8(123)).description)
-        XCTAssertEqual("45",Decimal(Int8(45)).description)
-        XCTAssertEqual("3.14159265358979323846264338327950288419",Decimal.pi.description)
-        XCTAssertEqual("-30000000000",Decimal(sign: .minus, exponent: 10, significand: Decimal(3)).description)
-        XCTAssertEqual("300000",Decimal(sign: .plus, exponent: 5, significand: Decimal(3)).description)
-        XCTAssertEqual("5",Decimal(signOf: Decimal(3), magnitudeOf: Decimal(5)).description)
-        XCTAssertEqual("-5",Decimal(signOf: Decimal(-3), magnitudeOf: Decimal(5)).description)
-        XCTAssertEqual("5",Decimal(signOf: Decimal(3), magnitudeOf: Decimal(-5)).description)
-        XCTAssertEqual("-5",Decimal(signOf: Decimal(-3), magnitudeOf: Decimal(-5)).description)
+        XCTAssertEqual("0", Decimal().description)
+        XCTAssertEqual("0", Decimal(0).description)
+        XCTAssertEqual("10", Decimal(_exponent: 1, _length: 1, _isNegative: 0, _isCompact: 1, _reserved: 0, _mantissa: (1, 0, 0, 0, 0, 0, 0, 0)).description)
+        XCTAssertEqual("10", Decimal(10).description)
+        XCTAssertEqual("123.458", Decimal(_exponent: -3, _length: 2, _isNegative: 0, _isCompact:1, _reserved: 0, _mantissa: (57922, 1, 0, 0, 0, 0, 0, 0)).description)
+        XCTAssertEqual("123.458", Decimal(123.458).description)
+        XCTAssertEqual("123", Decimal(UInt8(123)).description)
+        XCTAssertEqual("45", Decimal(Int8(45)).description)
+        XCTAssertEqual("3.14159265358979323846264338327950288419", Decimal.pi.description)
+        XCTAssertEqual("-30000000000", Decimal(sign: .minus, exponent: 10, significand: Decimal(3)).description)
+        XCTAssertEqual("300000", Decimal(sign: .plus, exponent: 5, significand: Decimal(3)).description)
+        XCTAssertEqual("5", Decimal(signOf: Decimal(3), magnitudeOf: Decimal(5)).description)
+        XCTAssertEqual("-5", Decimal(signOf: Decimal(-3), magnitudeOf: Decimal(5)).description)
+        XCTAssertEqual("5", Decimal(signOf: Decimal(3), magnitudeOf: Decimal(-5)).description)
+        XCTAssertEqual("-5", Decimal(signOf: Decimal(-3), magnitudeOf: Decimal(-5)).description)
     }
 
     func test_ExplicitConstruction() {
@@ -109,7 +183,7 @@
             _isNegative: 3,
             _isCompact: 4,
             _reserved: UInt32(1<<18 + 1<<17 + 1),
-            _mantissa: (6,7,8,9,10,11,12,13)
+            _mantissa: (6, 7, 8, 9, 10, 11, 12, 13)
         )
         XCTAssertEqual(0x7f, explicit._exponent)
         XCTAssertEqual(0x7f, explicit.exponent)
@@ -119,7 +193,7 @@
         XCTAssertTrue(explicit.isSignMinus)
         XCTAssertEqual(0, explicit._isCompact)
         XCTAssertEqual(UInt32(1<<17 + 1), explicit._reserved)
-        let (m0,m1,m2,m3,m4,m5,m6,m7) = explicit._mantissa
+        let (m0, m1, m2, m3, m4, m5, m6, m7) = explicit._mantissa
         XCTAssertEqual(6, m0)
         XCTAssertEqual(7, m1)
         XCTAssertEqual(8, m2)
@@ -143,7 +217,7 @@
         XCTAssertEqual(0, significand._isNegative)
         XCTAssertEqual(1, significand._isCompact)
         XCTAssertEqual(0, significand._reserved)
-        let (sm0,sm1,sm2,sm3,sm4,sm5,sm6,sm7) = significand._mantissa
+        let (sm0, sm1, sm2, sm3, sm4, sm5, sm6, sm7) = significand._mantissa
         XCTAssertEqual(6, sm0)
         XCTAssertEqual(7, sm1)
         XCTAssertEqual(8, sm2)
@@ -204,14 +278,14 @@
     }
 
     func test_Misc() {
-        XCTAssertEqual(.minus,Decimal(-5.2).sign)
-        XCTAssertEqual(.plus,Decimal(5.2).sign)
+        XCTAssertEqual(.minus, Decimal(-5.2).sign)
+        XCTAssertEqual(.plus, Decimal(5.2).sign)
         var d = Decimal(5.2)
-        XCTAssertEqual(.plus,d.sign)
+        XCTAssertEqual(.plus, d.sign)
         d.negate()
-        XCTAssertEqual(.minus,d.sign)
+        XCTAssertEqual(.minus, d.sign)
         d.negate()
-        XCTAssertEqual(.plus,d.sign)
+        XCTAssertEqual(.plus, d.sign)
         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)))
@@ -228,46 +302,226 @@
         XCTAssertFalse(Decimal.nan.isTotallyOrdered(belowOrEqualTo: Decimal(2.3)))
         XCTAssertTrue(Decimal(2) < Decimal(3))
         XCTAssertTrue(Decimal(3) > Decimal(2))
-        XCTAssertEqual(3275573729074,Decimal(1234).hashValue)
+        XCTAssertEqual(3275573729074, Decimal(1234).hashValue)
         XCTAssertEqual(Decimal(-9), Decimal(1) - Decimal(10))
-        XCTAssertEqual(Decimal(3),Decimal(2).nextUp)
-        XCTAssertEqual(Decimal(2),Decimal(3).nextDown)
-        XCTAssertEqual(Decimal(-476),Decimal(1024).distance(to: Decimal(1500)))
-        XCTAssertEqual(Decimal(68040),Decimal(386).advanced(by: Decimal(67654)))
-        XCTAssertEqual(Decimal(1.234),abs(Decimal(1.234)))
-        XCTAssertEqual(Decimal(1.234),abs(Decimal(-1.234)))
+        XCTAssertEqual(Decimal(3), Decimal(2).nextUp)
+        XCTAssertEqual(Decimal(2), Decimal(3).nextDown)
+        XCTAssertEqual(Decimal(-476), Decimal(1024).distance(to: Decimal(1500)))
+        XCTAssertEqual(Decimal(68040), Decimal(386).advanced(by: Decimal(67654)))
+        XCTAssertEqual(Decimal(1.234), abs(Decimal(1.234)))
+        XCTAssertEqual(Decimal(1.234), abs(Decimal(-1.234)))
         var a = Decimal(1234)
-        XCTAssertEqual(.noError,NSDecimalMultiplyByPowerOf10(&a,&a,1,.plain))
-        XCTAssertEqual(Decimal(12340),a)
+        XCTAssertEqual(.noError, NSDecimalMultiplyByPowerOf10(&a, &a, 1, .plain))
+        XCTAssertEqual(Decimal(12340), a)
         a = Decimal(1234)
-        XCTAssertEqual(.noError,NSDecimalMultiplyByPowerOf10(&a,&a,2,.plain))
-        XCTAssertEqual(Decimal(123400),a)
-        XCTAssertEqual(.overflow,NSDecimalMultiplyByPowerOf10(&a,&a,128,.plain))
+        XCTAssertEqual(.noError, NSDecimalMultiplyByPowerOf10(&a, &a, 2, .plain))
+        XCTAssertEqual(Decimal(123400), a)
+        XCTAssertEqual(.overflow, NSDecimalMultiplyByPowerOf10(&a, &a, 128, .plain))
         XCTAssertTrue(a.isNaN)
         a = Decimal(1234)
-        XCTAssertEqual(.noError,NSDecimalMultiplyByPowerOf10(&a,&a,-2,.plain))
-        XCTAssertEqual(Decimal(12.34),a)
-        XCTAssertEqual(.underflow,NSDecimalMultiplyByPowerOf10(&a,&a,-128,.plain))
+        XCTAssertEqual(.noError, NSDecimalMultiplyByPowerOf10(&a, &a, -2, .plain))
+        XCTAssertEqual(Decimal(12.34), a)
+        XCTAssertEqual(.underflow, NSDecimalMultiplyByPowerOf10(&a, &a, -128, .plain))
         XCTAssertTrue(a.isNaN)
         a = Decimal(1234)
-        XCTAssertEqual(.noError,NSDecimalPower(&a,&a,0,.plain))
-        XCTAssertEqual(Decimal(1),a)
+        XCTAssertEqual(.noError, NSDecimalPower(&a, &a, 0, .plain))
+        XCTAssertEqual(Decimal(1), a)
         a = Decimal(8)
-        XCTAssertEqual(.noError,NSDecimalPower(&a,&a,2,.plain))
-        XCTAssertEqual(Decimal(64),a)
+        XCTAssertEqual(.noError, NSDecimalPower(&a, &a, 2, .plain))
+        XCTAssertEqual(Decimal(64), a)
         a = Decimal(-2)
-        XCTAssertEqual(.noError,NSDecimalPower(&a,&a,3,.plain))
-        XCTAssertEqual(Decimal(-8),a)
+        XCTAssertEqual(.noError, NSDecimalPower(&a, &a, 3, .plain))
+        XCTAssertEqual(Decimal(-8), a)
         for i in -2...10 {
             for j in 0...5 {
                 var actual = Decimal(i)
-                XCTAssertEqual(.noError,NSDecimalPower(&actual,&actual,j,.plain))
-                let expected = Decimal(pow(Double(i),Double(j)))
+                XCTAssertEqual(.noError, NSDecimalPower(&actual, &actual, j, .plain))
+                let expected = Decimal(pow(Double(i), Double(j)))
                 XCTAssertEqual(expected, actual, "\(actual) == \(i)^\(j)")
             }
         }
     }
 
+    func test_MultiplicationOverflow() {
+        var multiplicand = Decimal(_exponent: 0, _length: 8, _isNegative: 0, _isCompact: 0, _reserved: 0, _mantissa: ( 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff ))
+
+        var result = Decimal()
+        var multiplier = Decimal(1)
+
+        multiplier._mantissa.0 = 2
+
+        XCTAssertEqual(.noError, NSDecimalMultiply(&result, &multiplicand, &multiplier, .plain), "2 * max mantissa")
+        XCTAssertEqual(.noError, NSDecimalMultiply(&result, &multiplier, &multiplicand, .plain), "max mantissa * 2")
+
+        multiplier._exponent = 0x7f
+        XCTAssertEqual(.overflow, NSDecimalMultiply(&result, &multiplicand, &multiplier, .plain), "2e127 * max mantissa")
+        XCTAssertEqual(.overflow, NSDecimalMultiply(&result, &multiplier, &multiplicand, .plain), "max mantissa * 2e127")
+    }
+
+    func test_NaNInput() {
+        var NaN = Decimal.nan
+        var one = Decimal(1)
+        var result = Decimal()
+
+        XCTAssertNotEqual(.noError, NSDecimalAdd(&result, &NaN, &one, .plain))
+        XCTAssertTrue(NSDecimalIsNotANumber(&result), "NaN + 1")
+        XCTAssertNotEqual(.noError, NSDecimalAdd(&result, &one, &NaN, .plain))
+        XCTAssertTrue(NSDecimalIsNotANumber(&result), "1 + NaN")
+
+        XCTAssertNotEqual(.noError, NSDecimalSubtract(&result, &NaN, &one, .plain))
+        XCTAssertTrue(NSDecimalIsNotANumber(&result), "NaN - 1")
+        XCTAssertNotEqual(.noError, NSDecimalSubtract(&result, &one, &NaN, .plain))
+        XCTAssertTrue(NSDecimalIsNotANumber(&result), "1 - NaN")
+
+        XCTAssertNotEqual(.noError, NSDecimalMultiply(&result, &NaN, &one, .plain))
+        XCTAssertTrue(NSDecimalIsNotANumber(&result), "NaN * 1")
+        XCTAssertNotEqual(.noError, NSDecimalMultiply(&result, &one, &NaN, .plain))
+        XCTAssertTrue(NSDecimalIsNotANumber(&result), "1 * NaN")
+
+        XCTAssertNotEqual(.noError, NSDecimalDivide(&result, &NaN, &one, .plain))
+        XCTAssertTrue(NSDecimalIsNotANumber(&result), "NaN / 1")
+        XCTAssertNotEqual(.noError, NSDecimalDivide(&result, &one, &NaN, .plain))
+        XCTAssertTrue(NSDecimalIsNotANumber(&result), "1 / NaN")
+
+        XCTAssertNotEqual(.noError, NSDecimalPower(&result, &NaN, 0, .plain))
+        XCTAssertTrue(NSDecimalIsNotANumber(&result), "NaN ^ 0")
+        XCTAssertNotEqual(.noError, NSDecimalPower(&result, &NaN, 4, .plain))
+        XCTAssertTrue(NSDecimalIsNotANumber(&result), "NaN ^ 4")
+        XCTAssertNotEqual(.noError, NSDecimalPower(&result, &NaN, 5, .plain))
+        XCTAssertTrue(NSDecimalIsNotANumber(&result), "NaN ^ 5")
+
+        XCTAssertNotEqual(.noError, NSDecimalMultiplyByPowerOf10(&result, &NaN, 0, .plain))
+        XCTAssertTrue(NSDecimalIsNotANumber(&result), "NaN e0")
+        XCTAssertNotEqual(.noError, NSDecimalMultiplyByPowerOf10(&result, &NaN, 4, .plain))
+        XCTAssertTrue(NSDecimalIsNotANumber(&result), "NaN e4")
+        XCTAssertNotEqual(.noError, NSDecimalMultiplyByPowerOf10(&result, &NaN, 5, .plain))
+        XCTAssertTrue(NSDecimalIsNotANumber(&result), "NaN e5")
+    }
+
+    func test_NegativeAndZeroMultiplication() {
+        var one = Decimal(1)
+        var zero = Decimal(0)
+        var negativeOne = Decimal(-1)
+
+        var result = Decimal()
+
+        XCTAssertEqual(.noError, NSDecimalMultiply(&result, &one, &one, .plain), "1 * 1")
+        XCTAssertEqual(.orderedSame, NSDecimalCompare(&one, &result), "1 * 1")
+
+        XCTAssertEqual(.noError, NSDecimalMultiply(&result, &one, &negativeOne, .plain), "1 * -1")
+        XCTAssertEqual(.orderedSame, NSDecimalCompare(&negativeOne, &result), "1 * -1")
+
+        XCTAssertEqual(.noError, NSDecimalMultiply(&result, &negativeOne, &one, .plain), "-1 * 1")
+        XCTAssertEqual(.orderedSame, NSDecimalCompare(&negativeOne, &result), "-1 * 1")
+
+        XCTAssertEqual(.noError, NSDecimalMultiply(&result, &negativeOne, &negativeOne, .plain), "-1 * -1")
+        XCTAssertEqual(.orderedSame, NSDecimalCompare(&one, &result), "-1 * -1")
+
+        XCTAssertEqual(.noError, NSDecimalMultiply(&result, &one, &zero, .plain), "1 * 0")
+        XCTAssertEqual(.orderedSame, NSDecimalCompare(&zero, &result), "1 * 0")
+        XCTAssertEqual(0, result._isNegative, "1 * 0")
+
+        XCTAssertEqual(.noError, NSDecimalMultiply(&result, &zero, &one, .plain), "0 * 1")
+        XCTAssertEqual(.orderedSame, NSDecimalCompare(&zero, &result), "0 * 1")
+        XCTAssertEqual(0, result._isNegative, "0 * 1")
+
+        XCTAssertEqual(.noError, NSDecimalMultiply(&result, &negativeOne, &zero, .plain), "-1 * 0")
+        XCTAssertEqual(.orderedSame, NSDecimalCompare(&zero, &result), "-1 * 0")
+        XCTAssertEqual(0, result._isNegative, "-1 * 0")
+
+        XCTAssertEqual(.noError, NSDecimalMultiply(&result, &zero, &negativeOne, .plain), "0 * -1")
+        XCTAssertEqual(.orderedSame, NSDecimalCompare(&zero, &result), "0 * -1")
+        XCTAssertEqual(0, result._isNegative, "0 * -1")
+    }
+
+    func test_Normalise() {
+        var one = Decimal(1)
+        var ten = Decimal(-10)
+        XCTAssertEqual(.noError, NSDecimalNormalize(&one, &ten, .plain))
+        XCTAssertEqual(Decimal(1), one)
+        XCTAssertEqual(Decimal(-10), ten)
+        XCTAssertEqual(1, one._length)
+        XCTAssertEqual(1, ten._length)
+        one = Decimal(1)
+        ten = Decimal(10)
+        XCTAssertEqual(.noError, NSDecimalNormalize(&one, &ten, .plain))
+        XCTAssertEqual(Decimal(1), one)
+        XCTAssertEqual(Decimal(10), ten)
+        XCTAssertEqual(1, one._length)
+        XCTAssertEqual(1, ten._length)
+    }
+
+    func test_NSDecimal() {
+        var nan = Decimal.nan
+        XCTAssertTrue(NSDecimalIsNotANumber(&nan))
+        var zero = Decimal()
+        XCTAssertFalse(NSDecimalIsNotANumber(&zero))
+        var three = Decimal(3)
+        var guess = Decimal()
+        NSDecimalCopy(&guess, &three)
+        XCTAssertEqual(three, guess)
+
+        var f = Decimal(_exponent: 0, _length: 2, _isNegative: 0, _isCompact: 0, _reserved: 0, _mantissa: (0x0000, 0x0001, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000))
+        let before = f.description
+        XCTAssertEqual(0, f._isCompact)
+        NSDecimalCompact(&f)
+        XCTAssertEqual(1, f._isCompact)
+        let after = f.description
+        XCTAssertEqual(before, after)
+    }
+
+    func test_PositivePowers() {
+        let six = NSDecimalNumber(integerLiteral: 6)
+
+        XCTAssertEqual(6, six.raising(toPower:1).intValue)
+        XCTAssertEqual(36, six.raising(toPower:2).intValue)
+        XCTAssertEqual(216, six.raising(toPower:3).intValue)
+        XCTAssertEqual(1296, six.raising(toPower:4).intValue)
+        XCTAssertEqual(7776, six.raising(toPower:5).intValue)
+        XCTAssertEqual(46656, six.raising(toPower:6).intValue)
+        XCTAssertEqual(279936, six.raising(toPower:7).intValue)
+        XCTAssertEqual(1679616, six.raising(toPower:8).intValue)
+        XCTAssertEqual(10077696, six.raising(toPower:9).intValue)
+
+        let negativeSix = NSDecimalNumber(integerLiteral: -6)
+
+        XCTAssertEqual(-6, negativeSix.raising(toPower:1).intValue)
+        XCTAssertEqual(36, negativeSix.raising(toPower:2).intValue)
+        XCTAssertEqual(-216, negativeSix.raising(toPower:3).intValue)
+        XCTAssertEqual(1296, negativeSix.raising(toPower:4).intValue)
+        XCTAssertEqual(-7776, negativeSix.raising(toPower:5).intValue)
+        XCTAssertEqual(46656, negativeSix.raising(toPower:6).intValue)
+        XCTAssertEqual(-279936, negativeSix.raising(toPower:7).intValue)
+        XCTAssertEqual(1679616, negativeSix.raising(toPower:8).intValue)
+        XCTAssertEqual(-10077696, negativeSix.raising(toPower:9).intValue)
+    }
+
+    func test_RepeatingDivision()  {
+        let repeatingNumerator = Decimal(16)
+        let repeatingDenominator = Decimal(9)
+        let repeating = repeatingNumerator / repeatingDenominator
+
+        let numerator = Decimal(1010)
+        var result = numerator / repeating
+
+        var expected = Decimal()
+        expected._exponent = -35;
+        expected._length = 8;
+        expected._isNegative = 0;
+        expected._isCompact = 1;
+        expected._reserved = 0;
+        expected._mantissa.0 = 51946;
+        expected._mantissa.1 = 3;
+        expected._mantissa.2 = 15549;
+        expected._mantissa.3 = 55864;
+        expected._mantissa.4 = 57984;
+        expected._mantissa.5 = 55436;
+        expected._mantissa.6 = 45186;
+        expected._mantissa.7 = 10941;
+
+        XCTAssertEqual(.orderedSame, NSDecimalCompare(&expected, &result), "568.12500000000000000000000000000248554: \(expected.description) != \(result.description)");
+    }
+
     func test_Round() {
         let testCases = [
             // expected, start, scale, round
@@ -290,48 +544,65 @@
             ( -5.5, -5.5, 1, Decimal.RoundingMode.up ),
             ( -6.5, -6.5, 1, Decimal.RoundingMode.plain ),
             ( -7.5, -7.5, 1, Decimal.RoundingMode.bankers ),
-        ]
+            ]
         for testCase in testCases {
             let (expected, start, scale, mode) = testCase
             var num = Decimal(start)
-            NSDecimalRound(&num,&num,scale,mode)
+            NSDecimalRound(&num, &num, scale, mode)
             XCTAssertEqual(Decimal(expected), num)
         }
     }
 
-    func test_Normalise() {
-        var one = Decimal(1)
-        var ten = Decimal(-10)
-        XCTAssertEqual(.noError,NSDecimalNormalize(&one,&ten,.plain))
-        XCTAssertEqual(Decimal(1),one)
-        XCTAssertEqual(Decimal(-10),ten)
-        XCTAssertEqual(1,one._length)
-        XCTAssertEqual(1,ten._length)
-        one = Decimal(1)
-        ten = Decimal(10)
-        XCTAssertEqual(.noError,NSDecimalNormalize(&one,&ten,.plain))
-        XCTAssertEqual(Decimal(1),one)
-        XCTAssertEqual(Decimal(10),ten)
-        XCTAssertEqual(1,one._length)
-        XCTAssertEqual(1,ten._length)
+    func test_SimpleMultiplication() {
+        var multiplicand = Decimal()
+        multiplicand._isNegative = 0
+        multiplicand._isCompact = 0
+        multiplicand._length = 1
+        multiplicand._exponent = 1
+
+        var multiplier = multiplicand
+        multiplier._exponent = 2
+
+        var expected = multiplicand
+        expected._isNegative = 0
+        expected._isCompact = 0
+        expected._exponent = 3
+        expected._length = 1
+
+        var result = Decimal()
+
+        for i in 1..<UInt8.max {
+            multiplicand._mantissa.0 = UInt16(i)
+
+            for j in 1..<UInt8.max {
+                multiplier._mantissa.0 = UInt16(j)
+                expected._mantissa.0 = UInt16(i) * UInt16(j)
+
+                XCTAssertEqual(.noError, NSDecimalMultiply(&result, &multiplicand, &multiplier, .plain), "\(i) * \(j)")
+                XCTAssertEqual(.orderedSame, NSDecimalCompare(&expected, &result), "\(expected._mantissa.0) == \(i) * \(j)");
+            }
+        }
     }
 
-    func test_NSDecimal() {
-        var nan = Decimal.nan
-        XCTAssertTrue(NSDecimalIsNotANumber(&nan))
-        var zero = Decimal()
-        XCTAssertFalse(NSDecimalIsNotANumber(&zero))
-        var three = Decimal(3)
-        var guess = Decimal()
-        NSDecimalCopy(&guess,&three)
-        XCTAssertEqual(three,guess)
+    func test_SmallerNumbers() {
+        var number = NSDecimalNumber(booleanLiteral:true)
+        XCTAssertTrue(number.boolValue, "Should have received true")
 
-        var f = Decimal(_exponent: 0, _length: 2, _isNegative: 0, _isCompact: 0, _reserved: 0, _mantissa: (0x0000, 0x0001, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000))
-        let before = f.description
-        XCTAssertEqual(0,f._isCompact)
-        NSDecimalCompact(&f)
-        XCTAssertEqual(1,f._isCompact)
-        let after = f.description
-        XCTAssertEqual(before,after)
+        number = NSDecimalNumber(mantissa:0, exponent:0, isNegative:false)
+        XCTAssertFalse(number.boolValue, "Should have received false")
+
+        number = NSDecimalNumber(mantissa:1, exponent:0, isNegative:false)
+        XCTAssertTrue(number.boolValue, "Should have received true")
+
+        XCTAssertEqual(100,number.objCType.pointee, "ObjC type for NSDecimalNumber is 'd'")
     }
+
+    func test_ZeroPower() {
+        let six = NSDecimalNumber(integerLiteral: 6)
+        XCTAssertEqual(1, six.raising(toPower: 0))
+
+        let negativeSix = NSDecimalNumber(integerLiteral: -6)
+        XCTAssertEqual(1, negativeSix.raising(toPower: 0))
+    }
+
 }
diff --git a/TestFoundation/TestNSKeyedArchiver.swift b/TestFoundation/TestNSKeyedArchiver.swift
index 19ba3d0..6e6b529 100644
--- a/TestFoundation/TestNSKeyedArchiver.swift
+++ b/TestFoundation/TestNSKeyedArchiver.swift
@@ -16,7 +16,7 @@
     import SwiftXCTest
 #endif
 
-public class UserClass : NSObject, NSSecureCoding {
+public class NSUserClass : NSObject, NSSecureCoding {
     var ivar : Int
     
     public class var supportsSecureCoding: Bool {
@@ -37,12 +37,12 @@
     
     public override var description: String {
         get {
-            return "UserClass \(ivar)"
+            return "NSUserClass \(ivar)"
         }
     }
     
     public override func isEqual(_ object: Any?) -> Bool {
-        if let custom = object as? UserClass {
+        if let custom = object as? NSUserClass {
             return self.ivar == custom.ivar
         } else {
             return false
@@ -50,6 +50,40 @@
     }
 }
 
+public class UserClass : CustomStringConvertible, Equatable, Hashable, NSSecureCoding {
+    var ivar : Int
+    
+    public class var supportsSecureCoding: Bool {
+        return true
+    }
+    
+    public func encode(with aCoder : NSCoder) {
+        aCoder.encode(ivar, forKey:"$ivar") // also test escaping
+    }
+    
+    init(_ value: Int) {
+        self.ivar = value
+    }
+    
+    public required init?(coder aDecoder: NSCoder) {
+        self.ivar = aDecoder.decodeInteger(forKey: "$ivar")
+    }
+    
+    public var description: String {
+        get {
+            return "UserClass \(ivar)"
+        }
+    }
+    
+    public static func ==(lhs: UserClass, rhs: UserClass) -> Bool {
+        return lhs.ivar == rhs.ivar
+    }
+    
+    public var hashValue: Int {
+        return ivar
+    }
+}
+
 class TestNSKeyedArchiver : XCTestCase {
     static var allTests: [(String, (TestNSKeyedArchiver) -> () throws -> Void)] {
         return [
@@ -62,6 +96,7 @@
             ("test_archive_string", test_archive_string),
             ("test_archive_mutable_array", test_archive_mutable_array),
             ("test_archive_mutable_dictionary", test_archive_mutable_dictionary),
+            ("test_archive_ns_user_class", test_archive_ns_user_class),
             ("test_archive_nspoint", test_archive_nspoint),
             ("test_archive_nsrange", test_archive_nsrange),
             ("test_archive_nsrect", test_archive_nsrect),
@@ -69,7 +104,8 @@
             ("test_archive_set", test_archive_set),
             ("test_archive_url", test_archive_url),
             ("test_archive_user_class", test_archive_user_class),
-            ("test_archive_uuid", test_archive_uuid),
+            ("test_archive_uuid_bvref", test_archive_uuid_byref),
+            ("test_archive_uuid_byvalue", test_archive_uuid_byvalue),
         ]
     }
 
@@ -85,7 +121,7 @@
         XCTAssertTrue(decode(unarchiver))
     }
     
-    private func test_archive(_ object: NSObject, classes: [AnyClass], allowsSecureCoding: Bool = true, outputFormat: PropertyListSerialization.PropertyListFormat) {
+    private func test_archive(_ object: Any, classes: [AnyClass], allowsSecureCoding: Bool = true, outputFormat: PropertyListSerialization.PropertyListFormat) {
         test_archive({ archiver -> Bool in
                 archiver.requiresSecureCoding = allowsSecureCoding
                 archiver.outputFormat = outputFormat
@@ -97,12 +133,12 @@
                 unarchiver.requiresSecureCoding = allowsSecureCoding
                 
                 do {
-                    let rootObj = try unarchiver.decodeTopLevelObject(of: classes, forKey: NSKeyedArchiveRootObjectKey)
-                    guard let root = rootObj as? NSObject else {
+                    guard let rootObj = try unarchiver.decodeTopLevelObject(of: classes, forKey: NSKeyedArchiveRootObjectKey) else {
                         XCTFail("Unable to decode data")
                         return false
                     }
-                    XCTAssertEqual(object, root, "unarchived object \(root) does not match \(object)")
+                
+                    XCTAssertEqual(object as? AnyHashable, rootObj as? AnyHashable, "unarchived object \(rootObj) does not match \(object)")
                 } catch {
                     XCTFail("Error thrown: \(error)")
                 }
@@ -110,13 +146,13 @@
         })
     }
     
-    private func test_archive(_ object: NSObject, classes: [AnyClass], allowsSecureCoding: Bool = true) {
+    private func test_archive(_ object: Any, classes: [AnyClass], allowsSecureCoding: Bool = true) {
         // test both XML and binary encodings
         test_archive(object, classes: classes, allowsSecureCoding: allowsSecureCoding, outputFormat: PropertyListSerialization.PropertyListFormat.xml)
         test_archive(object, classes: classes, allowsSecureCoding: allowsSecureCoding, outputFormat: PropertyListSerialization.PropertyListFormat.binary)
     }
     
-    private func test_archive(_ object: NSObject, allowsSecureCoding: Bool = true) {
+    private func test_archive(_ object: AnyObject, allowsSecureCoding: Bool = true) {
         return test_archive(object, classes: [type(of: object)], allowsSecureCoding: allowsSecureCoding)
     }
     
@@ -252,8 +288,18 @@
         test_archive(userClass)
     }
     
-    func test_archive_uuid() {
+    func test_archive_ns_user_class() {
+        let nsUserClass = NSUserClass(5678)
+        test_archive(nsUserClass)
+    }
+    
+    func test_archive_uuid_byref() {
         let uuid = NSUUID()
         test_archive(uuid)
     }
+    
+    func test_archive_uuid_byvalue() {
+        let uuid = UUID()
+        return test_archive(uuid, classes: [NSUUID.self])
+    }
 }
diff --git a/TestFoundation/TestNSRange.swift b/TestFoundation/TestNSRange.swift
index 5ce2ae4..927e989 100644
--- a/TestFoundation/TestNSRange.swift
+++ b/TestFoundation/TestNSRange.swift
@@ -23,7 +23,13 @@
         return [
             // currently disabled due to pending requirements for NSString
             // ("test_NSRangeFromString", test_NSRangeFromString ),
-            ("test_NSRangeBridging", test_NSRangeBridging)
+            ("test_NSRangeBridging", test_NSRangeBridging),
+            ("test_NSMaxRange", test_NSMaxRange),
+            ("test_NSLocationInRange", test_NSLocationInRange),
+            ("test_NSEqualRanges", test_NSEqualRanges),
+            ("test_NSUnionRange", test_NSUnionRange),
+            ("test_NSIntersectionRange", test_NSIntersectionRange),
+            ("test_NSStringFromRange", test_NSStringFromRange),
         ]
     }
     
@@ -66,4 +72,69 @@
         let swiftRange2 = range.toRange()
         XCTAssertEqual(swiftRange, swiftRange2)
     }
+
+    func test_NSMaxRange() {
+        let ranges = [(NSMakeRange(0, 3), 3),
+                      (NSMakeRange(7, 8), 15),
+                      (NSMakeRange(56, 1), 57)]
+        for (range, result) in ranges {
+            XCTAssertEqual(NSMaxRange(range), result)
+        }
+    }
+
+    func test_NSLocationInRange() {
+        let ranges = [(3, NSMakeRange(0, 5), true),
+                      (10, NSMakeRange(2, 9), true),
+                      (7, NSMakeRange(2, 5), false),
+                      (5, NSMakeRange(5, 1), true)];
+        for (location, range, result) in ranges {
+            XCTAssertEqual(NSLocationInRange(location, range), result);
+        }
+    }
+
+    func test_NSEqualRanges() {
+        let ranges = [(NSMakeRange(0, 3), NSMakeRange(0, 3), true),
+                      (NSMakeRange(0, 4), NSMakeRange(0, 8), false),
+                      (NSMakeRange(3, 6), NSMakeRange(3, 10), false),
+                      (NSMakeRange(0, 5), NSMakeRange(7, 8), false)]
+        for (first, second, result) in ranges {
+            XCTAssertEqual(NSEqualRanges(first, second), result)
+        }
+    }
+
+    
+    func test_NSUnionRange() {
+        let ranges = [(NSMakeRange(0, 5), NSMakeRange(3, 8), NSMakeRange(0, 11)),
+                      (NSMakeRange(6, 10), NSMakeRange(3, 8), NSMakeRange(3, 13)),
+                      (NSMakeRange(3, 8), NSMakeRange(6, 10), NSMakeRange(3, 13)),
+                      (NSMakeRange(0, 5), NSMakeRange(7, 8), NSMakeRange(0, 15)),
+                      (NSMakeRange(0, 3), NSMakeRange(1, 2), NSMakeRange(0, 3))]
+        for (first, second, result) in ranges {
+            XCTAssert(NSEqualRanges(NSUnionRange(first, second), result))
+        }
+    }
+
+    func test_NSIntersectionRange() {
+        let ranges = [(NSMakeRange(0, 5), NSMakeRange(3, 8), NSMakeRange(3, 2)),
+                      (NSMakeRange(6, 10), NSMakeRange(3, 8), NSMakeRange(6, 5)),
+                      (NSMakeRange(3, 8), NSMakeRange(6, 10), NSMakeRange(6, 5)),
+                      (NSMakeRange(0, 5), NSMakeRange(7, 8), NSMakeRange(0, 0)),
+                      (NSMakeRange(0, 3), NSMakeRange(1, 2), NSMakeRange(1, 2))]
+        for (first, second, result) in ranges {
+            XCTAssert(NSEqualRanges(NSIntersectionRange(first, second), result))
+        }
+    }
+
+    func test_NSStringFromRange() {
+        let ranges = ["{0, 0}": NSMakeRange(0, 0),
+                      "{6, 4}": NSMakeRange(6, 4),
+                      "{0, 10}": NSMakeRange(0, 10),
+                      "{10, 200}": NSMakeRange(10, 200),
+                      "{100, 10}": NSMakeRange(100, 10),
+                      "{1000, 100000}": NSMakeRange(1000, 100_000)];
+
+        for (string, range) in ranges {
+            XCTAssertEqual(NSStringFromRange(range), string)
+        }
+    }
 }
diff --git a/TestFoundation/TestNSString.swift b/TestFoundation/TestNSString.swift
index 1767982..ebb8fab 100644
--- a/TestFoundation/TestNSString.swift
+++ b/TestFoundation/TestNSString.swift
@@ -81,7 +81,11 @@
             ("test_resolvingSymlinksInPath", test_resolvingSymlinksInPath),
             ("test_expandingTildeInPath", test_expandingTildeInPath),
             ("test_standardizingPath", test_standardizingPath),
-            ("test_removingPercentEncoding", test_removingPercentEncoding),
+            ("test_addingPercentEncoding", test_addingPercentEncoding),
+            ("test_removingPercentEncodingInLatin", test_removingPercentEncodingInLatin),
+            ("test_removingPercentEncodingInNonLatin", test_removingPercentEncodingInNonLatin),
+            ("test_removingPersentEncodingWithoutEncoding", test_removingPersentEncodingWithoutEncoding),
+            ("test_addingPercentEncodingAndBack", test_addingPercentEncodingAndBack),
             ("test_stringByAppendingPathExtension", test_stringByAppendingPathExtension),
             ("test_deletingPathExtension", test_deletingPathExtension),
             ("test_ExternalRepresentation", test_ExternalRepresentation),
@@ -602,6 +606,9 @@
         let characterSet = CharacterSet.whitespaces
         let string: NSString = " abc   "
         XCTAssertEqual(string.trimmingCharacters(in: characterSet), "abc")
+        
+        let emojiString: NSString = " \u{1F62C}  "
+        XCTAssertEqual(emojiString.trimmingCharacters(in: characterSet), "\u{1F62C}")
     }
     
     func test_initializeWithFormat() {
@@ -864,13 +871,66 @@
         }
     }
 
-    func test_removingPercentEncoding() {
+    func test_addingPercentEncoding() {
+        let s1 = "a b".addingPercentEncoding(withAllowedCharacters: .alphanumerics)
+        XCTAssertEqual(s1, "a%20b")
+        
+        let s2 = "\u{0434}\u{043E}\u{043C}".addingPercentEncoding(withAllowedCharacters: .alphanumerics)
+        XCTAssertEqual(s2, "%D0%B4%D0%BE%D0%BC")
+    }
+    
+    func test_removingPercentEncodingInLatin() {
         let s1 = "a%20b".removingPercentEncoding
         XCTAssertEqual(s1, "a b")
         let s2 = "a%1 b".removingPercentEncoding
         XCTAssertNil(s2, "returns nil for a string with an invalid percent encoding")
     }
     
+    func test_removingPercentEncodingInNonLatin() {
+        let s1 = "\u{043C}\u{043E}\u{0439}%20\u{0434}\u{043E}\u{043C}".removingPercentEncoding
+        XCTAssertEqual(s1, "\u{043C}\u{043E}\u{0439} \u{0434}\u{043E}\u{043C}")
+        
+        let s2 = "%D0%B4%D0%BE%D0%BC".removingPercentEncoding
+        XCTAssertEqual(s2, "\u{0434}\u{043E}\u{043C}")
+        
+        let s3 = "\u{00E0}a%1 b".removingPercentEncoding
+        XCTAssertNil(s3, "returns nil for a string with an invalid percent encoding")
+    }
+    
+    func test_removingPersentEncodingWithoutEncoding() {
+        let cyrillicString = "\u{0434}\u{043E}\u{043C}"
+        let cyrillicEscapedString = cyrillicString.removingPercentEncoding
+        XCTAssertEqual(cyrillicString, cyrillicEscapedString)
+        
+        let chineseString = "\u{623F}\u{5B50}"
+        let chineseEscapedString = chineseString.removingPercentEncoding
+        XCTAssertEqual(chineseString, chineseEscapedString)
+        
+        let arabicString = "\u{0645}\u{0646}\u{0632}\u{0644}"
+        let arabicEscapedString = arabicString.removingPercentEncoding
+        XCTAssertEqual(arabicString, arabicEscapedString)
+        
+        let randomString = "\u{00E0}\u{00E6}"
+        let randomEscapedString = randomString.removingPercentEncoding
+        XCTAssertEqual(randomString, randomEscapedString)
+        
+        let latinString = "home"
+        let latinEscapedString = latinString.removingPercentEncoding
+        XCTAssertEqual(latinString, latinEscapedString)
+    }
+    
+    func test_addingPercentEncodingAndBack() {
+        let latingString = "a b"
+        let escapedLatingString = latingString.addingPercentEncoding(withAllowedCharacters: .alphanumerics)
+        let returnedLatingString = escapedLatingString?.removingPercentEncoding
+        XCTAssertEqual(returnedLatingString, latingString)
+        
+        let cyrillicString = "\u{0434}\u{043E}\u{043C}"
+        let escapedCyrillicString = cyrillicString.addingPercentEncoding(withAllowedCharacters: .alphanumerics)
+        let returnedCyrillicString = escapedCyrillicString?.removingPercentEncoding
+        XCTAssertEqual(returnedCyrillicString, cyrillicString)
+    }
+    
     func test_stringByAppendingPathExtension() {
         let values = [
             NSString(string: "/tmp/scratch.old") : "/tmp/scratch.old.tiff",
diff --git a/TestFoundation/TestNSURLCredential.swift b/TestFoundation/TestNSURLCredential.swift
index 542c857..037b114 100644
--- a/TestFoundation/TestNSURLCredential.swift
+++ b/TestFoundation/TestNSURLCredential.swift
@@ -21,7 +21,8 @@
     static var allTests: [(String, (TestNSURLCredential) -> () throws -> Void)] {
         return [
                    ("test_construction", test_construction),
-                   ("test_copy", test_copy)
+                   ("test_copy", test_copy),
+                   ("test_NSCoding", test_NSCoding)
         ]
     }
     
@@ -39,4 +40,10 @@
         let copy = credential.copy() as! URLCredential
         XCTAssertTrue(copy.isEqual(credential))
     }
+    
+    func test_NSCoding() {
+        let credentialA = URLCredential(user: "swiftUser", password: "swiftPassword", persistence: .forSession)
+        let credentialB = NSKeyedUnarchiver.unarchiveObject(with: NSKeyedArchiver.archivedData(withRootObject: credentialA)) as! URLCredential
+        XCTAssertEqual(credentialA, credentialB, "Archived then unarchived url credential must be equal.")
+    }
 }
diff --git a/TestFoundation/TestNotification.swift b/TestFoundation/TestNotification.swift
new file mode 100644
index 0000000..9c1bd38
--- /dev/null
+++ b/TestFoundation/TestNotification.swift
@@ -0,0 +1,56 @@
+// This source file is part of the Swift.org open source project
+//
+// Copyright (c) 2014 - 2016 Apple Inc. and the Swift project authors
+// Licensed under Apache License v2.0 with Runtime Library Exception
+//
+// See http://swift.org/LICENSE.txt for license information
+// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
+//
+
+
+
+#if DEPLOYMENT_RUNTIME_OBJC || os(Linux)
+    import Foundation
+    import XCTest
+#else
+    import SwiftFoundation
+    import SwiftXCTest
+#endif
+
+
+
+class TestNotification : XCTestCase {
+
+    static var allTests: [(String, (TestNotification) -> () throws -> Void)] {
+        return [
+            ("test_customReflection", test_customReflection),
+        ]
+    }
+
+    func test_customReflection() {
+        let someName = "somenotifname"
+        let targetObject = NSObject()
+        let userInfo = ["hello": "world", "indexThis": 350] as [AnyHashable: Any]
+        let notif = Notification(name: Notification.Name(rawValue: someName), object: targetObject, userInfo: userInfo)
+        let mirror = notif.customMirror
+
+        XCTAssertEqual(mirror.displayStyle, .class)
+        XCTAssertNil(mirror.superclassMirror)
+
+        var children = Array(mirror.children).makeIterator()
+        let firstChild = children.next()
+        let secondChild = children.next()
+        let thirdChild = children.next()
+        XCTAssertEqual(firstChild?.label, "name")
+        XCTAssertEqual(firstChild?.value as? String, someName)
+
+        XCTAssertEqual(secondChild?.label, "object")
+        XCTAssertEqual(secondChild?.value as? NSObject, targetObject)
+
+        XCTAssertEqual(thirdChild?.label, "userInfo")
+        XCTAssertEqual((thirdChild?.value as? [AnyHashable: Any])?["hello"] as? String, "world")
+        XCTAssertEqual((thirdChild?.value as? [AnyHashable: Any])?["indexThis"] as? Int, 350)
+
+    }
+
+}
diff --git a/TestFoundation/main.swift b/TestFoundation/main.swift
index 517d740..732bf17 100644
--- a/TestFoundation/main.swift
+++ b/TestFoundation/main.swift
@@ -87,4 +87,5 @@
     testCase(TestProgressFraction.allTests),
     testCase(TestProgress.allTests),
     testCase(TestObjCRuntime.allTests),
+    testCase(TestNotification.allTests),
 ])