-
Notifications
You must be signed in to change notification settings - Fork 87
/
Content.swift
90 lines (72 loc) · 2.55 KB
/
Content.swift
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
import Venice
import Core
public enum ContentError : Error {
case unsupportedType
}
public protocol Content {
static var mediaType: MediaType { get }
static func parse(from readable: Readable, deadline: Deadline) throws -> Self
func serialize(to writable: Writable, deadline: Deadline) throws
}
extension Content {
public static func parse(_ buffer: UnsafeRawBufferPointer, deadline: Deadline) throws -> Self {
let readable = BufferReadable(buffer: buffer)
return try parse(from: readable, deadline: deadline)
}
}
public protocol ContentConvertible {
static var contentTypes: ContentTypes<Self> { get }
}
public struct ContentTypes<T> : ExpressibleByArrayLiteral, Sequence {
var types: [ContentType<T>]
public init(arrayLiteral types: ContentType<T>...) {
self.types = types
}
public func makeIterator() -> IndexingIterator<Array<ContentType<T>>> {
return types.makeIterator()
}
public var `default`: ContentType<T>? {
return types.first
}
}
public struct ContentType<T> {
public typealias Initialize<C> = (C) throws -> T
public typealias Represent<C> = (T) -> (Void) -> C
public typealias InitializeContent = (Content) throws -> T
public typealias RepresentContent = (T) -> (Void) -> Content
public let type: Content.Type
public let mediaType: MediaType
public let initialize: InitializeContent?
public let represent: RepresentContent?
public init<C : Content>(
_ initialize: @escaping Initialize<C>,
_ represent: @escaping Represent<C>
) {
self.type = C.self
self.mediaType = type.mediaType
self.initialize = { content in
guard let content = content as? C else {
throw ContentError.unsupportedType
}
return try initialize(content)
}
self.represent = { represent($0) }
}
public init<C : Content>(_ initialize: @escaping Initialize<C>) {
self.type = C.self
self.mediaType = type.mediaType
self.represent = nil
self.initialize = { content in
guard let content = content as? C else {
throw ContentError.unsupportedType
}
return try initialize(content)
}
}
public init<C : Content>(_ represent: @escaping Represent<C>) {
self.type = C.self
self.mediaType = type.mediaType
self.initialize = nil
self.represent = { represent($0) }
}
}