Skip to content

Instantly share code, notes, and snippets.

@kaqu
Last active August 7, 2018 10:50
Show Gist options
  • Save kaqu/762e29e12a984b4a53cd9fb720f2ea89 to your computer and use it in GitHub Desktop.
Save kaqu/762e29e12a984b4a53cd9fb720f2ea89 to your computer and use it in GitHub Desktop.
protocol Buildable {
init(dict: [AnyKeyPath: Any]) throws
}
struct BuilderError : Error {
let reason: String
}
struct SomeBuildable : Buildable {
let field1: String
let field2: Int?
let field3: [SomeEnum]
enum SomeEnum {
case first
}
init(dict: [AnyKeyPath: Any]) throws {
guard let field1 = dict[\SomeBuildable.field1] as? String else {
throw BuilderError(reason: "Missing field1")
}
self.field1 = field1
guard let field2 = dict[\SomeBuildable.field2] as? Int else {
throw BuilderError(reason: "Missing field2")
}
self.field2 = field2
guard let field3 = dict[\SomeBuildable.field3] as? [SomeEnum] else {
throw BuilderError(reason: "Missing field3")
}
self.field3 = field3
}
}
struct Builder<E : Buildable> {
var dict: [AnyKeyPath: Any] = [:]
mutating func setValue<T>(_ val: T, for keyPath: KeyPath<E, T>) {
dict[keyPath] = val
}
func build() throws -> E {
return try E.init(dict: dict)
}
}
var builder = Builder<SomeBuildable>.init()
builder.setValue("Value", for: \SomeBuildable.field1)
builder.setValue(nil, for: \SomeBuildable.field2)
builder.setValue([.first], for: \SomeBuildable.field3)
let product = try? builder.build()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment