Skip to content

Instantly share code, notes, and snippets.

@jayrhynas
Last active February 2, 2022 11:11
Show Gist options
  • Save jayrhynas/9b4138cee10d998e7d8af19152f9e20e to your computer and use it in GitHub Desktop.
Save jayrhynas/9b4138cee10d998e7d8af19152f9e20e to your computer and use it in GitHub Desktop.
@dynamicMemberLookup
struct Partial<Wrapped> {
private struct AnyProperty {
let keyPath: PartialKeyPath<Wrapped>
let value: Any
let writer: (inout Wrapped, Any) -> Void
init<T>(keyPath: WritableKeyPath<Wrapped, T>, value: T) {
self.keyPath = keyPath
self.value = value
self.writer = { instance, value in
instance[keyPath: keyPath] = value as! T
}
}
func update(_ wrapped: inout Wrapped) {
self.writer(&wrapped, value)
}
}
private var values: [PartialKeyPath<Wrapped>: AnyProperty] = [:]
subscript<T>(dynamicMember keyPath: WritableKeyPath<Wrapped, T>) -> T? {
get { self.values[keyPath]?.value as? T }
set {
if let value = newValue {
self.values[keyPath] = AnyProperty(keyPath: keyPath, value: value)
} else {
self.values.removeValue(forKey: keyPath)
}
}
}
func apply(to original: Wrapped) -> Wrapped {
var copy = original
for (_, property) in values {
property.update(&copy)
}
return copy
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment