refactor, make use of try catch

This commit is contained in:
Lukas Schmidt 2015-09-07 15:08:10 +02:00
parent fb9b19820b
commit 2bd612e47a
4 changed files with 109 additions and 89 deletions

48
GenericSocketParser.swift Normal file
View File

@ -0,0 +1,48 @@
//
// GenericSocketParser.swift
// Socket.IO-Client-Swift
//
// Created by Lukas Schmidt on 07.09.15.
//
//
import Foundation
struct GenericParser {
let message: String
var currentIndex:Int
var messageCharacters: Array<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<String.Index>(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<String.Index>(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)
}
}

View File

@ -43,6 +43,8 @@
74781D5C1B7E83930042CACA /* SocketIOClientStatus.swift in Sources */ = {isa = PBXBuildFile; fileRef = 74781D591B7E83930042CACA /* SocketIOClientStatus.swift */; }; 74781D5C1B7E83930042CACA /* SocketIOClientStatus.swift in Sources */ = {isa = PBXBuildFile; fileRef = 74781D591B7E83930042CACA /* SocketIOClientStatus.swift */; };
74781D5D1B7E83930042CACA /* 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 */; }; 941A4ABA1B67A56C00C42318 /* TestKind.swift in Sources */ = {isa = PBXBuildFile; fileRef = 941A4AB91B67A56C00C42318 /* TestKind.swift */; };
9421F5D01B9DBF5900D625BB /* GenericSocketParser.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9421F5CF1B9DBF5900D625BB /* GenericSocketParser.swift */; settings = {ASSET_TAGS = (); }; };
9421F5D11B9DBF5900D625BB /* GenericSocketParser.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9421F5CF1B9DBF5900D625BB /* GenericSocketParser.swift */; settings = {ASSET_TAGS = (); }; };
94242BB81B67B0E500AAAC9D /* SocketNamespaceAcknowledgementTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 94242BB71B67B0E500AAAC9D /* SocketNamespaceAcknowledgementTest.swift */; }; 94242BB81B67B0E500AAAC9D /* SocketNamespaceAcknowledgementTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 94242BB71B67B0E500AAAC9D /* SocketNamespaceAcknowledgementTest.swift */; };
945B65351B5FCEEA0081E995 /* SocketAckManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5764DF7C1B51F254004FF46E /* SocketAckManager.swift */; }; 945B65351B5FCEEA0081E995 /* SocketAckManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5764DF7C1B51F254004FF46E /* SocketAckManager.swift */; };
945B65361B5FCEEA0081E995 /* SocketAnyEvent.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5764DF7D1B51F254004FF46E /* SocketAnyEvent.swift */; }; 945B65361B5FCEEA0081E995 /* SocketAnyEvent.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5764DF7D1B51F254004FF46E /* SocketAnyEvent.swift */; };
@ -110,6 +112,7 @@
5764DF881B51F254004FF46E /* WebSocket.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = WebSocket.swift; path = SocketIOClientSwift/WebSocket.swift; sourceTree = "<group>"; }; 5764DF881B51F254004FF46E /* WebSocket.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = WebSocket.swift; path = SocketIOClientSwift/WebSocket.swift; sourceTree = "<group>"; };
74781D591B7E83930042CACA /* SocketIOClientStatus.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = SocketIOClientStatus.swift; path = SocketIOClientSwift/SocketIOClientStatus.swift; sourceTree = "<group>"; }; 74781D591B7E83930042CACA /* SocketIOClientStatus.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = SocketIOClientStatus.swift; path = SocketIOClientSwift/SocketIOClientStatus.swift; sourceTree = "<group>"; };
941A4AB91B67A56C00C42318 /* TestKind.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TestKind.swift; sourceTree = "<group>"; }; 941A4AB91B67A56C00C42318 /* TestKind.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TestKind.swift; sourceTree = "<group>"; };
9421F5CF1B9DBF5900D625BB /* GenericSocketParser.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = GenericSocketParser.swift; sourceTree = "<group>"; };
94242BB71B67B0E500AAAC9D /* SocketNamespaceAcknowledgementTest.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SocketNamespaceAcknowledgementTest.swift; sourceTree = "<group>"; }; 94242BB71B67B0E500AAAC9D /* SocketNamespaceAcknowledgementTest.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SocketNamespaceAcknowledgementTest.swift; sourceTree = "<group>"; };
945B65421B63D9DB0081E995 /* SocketEmitTest.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SocketEmitTest.swift; sourceTree = "<group>"; }; 945B65421B63D9DB0081E995 /* SocketEmitTest.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SocketEmitTest.swift; sourceTree = "<group>"; };
949FAE8C1B9B94E600073BE9 /* SocketParserTest.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SocketParserTest.swift; sourceTree = "<group>"; }; 949FAE8C1B9B94E600073BE9 /* SocketParserTest.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SocketParserTest.swift; sourceTree = "<group>"; };
@ -267,6 +270,7 @@
5764DF831B51F254004FF46E /* SocketLogger.swift */, 5764DF831B51F254004FF46E /* SocketLogger.swift */,
5764DF841B51F254004FF46E /* SocketPacket.swift */, 5764DF841B51F254004FF46E /* SocketPacket.swift */,
5764DF851B51F254004FF46E /* SocketParser.swift */, 5764DF851B51F254004FF46E /* SocketParser.swift */,
9421F5CF1B9DBF5900D625BB /* GenericSocketParser.swift */,
5764DF861B51F254004FF46E /* SocketTypes.swift */, 5764DF861B51F254004FF46E /* SocketTypes.swift */,
5764DF871B51F254004FF46E /* SwiftRegex.swift */, 5764DF871B51F254004FF46E /* SwiftRegex.swift */,
5764DF881B51F254004FF46E /* WebSocket.swift */, 5764DF881B51F254004FF46E /* WebSocket.swift */,
@ -454,6 +458,7 @@
5764DF911B51F254004FF46E /* SocketEventHandler.swift in Sources */, 5764DF911B51F254004FF46E /* SocketEventHandler.swift in Sources */,
5764DF931B51F254004FF46E /* SocketFixUTF8.swift in Sources */, 5764DF931B51F254004FF46E /* SocketFixUTF8.swift in Sources */,
5764DF951B51F254004FF46E /* SocketIOClient.swift in Sources */, 5764DF951B51F254004FF46E /* SocketIOClient.swift in Sources */,
9421F5D01B9DBF5900D625BB /* GenericSocketParser.swift in Sources */,
5764DF8B1B51F254004FF46E /* SocketAnyEvent.swift in Sources */, 5764DF8B1B51F254004FF46E /* SocketAnyEvent.swift in Sources */,
5764DF971B51F254004FF46E /* SocketLogger.swift in Sources */, 5764DF971B51F254004FF46E /* SocketLogger.swift in Sources */,
74781D5A1B7E83930042CACA /* SocketIOClientStatus.swift in Sources */, 74781D5A1B7E83930042CACA /* SocketIOClientStatus.swift in Sources */,
@ -475,6 +480,7 @@
94CB8F0B1B6E48B90019ED53 /* SocketTestCases.swift in Sources */, 94CB8F0B1B6E48B90019ED53 /* SocketTestCases.swift in Sources */,
945B65371B5FCEEA0081E995 /* SocketEngine.swift in Sources */, 945B65371B5FCEEA0081E995 /* SocketEngine.swift in Sources */,
945B65351B5FCEEA0081E995 /* SocketAckManager.swift in Sources */, 945B65351B5FCEEA0081E995 /* SocketAckManager.swift in Sources */,
9421F5D11B9DBF5900D625BB /* GenericSocketParser.swift in Sources */,
941A4ABA1B67A56C00C42318 /* TestKind.swift in Sources */, 941A4ABA1B67A56C00C42318 /* TestKind.swift in Sources */,
94CB8F0D1B6E66E60019ED53 /* AbstractSocketTest.swift in Sources */, 94CB8F0D1B6E66E60019ED53 /* AbstractSocketTest.swift in Sources */,
945B65431B63D9DB0081E995 /* SocketEmitTest.swift in Sources */, 945B65431B63D9DB0081E995 /* SocketEmitTest.swift in Sources */,

View File

@ -17,8 +17,7 @@ class SocketParserTest: XCTestCase {
"51-/swift,[\"testMultipleItemsWithBufferEmitReturn\",[1,2],{\"test\":\"bob\"},25,\"polo\",{\"_placeholder\":true,\"num\":0}]": ("/swift", ["testMultipleItemsWithBufferEmitReturn", [1, 2], ["test": "bob"], 25, "polo", "~~0"], [], -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), "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), "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), "4/swift,": ("/swift", [], [], -1)]
"10": ("/swift", [], [], -1)]
func testDisconnect() { func testDisconnect() {
let message = "1" let message = "1"
@ -57,8 +56,12 @@ class SocketParserTest: XCTestCase {
func testInvalidInput() { func testInvalidInput() {
let message = "8" let message = "8"
let packet = SocketParser.parseString(message) do {
XCTAssertNil(packet) try SocketParser.parseString(message)
XCTFail("Should throw exeption")
} catch {
}
} }
func testGenericParser() { func testGenericParser() {
@ -66,32 +69,27 @@ class SocketParserTest: XCTestCase {
XCTAssertEqual(parser.read(1), "6") XCTAssertEqual(parser.read(1), "6")
XCTAssertEqual(parser.currentCharacter, "1") XCTAssertEqual(parser.currentCharacter, "1")
XCTAssertEqual(parser.readUntilStringOccurence("-"), "1") XCTAssertEqual(parser.readUntilStringOccurence("-"), "1")
XCTAssertEqual(parser.currentCharacter, "-") XCTAssertEqual(parser.currentCharacter, "-")
} }
func validateParseResult(message:String) { func validateParseResult(message:String) {
let validValues = SocketParserTest.packetTypes[message]! let validValues = SocketParserTest.packetTypes[message]!
let packet = SocketParser.parseString(message) let packet = try! SocketParser.parseString(message)
let type = message.substringWithRange(Range<String.Index>(start: message.startIndex, end: message.startIndex.advancedBy(1))) let type = message.substringWithRange(Range<String.Index>(start: message.startIndex, end: message.startIndex.advancedBy(1)))
if let packet = packet { XCTAssertEqual(packet.type, SocketPacket.PacketType(str:type)!)
XCTAssertEqual(packet.type, SocketPacket.PacketType(str:type)!) XCTAssertEqual(packet.nsp, validValues.0)
XCTAssertEqual(packet.nsp, validValues.0) XCTAssertTrue((packet.data as NSArray).isEqualToArray(validValues.1))
XCTAssertTrue((packet.data as NSArray).isEqualToArray(validValues.1)) XCTAssertTrue((packet.binary as NSArray).isEqualToArray(validValues.2))
XCTAssertTrue((packet.binary as NSArray).isEqualToArray(validValues.2)) XCTAssertEqual(packet.id, validValues.3)
XCTAssertEqual(packet.id, validValues.3)
}else {
XCTFail()
}
} }
func testParsePerformance() { func testParsePerformance() {
let keys = Array(SocketParserTest.packetTypes.keys) let keys = Array(SocketParserTest.packetTypes.keys)
measureBlock({ measureBlock({
for item in keys.enumerate() { for item in keys.enumerate() {
SocketParser.parseString(item.element) try! SocketParser.parseString(item.element)
} }
}) })
} }
} }

View File

@ -22,43 +22,8 @@
import Foundation import Foundation
struct GenericParser { enum SocketParserError: ErrorType {
let message: String case InvalidMessageType, InvalidBinaryPalceholder
var currentIndex:Int
var messageCharacters: Array<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<String.Index>(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<String.Index>(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)
}
} }
class SocketParser { class SocketParser {
@ -111,12 +76,12 @@ class SocketParser {
} }
// Translation of socket.io-client#decodeString // Translation of socket.io-client#decodeString
static func parseString(str: String) -> SocketPacket? { static func parseString(str: String) throws -> SocketPacket {
var parser = GenericParser(message: str, currentIndex: 0) var parser = GenericParser(message: str, currentIndex: 0)
let messageCharacters = Array(str.characters) let messageCharacters = Array(str.characters)
guard let typeString = parser.read(1), let type = SocketPacket.PacketType(str: typeString) else { guard let typeString = parser.read(1), let type = SocketPacket.PacketType(str: typeString) else {
NSLog("Error parsing \(str)") throw SocketParserError.InvalidMessageType
return nil} }
if messageCharacters.count == 1 { if messageCharacters.count == 1 {
return SocketPacket(type: type, nsp: "/") return SocketPacket(type: type, nsp: "/")
@ -129,8 +94,7 @@ class SocketParser {
if let buffer = parser.readUntilStringOccurence("-"), let holders = Int(buffer) where parser.read(1)! == "-" { if let buffer = parser.readUntilStringOccurence("-"), let holders = Int(buffer) where parser.read(1)! == "-" {
placeholders = holders placeholders = holders
} else { } else {
NSLog("Error parsing \(str)") throw SocketParserError.InvalidBinaryPalceholder
return nil
} }
} }
if parser.currentCharacter == "/" { if parser.currentCharacter == "/" {
@ -154,16 +118,12 @@ class SocketParser {
} }
} }
if parser.currentIndex < messageCharacters.count { let d = str[str.startIndex.advancedBy(parser.currentIndex + 1)...str.startIndex.advancedBy(str.characters.count - 1)]
let d = str[str.startIndex.advancedBy(parser.currentIndex + 1)...str.startIndex.advancedBy(str.characters.count-1)] let noPlaceholders = d["(\\{\"_placeholder\":true,\"num\":(\\d*)\\})"] ~= "\"~~$2\""
let noPlaceholders = d["(\\{\"_placeholder\":true,\"num\":(\\d*)\\})"] ~= "\"~~$2\"" let data = SocketParser.parseData(noPlaceholders) as? [AnyObject] ?? [noPlaceholders]
let data = SocketParser.parseData(noPlaceholders) as? [AnyObject] ?? [noPlaceholders]
return SocketPacket(type: type, data: data, id: Int(idString) ?? -1,
nsp: nsp ?? "/", placeholders: placeholders)
}
return nil return SocketPacket(type: type, data: data, id: Int(idString) ?? -1,
nsp: nsp ?? "/", placeholders: placeholders)
} }
// Parses data for events // Parses data for events
@ -184,29 +144,37 @@ class SocketParser {
Logger.log("Parsing %@", type: "SocketParser", args: stringMessage) Logger.log("Parsing %@", type: "SocketParser", args: stringMessage)
guard let pack = parseString(stringMessage) else { do {
socket.didError("Error parsing packet") let pack = try parseString(stringMessage)
return Logger.log("Decoded packet as: %@", type: "SocketParser", args: pack.description)
switch pack.type {
case .Event:
handleEvent(pack, socket: socket)
case .Ack:
handleAck(pack, socket: socket)
case .BinaryEvent:
handleBinaryEvent(pack, socket: socket)
case .BinaryAck:
handleBinaryAck(pack, socket: socket)
case .Connect:
handleConnect(pack, socket: socket)
case .Disconnect:
socket.didDisconnect("Got Disconnect")
case .Error:
socket.didError("Error: \(pack.data)")
}
}catch SocketParserError.InvalidBinaryPalceholder {
Logger.error("Parsed Invalid Binary Placeholder", type: "SocketParser")
} }
catch SocketParserError.InvalidMessageType {
Logger.log("Decoded packet as: %@", type: "SocketParser", args: pack.description) Logger.error("Parsed Invalid Binary Placeholder", type: "SocketParser")
switch pack.type {
case .Event:
handleEvent(pack, socket: socket)
case .Ack:
handleAck(pack, socket: socket)
case .BinaryEvent:
handleBinaryEvent(pack, socket: socket)
case .BinaryAck:
handleBinaryAck(pack, socket: socket)
case .Connect:
handleConnect(pack, socket: socket)
case .Disconnect:
socket.didDisconnect("Got Disconnect")
case .Error:
socket.didError("Error: \(pack.data)")
} }
catch {
}
} }
static func parseBinaryData(data: NSData, socket: SocketIOClient) { static func parseBinaryData(data: NSData, socket: SocketIOClient) {