THRIFT-2905 Cocoa compiler should have option to produce "modern" Objective-C
Client: Cocoa (ObjectiveC & Swift)
Author: Kevin Wooten <kevin@wooten.com>

This closes #539
diff --git a/lib/cocoa/src/TProtocol.swift b/lib/cocoa/src/TProtocol.swift
new file mode 100644
index 0000000..1775849
--- /dev/null
+++ b/lib/cocoa/src/TProtocol.swift
@@ -0,0 +1,190 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+import Foundation
+
+
+public extension TProtocol {
+  
+  public func readMessageBegin() throws -> (String, TMessageType, Int) {
+    
+    var name : NSString?
+    var type : Int32 = -1
+    var sequenceID : Int32 = -1
+    
+    try readMessageBeginReturningName(&name, type: &type, sequenceID: &sequenceID)
+    
+    return (name as String!, TMessageType(rawValue: type)!, Int(sequenceID))
+  }
+  
+  public func writeMessageBeginWithName(name: String, type: TMessageType, sequenceID: Int) throws {
+    try writeMessageBeginWithName(name, type: type.rawValue, sequenceID: Int32(sequenceID))
+  }
+  
+  public func readStructBegin() throws -> (String?) {
+    
+    var name : NSString? = nil
+    
+    try readStructBeginReturningName(&name)
+    
+    return (name as String?)
+  }
+  
+  public func readFieldBegin() throws -> (String?, TType, Int) {
+    
+    var name : NSString? = nil
+    var type : Int32 = -1
+    var fieldID : Int32 = -1
+    
+    try readFieldBeginReturningName(&name, type: &type, fieldID: &fieldID)
+    
+    return (name as String?, TType(rawValue: type)!, Int(fieldID))
+  }
+  
+  public func writeFieldBeginWithName(name: String, type: TType, fieldID: Int) throws {
+    try writeFieldBeginWithName(name, type: type.rawValue, fieldID: Int32(fieldID))
+  }
+  
+  public func readMapBegin() throws -> (TType, TType, Int32) {
+    
+    var keyType : Int32 = -1
+    var valueType : Int32 = -1
+    var size : Int32 = 0
+    
+    try readMapBeginReturningKeyType(&keyType, valueType: &valueType, size: &size)
+    
+    return (TType(rawValue: keyType)!, TType(rawValue: valueType)!, size)
+  }
+  
+  public func writeMapBeginWithKeyType(keyType: TType, valueType: TType, size: Int) throws {
+    try writeMapBeginWithKeyType(keyType.rawValue, valueType: valueType.rawValue, size: Int32(size))
+  }
+  
+  public func readSetBegin() throws -> (TType, Int32) {
+    
+    var elementType : Int32 = -1
+    var size : Int32 = 0
+    
+    try readSetBeginReturningElementType(&elementType, size: &size)
+    
+    return (TType(rawValue: elementType)!, size)
+  }
+  
+  public func writeSetBeginWithElementType(elementType: TType, size: Int) throws {
+    try writeSetBeginWithElementType(elementType.rawValue, size: Int32(size))
+  }
+  
+  public func readListBegin() throws -> (TType, Int32) {
+    
+    var elementType : Int32 = -1
+    var size : Int32 = 0
+    
+    try readListBeginReturningElementType(&elementType, size: &size)
+    
+    return (TType(rawValue: elementType)!, size)
+  }
+  
+  public func writeListBeginWithElementType(elementType: TType, size: Int) throws {
+    try writeListBeginWithElementType(elementType.rawValue, size: Int32(size))
+  }
+  
+  public func writeFieldValue<T: TSerializable>(value: T, name: String, type: TType, id: Int32) throws {
+    try writeFieldBeginWithName(name, type: type.rawValue, fieldID: id)
+    try writeValue(value)
+    try writeFieldEnd()
+  }
+  
+  public func readValue<T: TSerializable>() throws -> T {
+    return try T.readValueFromProtocol(self)
+  }
+  
+  public func writeValue<T: TSerializable>(value: T) throws {
+    try T.writeValue(value, toProtocol: self)
+  }
+  
+  public func readResultMessageBegin() throws {
+    
+    let (_, type, _) = try readMessageBegin();
+    
+    if type == .EXCEPTION {
+      let x = try readException()
+      throw x
+    }
+    
+    return
+  }
+  
+  public func validateValue(value: Any?, named name: String) throws {
+    
+    if value == nil {
+      throw NSError(
+        domain: TProtocolErrorDomain,
+        code: Int(TProtocolError.Unknown.rawValue),
+        userInfo: [TProtocolErrorFieldNameKey: name])
+    }
+    
+  }
+  
+  public func readException() throws -> ErrorType {
+    
+    var reason : String?
+    var type = TApplicationError.Unknown
+    
+    try readStructBegin()
+    
+    fields: while (true) {
+      
+      let (_, fieldType, fieldID) = try readFieldBegin()
+      
+      switch (fieldID, fieldType) {
+      case (_, .STOP):
+        break fields
+        
+      case (1, .STRING):
+        reason = try readValue() as String
+        
+      case (2, .I32):
+        let typeVal = try readValue() as Int32
+        if let tmp = TApplicationError(rawValue: typeVal) {
+          type = tmp
+        }
+        
+      case let (_, unknownType):
+        try skipType(unknownType)
+      }
+      
+      try readFieldEnd()
+    }
+    
+    try readStructEnd()
+    
+    return NSError(type:type, reason:reason ?? "")
+  }
+  
+  public func writeExceptionForMessageName(name: String, sequenceID: Int, ex: NSError) throws {
+    try writeMessageBeginWithName(name, type: .EXCEPTION, sequenceID: sequenceID)
+    try ex.write(self)
+    try writeMessageEnd()
+  }
+  
+  public func skipType(type: TType) throws {
+    try TProtocolUtil.skipType(type.rawValue, onProtocol: self)
+  }
+  
+}