Merge remote-tracking branch 'origin/master' into swift-4.0-branch
diff --git a/Foundation/NSGeometry.swift b/Foundation/NSGeometry.swift
index 454014a..1a69a60 100644
--- a/Foundation/NSGeometry.swift
+++ b/Foundation/NSGeometry.swift
@@ -76,6 +76,21 @@
     }
 }
 
+extension CGPoint : Codable {
+    public init(from decoder: Decoder) throws {
+        var container = try decoder.unkeyedContainer()
+        let x = try container.decode(CGFloat.self)
+        let y = try container.decode(CGFloat.self)
+        self.init(x: x, y: y)
+    }
+    
+    public func encode(to encoder: Encoder) throws {
+        var container = encoder.unkeyedContainer()
+        try container.encode(x)
+        try container.encode(y)
+    }
+}
+
 public struct CGSize {
     public var width: CGFloat
     public var height: CGFloat
@@ -139,6 +154,21 @@
     }
 }
 
+extension CGSize : Codable {
+    public init(from decoder: Decoder) throws {
+        var container = try decoder.unkeyedContainer()
+        let width = try container.decode(CGFloat.self)
+        let height = try container.decode(CGFloat.self)
+        self.init(width: width, height: height)
+    }
+    
+    public func encode(to encoder: Encoder) throws {
+        var container = encoder.unkeyedContainer()
+        try container.encode(width)
+        try container.encode(height)
+    }
+}
+
 public struct CGRect {
     public var origin: CGPoint
     public var size: CGSize
@@ -157,6 +187,21 @@
     }
 }
 
+extension CGRect : Codable {
+    public init(from decoder: Decoder) throws {
+        var container = try decoder.unkeyedContainer()
+        let origin = try container.decode(CGPoint.self)
+        let size = try container.decode(CGSize.self)
+        self.init(origin: origin, size: size)
+    }
+    
+    public func encode(to encoder: Encoder) throws {
+        var container = encoder.unkeyedContainer()
+        try container.encode(origin)
+        try container.encode(size)
+    }
+}
+
 public typealias NSPoint = CGPoint
 
 public typealias NSPointPointer = UnsafeMutablePointer<NSPoint>
diff --git a/TestFoundation/TestCodable.swift b/TestFoundation/TestCodable.swift
index 23650d1..9369f67 100644
--- a/TestFoundation/TestCodable.swift
+++ b/TestFoundation/TestCodable.swift
@@ -220,6 +220,54 @@
             expectRoundTripEqualityThroughJSON(for: decimal)
         }
     }
+    
+    // MARK: - CGPoint
+    lazy var cgpointValues: [CGPoint] = [
+        CGPoint(),
+        CGPoint(x: 10, y: 20),
+        CGPoint(x: -10, y: -20),
+        // Disabled due to limit on magnitude in JSON. See SR-5346
+        // CGPoint(x: .greatestFiniteMagnitude, y: .greatestFiniteMagnitude),
+    ]
+    
+    func test_CGPoint_JSON() {
+        for point in cgpointValues {
+            expectRoundTripEqualityThroughJSON(for: point)
+        }
+    }
+    
+    // MARK: - CGSize
+    lazy var cgsizeValues: [CGSize] = [
+        CGSize(),
+        CGSize(width: 30, height: 40),
+        CGSize(width: -30, height: -40),
+        // Disabled due to limit on magnitude in JSON. See SR-5346
+        // CGSize(width: .greatestFiniteMagnitude, height: .greatestFiniteMagnitude),
+    ]
+    
+    func test_CGSize_JSON() {
+        for size in cgsizeValues {
+            expectRoundTripEqualityThroughJSON(for: size)
+        }
+    }
+    
+    // MARK: - CGRect
+    lazy var cgrectValues: [CGRect] = [
+        CGRect(),
+        CGRect(origin: CGPoint(x: 10, y: 20), size: CGSize(width: 30, height: 40)),
+        CGRect(origin: CGPoint(x: -10, y: -20), size: CGSize(width: -30, height: -40)),
+        // Disabled due to limit on magnitude in JSON. See SR-5346
+        // CGRect(origin: CGPoint(x: -.greatestFiniteMagnitude / 2,
+        //                        y: -.greatestFiniteMagnitude / 2),
+        //        size: CGSize(width: .greatestFiniteMagnitude,
+        //                     height: .greatestFiniteMagnitude)),
+    ]
+    
+    func test_CGRect_JSON() {
+        for rect in cgrectValues {
+            expectRoundTripEqualityThroughJSON(for: rect)
+        }
+    }
 
 }
 
@@ -235,6 +283,9 @@
             ("test_IndexPath_JSON", test_IndexPath_JSON),
             ("test_AffineTransform_JSON", test_AffineTransform_JSON),
             ("test_Decimal_JSON", test_Decimal_JSON),
+            ("test_CGPoint_JSON", test_CGPoint_JSON),
+            ("test_CGSize_JSON", test_CGSize_JSON),
+            ("test_CGRect_JSON", test_CGRect_JSON),
         ]
     }
 }