Skip to content

Codable conformance to some Foundation types #1108

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 13 commits into from
Jul 18, 2017
Merged
6 changes: 4 additions & 2 deletions Foundation.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -353,6 +353,7 @@
D51239DF1CD9DA0800D433EE /* CFSocket.c in Sources */ = {isa = PBXBuildFile; fileRef = 5B5D88E01BBC9B0300234F36 /* CFSocket.c */; };
D512D17C1CD883F00032E6A5 /* TestFileHandle.swift in Sources */ = {isa = PBXBuildFile; fileRef = D512D17B1CD883F00032E6A5 /* TestFileHandle.swift */; };
D5C40F331CDA1D460005690C /* TestNSOperationQueue.swift in Sources */ = {isa = PBXBuildFile; fileRef = D5C40F321CDA1D460005690C /* TestNSOperationQueue.swift */; };
DCA8120B1F046D13000D0C86 /* TestCodable.swift in Sources */ = {isa = PBXBuildFile; fileRef = DCA8120A1F046D13000D0C86 /* TestCodable.swift */; };
E1A03F361C4828650023AF4D /* PropertyList-1.0.dtd in Resources */ = {isa = PBXBuildFile; fileRef = E1A03F351C4828650023AF4D /* PropertyList-1.0.dtd */; };
E1A03F381C482C730023AF4D /* NSXMLDTDTestData.xml in Resources */ = {isa = PBXBuildFile; fileRef = E1A03F371C482C730023AF4D /* NSXMLDTDTestData.xml */; };
E1A3726F1C31EBFB0023AF4D /* NSXMLDocumentTestData.xml in Resources */ = {isa = PBXBuildFile; fileRef = E1A3726E1C31EBFB0023AF4D /* NSXMLDocumentTestData.xml */; };
Expand Down Expand Up @@ -820,6 +821,7 @@
D512D17B1CD883F00032E6A5 /* TestFileHandle.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TestFileHandle.swift; sourceTree = "<group>"; };
D5C40F321CDA1D460005690C /* TestNSOperationQueue.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TestNSOperationQueue.swift; sourceTree = "<group>"; };
D834F9931C31C4060023812A /* TestNSOrderedSet.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TestNSOrderedSet.swift; sourceTree = "<group>"; };
DCA8120A1F046D13000D0C86 /* TestCodable.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TestCodable.swift; sourceTree = "<group>"; };
DCDBB8321C1768AC00313299 /* TestNSData.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TestNSData.swift; sourceTree = "<group>"; };
E1A03F351C4828650023AF4D /* PropertyList-1.0.dtd */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xml; path = "PropertyList-1.0.dtd"; sourceTree = "<group>"; };
E1A03F371C482C730023AF4D /* NSXMLDTDTestData.xml */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xml; path = NSXMLDTDTestData.xml; sourceTree = "<group>"; };
Expand Down Expand Up @@ -1421,8 +1423,7 @@
A058C2011E529CF100B07AA1 /* TestMassFormatter.swift */,
BF8E65301DC3B3CB005AB5C3 /* TestNotification.swift */,
3EA9D66F1EF0532D00B362D6 /* TestJSONEncoder.swift */,
159884911DCC877700E3314C /* TestNSHTTPCookieStorage.swift */,
D4FE895A1D703D1100DA7986 /* TestURLRequest.swift */,
DCA8120A1F046D13000D0C86 /* TestCodable.swift */,
C93559281C12C49F009FD6A9 /* TestNSAffineTransform.swift */,
EA66F63C1BF1619600136161 /* TestNSArray.swift */,
294E3C1C1CC5E19300E4F44C /* TestNSAttributedString.swift */,
Expand Down Expand Up @@ -2426,6 +2427,7 @@
5B13B3271C582D4C00651CE2 /* TestNSArray.swift in Sources */,
5B13B3461C582D4C00651CE2 /* TestProcess.swift in Sources */,
555683BD1C1250E70041D4C6 /* TestNSUserDefaults.swift in Sources */,
DCA8120B1F046D13000D0C86 /* TestCodable.swift in Sources */,
7900433B1CACD33E00ECCBF1 /* TestNSCompoundPredicate.swift in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
Expand Down
32 changes: 32 additions & 0 deletions Foundation/CGFloat.swift
Original file line number Diff line number Diff line change
Expand Up @@ -949,3 +949,35 @@ extension CGFloat : _CVarArgPassedAsDouble, _CVarArgAligned {
return native._cVarArgAlignment
}
}

extension CGFloat : Codable {
@_transparent
public init(from decoder: Decoder) throws {
let container = try decoder.singleValueContainer()
do {
self.native = try container.decode(NativeType.self)
} catch DecodingError.typeMismatch(let type, let context) {
// We may have encoded as a different type on a different platform. A
// strict fixed-format decoder may disallow a conversion, so let's try the
// other type.
do {
if NativeType.self == Float.self {
self.native = NativeType(try container.decode(Double.self))
} else {
self.native = NativeType(try container.decode(Float.self))
}
} catch {
// Failed to decode as the other type, too. This is neither a Float nor
// a Double. Throw the old error; we don't want to clobber the original
// info.
throw DecodingError.typeMismatch(type, context)
}
}
}

@_transparent
public func encode(to encoder: Encoder) throws {
var container = encoder.singleValueContainer()
try container.encode(self.native)
}
}
32 changes: 16 additions & 16 deletions Foundation/CharacterSet.swift
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
//===----------------------------------------------------------------------===//
//===----------------------------------------------------------------------===//
//
// This source file is part of the Swift.org open source project
//
Expand All @@ -13,7 +13,7 @@
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))
}
Expand Down Expand Up @@ -57,9 +57,9 @@ internal final class _SwiftNSCharacterSet : NSCharacterSet, _SwiftNativeFoundati
deinit {
releaseWrappedObject()
}


override func copy(with zone: NSZone? = nil) -> Any {
override func copy(with zone: NSZone? = nil) -> Any {
return _mapUnmanaged { $0.copy(with: zone) }
}

Expand All @@ -74,23 +74,23 @@ internal final class _SwiftNSCharacterSet : NSCharacterSet, _SwiftNativeFoundati
override var bitmapRepresentation: Data {
return _mapUnmanaged { $0.bitmapRepresentation }
}

override var inverted : CharacterSet {
return _mapUnmanaged { $0.inverted }
}

override func hasMemberInPlane(_ thePlane: UInt8) -> Bool {
return _mapUnmanaged {$0.hasMemberInPlane(thePlane) }
}

override func characterIsMember(_ member: unichar) -> Bool {
return _mapUnmanaged { $0.characterIsMember(member) }
}

override func longCharacterIsMember(_ member: UInt32) -> Bool {
return _mapUnmanaged { $0.longCharacterIsMember(member) }
}

override func isSuperset(of other: CharacterSet) -> Bool {
return _mapUnmanaged { $0.isSuperset(of: other) }
}
Expand Down Expand Up @@ -367,7 +367,7 @@ public struct CharacterSet : ReferenceConvertible, Equatable, Hashable, SetAlgeb
// -----
// MARK: -
// MARK: SetAlgebraType

/// Insert a `UnicodeScalar` representation of a character into the `CharacterSet`.
///
/// `UnicodeScalar` values are available on `Swift.String.UnicodeScalarView`.
Expand Down Expand Up @@ -441,17 +441,17 @@ public struct CharacterSet : ReferenceConvertible, Equatable, Hashable, SetAlgeb
$0.formIntersection(with: other)
}
}

/// Returns a `CharacterSet` created by removing elements in `other` from `self`.
public func subtracting(_ other: CharacterSet) -> CharacterSet {
return intersection(other.inverted)
}

/// Sets the value to a `CharacterSet` created by removing elements in `other` from `self`.
public mutating func subtract(_ other: CharacterSet) {
self = subtracting(other)
}

/// Returns an exclusive or of the `CharacterSet` with another `CharacterSet`.
public func symmetricDifference(_ other: CharacterSet) -> CharacterSet {
return union(other).subtracting(intersection(other))
Expand All @@ -466,7 +466,7 @@ public struct CharacterSet : ReferenceConvertible, Equatable, Hashable, SetAlgeb
public func isSuperset(of other: CharacterSet) -> Bool {
return _mapUnmanaged { $0.isSuperset(of: other) }
}

/// Returns true if the two `CharacterSet`s are equal.
public static func ==(lhs : CharacterSet, rhs: CharacterSet) -> Bool {
return lhs._wrapped.isEqual(rhs._bridgeToObjectiveC()) // TODO: mlehew - as NSCharacterSet
Expand All @@ -475,7 +475,7 @@ public struct CharacterSet : ReferenceConvertible, Equatable, Hashable, SetAlgeb


// MARK: Objective-C Bridging
extension CharacterSet : _ObjectTypeBridgeable {
extension CharacterSet : _ObjectTypeBridgeable {
public static func _isBridgedToObjectiveC() -> Bool {
return true
}
Expand Down
1 change: 0 additions & 1 deletion Foundation/IndexPath.swift
Original file line number Diff line number Diff line change
Expand Up @@ -851,4 +851,3 @@ extension IndexPath : Codable {
}
}
}

17 changes: 17 additions & 0 deletions Foundation/Locale.swift
Original file line number Diff line number Diff line change
Expand Up @@ -466,3 +466,20 @@ extension Locale : _ObjectTypeBridgeable {
return result!
}
}

extension Locale : Codable {
private enum CodingKeys : Int, CodingKey {
case identifier
}

public init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: CodingKeys.self)
let identifier = try container.decode(String.self, forKey: .identifier)
self.init(identifier: identifier)
}

public func encode(to encoder: Encoder) throws {
var container = encoder.container(keyedBy: CodingKeys.self)
try container.encode(self.identifier, forKey: .identifier)
}
}
22 changes: 22 additions & 0 deletions Foundation/NSAffineTransform.swift
Original file line number Diff line number Diff line change
Expand Up @@ -455,3 +455,25 @@ extension NSAffineTransform : _StructTypeBridgeable {
return AffineTransform._unconditionallyBridgeFromObjectiveC(self)
}
}

extension AffineTransform : Codable {
public init(from decoder: Decoder) throws {
var container = try decoder.unkeyedContainer()
m11 = try container.decode(CGFloat.self)
m12 = try container.decode(CGFloat.self)
m21 = try container.decode(CGFloat.self)
m22 = try container.decode(CGFloat.self)
tX = try container.decode(CGFloat.self)
tY = try container.decode(CGFloat.self)
}

public func encode(to encoder: Encoder) throws {
var container = encoder.unkeyedContainer()
try container.encode(self.m11)
try container.encode(self.m12)
try container.encode(self.m21)
try container.encode(self.m22)
try container.encode(self.tX)
try container.encode(self.tY)
}
}
55 changes: 55 additions & 0 deletions Foundation/NSDecimal.swift
Original file line number Diff line number Diff line change
Expand Up @@ -2087,3 +2087,58 @@ extension Scanner {
return result
}
}

extension Decimal : Codable {
private enum CodingKeys : Int, CodingKey {
case exponent
case length
case isNegative
case isCompact
case mantissa
}

public init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: CodingKeys.self)
let exponent = try container.decode(CInt.self, forKey: .exponent)
let length = try container.decode(CUnsignedInt.self, forKey: .length)
let isNegative = try container.decode(Bool.self, forKey: .isNegative)
let isCompact = try container.decode(Bool.self, forKey: .isCompact)

var mantissaContainer = try container.nestedUnkeyedContainer(forKey: .mantissa)
var mantissa: (CUnsignedShort, CUnsignedShort, CUnsignedShort, CUnsignedShort,
CUnsignedShort, CUnsignedShort, CUnsignedShort, CUnsignedShort) = (0,0,0,0,0,0,0,0)
mantissa.0 = try mantissaContainer.decode(CUnsignedShort.self)
mantissa.1 = try mantissaContainer.decode(CUnsignedShort.self)
mantissa.2 = try mantissaContainer.decode(CUnsignedShort.self)
mantissa.3 = try mantissaContainer.decode(CUnsignedShort.self)
mantissa.4 = try mantissaContainer.decode(CUnsignedShort.self)
mantissa.5 = try mantissaContainer.decode(CUnsignedShort.self)
mantissa.6 = try mantissaContainer.decode(CUnsignedShort.self)
mantissa.7 = try mantissaContainer.decode(CUnsignedShort.self)

self.init(_exponent: exponent,
_length: length,
_isNegative: CUnsignedInt(isNegative ? 1 : 0),
_isCompact: CUnsignedInt(isCompact ? 1 : 0),
_reserved: 0,
_mantissa: mantissa)
}

public func encode(to encoder: Encoder) throws {
var container = encoder.container(keyedBy: CodingKeys.self)
try container.encode(_exponent, forKey: .exponent)
try container.encode(_length, forKey: .length)
try container.encode(_isNegative == 0 ? false : true, forKey: .isNegative)
try container.encode(_isCompact == 0 ? false : true, forKey: .isCompact)

var mantissaContainer = container.nestedUnkeyedContainer(forKey: .mantissa)
try mantissaContainer.encode(_mantissa.0)
try mantissaContainer.encode(_mantissa.1)
try mantissaContainer.encode(_mantissa.2)
try mantissaContainer.encode(_mantissa.3)
try mantissaContainer.encode(_mantissa.4)
try mantissaContainer.encode(_mantissa.5)
try mantissaContainer.encode(_mantissa.6)
try mantissaContainer.encode(_mantissa.7)
}
}
33 changes: 33 additions & 0 deletions Foundation/PersonNameComponents.swift
Original file line number Diff line number Diff line change
Expand Up @@ -137,3 +137,36 @@ extension NSPersonNameComponents : _HasCustomAnyHashableRepresentation {
return AnyHashable(self._bridgeToSwift())
}
}

extension PersonNameComponents : Codable {
private enum CodingKeys : Int, CodingKey {
case namePrefix
case givenName
case middleName
case familyName
case nameSuffix
case nickname
}

public init(from decoder: Decoder) throws {
self.init()

let container = try decoder.container(keyedBy: CodingKeys.self)
self.namePrefix = try container.decodeIfPresent(String.self, forKey: .namePrefix)
self.givenName = try container.decodeIfPresent(String.self, forKey: .givenName)
self.middleName = try container.decodeIfPresent(String.self, forKey: .middleName)
self.familyName = try container.decodeIfPresent(String.self, forKey: .familyName)
self.nameSuffix = try container.decodeIfPresent(String.self, forKey: .nameSuffix)
self.nickname = try container.decodeIfPresent(String.self, forKey: .nickname)
}

public func encode(to encoder: Encoder) throws {
var container = encoder.container(keyedBy: CodingKeys.self)
if let np = self.namePrefix { try container.encode(np, forKey: .namePrefix) }
if let gn = self.givenName { try container.encode(gn, forKey: .givenName) }
if let mn = self.middleName { try container.encode(mn, forKey: .middleName) }
if let fn = self.familyName { try container.encode(fn, forKey: .familyName) }
if let ns = self.nameSuffix { try container.encode(ns, forKey: .nameSuffix) }
if let nn = self.nickname { try container.encode(nn, forKey: .nickname) }
}
}
18 changes: 18 additions & 0 deletions Foundation/UUID.swift
Original file line number Diff line number Diff line change
Expand Up @@ -163,3 +163,21 @@ extension NSUUID : _HasCustomAnyHashableRepresentation {
}
}

extension UUID : Codable {
public init(from decoder: Decoder) throws {
let container = try decoder.singleValueContainer()
let uuidString = try container.decode(String.self)

guard let uuid = UUID(uuidString: uuidString) else {
throw DecodingError.dataCorrupted(DecodingError.Context(codingPath: decoder.codingPath,
debugDescription: "Attempted to decode UUID from invalid UUID string."))
}

self = uuid
}

public func encode(to encoder: Encoder) throws {
var container = encoder.singleValueContainer()
try container.encode(self.uuidString)
}
}
Loading