-
-
Save jckarter/96d4ff1e90e4c41dfcb271f2d6df9206 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
struct Point: Hashable, KeyPathSchema { | |
var x: Double, y: Double | |
// We can describe the schema of our type as an array of key paths, one for each property | |
// that makes up the value | |
static let schema: [PartialKeyPath<Point>] = [\Point.x, \Point.y] | |
} | |
// By defining a protocol for type schemas... | |
protocol KeyPathSchema { | |
static var schema: [PartialKeyPath<Self>] { get } | |
} | |
// ...we can provide default implementations of other protocols for reflectiony things that | |
// want to walk all of the fields of a type, such as equality, hashing, comparison, printing, | |
// etc. Here's an example of == and hashValue: | |
extension Hashable where Self: KeyPathSchema { | |
static func ==(a: Self, b: Self) -> Bool { | |
for key in Self.schema { | |
guard let aValue = a[keyPath: key] as? AnyHashable, | |
let bValue = b[keyPath: key] as? AnyHashable, | |
aValue == bValue | |
else { | |
return false | |
} | |
} | |
return true | |
} | |
var hashValue: Int { | |
var hash = unsafeBitCast(Self.self, to: Int.self) | |
for key in Self.schema { | |
if let value = self[keyPath: key] as? AnyHashable { | |
// You should use a real hash combining function here | |
hash = hash &* 17 ^ value.hashValue | |
} | |
} | |
return hash | |
} | |
} | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
For those who's want that auto-generated for your own types, you could even use Sourcery to generate that automatically 😉
See AliSoftware/SourceryTemplates#4