Skip to content

Commit

Permalink
improve content negotiation
Browse files Browse the repository at this point in the history
  • Loading branch information
paulofaria committed May 26, 2017
1 parent 983b444 commit 13d202e
Show file tree
Hide file tree
Showing 31 changed files with 792 additions and 235 deletions.
1 change: 1 addition & 0 deletions Package.swift
Expand Up @@ -14,6 +14,7 @@ let package = Package(
Target(name: "Content", dependencies: ["CYAJL", "Core"]),
Target(name: "Crypto", dependencies: ["Core", "CArgon2"]),
Target(name: "IO", dependencies: ["Core", "CDsock"]),
Target(name: "JWT", dependencies: ["Crypto", "Content"]),
Target(name: "HTTP", dependencies: ["Content", "IO", "CHTTPParser"]),
],
dependencies: [
Expand Down
7 changes: 7 additions & 0 deletions Sources/Content/Content/Content.swift
Expand Up @@ -11,6 +11,13 @@ public protocol Content {
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 }
}
Expand Down
30 changes: 15 additions & 15 deletions Sources/Content/JSON/JSON.swift
@@ -1,9 +1,9 @@
import Foundation

public enum JSONError : Error {
case noContent(type: JSONInitializable.Type)
case cannotInitializeWithContent(type: JSONInitializable.Type, content: Content.Type)
case cannotInitialize(type: JSONInitializable.Type, json: JSON)
case noContent(type: Any.Type)
case cannotInitializeWithContent(type: Any.Type, content: Content.Type)
case cannotInitialize(type: Any.Type, json: JSON)
case valueNotArray(indexPath: [IndexPathComponentValue], json: JSON)
case outOfBounds(indexPath: [IndexPathComponentValue], json: JSON)
case valueNotDictionary(indexPath: [IndexPathComponentValue], json: JSON)
Expand Down Expand Up @@ -39,7 +39,7 @@ public enum JSON {
case int(Int)
case string(String)
case array([JSON])
case dictionary([String: JSON])
case object([String: JSON])
}

extension JSON {
Expand Down Expand Up @@ -75,7 +75,7 @@ extension JSON {
dictionary[key] = value
}

self = .dictionary(dictionary)
self = .object(dictionary)
} else {
self = .null
}
Expand All @@ -90,7 +90,7 @@ extension JSON {
dictionary[key] = value
}

self = .dictionary(dictionary)
self = .object(dictionary)
} else {
self = .null
}
Expand Down Expand Up @@ -138,15 +138,15 @@ extension String : IndexPathComponent {

extension JSON {
public func get<T : JSONInitializable>(_ indexPath: IndexPathComponent...) throws -> T {
let content = try get(indexPath)
let content = try _get(indexPath as [IndexPathComponent])
return try T(json: content)
}

public func get(_ indexPath: IndexPathComponent...) throws -> JSON {
return try get(indexPath)
return try _get(indexPath as [IndexPathComponent])
}

private func get(_ indexPath: [IndexPathComponent]) throws -> JSON {
private func _get(_ indexPath: [IndexPathComponent]) throws -> JSON {
var value = self
var visited: [IndexPathComponentValue] = []

Expand All @@ -165,7 +165,7 @@ extension JSON {

value = array[index]
case let .key(key):
guard case let .dictionary(dictionary) = value else {
guard case let .object(dictionary) = value else {
throw JSONError.valueNotDictionary(indexPath: visited, json: self)
}

Expand All @@ -191,7 +191,7 @@ extension JSON : Equatable {
case let (.string(l), .string(r)) where l == r: return true
case let (.double(l), .double(r)) where l == r: return true
case let (.array(l), .array(r)) where l == r: return true
case let (.dictionary(l), .dictionary(r)) where l == r: return true
case let (.object(l), .object(r)) where l == r: return true
default: return false
}
}
Expand Down Expand Up @@ -244,21 +244,21 @@ extension JSON : ExpressibleByStringLiteral {

extension JSON : ExpressibleByArrayLiteral {
/// :nodoc:
public init(arrayLiteral elements: JSONRepresentable...) {
public init(arrayLiteral elements: JSON...) {
self = .array(elements.map({ $0.json() }))
}
}

extension JSON : ExpressibleByDictionaryLiteral {
/// :nodoc:
public init(dictionaryLiteral elements: (String, JSONRepresentable)...) {
public init(dictionaryLiteral elements: (String, JSON)...) {
var dictionary = [String: JSON](minimumCapacity: elements.count)

for (key, value) in elements {
dictionary[key] = value.json()
}

self = .dictionary(dictionary)
self = .object(dictionary)
}
}

Expand Down Expand Up @@ -300,7 +300,7 @@ extension JSON : CustomStringConvertible {
case .int(let number): return String(number)
case .string(let string): return escape(string)
case .array(let array): return serialize(array: array)
case .dictionary(let dictionary): return serialize(dictionary: dictionary)
case .object(let dictionary): return serialize(dictionary: dictionary)
}
}

Expand Down
40 changes: 29 additions & 11 deletions Sources/Content/JSON/JSONConvertible.swift
@@ -1,23 +1,41 @@
import struct Foundation.Data
import struct Foundation.UUID

public protocol JSONInitializable {
public protocol JSONInitializable : ContentConvertible {
init(json: JSON) throws
}

public protocol JSONRepresentable {
extension JSONInitializable {
public static var contentTypes: ContentTypes<Self> {
return [
ContentType(Self.init(json:))
]
}
}

public protocol JSONRepresentable : ContentConvertible {
func json() -> JSON
}

public protocol JSONConvertible : ContentConvertible, JSONInitializable, JSONRepresentable {}
extension JSONRepresentable {
public static var contentTypes: ContentTypes<Self> {
return [
ContentType(Self.json)
]
}
}

public protocol JSONConvertible : JSONInitializable, JSONRepresentable {}

extension JSONConvertible {
static var contentTypes: ContentTypes<Self> {
return [ContentType(Self.init(json:), Self.json)]
public static var contentTypes: ContentTypes<Self> {
return [
ContentType(Self.init(json:), Self.json)
]
}
}

extension JSON : JSONInitializable, JSONRepresentable {
extension JSON : JSONConvertible {
public init(json: JSON) throws {
self = json
}
Expand All @@ -27,7 +45,7 @@ extension JSON : JSONInitializable, JSONRepresentable {
}
}

extension Int : JSONInitializable, JSONRepresentable {
extension Int : JSONConvertible {
public init(json: JSON) throws {
guard case let .int(value) = json else {
throw JSONError.cannotInitialize(type: type(of: self), json: json)
Expand All @@ -41,7 +59,7 @@ extension Int : JSONInitializable, JSONRepresentable {
}
}

extension Bool : JSONInitializable, JSONRepresentable {
extension Bool : JSONConvertible {
public init(json: JSON) throws {
guard case let .bool(value) = json else {
throw JSONError.cannotInitialize(type: type(of: self), json: json)
Expand All @@ -55,7 +73,7 @@ extension Bool : JSONInitializable, JSONRepresentable {
}
}

extension String : JSONInitializable, JSONRepresentable {
extension String : JSONConvertible {
public init(json: JSON) throws {
guard case let .string(value) = json else {
throw JSONError.cannotInitialize(type: type(of: self), json: json)
Expand All @@ -69,7 +87,7 @@ extension String : JSONInitializable, JSONRepresentable {
}
}

extension Double : JSONInitializable, JSONRepresentable {
extension Double : JSONConvertible {
public init(json: JSON) throws {
guard case let .double(value) = json else {
throw JSONError.cannotInitialize(type: type(of: self), json: json)
Expand All @@ -83,7 +101,7 @@ extension Double : JSONInitializable, JSONRepresentable {
}
}

extension UUID : JSONInitializable, JSONRepresentable {
extension UUID : JSONConvertible {
public init(json: JSON) throws {
guard case let .string(value) = json, let uuid = UUID(uuidString: value) else {
throw JSONError.cannotInitialize(type: type(of: self), json: json)
Expand Down
32 changes: 16 additions & 16 deletions Sources/Content/JSON/JSONParser.swift
Expand Up @@ -114,9 +114,9 @@ public final class JSONParser {
}

if stack.count == 0 || final {
switch state.content {
case .dictionary(let value):
result = value["root"]
switch state.json {
case .object(let object):
result = object["root"]
default:
break
}
Expand Down Expand Up @@ -176,7 +176,7 @@ public final class JSONParser {
}

var previousState = stack.removeLast()
let result: Int32 = previousState.append(state.content)
let result: Int32 = previousState.append(state.json)
state = previousState
return result
}
Expand All @@ -193,7 +193,7 @@ public final class JSONParser {
}

var previousState = stack.removeLast()
let result: Int32 = previousState.append(state.content)
let result: Int32 = previousState.append(state.json)
state = previousState
return result
}
Expand All @@ -203,32 +203,32 @@ fileprivate struct JSONParserState {
let isDictionary: Bool
var dictionaryKey: String = ""

var content: JSON {
var json: JSON {
if isDictionary {
return .dictionary(dictionary)
return .object(object)
} else {
return .array(array)
}
}

private var dictionary: [String: JSON]
private var object: [String: JSON]
private var array: [JSON]

init(dictionary: Bool) {
self.isDictionary = dictionary
if dictionary {
self.dictionary = Dictionary<String, JSON>(minimumCapacity: 32)
self.object = Dictionary<String, JSON>(minimumCapacity: 32)
self.array = []
} else {
self.dictionary = [:]
self.object = [:]
self.array = []
self.array.reserveCapacity(32)
}
}

mutating func append(_ value: Bool) -> Int32 {
if isDictionary {
dictionary[dictionaryKey] = .bool(value)
object[dictionaryKey] = .bool(value)
} else {
array.append(.bool(value))
}
Expand All @@ -238,7 +238,7 @@ fileprivate struct JSONParserState {

mutating func append(_ value: Int64) -> Int32 {
if isDictionary {
dictionary[self.dictionaryKey] = .int(Int(value))
object[self.dictionaryKey] = .int(Int(value))
} else {
array.append(.int(Int(value)))
}
Expand All @@ -248,7 +248,7 @@ fileprivate struct JSONParserState {

mutating func append(_ value: Double) -> Int32 {
if isDictionary {
dictionary[dictionaryKey] = .double(value)
object[dictionaryKey] = .double(value)
} else {
array.append(.double(value))
}
Expand All @@ -258,7 +258,7 @@ fileprivate struct JSONParserState {

mutating func append(_ value: String) -> Int32 {
if isDictionary {
dictionary[dictionaryKey] = .string(value)
object[dictionaryKey] = .string(value)
} else {
array.append(.string(value))
}
Expand All @@ -268,7 +268,7 @@ fileprivate struct JSONParserState {

mutating func appendNull() -> Int32 {
if isDictionary {
dictionary[dictionaryKey] = .null
object[dictionaryKey] = .null
} else {
array.append(.null)
}
Expand All @@ -278,7 +278,7 @@ fileprivate struct JSONParserState {

mutating func append(_ value: JSON) -> Int32 {
if isDictionary {
dictionary[dictionaryKey] = value
object[dictionaryKey] = value
} else {
array.append(value)
}
Expand Down
4 changes: 2 additions & 2 deletions Sources/Content/JSON/JSONSerializer.swift
Expand Up @@ -56,8 +56,8 @@ public final class JSONSerializer {
try generate(string)
case .array(let array):
try generate(array, body: body)
case .dictionary(let dictionary):
try generate(dictionary, body: body)
case .object(let object):
try generate(object, body: body)
}

try write(highwater: bufferSize, body: body)
Expand Down
8 changes: 1 addition & 7 deletions Sources/Content/PlainText/PlainText.swift
Expand Up @@ -18,13 +18,7 @@ public protocol PlainTextRepresentable {
func plainText() -> PlainText
}

public protocol PlainTextConvertible : ContentConvertible, PlainTextInitializable, PlainTextRepresentable {}

extension PlainTextConvertible {
static var contentTypes: ContentTypes<Self> {
return [ContentType(Self.init(plainText:), Self.plainText)]
}
}
public protocol PlainTextConvertible : PlainTextInitializable, PlainTextRepresentable {}

extension PlainText : PlainTextInitializable {
public init(plainText: PlainText) throws {
Expand Down
10 changes: 5 additions & 5 deletions Sources/Content/XML/XML.swift
Expand Up @@ -106,15 +106,15 @@ public final class XML {
}

public func get(_ indexPath: IndexPathComponent...) throws -> XML {
return try get(indexPath)
return try _get(indexPath as [IndexPathComponent])
}

public func get(_ indexPath: IndexPathComponent...) throws -> [XML] {
return try get(indexPath)
return try _get(indexPath as [IndexPathComponent])
}

func get(_ indexPath: [IndexPathComponent]) throws -> XML {
let elements: [XML] = try get(indexPath)
internal func _get(_ indexPath: [IndexPathComponent]) throws -> XML {
let elements: [XML] = try _get(indexPath)

guard elements.count == 1, let element = elements.first else {
throw XMLError.valueNotFound(indexPath: [], content: "")
Expand All @@ -123,7 +123,7 @@ public final class XML {
return element
}

func get(_ indexPath: [IndexPathComponent]) throws -> [XML] {
internal func _get(_ indexPath: [IndexPathComponent]) throws -> [XML] {
var value = [self]
var single = true
var visited: [IndexPathComponentValue] = []
Expand Down

0 comments on commit 13d202e

Please sign in to comment.