Skip to content

Instantly share code, notes, and snippets.

@sidepelican
Last active June 5, 2024 08:27
Show Gist options
  • Save sidepelican/130fd3c61080a071aa176a12083a3e80 to your computer and use it in GitHub Desktop.
Save sidepelican/130fd3c61080a071aa176a12083a3e80 to your computer and use it in GitHub Desktop.
resultBuilderと雪だるまジェネリクスで型の組み立て
import Foundation
@dynamicMemberLookup
struct Concat<L: Decodable, R: Decodable>: Decodable {
init(left: L, right: R) {
self.left = left
self.right = right
}
private var left: L
private var right: R
subscript<T>(dynamicMember keyPath: KeyPath<L, T>) -> T {
left[keyPath: keyPath]
}
subscript<T>(dynamicMember keyPath: KeyPath<R, T>) -> T {
right[keyPath: keyPath]
}
init(from decoder: any Decoder) throws {
var container = try decoder.singleValueContainer()
self.left = try container.decode(L.self)
self.right = try container.decode(R.self)
}
}
struct p_id: Decodable {
var id: Int
}
struct p_name: Decodable {
var name: String
}
struct p_createdAt: Decodable {
var createdAt: Int
}
@resultBuilder
struct RowBuilder {
static func buildBlock<T>(_ component: T) -> T {
component
}
static func buildPartialBlock<T: Decodable>(first: T) -> T {
first
}
static func buildPartialBlock<Accumulated, Next>(
accumulated: Accumulated,
next: Next
) -> Concat<Accumulated, Next>
{
Concat(left: accumulated, right: next)
}
}
func buildRow<Row>(@RowBuilder _ builder: () -> Row) -> Row {
builder()
}
let row = buildRow {
p_id(id: 1)
p_name(name: "Taro")
p_createdAt(createdAt: 123)
}
print(row.id)
print(row.name)
print(row.createdAt)
let json = """
{
"id": 2,
"name": "Hanako",
"createdAt": 456
}
""".data(using: .utf8)!
func jsonDecode<T: Decodable>(typeOf _: T, from data: Data) throws -> T {
return try JSONDecoder().decode(T.self, from: data)
}
let row2 = try jsonDecode(typeOf: row, from: json)
print(row2.id)
print(row2.name)
print(row2.createdAt)
1
Taro
123
2
Hanako
456
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment