Skip to content

Commit

Permalink
Workaround bridging deficiencies of Swift on Linux
Browse files Browse the repository at this point in the history
Likely temporary, but currently needed.
  • Loading branch information
neonichu committed Jan 25, 2016
1 parent 125ae42 commit 3e9db95
Show file tree
Hide file tree
Showing 4 changed files with 102 additions and 2 deletions.
4 changes: 4 additions & 0 deletions Contentful.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
A114BBC31C50EA3200DE6679 /* SyncTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = A114BBC11C50E9E200DE6679 /* SyncTests.swift */; };
A114BBC51C5107EC00DE6679 /* DeletedResource.swift in Sources */ = {isa = PBXBuildFile; fileRef = A114BBC41C5107EC00DE6679 /* DeletedResource.swift */; };
A119937D1C5252BF00749579 /* DecodableData.swift in Sources */ = {isa = PBXBuildFile; fileRef = A119937C1C5252BF00749579 /* DecodableData.swift */; };
A127DEC11C56E4E60050EF72 /* Bridging.swift in Sources */ = {isa = PBXBuildFile; fileRef = A127DEC01C56E4E60050EF72 /* Bridging.swift */; };
A17D044D1C4F974F002E568B /* UtilityTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = A17D044C1C4F974F002E568B /* UtilityTests.swift */; };
A19C743F1C47A7F5005334AD /* ContentTypeTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = A19C743E1C47A7F5005334AD /* ContentTypeTests.swift */; };
A19C74411C47A804005334AD /* EntryTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = A19C74401C47A804005334AD /* EntryTests.swift */; };
Expand Down Expand Up @@ -56,6 +57,7 @@
A114BBC11C50E9E200DE6679 /* SyncTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SyncTests.swift; sourceTree = "<group>"; };
A114BBC41C5107EC00DE6679 /* DeletedResource.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DeletedResource.swift; sourceTree = "<group>"; };
A119937C1C5252BF00749579 /* DecodableData.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DecodableData.swift; sourceTree = "<group>"; };
A127DEC01C56E4E60050EF72 /* Bridging.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Bridging.swift; sourceTree = "<group>"; };
A15193A91BB91DE700FB83CD /* Space.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Space.swift; sourceTree = "<group>"; };
A15193AB1BB91FED00FB83CD /* ContentType.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ContentType.swift; sourceTree = "<group>"; };
A15193AD1BB9236300FB83CD /* Asset.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Asset.swift; sourceTree = "<group>"; };
Expand Down Expand Up @@ -148,6 +150,7 @@
children = (
A19CA3E31B83888200A0EFCD /* Array.swift */,
A15193AD1BB9236300FB83CD /* Asset.swift */,
A127DEC01C56E4E60050EF72 /* Bridging.swift */,
A19CA3DF1B836F2500A0EFCD /* Client.swift */,
A19CA3E11B8386CC00A0EFCD /* Configuration.swift */,
A15193AB1BB91FED00FB83CD /* ContentType.swift */,
Expand Down Expand Up @@ -396,6 +399,7 @@
A19CA3E81B83890D00A0EFCD /* Resource.swift in Sources */,
A1B2E3651BBACF2C00814D63 /* Decoding.swift in Sources */,
A10FF9D51BBB3676001AA4E9 /* Error.swift in Sources */,
A127DEC11C56E4E60050EF72 /* Bridging.swift in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
Expand Down
51 changes: 51 additions & 0 deletions Sources/Bridging.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
//
// Bridging.swift
// Contentful
//
// Created by Boris Bügling on 26/01/16.
// Copyright © 2016 Contentful GmbH. All rights reserved.
//

/*
This is needed with Swift 2.2 snapshots as of 2016/01/26, probably can go away in the future.
*/

import Foundation

#if os(Linux)
func bridge(any: Any) -> AnyObject {
if let any = any as? [String:Any] { return bridge(any) }

if let any = any as? [Any] {
let array = NSMutableArray()
any.forEach { array.addObject(bridge($0)) }
return array
}

if let any = any as? String { return NSString(string: any) }
if let any = any as? Bool { return NSNumber(bool: any) }
if let any = any as? Double { return NSNumber(double: any) }

fatalError("Could not bridge \(any.dynamicType)")
}

func bridge(dict: [String:Any]) -> NSDictionary {
let result = NSMutableDictionary()
for (key, obj) in dict {
if let obj = obj as? AnyObject {
result.setObject(obj, forKey: NSString(string: key))
} else {
result.setObject(bridge(obj), forKey: NSString(string: key))
}
}
return result
}

func bridge(array: [NSObject:AnyObject]) -> [String:AnyObject] {
var result = [String:AnyObject]()
for (key, value) in array {
result[key.description] = value
}
return result
}
#endif
13 changes: 11 additions & 2 deletions Sources/Client.swift
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import Interstellar
#if os(Linux)
import RequestSession

public typealias NSURLResponse = RequestSession.HTTPURLResponse
typealias NSURLSession = RequestSession.HTTPSession
typealias NSURLSessionConfiguration = RequestSession.HTTPSessionConfiguration
public typealias NSURLSessionDataTask = RequestSession.HTTPSessionDataTask
Expand Down Expand Up @@ -75,8 +76,12 @@ public class Client {

private func handleJSON<T: Decodable>(data: NSData, _ completion: Result<T> -> Void) {
do {
let json = try NSJSONSerialization.JSONObjectWithData(data, options: []) as! AnyObject
#if os(Linux)
let json = bridge(try NSJSONSerialization.JSONObjectWithData(data, options: []) as! [String : Any])
#else
let json = try NSJSONSerialization.JSONObjectWithData(data, options: [])
if let json = json as? NSDictionary { json.client = self }
#endif
completion(.Success(try T.decode(json)))
} catch let error as DecodingError {
completion(.Error(Error.UnparseableJSON(data: data, errorMessage: error.debugDescription)))
Expand Down Expand Up @@ -300,7 +305,11 @@ extension Client {
*/
public func initialSync(matching: [String:AnyObject] = [String:AnyObject](), completion: Result<SyncSpace> -> Void) -> NSURLSessionDataTask? {
var parameters = matching
parameters["initial"] = true as? AnyObject
#if os(Linux)
parameters["initial"] = NSNumber(bool: true)
#else
parameters["initial"] = true
#endif
return sync(parameters, completion: completion)
}

Expand Down
36 changes: 36 additions & 0 deletions Sources/Decoding.swift
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,13 @@ private func determineDefaultLocale(json: AnyObject) -> String {
}

private func parseLocalizedFields(json: AnyObject) throws -> (String, [String:[String:Any]]) {
#if os(Linux)
let fields = bridge((try json => "fields" as! NSDictionary).bridge())
let locale: String? = ((try? json => "sys" => "locale") as? NSString)?.bridge()
#else
let fields = try json => "fields" as! [String:AnyObject]
let locale: String? = try? json => "sys" => "locale"
#endif

var localizedFields = [String:[String:Any]]()

Expand Down Expand Up @@ -191,6 +196,17 @@ extension Entry: Decodable {
public static func decode(json: AnyObject) throws -> Entry {
let (locale, localizedFields) = try parseLocalizedFields(json)

#if os(Linux)
return try Entry(
sys: bridge((json => "sys" as! NSDictionary).bridge()),
localizedFields: localizedFields,
defaultLocale: determineDefaultLocale(json),

identifier: (json => "sys" => "id" as! NSString).bridge(),
type: (json => "sys" => "type" as! NSString).bridge(),
locale: locale
)
#else
return try Entry(
sys: (json => "sys") as! [String : AnyObject],
localizedFields: localizedFields,
Expand All @@ -200,6 +216,7 @@ extension Entry: Decodable {
type: json => "sys" => "type",
locale: locale
)
#endif
}
}

Expand Down Expand Up @@ -234,11 +251,19 @@ extension Field: Decodable {
extension Locale: Decodable {
/// Decode JSON for a Locale
public static func decode(json: AnyObject) throws -> Locale {
#if os(Linux)
return try Locale(
code: (json => "code" as! NSString).bridge(),
isDefault: (json => "default" as! NSNumber).boolValue,
name: (json => "name" as! NSString).bridge()
)
#else
return try Locale(
code: json => "code",
isDefault: json => "default",
name: json => "name"
)
#endif
}
}

Expand All @@ -260,6 +285,16 @@ private extension Resource {
extension Space: Decodable {
/// Decode JSON for a Space
public static func decode(json: AnyObject) throws -> Space {
#if os(Linux)
return try Space(
sys: bridge((json => "sys" as! NSDictionary).bridge()),

identifier: (json => "sys" => "id" as! NSString).bridge(),
locales: json => "locales",
name: (json => "name" as! NSString).bridge(),
type: (json => "sys" => "type" as! NSString).bridge()
)
#else
return try Space(
sys: (json => "sys") as! [String : AnyObject],

Expand All @@ -268,6 +303,7 @@ extension Space: Decodable {
name: json => "name",
type: json => "sys" => "type"
)
#endif
}
}

Expand Down

0 comments on commit 3e9db95

Please sign in to comment.