Skip to content

Commit

Permalink
refactor: Remove extra Hashable conformance for ParseObject (#182)
Browse files Browse the repository at this point in the history
* fix: Remove extra Hashable conformance for ParseObject

* remove more double conformance

* make public version of encoding ParseObject

* remove public encoder

* use xcbeautify in CI

* Update ci.yml

* doc nits

* Update ci.yml

* Update ci.yml

* test not running installation tests on Windows

* disable more windows using Installation

* revert testing windows

* Update ci.yml
  • Loading branch information
cbaker6 authored Sep 2, 2024
1 parent b56de0a commit 3f02f59
Show file tree
Hide file tree
Showing 21 changed files with 93 additions and 62 deletions.
14 changes: 7 additions & 7 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ jobs:
action: 'test'
steps:
- uses: actions/checkout@v4
- name: Install SwiftLint
- name: Install Extra Packages
run: brew install swiftlint
- name: Create and set the default keychain
run: |
Expand All @@ -46,7 +46,7 @@ jobs:
security unlock-keychain -p "" temporary
security set-keychain-settings -lut 7200 temporary
- name: Build-Test
run: set -o pipefail && env NSUnbufferedIO=YES xcodebuild -workspace Parse.xcworkspace -scheme ParseSwift -derivedDataPath DerivedData -destination ${{ matrix.destination }} ${{ matrix.action }} | xcpretty -c
run: set -o pipefail && env NSUnbufferedIO=YES xcodebuild -workspace Parse.xcworkspace -scheme ParseSwift -derivedDataPath DerivedData -destination ${{ matrix.destination }} ${{ matrix.action }} 2>&1 | xcbeautify --renderer github-actions
env:
DEVELOPER_DIR: ${{ env.CI_XCODE_LATEST }}
- name: Prepare codecov
Expand Down Expand Up @@ -80,7 +80,7 @@ jobs:
- name: Install SwiftLint
run: brew install swiftlint
- name: Build-Test
run: set -o pipefail && env NSUnbufferedIO=YES swift test --enable-code-coverage | xcpretty -c
run: set -o pipefail && env NSUnbufferedIO=YES swift test --enable-code-coverage 2>&1 | xcbeautify --renderer github-actions
env:
DEVELOPER_DIR: ${{ env.CI_XCODE_LATEST }}
- name: Prepare codecov
Expand Down Expand Up @@ -108,7 +108,7 @@ jobs:
steps:
- uses: actions/checkout@v4
- name: Build-Test
run: set -o pipefail && env NSUnbufferedIO=YES xcodebuild -workspace Parse.xcworkspace -scheme ParseSwift -destination platform\=iOS\ Simulator,name\=iPhone\ 13\ Pro\ Max -derivedDataPath DerivedData build | xcpretty -c
run: set -o pipefail && env NSUnbufferedIO=YES xcodebuild -workspace Parse.xcworkspace -scheme ParseSwift -destination platform\=iOS\ Simulator,name\=iPhone\ 13\ Pro\ Max -derivedDataPath DerivedData build 2>&1 | xcbeautify --renderer github-actions
env:
DEVELOPER_DIR: ${{ env.CI_XCODE_OLDEST }}

Expand Down Expand Up @@ -141,11 +141,11 @@ jobs:
- uses: actions/checkout@v4
- uses: compnerd/[email protected]
with:
branch: swift-5.10-release
tag: 5.10-RELEASE
branch: swift-5.10.1-release
tag: 5.10.1-RELEASE
- name: Build
run: |
swift build -v
swift build --enable-test-discovery -v
- name: Upload coverage to Codecov
uses: codecov/codecov-action@v4
with:
Expand Down
8 changes: 7 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,15 @@
# Parse-Swift Changelog

### main
[Full Changelog](https://github.com/netreconlab/Parse-Swift/compare/5.11.2...main), [Documentation](https://swiftpackageindex.com/netreconlab/Parse-Swift/main/documentation/parseswift)
[Full Changelog](https://github.com/netreconlab/Parse-Swift/compare/5.11.3...main), [Documentation](https://swiftpackageindex.com/netreconlab/Parse-Swift/main/documentation/parseswift)
* _Contributing to this repo? Add info about your change here to be included in the next release_

### 5.11.3
[Full Changelog](https://github.com/netreconlab/Parse-Swift/compare/5.11.2...5.11.3), [Documentation](https://swiftpackageindex.com/netreconlab/Parse-Swift/5.11.3/documentation/parseswift)

__Fixes__
* Remove all double conformance of Hashable and Equatable ([#182](https://github.com/netreconlab/Parse-Swift/pull/182)), thanks to [Corey Baker](https://github.com/cbaker6).

### 5.11.2
[Full Changelog](https://github.com/netreconlab/Parse-Swift/compare/5.11.1...5.11.2), [Documentation](https://swiftpackageindex.com/netreconlab/Parse-Swift/5.11.2/documentation/parseswift)

Expand Down
2 changes: 1 addition & 1 deletion Sources/ParseSwift/API/API+NonParseBodyCommand.swift
Original file line number Diff line number Diff line change
Expand Up @@ -145,7 +145,7 @@ internal extension API.NonParseBodyCommand {
objectsSavedBeforeThisOne: [String: PointerType]?,
// swiftlint:disable:next line_length
filesSavedBeforeThisOne: [String: ParseFile]?) async throws -> RESTBatchCommandTypeEncodablePointer<AnyCodable> {
try await yieldIfNotInitialized()

let defaultACL = try? await ParseACL.defaultACL()
let batchCommands = try objects.compactMap { (object) -> API.BatchCommand<AnyCodable, PointerType>? in
guard var objectable = object as? Objectable else {
Expand Down
91 changes: 59 additions & 32 deletions Sources/ParseSwift/Coding/ParseEncoder.swift
Original file line number Diff line number Diff line change
Expand Up @@ -50,9 +50,11 @@ extension Dictionary: _JSONStringDictionaryEncodableMarker where Key == String,
/** An object that encodes Parse instances of a data type as JSON objects.
- note: `JSONEncoder` facilitates the encoding of `Encodable` values into JSON.
`ParseEncoder` facilitates the encoding of `ParseEncodable` values into JSON.
All Credit to Apple, this is a custom encoder with capability of skipping keys at runtime.
ParseEncoder matches the features of the [Swift 5.4 JSONEncoder ](https://github.com/apple/swift/blob/main/stdlib/public/Darwin/Foundation/JSONEncoder.swift).
Update commits as needed for improvement.
All Credit to Apple for the baseline encoder. The `ParseEncoder` is a custom encoder
with capability of skipping keys at runtime and encoding objects into a digestable format
for a [parse-server](https://github.com/parse-community/parse-server).
`ParseEncoder` matches the features of the [Swift 5.4 JSONEncoder ](https://github.com/apple/swift/blob/main/stdlib/public/Darwin/Foundation/JSONEncoder.swift).
Update comments as needed for improvement.
*/
public struct ParseEncoder: Sendable {
let dateEncodingStrategy: JSONEncoder.DateEncodingStrategy?
Expand Down Expand Up @@ -109,11 +111,13 @@ public struct ParseEncoder: Sendable {
self.outputFormatting = outputFormatting
}

func encode(_ value: Encodable,
acl: ParseACL? = nil,
batching: Bool = false,
objectsSavedBeforeThisOne: [String: PointerType]? = nil,
filesSavedBeforeThisOne: [String: ParseFile]? = nil) throws -> Data {
func encode(
_ value: Encodable,
acl: ParseACL? = nil,
batching: Bool = false,
objectsSavedBeforeThisOne: [String: PointerType]? = nil,
filesSavedBeforeThisOne: [String: ParseFile]? = nil
) throws -> Data {
var keysToSkip = SkipKeys.none.keys()
if batching {
keysToSkip = SkipKeys.object.keys()
Expand All @@ -137,53 +141,76 @@ public struct ParseEncoder: Sendable {
/**
Encodes an instance of the indicated `ParseEncodable`.
- parameter value: The `ParseEncodable` instance to encode.
- parameter acl: The `ParseACL` to add to the value if it is an `ParseObject`. Defaults to `nil`.
- parameter skipKeys: The set of keys to skip during encoding.
*/
public func encode<T: ParseEncodable>(_ value: T,
acl: ParseACL? = nil,
skipKeys: SkipKeys) throws -> Data {
let encoder = _ParseEncoder(codingPath: [], dictionary: NSMutableDictionary(), skippingKeys: skipKeys.keys())
public func encode<T: ParseEncodable>(
_ value: T,
acl: ParseACL? = nil,
skipKeys: SkipKeys
) throws -> Data {
let encoder = _ParseEncoder(
codingPath: [],
dictionary: NSMutableDictionary(),
skippingKeys: skipKeys.keys()
)
if let dateEncodingStrategy = dateEncodingStrategy {
encoder.dateEncodingStrategy = dateEncodingStrategy
}
if let outputFormatting = outputFormatting {
encoder.outputFormatting = outputFormatting
}
return try encoder.encodeObject(value,
acl: acl,
collectChildren: false,
uniquePointer: nil,
objectsSavedBeforeThisOne: nil,
filesSavedBeforeThisOne: nil).encoded
let encodedData = try encoder.encodeObject(
value,
acl: acl,
collectChildren: false,
uniquePointer: nil,
objectsSavedBeforeThisOne: nil,
filesSavedBeforeThisOne: nil
).encoded

return encodedData
}

// swiftlint:disable large_tuple
internal func encode<T: ParseObject>(_ value: T,
acl: ParseACL? = nil,
collectChildren: Bool,
objectsSavedBeforeThisOne: [String: PointerType]?,
filesSavedBeforeThisOne: [String: ParseFile]?) throws -> (encoded: Data,
unique: PointerType?,
unsavedChildren: [Encodable]) {
func encode<T: ParseObject>(
_ value: T,
acl: ParseACL? = nil,
collectChildren: Bool,
objectsSavedBeforeThisOne: [String: PointerType]?,
filesSavedBeforeThisOne: [String: ParseFile]?
) throws -> (
encoded: Data,
unique: PointerType?,
unsavedChildren: [Encodable]
) {
let keysToSkip: Set<String>!
if !Parse.configuration.isRequiringCustomObjectIds {
keysToSkip = SkipKeys.object.keys()
} else {
keysToSkip = SkipKeys.customObjectId.keys()
}
let encoder = _ParseEncoder(codingPath: [], dictionary: NSMutableDictionary(), skippingKeys: keysToSkip)
let encoder = _ParseEncoder(
codingPath: [],
dictionary: NSMutableDictionary(),
skippingKeys: keysToSkip
)
if let dateEncodingStrategy = dateEncodingStrategy {
encoder.dateEncodingStrategy = dateEncodingStrategy
}
if let outputFormatting = outputFormatting {
encoder.outputFormatting = outputFormatting
}
return try encoder.encodeObject(value,
acl: acl,
collectChildren: collectChildren,
uniquePointer: try? value.toPointer(),
objectsSavedBeforeThisOne: objectsSavedBeforeThisOne,
filesSavedBeforeThisOne: filesSavedBeforeThisOne)
let encodedObject = try encoder.encodeObject(
value,
acl: acl,
collectChildren: collectChildren,
uniquePointer: try? value.toPointer(),
objectsSavedBeforeThisOne: objectsSavedBeforeThisOne,
filesSavedBeforeThisOne: filesSavedBeforeThisOne
)

return encodedObject
}

internal func encode(_ value: ParseEncodable,
Expand Down
2 changes: 1 addition & 1 deletion Sources/ParseSwift/LiveQuery/LiveQueryConstants.swift
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ import Foundation
- Updated: The object has been updated, and is still a part of the query.
- Deleted: The object has been deleted, and is no longer included in the query.
*/
public enum Event<T: ParseObject>: Equatable {
public enum Event<T: ParseObject>: Equatable, Sendable {
/// The object has been updated, and is now included in the query.
case entered(T)

Expand Down
2 changes: 1 addition & 1 deletion Sources/ParseSwift/LiveQuery/Operations.swift
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,6 @@ enum OperationErrorResponse: String, Codable {

// An opaque placeholder structed used to ensure that we type-safely create request IDs and do not shoot ourself in
// the foot with array indexes.
struct RequestId: Hashable, Equatable, Codable {
struct RequestId: Hashable, Codable {
let value: Int
}
3 changes: 1 addition & 2 deletions Sources/ParseSwift/Objects/ParseObject.swift
Original file line number Diff line number Diff line change
Expand Up @@ -44,8 +44,7 @@ public protocol ParseObject: ParseTypeable,
Fetchable,
Savable,
Deletable,
Identifiable,
Hashable {
Identifiable {

/**
A JSON encoded version of this `ParseObject` before `.set()` or
Expand Down
2 changes: 1 addition & 1 deletion Sources/ParseSwift/ParseConstants.swift
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import Foundation

enum ParseConstants {
static let sdk = "swift"
static let version = "5.11.2"
static let version = "5.11.3"
static let fileManagementDirectory = "parse/"
static let fileManagementPrivateDocumentsDirectory = "Private Documents/"
static let fileManagementLibraryDirectory = "Library/"
Expand Down
4 changes: 2 additions & 2 deletions Sources/ParseSwift/Protocols/ParseConfig.swift
Original file line number Diff line number Diff line change
Expand Up @@ -94,12 +94,12 @@ extension ParseConfig {
}
}

internal struct ConfigUpdateBody<T>: ParseTypeable, Decodable where T: ParseConfig {
internal struct ConfigUpdateBody<T>: ParseTypeable where T: ParseConfig {
let params: T
}

// MARK: Current
struct CurrentConfigContainer<T: ParseConfig>: Codable, Equatable {
struct CurrentConfigContainer<T: ParseConfig>: Codable, Hashable {
var currentConfig: T?
}

Expand Down
2 changes: 1 addition & 1 deletion Sources/ParseSwift/Protocols/ParsePointerable.swift
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ extension ParsePointer {
}
}

public protocol ParsePointerObject: ParsePointer, ParseTypeable, Fetchable, Hashable {
public protocol ParsePointerObject: ParsePointer, ParseTypeable, Fetchable {
associatedtype Object: ParseObject
}

Expand Down
4 changes: 2 additions & 2 deletions Sources/ParseSwift/Protocols/ParseTypeable.swift
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,8 @@ import Foundation
/**
A special type that is considered a Parse type.
*/
public protocol ParseTypeable: Codable,
Sendable,
public protocol ParseTypeable: ParseEncodable,
Codable,
Hashable,
CustomDebugStringConvertible,
CustomStringConvertible {}
Expand Down
3 changes: 1 addition & 2 deletions Sources/ParseSwift/Types/ParseACL.swift
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,7 @@ import Foundation
**the public** so that, for example, any user could read a particular object but only a
particular set of users could write to that object.
*/
public struct ParseACL: ParseTypeable,
Hashable {
public struct ParseACL: ParseTypeable {
private static let publicScope = "*"
private var acl: [String: [Access: Bool]]?

Expand Down
2 changes: 1 addition & 1 deletion Sources/ParseSwift/Types/ParseAnalytics.swift
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ import UIKit
/**
`ParseAnalytics` provides an interface to Parse's logging and analytics backend.
*/
public struct ParseAnalytics: ParseTypeable, Hashable {
public struct ParseAnalytics: ParseTypeable {

/// The name of the custom event to report to Parse as having happened.
public var name: String
Expand Down
2 changes: 1 addition & 1 deletion Sources/ParseSwift/Types/ParseBytes.swift
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import Foundation
/**
`ParseBytes` is used to store base 64 data.
*/
public struct ParseBytes: ParseTypeable, Hashable {
public struct ParseBytes: ParseTypeable {
private let __type: String = "Bytes" // swiftlint:disable:this identifier_name
public let base64: String

Expand Down
2 changes: 1 addition & 1 deletion Sources/ParseSwift/Types/ParseGeoPoint.swift
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import CoreLocation
- warning:Currently, instances of `ParseObject` may only have one key associated with a `ParseGeoPoint` type.
*/
public struct ParseGeoPoint: ParseTypeable, Hashable {
public struct ParseGeoPoint: ParseTypeable {
private let __type: String = "GeoPoint" // swiftlint:disable:this identifier_name
static let earthRadiusMiles = 3958.8
static let earthRadiusKilometers = 6371.0
Expand Down
2 changes: 1 addition & 1 deletion Sources/ParseSwift/Types/ParseKeychainAccessGroup.swift
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
#if !os(Linux) && !os(Android) && !os(Windows)
import Foundation

struct ParseKeychainAccessGroup: ParseTypeable, Hashable {
struct ParseKeychainAccessGroup: ParseTypeable {

var accessGroup: String?
var isSyncingKeychainAcrossDevices = false
Expand Down
2 changes: 1 addition & 1 deletion Sources/ParseSwift/Types/ParsePolygon.swift
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
that may be associated with a key in a `ParseObject` or used as a reference point
for geo queries. This allows proximity-based queries on the key.
*/
public struct ParsePolygon: ParseTypeable, Hashable {
public struct ParsePolygon: ParseTypeable {
private let __type: String = "Polygon" // swiftlint:disable:this identifier_name
public let coordinates: [ParseGeoPoint]
var isSwappingCoordinates = false
Expand Down
2 changes: 1 addition & 1 deletion Sources/ParseSwift/Types/ParseRelation.swift
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ import Foundation
In most cases, you do not need to create an instance of `ParseRelation` directly as it can be
indirectly created from any `ParseObject` by using the respective `relation` property.
*/
public struct ParseRelation<T>: ParseTypeable, Hashable where T: ParseObject {
public struct ParseRelation<T>: ParseTypeable where T: ParseObject {
internal let __type: String = "Relation" // swiftlint:disable:this identifier_name

/// The parent `ParseObject`
Expand Down
2 changes: 1 addition & 1 deletion Sources/ParseSwift/Types/ParseSchema.swift
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ import Foundation
use the primary key in server-side applications where the key is kept secure and not
exposed to the public.
*/
public struct ParseSchema<SchemaObject: ParseObject>: ParseTypeable, Decodable, Equatable {
public struct ParseSchema<SchemaObject: ParseObject>: ParseTypeable {

/// The class name of the `ParseSchema`.
public var className: String
Expand Down
2 changes: 1 addition & 1 deletion Sources/ParseSwift/Types/ParseVersion.swift
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import Foundation

/// `ParseVersion` is used to determine the version of the SDK. The current
/// version of the SDK is persisted to the Keychain.
public struct ParseVersion: ParseTypeable, Hashable {
public struct ParseVersion: ParseTypeable {

var major: Int
var minor: Int
Expand Down
2 changes: 1 addition & 1 deletion Sources/ParseSwift/Types/QueryConstraint.swift
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
import Foundation

/// Used to constrain a query.
public struct QueryConstraint: ParseTypeable, Hashable {
public struct QueryConstraint: ParseTypeable {
enum Comparator: String, CodingKey, Codable, CaseIterable {
case lessThan = "$lt"
case lessThanOrEqualTo = "$lte"
Expand Down

0 comments on commit 3f02f59

Please sign in to comment.