Skip to content
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

refactor: Remove extra Hashable conformance for ParseObject #182

Merged
merged 14 commits into from
Sep 2, 2024
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 @@

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 All @@ -26,7 +26,7 @@
static let deviceType = "tvos"
#elseif os(watchOS)
static let deviceType = "applewatch"
#elseif os(visionOS)

Check warning on line 29 in Sources/ParseSwift/ParseConstants.swift

View workflow job for this annotation

GitHub Actions / xcode-test-5_7

unknown operating system for build configuration 'os'

Check warning on line 29 in Sources/ParseSwift/ParseConstants.swift

View workflow job for this annotation

GitHub Actions / xcode-test-5_7

unknown operating system for build configuration 'os'
static let deviceType = "visionos"
#elseif os(Linux)
static let deviceType = "linux"
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
Loading