diff --git a/Socket.IO-Client-Swift.xcodeproj/project.pbxproj b/Socket.IO-Client-Swift.xcodeproj/project.pbxproj index 3315a7a..3800e67 100644 --- a/Socket.IO-Client-Swift.xcodeproj/project.pbxproj +++ b/Socket.IO-Client-Swift.xcodeproj/project.pbxproj @@ -43,6 +43,8 @@ 74781D5C1B7E83930042CACA /* SocketIOClientStatus.swift in Sources */ = {isa = PBXBuildFile; fileRef = 74781D591B7E83930042CACA /* SocketIOClientStatus.swift */; }; 74781D5D1B7E83930042CACA /* SocketIOClientStatus.swift in Sources */ = {isa = PBXBuildFile; fileRef = 74781D591B7E83930042CACA /* SocketIOClientStatus.swift */; }; 941A4ABA1B67A56C00C42318 /* TestKind.swift in Sources */ = {isa = PBXBuildFile; fileRef = 941A4AB91B67A56C00C42318 /* TestKind.swift */; }; + 9421F5D01B9DBF5900D625BB /* SocketGenericParser.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9421F5CF1B9DBF5900D625BB /* SocketGenericParser.swift */; settings = {ASSET_TAGS = (); }; }; + 9421F5D11B9DBF5900D625BB /* SocketGenericParser.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9421F5CF1B9DBF5900D625BB /* SocketGenericParser.swift */; settings = {ASSET_TAGS = (); }; }; 94242BB81B67B0E500AAAC9D /* SocketNamespaceAcknowledgementTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 94242BB71B67B0E500AAAC9D /* SocketNamespaceAcknowledgementTest.swift */; }; 945B65351B5FCEEA0081E995 /* SocketAckManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5764DF7C1B51F254004FF46E /* SocketAckManager.swift */; }; 945B65361B5FCEEA0081E995 /* SocketAnyEvent.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5764DF7D1B51F254004FF46E /* SocketAnyEvent.swift */; }; @@ -58,6 +60,8 @@ 945B65401B5FCEEA0081E995 /* SwiftRegex.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5764DF871B51F254004FF46E /* SwiftRegex.swift */; }; 945B65411B5FCEEA0081E995 /* WebSocket.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5764DF881B51F254004FF46E /* WebSocket.swift */; }; 945B65431B63D9DB0081E995 /* SocketEmitTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 945B65421B63D9DB0081E995 /* SocketEmitTest.swift */; }; + 949FAE8D1B9B94E600073BE9 /* SocketParserTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 949FAE8C1B9B94E600073BE9 /* SocketParserTest.swift */; settings = {ASSET_TAGS = (); }; }; + 94A20D611B99E22F00BF9E44 /* SocketAckManagerTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 94A20D601B99E22F00BF9E44 /* SocketAckManagerTest.swift */; settings = {ASSET_TAGS = (); }; }; 94ADAC491B652D3300FD79AE /* SocketNamespaceEmitTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 94ADAC481B652D3300FD79AE /* SocketNamespaceEmitTest.swift */; }; 94ADAC4B1B6632DD00FD79AE /* SocketAcknowledgementTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 94ADAC4A1B6632DD00FD79AE /* SocketAcknowledgementTest.swift */; }; 94CB8F0B1B6E48B90019ED53 /* SocketTestCases.swift in Sources */ = {isa = PBXBuildFile; fileRef = 94CB8F0A1B6E48B90019ED53 /* SocketTestCases.swift */; }; @@ -108,8 +112,11 @@ 5764DF881B51F254004FF46E /* WebSocket.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = WebSocket.swift; path = SocketIOClientSwift/WebSocket.swift; sourceTree = ""; }; 74781D591B7E83930042CACA /* SocketIOClientStatus.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = SocketIOClientStatus.swift; path = SocketIOClientSwift/SocketIOClientStatus.swift; sourceTree = ""; }; 941A4AB91B67A56C00C42318 /* TestKind.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TestKind.swift; sourceTree = ""; }; + 9421F5CF1B9DBF5900D625BB /* SocketGenericParser.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SocketGenericParser.swift; sourceTree = ""; }; 94242BB71B67B0E500AAAC9D /* SocketNamespaceAcknowledgementTest.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SocketNamespaceAcknowledgementTest.swift; sourceTree = ""; }; 945B65421B63D9DB0081E995 /* SocketEmitTest.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SocketEmitTest.swift; sourceTree = ""; }; + 949FAE8C1B9B94E600073BE9 /* SocketParserTest.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SocketParserTest.swift; sourceTree = ""; }; + 94A20D601B99E22F00BF9E44 /* SocketAckManagerTest.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SocketAckManagerTest.swift; sourceTree = ""; }; 94ADAC481B652D3300FD79AE /* SocketNamespaceEmitTest.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SocketNamespaceEmitTest.swift; sourceTree = ""; }; 94ADAC4A1B6632DD00FD79AE /* SocketAcknowledgementTest.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SocketAcknowledgementTest.swift; sourceTree = ""; }; 94CB8F0A1B6E48B90019ED53 /* SocketTestCases.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SocketTestCases.swift; sourceTree = ""; }; @@ -200,7 +207,9 @@ 941A4AB91B67A56C00C42318 /* TestKind.swift */, 94CB8F0A1B6E48B90019ED53 /* SocketTestCases.swift */, 94CB8F0C1B6E66E60019ED53 /* AbstractSocketTest.swift */, + 94A20D601B99E22F00BF9E44 /* SocketAckManagerTest.swift */, 572EF2291B51F16C00EEBB58 /* Supporting Files */, + 949FAE8C1B9B94E600073BE9 /* SocketParserTest.swift */, ); path = "SocketIO-iOSTests"; sourceTree = ""; @@ -261,6 +270,7 @@ 5764DF831B51F254004FF46E /* SocketLogger.swift */, 5764DF841B51F254004FF46E /* SocketPacket.swift */, 5764DF851B51F254004FF46E /* SocketParser.swift */, + 9421F5CF1B9DBF5900D625BB /* SocketGenericParser.swift */, 5764DF861B51F254004FF46E /* SocketTypes.swift */, 5764DF871B51F254004FF46E /* SwiftRegex.swift */, 5764DF881B51F254004FF46E /* WebSocket.swift */, @@ -448,6 +458,7 @@ 5764DF911B51F254004FF46E /* SocketEventHandler.swift in Sources */, 5764DF931B51F254004FF46E /* SocketFixUTF8.swift in Sources */, 5764DF951B51F254004FF46E /* SocketIOClient.swift in Sources */, + 9421F5D01B9DBF5900D625BB /* SocketGenericParser.swift in Sources */, 5764DF8B1B51F254004FF46E /* SocketAnyEvent.swift in Sources */, 5764DF971B51F254004FF46E /* SocketLogger.swift in Sources */, 74781D5A1B7E83930042CACA /* SocketIOClientStatus.swift in Sources */, @@ -469,17 +480,20 @@ 94CB8F0B1B6E48B90019ED53 /* SocketTestCases.swift in Sources */, 945B65371B5FCEEA0081E995 /* SocketEngine.swift in Sources */, 945B65351B5FCEEA0081E995 /* SocketAckManager.swift in Sources */, + 9421F5D11B9DBF5900D625BB /* SocketGenericParser.swift in Sources */, 941A4ABA1B67A56C00C42318 /* TestKind.swift in Sources */, 94CB8F0D1B6E66E60019ED53 /* AbstractSocketTest.swift in Sources */, 945B65431B63D9DB0081E995 /* SocketEmitTest.swift in Sources */, 945B65401B5FCEEA0081E995 /* SwiftRegex.swift in Sources */, 945B653C1B5FCEEA0081E995 /* SocketLogger.swift in Sources */, + 94A20D611B99E22F00BF9E44 /* SocketAckManagerTest.swift in Sources */, 945B65381B5FCEEA0081E995 /* SocketEngineClient.swift in Sources */, 945B65361B5FCEEA0081E995 /* SocketAnyEvent.swift in Sources */, 94ADAC4B1B6632DD00FD79AE /* SocketAcknowledgementTest.swift in Sources */, 945B653F1B5FCEEA0081E995 /* SocketTypes.swift in Sources */, 74781D5B1B7E83930042CACA /* SocketIOClientStatus.swift in Sources */, 945B653B1B5FCEEA0081E995 /* SocketIOClient.swift in Sources */, + 949FAE8D1B9B94E600073BE9 /* SocketParserTest.swift in Sources */, 94ADAC491B652D3300FD79AE /* SocketNamespaceEmitTest.swift in Sources */, 945B65411B5FCEEA0081E995 /* WebSocket.swift in Sources */, 94242BB81B67B0E500AAAC9D /* SocketNamespaceAcknowledgementTest.swift in Sources */, diff --git a/SocketGenericParser.swift b/SocketGenericParser.swift new file mode 100644 index 0000000..0320084 --- /dev/null +++ b/SocketGenericParser.swift @@ -0,0 +1,52 @@ +// +// GenericSocketParser.swift +// Socket.IO-Client-Swift +// +// Created by Lukas Schmidt on 07.09.15. +// +// + +import Foundation + +struct SocketGenericParser { + let message: String + var currentIndex: Int + var messageCharacters: [Character] { + get { + return Array(message.characters) + } + } + var currentCharacter: String? { + get{ + if currentIndex >= messageCharacters.count { + return nil + } + return String(messageCharacters[currentIndex]) + } + } + + mutating func read(characterLength:Int) -> String? { + let startIndex = message.startIndex.advancedBy(currentIndex) + let range = Range(start: startIndex, end: startIndex.advancedBy(characterLength)) + currentIndex = currentIndex + characterLength + + return message.substringWithRange(range) + } + + mutating func readUntilStringOccurence(string:String) -> String? { + let startIndex = message.startIndex.advancedBy(currentIndex) + let range = Range(start: startIndex, end: message.endIndex) + let subString = message.substringWithRange(range) as NSString + let foundRange = subString.rangeOfString(string) + if foundRange.location == Int.max { + return nil + } + currentIndex = currentIndex + foundRange.location + + return subString.substringToIndex(foundRange.location) + } + + mutating func readUntilEnd() ->String { + return read(messageCharacters.count - currentIndex)! + } +} \ No newline at end of file diff --git a/SocketIO-iOSTests/SocketAckManagerTest.swift b/SocketIO-iOSTests/SocketAckManagerTest.swift new file mode 100644 index 0000000..e2664d9 --- /dev/null +++ b/SocketIO-iOSTests/SocketAckManagerTest.swift @@ -0,0 +1,26 @@ +// +// SocketAckManagerTest.swift +// Socket.IO-Client-Swift +// +// Created by Lukas Schmidt on 04.09.15. +// +// + +import XCTest + +class SocketAckManagerTest: XCTestCase { + var ackManager = SocketAckManager() + + func testAddAcks() { + let callbackExpection = self.expectationWithDescription("callbackExpection") + let itemsArray = ["Hi", "ho"] + func callback(items: NSArray?) { + callbackExpection.fulfill() + items?.isEqualToArray(itemsArray) + } + ackManager.addAck(1, callback: callback) + ackManager.executeAck(1, items: itemsArray) + waitForExpectationsWithTimeout(3.0, handler: nil) + + } +} diff --git a/SocketIO-iOSTests/SocketAcknowledgementTest.swift b/SocketIO-iOSTests/SocketAcknowledgementTest.swift index 0f1f425..4a8c7ad 100644 --- a/SocketIO-iOSTests/SocketAcknowledgementTest.swift +++ b/SocketIO-iOSTests/SocketAcknowledgementTest.swift @@ -21,11 +21,12 @@ class SocketAcknowledgementTest: AbstractSocketTest { "forcePolling": false, "forceWebsockets": false,// default false "path": ""]) + openConnection() }else { AbstractSocketTest.socket.leaveNamespace() } - openConnection() + } func testConnectionStatus() { diff --git a/SocketIO-iOSTests/SocketEmitTest.swift b/SocketIO-iOSTests/SocketEmitTest.swift index 5e58491..baffb95 100644 --- a/SocketIO-iOSTests/SocketEmitTest.swift +++ b/SocketIO-iOSTests/SocketEmitTest.swift @@ -22,11 +22,12 @@ class SocketEmitTest: AbstractSocketTest { "forceWebsockets": false,// default false "path": ""] ) + openConnection() }else { AbstractSocketTest.socket.leaveNamespace() } - openConnection() + } override func tearDown() { diff --git a/SocketIO-iOSTests/SocketNamespaceAcknowledgementTest.swift b/SocketIO-iOSTests/SocketNamespaceAcknowledgementTest.swift index a0604f3..ce7e272 100644 --- a/SocketIO-iOSTests/SocketNamespaceAcknowledgementTest.swift +++ b/SocketIO-iOSTests/SocketNamespaceAcknowledgementTest.swift @@ -22,11 +22,12 @@ class SocketNamespaceAcknowledgementTest: AbstractSocketTest { "forceWebsockets": false,// default false "path": "", "nsp": "/swift"]) + openConnection() }else { AbstractSocketTest.socket.joinNamespace("/swift") } - openConnection() + } func testConnectionStatus() { diff --git a/SocketIO-iOSTests/SocketNamespaceEmitTest.swift b/SocketIO-iOSTests/SocketNamespaceEmitTest.swift index e02ede3..9573a64 100644 --- a/SocketIO-iOSTests/SocketNamespaceEmitTest.swift +++ b/SocketIO-iOSTests/SocketNamespaceEmitTest.swift @@ -22,13 +22,12 @@ class SocketNamespaceEmitTest: AbstractSocketTest { "forceWebsockets": false,// default false "path": "", "nsp": "/swift"]) + openConnection() }else { AbstractSocketTest.socket.joinNamespace("/swift") } - - openConnection() } - + func testConnectionStatus() { super.checkConnectionStatus() } diff --git a/SocketIO-iOSTests/SocketParserTest.swift b/SocketIO-iOSTests/SocketParserTest.swift new file mode 100644 index 0000000..7198b4c --- /dev/null +++ b/SocketIO-iOSTests/SocketParserTest.swift @@ -0,0 +1,105 @@ +// +// SocketParserTest.swift +// Socket.IO-Client-Swift +// +// Created by Lukas Schmidt on 05.09.15. +// +// + +import XCTest + +class SocketParserTest: XCTestCase { + + //Format key: message; namespace-data-binary-id + static let packetTypes: Dictionary = [ + "0": ("/", [], [], -1), "1": ("/", [], [], -1), + "2/swift,[\"testArrayEmitReturn\",[\"test3\",\"test4\"]]": ("/swift", ["testArrayEmitReturn", ["test3", "test4"]], [], -1), + "51-/swift,[\"testMultipleItemsWithBufferEmitReturn\",[1,2],{\"test\":\"bob\"},25,\"polo\",{\"_placeholder\":true,\"num\":0}]": ("/swift", ["testMultipleItemsWithBufferEmitReturn", [1, 2], ["test": "bob"], 25, "polo", "~~0"], [], -1), + "3/swift,0[[\"test3\",\"test4\"]]": ("/swift", [["test3", "test4"]], [], 0), + "61-/swift,19[[1,2],{\"test\":\"bob\"},25,\"polo\",{\"_placeholder\":true,\"num\":0}]": ("/swift", [ [1, 2], ["test": "bob"], 25, "polo", "~~0"], [], 19), + "4/swift,": ("/swift", [], [], -1), + "0/swift": ("/swift", [], [], -1), + "1/swift": ("/swift", [], [], -1)] + + func testDisconnect() { + let message = "1" + validateParseResult(message) + } + + func testConnect() { + let message = "0" + validateParseResult(message) + } + + func testDisconnectNameSpace() { + let message = "1/swift" + validateParseResult(message) + } + + func testConnecttNameSpace() { + let message = "0/swift" + validateParseResult(message) + } + + func testNameSpaceArrayParse() { + let message = "2/swift,[\"testArrayEmitReturn\",[\"test3\",\"test4\"]]" + validateParseResult(message) + } + + func testNameSpaceArrayAckParse() { + let message = "3/swift,0[[\"test3\",\"test4\"]]" + validateParseResult(message) + } + + func testNameSpaceBinaryEventParse() { + let message = "51-/swift,[\"testMultipleItemsWithBufferEmitReturn\",[1,2],{\"test\":\"bob\"},25,\"polo\",{\"_placeholder\":true,\"num\":0}]" + validateParseResult(message) + } + + func testNameSpaceBinaryAckParse() { + let message = "61-/swift,19[[1,2],{\"test\":\"bob\"},25,\"polo\",{\"_placeholder\":true,\"num\":0}]" + validateParseResult(message) + } + + func testNamespaceErrorParse() { + let message = "4/swift," + validateParseResult(message) + } + + func testInvalidInput() { + let message = "8" + XCTAssertNil(SocketParser.parseString(message)) + } + + func testGenericParser() { + var parser = SocketGenericParser(message: "61-/swift,", currentIndex: 0) + XCTAssertEqual(parser.read(1), "6") + XCTAssertEqual(parser.currentCharacter, "1") + XCTAssertEqual(parser.readUntilStringOccurence("-"), "1") + XCTAssertEqual(parser.currentCharacter, "-") + } + + func validateParseResult(message:String) { + let validValues = SocketParserTest.packetTypes[message]! + let packet = SocketParser.parseString(message) + let type = message.substringWithRange(Range(start: message.startIndex, end: message.startIndex.advancedBy(1))) + if let packet = packet { + XCTAssertEqual(packet.type, SocketPacket.PacketType(str:type)!) + XCTAssertEqual(packet.nsp, validValues.0) + XCTAssertTrue((packet.data as NSArray).isEqualToArray(validValues.1)) + XCTAssertTrue((packet.binary as NSArray).isEqualToArray(validValues.2)) + XCTAssertEqual(packet.id, validValues.3) + }else { + XCTFail() + } + } + + func testParsePerformance() { + let keys = Array(SocketParserTest.packetTypes.keys) + measureBlock({ + for item in keys.enumerate() { + SocketParser.parseString(item.element) + } + }) + } +} diff --git a/SocketIOClientSwift/SocketPacket.swift b/SocketIOClientSwift/SocketPacket.swift index a8b44d3..308c1b0 100644 --- a/SocketIOClientSwift/SocketPacket.swift +++ b/SocketIOClientSwift/SocketPacket.swift @@ -62,15 +62,7 @@ struct SocketPacket { var binary: [NSData] var data: [AnyObject] var description: String { - var better = "SocketPacket {type: ~~0; data: ~~1; " + - "id: ~~2; placeholders: ~~3;}" - - better = better["~~0"] ~= String(type.rawValue) - better = better["~~1"] ~= String(data) - better = better["~~2"] ~= String(id) - better = better["~~3"] ~= String(placeholders) - - return better + return "SocketPacket {type: \(String(type.rawValue)); data: \(String(data)); id: \(id); placeholders: \(placeholders);}" } var event: String { diff --git a/SocketIOClientSwift/SocketParser.swift b/SocketIOClientSwift/SocketParser.swift index cbaff70..fc637a6 100644 --- a/SocketIOClientSwift/SocketParser.swift +++ b/SocketIOClientSwift/SocketParser.swift @@ -23,30 +23,25 @@ import Foundation class SocketParser { + private static func isCorrectNamespace(nsp: String, _ socket: SocketIOClient) -> Bool { return nsp == socket.nsp } + private static func handleEvent(p: SocketPacket, socket: SocketIOClient) { + guard isCorrectNamespace(p.nsp, socket) else { return } + socket.handleEvent(p.event, data: p.args, + isInternalMessage: false, wantsAck: p.id) + } + private static func handleAck(p: SocketPacket, socket: SocketIOClient) { - if !isCorrectNamespace(p.nsp, socket) { - return - } + guard isCorrectNamespace(p.nsp, socket) else { return } socket.handleAck(p.id, data: p.data) } - private static func handleBinaryAck(p: SocketPacket, socket: SocketIOClient) { - if !isCorrectNamespace(p.nsp, socket) { - return - } - - socket.waitingData.append(p) - } - - private static func handleBinaryEvent(p: SocketPacket, socket: SocketIOClient) { - if !isCorrectNamespace(p.nsp, socket) { - return - } + private static func handleBinary(p: SocketPacket, socket: SocketIOClient) { + guard isCorrectNamespace(p.nsp, socket) else { return } socket.waitingData.append(p) } @@ -61,169 +56,113 @@ class SocketParser { } } - private static func handleEvent(p: SocketPacket, socket: SocketIOClient) { - if !isCorrectNamespace(p.nsp, socket) { - return - } - - socket.handleEvent(p.event, data: p.args, - isInternalMessage: false, wantsAck: p.id) - } - // Translation of socket.io-client#decodeString - static func parseString(str: String) -> SocketPacket? { - let arr = Array(str.characters) - let type = String(arr[0]) - - if arr.count == 1 { - return SocketPacket(type: SocketPacket.PacketType(str: type)!, nsp: "/") + static func parseString(message: String) -> SocketPacket? { + var parser = SocketGenericParser(message: message, currentIndex: 0) + guard let typeString = parser.read(1), + let type = SocketPacket.PacketType(str: typeString) else { + return nil } - var id: Int? - var nsp:String? - var i = 0 + if parser.messageCharacters.count == 1 { + return SocketPacket(type: type, nsp: "/") + } + + var namespace: String? var placeholders = -1 - if type == "5" || type == "6" { - var buf = "" - - while arr[++i] != "-" { - buf += String(arr[i]) - if i == arr.count { - break - } - } - - if let holders = Int(buf) where arr[i] == "-" { + if type == .BinaryEvent || type == .BinaryAck { + if let buffer = parser.readUntilStringOccurence("-"), let holders = Int(buffer) + where parser.read(1)! == "-" { placeholders = holders } else { - NSLog("Error parsing \(str)") - return nil + return nil + } + } + if parser.currentCharacter == "/" { + namespace = parser.readUntilStringOccurence(",") ?? parser.readUntilEnd() + parser.currentIndex++ + } + + if parser.currentIndex >= parser.messageCharacters.count { + return SocketPacket(type: type, id: -1, + nsp: namespace ?? "/", placeholders: placeholders) + } + + var idString = "" + while parser.currentIndex < parser.messageCharacters.count { + if let next = parser.read(1), let int = Int(next) { + idString += String(int) + } else { + parser.currentIndex -= 2 + break } } - if arr[i + 1] == "/" { - nsp = "" - - while ++i < arr.count { - let c = arr[i] - - if c == "," { - break - } - - nsp! += String(c) - } - } + let d = message[message.startIndex.advancedBy(parser.currentIndex + 1)...message.startIndex.advancedBy(message.characters.count - 1)] + let noPlaceholders = d["(\\{\"_placeholder\":true,\"num\":(\\d*)\\})"] ~= "\"~~$2\"" + let data = parseData(noPlaceholders) as? [AnyObject] ?? [noPlaceholders] - if i + 1 >= arr.count { - return SocketPacket(type: SocketPacket.PacketType(str: type)!, id: id ?? -1, - nsp: nsp ?? "/", placeholders: placeholders) - } - - let next = String(arr[i + 1]) - - if Int(next) != nil { - var c = "" - while ++i < arr.count { - if let int = Int(String(arr[i])) { - c += String(int) - } else { - --i - break - } - } - - id = Int(c) - } - - if ++i < arr.count { - let d = str[str.startIndex.advancedBy(i)...str.startIndex.advancedBy(str.characters.count-1)] - let noPlaceholders = d["(\\{\"_placeholder\":true,\"num\":(\\d*)\\})"] ~= "\"~~$2\"" - let data = SocketParser.parseData(noPlaceholders) as? [AnyObject] ?? [noPlaceholders] - - return SocketPacket(type: SocketPacket.PacketType(str: type)!, data: data, id: id ?? -1, - nsp: nsp ?? "/", placeholders: placeholders) - } - - return nil + return SocketPacket(type: type, data: data, id: Int(idString) ?? -1, + nsp: namespace ?? "/", placeholders: placeholders) } // Parses data for events static func parseData(data: String) -> AnyObject? { - var err: NSError? let stringData = data.dataUsingEncoding(NSUTF8StringEncoding, allowLossyConversion: false) - let parsed: AnyObject? - do { - parsed = try NSJSONSerialization.JSONObjectWithData(stringData!, + return try NSJSONSerialization.JSONObjectWithData(stringData!, options: NSJSONReadingOptions.MutableContainers) - } catch let error as NSError { - err = error - parsed = nil - } - - if err != nil { - // println(err) + } catch { + Logger.error("Parsing JSON: %@", type: "SocketParser", args: data) return nil } - - return parsed } // Parses messages recieved - static func parseSocketMessage(stringMessage: String, socket: SocketIOClient) { - if stringMessage == "" { + static func parseSocketMessage(message: String, socket: SocketIOClient) { + guard !message.isEmpty else { return } + + Logger.log("Parsing %@", type: "SocketParser", args: message) + + guard let pack = parseString(message) else { + Logger.error("Parsing message", type: "SocketParser", args: message) return } + Logger.log("Decoded packet as: %@", type: "SocketParser", args: pack.description) - Logger.log("Parsing %@", type: "SocketParser", args: stringMessage) - - let p: SocketPacket - - if let pack = parseString(stringMessage) { - p = pack - } else { - socket.didError("Error parsing packet") - return - } - - Logger.log("Decoded packet as: %@", type: "SocketParser", args: p.description) - - switch p.type { - case SocketPacket.PacketType.Event: - handleEvent(p, socket: socket) - case SocketPacket.PacketType.Ack: - handleAck(p, socket: socket) - case SocketPacket.PacketType.BinaryEvent: - handleBinaryEvent(p, socket: socket) - case SocketPacket.PacketType.BinaryAck: - handleBinaryAck(p, socket: socket) - case SocketPacket.PacketType.Connect: - handleConnect(p, socket: socket) - case SocketPacket.PacketType.Disconnect: + switch pack.type { + case .Event: + handleEvent(pack, socket: socket) + case .Ack: + handleAck(pack, socket: socket) + case .BinaryEvent: + handleBinary(pack, socket: socket) + case .BinaryAck: + handleBinary(pack, socket: socket) + case .Connect: + handleConnect(pack, socket: socket) + case .Disconnect: socket.didDisconnect("Got Disconnect") - case SocketPacket.PacketType.Error: - socket.didError("Error: \(p.data)") + case .Error: + socket.didError("Error: \(pack.data)") } + } static func parseBinaryData(data: NSData, socket: SocketIOClient) { - if socket.waitingData.count == 0 { + guard !socket.waitingData.isEmpty else { Logger.error("Got data when not remaking packet", type: "SocketParser") return } let shouldExecute = socket.waitingData[0].addData(data) - - if !shouldExecute { - return - } + guard shouldExecute else { return } var packet = socket.waitingData.removeAtIndex(0) packet.fillInPlaceholders() - if packet.type != SocketPacket.PacketType.BinaryAck { + if packet.type != .BinaryAck { socket.handleEvent(packet.event, data: packet.args, isInternalMessage: false, wantsAck: packet.id) } else {