From e7773fcb8ff3e3a8c7620baa45c44ea6f74a324c Mon Sep 17 00:00:00 2001 From: Corey Baker Date: Tue, 9 Jan 2024 10:19:11 -0800 Subject: [PATCH 1/4] refactor: Create method for skipping Keys --- README.md | 2 +- Sources/ParseSwift/Coding/ParseEncoder.swift | 40 +++++++++++-------- .../ParseEncoderExtraTests.swift | 2 +- 3 files changed, 26 insertions(+), 18 deletions(-) diff --git a/README.md b/README.md index 768a6a7da..1fe4e890a 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@ ![parse-swift](https://user-images.githubusercontent.com/8621344/204069535-e1882bb0-bbcb-4178-87e6-58fd1bed96d1.png) -

iOS · macOS · watchOS · tvOS · Linux · Android · Windows

+

iOS · macOS · watchOS · tvOS · visionOS ·Linux · Android · Windows

⭐️ ParseSwift was highlighted in issue #560 of iOS Dev Weekly and discussed in episode 5 of Swift Package Index Twitter Spaces

diff --git a/Sources/ParseSwift/Coding/ParseEncoder.swift b/Sources/ParseSwift/Coding/ParseEncoder.swift index 7be469738..aac2d6419 100644 --- a/Sources/ParseSwift/Coding/ParseEncoder.swift +++ b/Sources/ParseSwift/Coding/ParseEncoder.swift @@ -435,60 +435,60 @@ private struct _ParseEncoderKeyedEncodingContainer: KeyedEncodin // MARK: - KeyedEncodingContainerProtocol Methods mutating func encodeNil(forKey key: Key) throws { - if self.encoder.skippedKeys.contains(key.stringValue) && !self.encoder.ignoreSkipKeys { return } + guard !shouldSkipKey(key) else { return } container[key.stringValue] = NSNull() } mutating func encode(_ value: Bool, forKey key: Key) throws { - if self.encoder.skippedKeys.contains(key.stringValue) && !self.encoder.ignoreSkipKeys { return } + guard !shouldSkipKey(key) else { return } self.container[key.stringValue] = self.encoder.box(value) } mutating func encode(_ value: Int, forKey key: Key) throws { - if self.encoder.skippedKeys.contains(key.stringValue) && !self.encoder.ignoreSkipKeys { return } + guard !shouldSkipKey(key) else { return } self.container[key.stringValue] = self.encoder.box(value) } mutating func encode(_ value: Int8, forKey key: Key) throws { - if self.encoder.skippedKeys.contains(key.stringValue) && !self.encoder.ignoreSkipKeys { return } + guard !shouldSkipKey(key) else { return } self.container[key.stringValue] = self.encoder.box(value) } mutating func encode(_ value: Int16, forKey key: Key) throws { - if self.encoder.skippedKeys.contains(key.stringValue) && !self.encoder.ignoreSkipKeys { return } + guard !shouldSkipKey(key) else { return } self.container[key.stringValue] = self.encoder.box(value) } mutating func encode(_ value: Int32, forKey key: Key) throws { - if self.encoder.skippedKeys.contains(key.stringValue) && !self.encoder.ignoreSkipKeys { return } + guard !shouldSkipKey(key) else { return } self.container[key.stringValue] = self.encoder.box(value) } mutating func encode(_ value: Int64, forKey key: Key) throws { - if self.encoder.skippedKeys.contains(key.stringValue) && !self.encoder.ignoreSkipKeys { return } + guard !shouldSkipKey(key) else { return } self.container[key.stringValue] = self.encoder.box(value) } mutating func encode(_ value: UInt, forKey key: Key) throws { - if self.encoder.skippedKeys.contains(key.stringValue) && !self.encoder.ignoreSkipKeys { return } + guard !shouldSkipKey(key) else { return } self.container[key.stringValue] = self.encoder.box(value) } mutating func encode(_ value: UInt8, forKey key: Key) throws { - if self.encoder.skippedKeys.contains(key.stringValue) && !self.encoder.ignoreSkipKeys { return } + guard !shouldSkipKey(key) else { return } self.container[key.stringValue] = self.encoder.box(value) } mutating func encode(_ value: UInt16, forKey key: Key) throws { - if self.encoder.skippedKeys.contains(key.stringValue) && !self.encoder.ignoreSkipKeys { return } + guard !shouldSkipKey(key) else { return } self.container[key.stringValue] = self.encoder.box(value) } mutating func encode(_ value: UInt32, forKey key: Key) throws { - if self.encoder.skippedKeys.contains(key.stringValue) && !self.encoder.ignoreSkipKeys { return } + guard !shouldSkipKey(key) else { return } self.container[key.stringValue] = self.encoder.box(value) } mutating func encode(_ value: UInt64, forKey key: Key) throws { - if self.encoder.skippedKeys.contains(key.stringValue) && !self.encoder.ignoreSkipKeys { return } + guard !shouldSkipKey(key) else { return } self.container[key.stringValue] = self.encoder.box(value) } mutating func encode(_ value: String, forKey key: Key) throws { - if self.encoder.skippedKeys.contains(key.stringValue) && !self.encoder.ignoreSkipKeys { return } + guard !shouldSkipKey(key) else { return } self.container[key.stringValue] = self.encoder.box(value) } mutating func encode(_ value: Float, forKey key: Key) throws { // Since the float may be invalid and throw, the coding path needs to contain this key. - if self.encoder.skippedKeys.contains(key.stringValue) && !self.encoder.ignoreSkipKeys { return } + guard !shouldSkipKey(key) else { return } self.encoder.codingPath.append(key) defer { self.encoder.codingPath.removeLast() } self.container[key.stringValue] = try self.encoder.box(value) @@ -496,14 +496,15 @@ private struct _ParseEncoderKeyedEncodingContainer: KeyedEncodin mutating func encode(_ value: Double, forKey key: Key) throws { // Since the double may be invalid and throw, the coding path needs to contain this key. - if self.encoder.skippedKeys.contains(key.stringValue) && !self.encoder.ignoreSkipKeys { return } + guard !shouldSkipKey(key) else { return } self.encoder.codingPath.append(key) defer { self.encoder.codingPath.removeLast() } self.container[key.stringValue] = try self.encoder.box(value) } mutating func encode(_ value: T, forKey key: Key) throws where T: Encodable { - if self.encoder.skippedKeys.contains(key.stringValue) && !self.encoder.ignoreSkipKeys { return } + + guard !shouldSkipKey(key) else { return } var valueToEncode: Encodable = value if ((value as? Objectable) != nil) @@ -542,6 +543,13 @@ private struct _ParseEncoderKeyedEncodingContainer: KeyedEncodin self.container[key.stringValue] = try self.encoder.box(valueToEncode) } + func shouldSkipKey(_ key: Key) -> Bool { + guard self.encoder.skippedKeys.contains(key.stringValue) && !self.encoder.ignoreSkipKeys else { + return false + } + return true + } + mutating func nestedContainer( keyedBy keyType: NestedKey.Type, forKey key: Key diff --git a/Tests/ParseSwiftTests/ParseEncoderTests/ParseEncoderExtraTests.swift b/Tests/ParseSwiftTests/ParseEncoderTests/ParseEncoderExtraTests.swift index 91c391004..ab5936ad1 100644 --- a/Tests/ParseSwiftTests/ParseEncoderTests/ParseEncoderExtraTests.swift +++ b/Tests/ParseSwiftTests/ParseEncoderTests/ParseEncoderExtraTests.swift @@ -74,7 +74,7 @@ class ParseEncoderTests: XCTestCase { let parseEncoded = try ParseCoding.jsonEncoder().encode(newACL) let parseDecoded = try ParseCoding.jsonDecoder().decode([String: [String: Bool]].self, from: parseEncoded) - XCTAssertEqual(jsonDecoded.keys.count, parseDecoded.keys.count) + XCTAssertEqual(jsonDecoded.keys.count, parseDecoded.keys.count) XCTAssertEqual(jsonDecoded.values.count, parseDecoded.values.count) XCTAssertEqual(jsonDecoded["*"]?["read"], true) XCTAssertEqual(parseDecoded["*"]?["read"], true) From 6a36d41c82db98847a69be79640e8a1f75959765 Mon Sep 17 00:00:00 2001 From: Corey Baker Date: Tue, 9 Jan 2024 11:13:17 -0800 Subject: [PATCH 2/4] test additiional types --- .../ParseEncoderExtraTests.swift | 64 +++++++++++++++++-- 1 file changed, 59 insertions(+), 5 deletions(-) diff --git a/Tests/ParseSwiftTests/ParseEncoderTests/ParseEncoderExtraTests.swift b/Tests/ParseSwiftTests/ParseEncoderTests/ParseEncoderExtraTests.swift index ab5936ad1..f696ec9d1 100644 --- a/Tests/ParseSwiftTests/ParseEncoderTests/ParseEncoderExtraTests.swift +++ b/Tests/ParseSwiftTests/ParseEncoderTests/ParseEncoderExtraTests.swift @@ -11,7 +11,7 @@ import XCTest class ParseEncoderTests: XCTestCase { struct GameScore: ParseObject, ParseQueryScorable { - //: These are required by ParseObject + // These are required by ParseObject var objectId: String? var createdAt: Date? var updatedAt: Date? @@ -19,13 +19,13 @@ class ParseEncoderTests: XCTestCase { var score: Double? var originalData: Data? - //: ParseUser property + // ParseUser property var emailVerified: Bool? - //: Your own properties + // Your own properties var points: Int - //: a custom initializer + // a custom initializer init() { self.points = 5 } @@ -34,6 +34,43 @@ class ParseEncoderTests: XCTestCase { } } + struct AdditionalTypes: ParseObject { + // These are required by ParseObject + var objectId: String? + var createdAt: Date? + var updatedAt: Date? + var ACL: ParseACL? + var score: Double? + var originalData: Data? + + // Your own properties + var int8: Int8 + var int16: Int16 + var int32: Int32 + var int64: Int64 + var uint: UInt + var uint8: UInt8 + var uint16: UInt16 + var uint32: UInt32 + var uint64: UInt64 + var float: Float + + // a custom initializer + init() { + self.int8 = 1 + self.int16 = 2 + self.int32 = 3 + self.int64 = 4 + self.uint = 5 + self.uint8 = 1 + self.uint16 = 2 + self.uint32 = 3 + self.uint64 = 4 + self.float = 1.1 + } + + } + struct Address: Codable { let street: String let city: String @@ -74,12 +111,29 @@ class ParseEncoderTests: XCTestCase { let parseEncoded = try ParseCoding.jsonEncoder().encode(newACL) let parseDecoded = try ParseCoding.jsonDecoder().decode([String: [String: Bool]].self, from: parseEncoded) - XCTAssertEqual(jsonDecoded.keys.count, parseDecoded.keys.count) + XCTAssertEqual(jsonDecoded.keys.count, parseDecoded.keys.count) XCTAssertEqual(jsonDecoded.values.count, parseDecoded.values.count) XCTAssertEqual(jsonDecoded["*"]?["read"], true) XCTAssertEqual(parseDecoded["*"]?["read"], true) } + func testEncodingAdditionalTypes() throws { + let object = AdditionalTypes() + + let encodedJSON = try ParseCoding.parseEncoder().encode(object, skipKeys: .object) + let decodedJSON = try ParseCoding.jsonDecoder().decode([String: AnyCodable].self, from: encodedJSON) + XCTAssertEqual(decodedJSON["int8"]?.value as? NSNumber, NSNumber(value: object.int8)) + XCTAssertEqual(decodedJSON["int16"]?.value as? NSNumber, NSNumber(value: object.int16)) + XCTAssertEqual(decodedJSON["int32"]?.value as? NSNumber, NSNumber(value: object.int32)) + XCTAssertEqual(decodedJSON["int64"]?.value as? NSNumber, NSNumber(value: object.int64)) + XCTAssertEqual(decodedJSON["uint"]?.value as? NSNumber, NSNumber(value: object.uint)) + XCTAssertEqual(decodedJSON["uint8"]?.value as? NSNumber, NSNumber(value: object.uint8)) + XCTAssertEqual(decodedJSON["uint16"]?.value as? NSNumber, NSNumber(value: object.uint16)) + XCTAssertEqual(decodedJSON["uint32"]?.value as? NSNumber, NSNumber(value: object.uint32)) + XCTAssertEqual(decodedJSON["uint64"]?.value as? NSNumber, NSNumber(value: object.uint64)) + XCTAssertEqual(decodedJSON["float"]?.value as? NSNumber, NSNumber(value: object.float)) + } + func testSkipKeysDefaultCodingKeys() throws { var score = GameScore(points: 10) score.objectId = "yarr" From 26f2e3aa09974850e902ec7e47ae3a621ca019d6 Mon Sep 17 00:00:00 2001 From: Corey Baker Date: Tue, 9 Jan 2024 11:18:52 -0800 Subject: [PATCH 3/4] fix linux test with NSNumber --- .../ParseEncoderTests/ParseEncoderExtraTests.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Tests/ParseSwiftTests/ParseEncoderTests/ParseEncoderExtraTests.swift b/Tests/ParseSwiftTests/ParseEncoderTests/ParseEncoderExtraTests.swift index f696ec9d1..8e577c034 100644 --- a/Tests/ParseSwiftTests/ParseEncoderTests/ParseEncoderExtraTests.swift +++ b/Tests/ParseSwiftTests/ParseEncoderTests/ParseEncoderExtraTests.swift @@ -131,7 +131,7 @@ class ParseEncoderTests: XCTestCase { XCTAssertEqual(decodedJSON["uint16"]?.value as? NSNumber, NSNumber(value: object.uint16)) XCTAssertEqual(decodedJSON["uint32"]?.value as? NSNumber, NSNumber(value: object.uint32)) XCTAssertEqual(decodedJSON["uint64"]?.value as? NSNumber, NSNumber(value: object.uint64)) - XCTAssertEqual(decodedJSON["float"]?.value as? NSNumber, NSNumber(value: object.float)) + XCTAssertEqual(decodedJSON["float"]?.value as? Double, Double(object.float)) } func testSkipKeysDefaultCodingKeys() throws { From 098d3e1e0f5580893d338b3adfa9523a814dd42b Mon Sep 17 00:00:00 2001 From: Corey Baker Date: Tue, 9 Jan 2024 11:34:37 -0800 Subject: [PATCH 4/4] remove float test from linux --- .../ParseEncoderTests/ParseEncoderExtraTests.swift | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Tests/ParseSwiftTests/ParseEncoderTests/ParseEncoderExtraTests.swift b/Tests/ParseSwiftTests/ParseEncoderTests/ParseEncoderExtraTests.swift index 8e577c034..64dcf8b9f 100644 --- a/Tests/ParseSwiftTests/ParseEncoderTests/ParseEncoderExtraTests.swift +++ b/Tests/ParseSwiftTests/ParseEncoderTests/ParseEncoderExtraTests.swift @@ -131,7 +131,9 @@ class ParseEncoderTests: XCTestCase { XCTAssertEqual(decodedJSON["uint16"]?.value as? NSNumber, NSNumber(value: object.uint16)) XCTAssertEqual(decodedJSON["uint32"]?.value as? NSNumber, NSNumber(value: object.uint32)) XCTAssertEqual(decodedJSON["uint64"]?.value as? NSNumber, NSNumber(value: object.uint64)) + #if !os(Linux) && !os(Android) && !os(Windows) XCTAssertEqual(decodedJSON["float"]?.value as? Double, Double(object.float)) + #endif } func testSkipKeysDefaultCodingKeys() throws {