0001    //
0002    //  Operators.swift
0003    //  Decodable
0004    //
0005    //  Created by Johannes Lund on 2015-07-08.
0006    //  Copyright © 2015 anviking. All rights reserved.
0007    //
0008    
0009    import Foundation
0010    
0011    // MARK: - Operators
0012    
0013    infix operator => { associativity right precedence 150 }
0014    infix operator =>? { associativity right precedence 150 }
0015    
0016    /// Try to decode as T, or throw
0017    public func => <T: Decodable>(lhs: AnyObject, rhs: String) throws -> T {
0018        return try parse(lhs, path: rhs, decode: T.decode)
0019    }
0020    
0021    /// Do not decode. Without an inferred return type, this overload will be called.
0022    public func => (lhs: AnyObject, rhs: String) throws -> AnyObject {
0023        return try parse(lhs, path: rhs, decode: { $0 })
0024    }
0025    
0026    /// Try to decode as T, or throw. Will return nil if the object at the keypath is NSNull.
0027    public func => <T: Decodable>(lhs: AnyObject, rhs: String) throws -> T? {
0028        return try parse(lhs, path: rhs, decode: catchNull(T.decode))
0029    }
0030    
0031    // MARK: Arrays
0032    
0033    /// Try to decode as NSArray, and decode each element as T. Will throw if decoding of any element in the array throws. I.e, if one element is faulty the entire array is "thrown away".
0034    public func => <T: Decodable>(lhs: AnyObject, rhs: String) throws -> [T] {
0035        return try parse(lhs, path: rhs, decode: decodeArray(T.decode))
0036    }
0037    
0038    /// Try to decode as NSArray, and decode each element as T. Will return nil if the object at the keypath is NSNull. Will throw if decoding of any element in the array throws. I.e, if one element is faulty the entire array is "thrown away".
0039    public func => <T: Decodable>(lhs: AnyObject, rhs: String) throws -> [T]? {
0040        return try parse(lhs, path: rhs, decode: catchNull(decodeArray(T.decode)))
0041    }
0042    
0043    /// Try to decode as NSArray, and decode each element as T or nil, if the element is NSNull.
0044    public func => <T: Decodable>(lhs: AnyObject, rhs: String) throws -> [T?] {
0045        return try parse(lhs, path: rhs, decode: decodeArray(catchNull(T.decode)))
0046    }
0047    
0048    /// Try to decode as NSArray, and decode each element as T or nil, if the element is NSNull, and the entire array will also be nil if the object at the keypath is NSNull.
0049    public func => <T: Decodable>(lhs: AnyObject, rhs: String) throws -> [T?]? {
0050        return try parse(lhs, path: rhs, decode: catchNull(decodeArray(catchNull(T.decode))))
0051    }
0052    
0053    // MARK: Dictionary 
0054    
0055    /// Try to decode as NSDictionary. Map the dictionary using the decode function on K and T. Does not handle, or object to duplicate keys (last to be set wins).
0056    public func => <T: Decodable>(lhs: AnyObject, rhs: String) throws -> [String: T] {
0057        return try parse(lhs, path: rhs, decode: decodeDictionary(String.decode, elementDecodeClosure: T.decode))
0058    }
0059    
0060    /// Try to decode as NSDictionary?. Returns nil if object at path is NSNull. Map the dictionary using the decode function on K and T. Does not handle, or object to duplicate keys (last to be set wins).
0061    public func => <T: Decodable>(lhs: AnyObject, rhs: String) throws -> [String: T]? {
0062        return try parse(lhs, path: rhs, decode: catchNull(decodeDictionary(String.decode, elementDecodeClosure: T.decode)))
0063    }
0064    
0065    /// Try to decode as NSDictionary?. Returns nil if object at path is NSNull. Maps key with K.decode. This is a workaround to ensure that there is only one => overload without generic types to avoid ambiguity.
0066    public func => <K: Decodable>(lhs: AnyObject, rhs: String) throws -> [K: AnyObject]? {
0067        return try parse(lhs, path: rhs, decode: catchNull(decodeDictionary(K.decode, elementDecodeClosure: {$0})))
0068    }
0069    
0070    // MARK: =>?
0071    
0072    /// Do not decode. Without an inferred return type, this overload will be called. Will return nil if the object at the keypath is NSNull or the keypath is missing.
0073    public func =>? (lhs: AnyObject, rhs: String) throws -> AnyObject? {
0074        return try parseAndAcceptMissingKey(lhs, path: rhs, decode: { $0 })
0075    }
0076    
0077    /// Try to decode as T, or throw. Will return nil if the object at the keypath is NSNull or the keypath is missing.
0078    public func =>? <T: Decodable>(lhs: AnyObject, rhs: String) throws -> T? {
0079        return try parseAndAcceptMissingKey(lhs, path: rhs, decode: T.decode)
0080    }
0081    
0082    // MARK: Arrays
0083    
0084    /// Try to decode as NSArray, and decode each element as T. Will return nil if the object at the keypath is NSNull or the keypath is missing. Will throw if decoding of any element in the array throws. I.e, if one element is faulty the entire array is "thrown away".
0085    public func =>? <T: Decodable>(lhs: AnyObject, rhs: String) throws -> [T]? {
0086        return try parseAndAcceptMissingKey(lhs, path: rhs, decode: decodeArray(T.decode))
0087    }
0088    
0089    /// Try to decode as NSArray, and decode each element as T or nil, if the element is NSNull. Will return nil if the object at the keypath is NSNull or the keypath is missing.
0090    public func =>? <T: Decodable>(lhs: AnyObject, rhs: String) throws -> [T?]? {
0091        return try parseAndAcceptMissingKey(lhs, path: rhs, decode: decodeArray(catchNull(T.decode)))
0092    }
0093    
0094    // MARK: Dictionary
0095    
0096    /// Try to decode as NSDictionary?. Returns nil if the object at the keypath is NSNull or the keypath is missing. Maps the dictionary using the decode function on K and T. Does not handle, or object to duplicate keys (last to be set wins).
0097    public func =>? <T: Decodable>(lhs: AnyObject, rhs: String) throws -> [String: T]? {
0098        return try parseAndAcceptMissingKey(lhs, path: rhs, decode: decodeDictionary(String.decode, elementDecodeClosure: T.decode) )
0099    }
0100    
0101    /// Try to decode as NSDictionary?. Returns nil if object at the keypath is NSNull or the keypath is missing. Maps key with K.decode. This is a workaround to ensure that there is only one => overload without generic types to avoid ambiguity.
0102    public func =>? <K: Decodable>(lhs: AnyObject, rhs: String) throws -> [K: AnyObject]? {
0103        return try parseAndAcceptMissingKey(lhs, path: rhs, decode: decodeDictionary(K.decode, elementDecodeClosure: {$0}))
0104    }
0105    
0106    
0107    // MARK: - JSONPath
0108    
0109    /// Enables parsing nested objects e.g json => "a" => "b"
0110    /// Uses \u{0} (null) as a separator
0111    public func => (lhs: String, rhs: String) -> String {
0112        return lhs + String(JSONPathSeparator) + rhs
0113    }
0114    
0115    // You can't have this in a key. Sorry.
0116    // This dramatically simplifies the implementation, halves the number of overloads required.
0117    // If this is a bad idea, please tell me.
0118    // http://stackoverflow.com/questions/1879860/most-reliable-split-character
0119    private let JSONPathSeparator
Operators.swift:112
    return lhs + String(JSONPathSeparator) + rhs
Operators.swift:123
		return self.characters.split(JSONPathSeparator).map(String.init)
= Character("\u{0}") 0120 0121 private extension String { 0122 func toJSONPathArray
Operators.swift:140
    return try parse(json, path: path.toJSONPathArray(), decode: decode)
Operators.swift:144
    return try parseAndAcceptMissingKey(json, path: path.toJSONPathArray(), decode: decode)
() -> [String] { 0123 return self.characters.split(JSONPathSeparator).map(String.init) 0124 } 0125 } 0126 0127 // MARK: Helpers 0128 0129 func catchNull
Operators.swift:28
    return try parse(lhs, path: rhs, decode: catchNull(T.decode))
Operators.swift:40
    return try parse(lhs, path: rhs, decode: catchNull(decodeArray(T.decode)))
Operators.swift:45
    return try parse(lhs, path: rhs, decode: decodeArray(catchNull(T.decode)))
Operators.swift:50
    return try parse(lhs, path: rhs, decode: catchNull(decodeArray(catchNull(T.decode))))
Operators.swift:50
    return try parse(lhs, path: rhs, decode: catchNull(decodeArray(catchNull(T.decode))))
Operators.swift:62
    return try parse(lhs, path: rhs, decode: catchNull(decodeDictionary(String.decode, elementDecodeClosure: T.decode)))
Operators.swift:67
    return try parse(lhs, path: rhs, decode: catchNull(decodeDictionary(K.decode, elementDecodeClosure: {$0})))
Operators.swift:91
    return try parseAndAcceptMissingKey(lhs, path: rhs, decode: decodeArray(catchNull(T.decode)))
Parse.swift:38
    return try catchAndRethrow(json, path) { try catchNull(decode)(object) }
<T>(decodeClosure: (AnyObject) throws -> T) -> (AnyObject) throws -> T? { 0130 return { json in 0131 if json is NSNull { 0132 return nil 0133 } else { 0134 return try decodeClosure(json) 0135 } 0136 } 0137 } 0138 0139 private func parse
Operators.swift:18
    return try parse(lhs, path: rhs, decode: T.decode)
Operators.swift:23
    return try parse(lhs, path: rhs, decode: { $0 })
Operators.swift:28
    return try parse(lhs, path: rhs, decode: catchNull(T.decode))
Operators.swift:35
    return try parse(lhs, path: rhs, decode: decodeArray(T.decode))
Operators.swift:40
    return try parse(lhs, path: rhs, decode: catchNull(decodeArray(T.decode)))
Operators.swift:45
    return try parse(lhs, path: rhs, decode: decodeArray(catchNull(T.decode)))
Operators.swift:50
    return try parse(lhs, path: rhs, decode: catchNull(decodeArray(catchNull(T.decode))))
Operators.swift:57
    return try parse(lhs, path: rhs, decode: decodeDictionary(String.decode, elementDecodeClosure: T.decode))
Operators.swift:62
    return try parse(lhs, path: rhs, decode: catchNull(decodeDictionary(String.decode, elementDecodeClosure: T.decode)))
Operators.swift:67
    return try parse(lhs, path: rhs, decode: catchNull(decodeDictionary(K.decode, elementDecodeClosure: {$0})))
<T>(json: AnyObject, path: String, decode: (AnyObject throws -> T)) throws -> T { 0140 return try parse(json, path: path.toJSONPathArray(), decode: decode) 0141 } 0142 0143 private func parseAndAcceptMissingKey
Operators.swift:74
    return try parseAndAcceptMissingKey(lhs, path: rhs, decode: { $0 })
Operators.swift:79
    return try parseAndAcceptMissingKey(lhs, path: rhs, decode: T.decode)
Operators.swift:86
    return try parseAndAcceptMissingKey(lhs, path: rhs, decode: decodeArray(T.decode))
Operators.swift:91
    return try parseAndAcceptMissingKey(lhs, path: rhs, decode: decodeArray(catchNull(T.decode)))
Operators.swift:98
    return try parseAndAcceptMissingKey(lhs, path: rhs, decode: decodeDictionary(String.decode, elementDecodeClosure: T.decode) )
Operators.swift:103
    return try parseAndAcceptMissingKey(lhs, path: rhs, decode: decodeDictionary(K.decode, elementDecodeClosure: {$0}))
<T>(json: AnyObject, path: String, decode: (AnyObject throws -> T)) throws -> T? { 0144 return try parseAndAcceptMissingKey(json, path: path.toJSONPathArray(), decode: decode) 0145 } 0146 0147