Skip to content

Instantly share code, notes, and snippets.

@floriankugler
Last active May 21, 2019 00:20
Show Gist options
  • Save floriankugler/02c8ea99ea6390a7eee765fa68b5d8df to your computer and use it in GitHub Desktop.
Save floriankugler/02c8ea99ea6390a7eee765fa68b5d8df to your computer and use it in GitHub Desktop.
import PlaygroundSupport
import Foundation
struct Resource<A> {
var request: URLRequest
var parse: (Data) throws -> A
}
protocol Loadable {
static var request: URLRequest { get }
init(parsing data: Data) throws
}
struct Country: Codable {
var alpha2Code: String
var name: String
var population: Int
}
extension Resource where A: Decodable {
init(get url: URL) {
self.init(request: URLRequest(url: url)) { data in
try JSONDecoder().decode(A.self, from: data)
}
}
}
extension Loadable where Self: Decodable {
init(parsing data: Data) throws {
self = try JSONDecoder().decode(Self.self, from: data)
}
}
let countries = Resource<[Country]>(get: URL(string: "https://restcountries.eu/rest/v2/all")!)
extension Array: Loadable where Element == Country {
static var request: URLRequest {
return URLRequest(url: URL(string: "https://restcountries.eu/rest/v2/all")!)
}
}
extension URLSession {
func load<A>(_ r: Resource<A>, callback: @escaping (Result<A, Error>) -> ()) {
dataTask(with: r.request) { data, response, err in
callback(Result {
if let e = err { throw e }
guard let d = data else { fatalError() }
return try r.parse(d)
})
}.resume()
}
func load<A: Loadable>(_ type: A.Type, callback: @escaping (Result<A, Error>) -> ()) {
dataTask(with: type.request) { data, response, err in
callback(Result {
if let e = err { throw e }
guard let d = data else { fatalError() }
return try type.init(parsing: d)
})
}.resume()
}
}
PlaygroundPage.current.needsIndefiniteExecution = true
URLSession.shared.load(countries) { print($0) }
URLSession.shared.load([Country].self) { print($0) }
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment