protobuf-swift/Source/ExtendableMessage.swift

451 lines
17 KiB
Swift

// Protocol Buffers for Swift
//
// Copyright 2014 Alexey Khohklov(AlexeyXo).
// Copyright 2008 Google Inc.
//
// Licensed 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
typealias ExtensionsValueType = Hashable & Equatable
open class ExtendableMessage : GeneratedMessage
{
fileprivate var extensionMap:[Int32:Any] = [Int32:Any]()
public var extensionRegistry:[Int32:ConcreateExtensionField] = [Int32:ConcreateExtensionField]()
required public init()
{
super.init()
}
//Override
override open class func className() -> String
{
return "ExtendableMessage"
}
override open func className() -> String
{
return "ExtendableMessage"
}
//
public func isInitialized(object:Any) throws
{
switch object
{
case let array as Array<Any>:
for child in array {
try isInitialized(object: child)
}
case let array as Array<GeneratedMessage>:
for child in array {
try isInitialized(object: child)
}
case let message as GeneratedMessage:
try message.isInitialized()
default:
return
}
}
open func extensionsAreInitialized() throws {
let arr = Array(extensionMap.values)
try isInitialized(object:arr)
}
internal func ensureExtensionIsRegistered(extensions:ConcreateExtensionField)
{
extensionRegistry[extensions.fieldNumber] = extensions
}
public func getExtension(extensions:ConcreateExtensionField) -> Any? {
ensureExtensionIsRegistered(extensions: extensions)
if let value = extensionMap[extensions.fieldNumber] {
return value
}
return extensions.defaultValue
}
public func hasExtension(extensions:ConcreateExtensionField) -> Bool
{
guard (extensionMap[extensions.fieldNumber] != nil) else
{
return false
}
return true
}
public func writeExtensionsTo(codedOutputStream:CodedOutputStream, startInclusive:Int32, endExclusive:Int32) throws
{
var keys = Array(extensionMap.keys)
keys.sort(by: { $0 < $1 })
for fieldNumber in keys {
if (fieldNumber >= startInclusive && fieldNumber < endExclusive) {
let extensions = extensionRegistry[fieldNumber]!
let value = extensionMap[fieldNumber]!
try extensions.writeValueIncludingTagToCodedOutputStream(value: value, output: codedOutputStream)
}
}
}
public func getExtensionDescription(startInclusive:Int32 ,endExclusive:Int32, indent:String) throws -> String {
var output = ""
var keys = Array(extensionMap.keys)
keys.sort(by: { $0 < $1 })
for fieldNumber in keys {
if (fieldNumber >= startInclusive && fieldNumber < endExclusive) {
let extensions = extensionRegistry[fieldNumber]!
let value = extensionMap[fieldNumber]!
output += try extensions.getDescription(value: value, indent: indent)
}
}
return output
}
public func isEqualExtensionsInOther(otherMessage:ExtendableMessage, startInclusive:Int32, endExclusive:Int32) -> Bool {
var keys = Array(extensionMap.keys)
keys.sort(by: { $0 < $1 })
for fieldNumber in keys {
if (fieldNumber >= startInclusive && fieldNumber < endExclusive) {
let value = extensionMap[fieldNumber]!
let otherValue = otherMessage.extensionMap[fieldNumber]!
return compare(lhs: value, rhs: otherValue)
}
}
return true
}
private func compare(lhs:Any, rhs:Any) -> Bool
{
switch (lhs,rhs)
{
case (let value as Int32, let value2 as Int32):
return value == value2
case (let value as Int64, let value2 as Int64):
return value == value2
case (let value as Double, let value2 as Double):
return value == value2
case (let value as Float, let value2 as Float):
return value == value2
case (let value as Bool, let value2 as Bool):
return value == value2
case (let value as String, let value2 as String):
return value == value2
case (let value as Data, let value2 as Data):
return value == value2
case (let value as UInt32, let value2 as UInt32):
return value == value2
case (let value as UInt64, let value2 as UInt64):
return value == value2
case (let value as GeneratedMessage, let value2 as GeneratedMessage):
return value == value2
case (let value as [Int32], let value2 as [Int32]):
return value == value2
case (let value as [Int64], let value2 as [Int64]):
return value == value2
case (let value as [Double], let value2 as [Double]):
return value == value2
case (let value as [Float], let value2 as [Float]):
return value == value2
case (let value as [Bool], let value2 as [Bool]):
return value == value2
case (let value as [String], let value2 as [String]):
return value == value2
case (let value as Array<Data>, let value2 as Array<Data>):
return value == value2
case (let value as [UInt32], let value2 as [UInt32]):
return value == value2
case (let value as [UInt64], let value2 as [UInt64]):
return value == value2
case (let value as [GeneratedMessage], let value2 as [GeneratedMessage]):
return value == value2
default:
return false
}
}
private func getHash<T>(lhs:T) -> Int!
{
switch lhs
{
case let value as Int32:
return getHashValue(lhs: value)
case let value as Int64:
return getHashValue(lhs: value)
case let value as UInt32:
return getHashValue(lhs: value)
case let value as UInt64:
return getHashValue(lhs: value)
case let value as Float:
return getHashValue(lhs: value)
case let value as Double:
return getHashValue(lhs: value)
case let value as Bool:
return getHashValue(lhs: value)
case let value as String:
return getHashValue(lhs: value)
case let value as GeneratedMessage:
return getHashValue(lhs: value)
case let value as Data:
return value.hashValue
case let value as [Int32]:
return getHashValueRepeated(lhs: value)
case let value as [Int64]:
return getHashValueRepeated(lhs: value)
case let value as [UInt32]:
return getHashValueRepeated(lhs: value)
case let value as [UInt64]:
return getHashValueRepeated(lhs: value)
case let value as [Float]:
return getHashValueRepeated(lhs: value)
case let value as [Double]:
return getHashValueRepeated(lhs: value)
case let value as [Bool]:
return getHashValueRepeated(lhs: value)
case let value as [String]:
return getHashValueRepeated(lhs: value)
case let value as Array<Data>:
return getHashValueRepeated(lhs: value)
case let value as [GeneratedMessage]:
return getHashValueRepeated(lhs: value)
default:
return nil
}
}
private func getHashValueRepeated<T>(lhs:T) -> Int! where T:Collection, T.Iterator.Element:Hashable & Equatable
{
var hashCode:Int = 0
for vv in lhs
{
hashCode = (hashCode &* 31) &+ vv.hashValue
}
return hashCode
}
private func getHashValue<T>(lhs:T) -> Int! where T:Hashable & Equatable
{
return lhs.hashValue
}
public func hashExtensionsFrom(startInclusive:Int32, endExclusive:Int32) -> Int {
var hashCode:Int = 0
var keys = Array(extensionMap.keys)
keys.sort(by: { $0 < $1 })
for fieldNumber in keys {
if (fieldNumber >= startInclusive && fieldNumber < endExclusive) {
let value = extensionMap[fieldNumber]!
hashCode = (hashCode &* 31) &+ getHash(lhs: value)!
}
}
return hashCode
}
public func extensionsSerializedSize() ->Int32 {
var size:Int32 = 0
for fieldNumber in extensionMap.keys {
let extensions = extensionRegistry[fieldNumber]!
let value = extensionMap[fieldNumber]!
size += extensions.computeSerializedSizeIncludingTag(value: value)
}
return size
}
}
open class ExtendableMessageBuilder:GeneratedMessageBuilder
{
override open var internalGetResult:ExtendableMessage {
get
{
return ExtendableMessage()
}
}
override open func checkInitialized() throws {
let result = internalGetResult
try result.isInitialized()
}
override open func checkInitializedParsed() throws {
let result = internalGetResult
try result.isInitialized()
}
override open func isInitialized() throws {
try internalGetResult.isInitialized()
}
@discardableResult
override open func merge(unknownField: UnknownFieldSet) throws -> Self {
let result:GeneratedMessage = internalGetResult
result.unknownFields = try UnknownFieldSet.builderWithUnknownFields(copyFrom: result.unknownFields).merge(unknownFields: unknownField).build()
return self
}
override public func parse(codedInputStream:CodedInputStream ,unknownFields:UnknownFieldSet.Builder, extensionRegistry:ExtensionRegistry, tag:Int32) throws -> Bool {
let message = internalGetResult
let wireType = WireFormat.getTagWireType(tag: tag)
let fieldNumber:Int32 = WireFormat.getTagFieldNumber(tag: tag)
let extensions = extensionRegistry.getExtension(clName: type(of: message), fieldNumber: fieldNumber)
if extensions != nil {
if extensions!.wireType.rawValue == wireType {
try extensions!.mergeFrom(codedInputStream: codedInputStream, unknownFields:unknownFields, extensionRegistry:extensionRegistry, builder:self, tag:tag)
return true
}
}
return try super.parse(codedInputStream: codedInputStream, unknownFields: unknownFields, extensionRegistry: extensionRegistry, tag: tag)
}
public func getExtension(extensions:ConcreateExtensionField) -> Any? {
return internalGetResult.getExtension(extensions: extensions)
}
public func hasExtension(extensions:ConcreateExtensionField) -> Bool {
return internalGetResult.hasExtension(extensions: extensions)
}
@discardableResult
public func setExtension(extensions:ConcreateExtensionField, value:Any) throws -> Self {
let message = internalGetResult
message.ensureExtensionIsRegistered(extensions: extensions)
guard !extensions.isRepeated else {
throw ProtocolBuffersError.illegalArgument("Must call addExtension() for repeated types.")
}
message.extensionMap[extensions.fieldNumber] = value
return self
}
@discardableResult
public func addExtension<T>(extensions:ConcreateExtensionField, value:T) throws -> ExtendableMessageBuilder {
let message = internalGetResult
message.ensureExtensionIsRegistered(extensions: extensions)
guard extensions.isRepeated else
{
throw ProtocolBuffersError.illegalArgument("Must call addExtension() for repeated types.")
}
let fieldNumber = extensions.fieldNumber
if let val = value as? GeneratedMessage
{
var list:[GeneratedMessage]! = message.extensionMap[fieldNumber] as? [GeneratedMessage] ?? []
list.append(val)
message.extensionMap[fieldNumber] = list
}
else
{
var list:[T]! = message.extensionMap[fieldNumber] as? [T] ?? []
list.append(value)
message.extensionMap[fieldNumber] = list
}
return self
}
@discardableResult
public func setExtension<T>(extensions:ConcreateExtensionField, index:Int32, value:T) throws -> Self {
let message = internalGetResult
message.ensureExtensionIsRegistered(extensions: extensions)
guard extensions.isRepeated else {
throw ProtocolBuffersError.illegalArgument("Must call setExtension() for singular types.")
}
let fieldNumber = extensions.fieldNumber
if let val = value as? GeneratedMessage
{
var list:[GeneratedMessage]! = message.extensionMap[fieldNumber] as? [GeneratedMessage] ?? []
list[Int(index)] = val
message.extensionMap[fieldNumber] = list
}
else
{
var list:[T]! = message.extensionMap[fieldNumber] as? [T] ?? []
list[Int(index)] = value
message.extensionMap[fieldNumber] = list
}
return self
}
@discardableResult
public func clearExtension(extensions:ConcreateExtensionField) -> Self {
let message = internalGetResult
message.ensureExtensionIsRegistered(extensions: extensions)
message.extensionMap.removeValue(forKey: extensions.fieldNumber)
return self
}
private func mergeRepeatedExtensionFields<T>(otherList:T, extensionMap:[Int32:Any], fieldNumber:Int32) -> [T.Iterator.Element] where T:Collection
{
var list:[T.Iterator.Element]! = extensionMap[fieldNumber] as? [T.Iterator.Element] ?? []
list! += otherList
return list!
}
public func mergeExtensionFields(other:ExtendableMessage) throws {
let thisMessage = internalGetResult
guard thisMessage.className() == other.className() else {
throw ProtocolBuffersError.illegalArgument("Cannot merge extensions from a different type")
}
if other.extensionMap.count > 0 {
var registry = other.extensionRegistry
for fieldNumber in other.extensionMap.keys {
let thisField = registry[fieldNumber]!
let value = other.extensionMap[fieldNumber]!
if thisField.isRepeated {
switch value
{
case let values as [Int32]:
thisMessage.extensionMap[fieldNumber] = mergeRepeatedExtensionFields(otherList: values, extensionMap: thisMessage.extensionMap, fieldNumber: fieldNumber)
case let values as [Int64]:
thisMessage.extensionMap[fieldNumber] = mergeRepeatedExtensionFields(otherList: values, extensionMap: thisMessage.extensionMap, fieldNumber: fieldNumber)
case let values as [UInt64]:
thisMessage.extensionMap[fieldNumber] = mergeRepeatedExtensionFields(otherList: values, extensionMap: thisMessage.extensionMap, fieldNumber: fieldNumber)
case let values as [UInt32]:
thisMessage.extensionMap[fieldNumber] = mergeRepeatedExtensionFields(otherList: values, extensionMap: thisMessage.extensionMap, fieldNumber: fieldNumber)
case let values as [Bool]:
thisMessage.extensionMap[fieldNumber] = mergeRepeatedExtensionFields(otherList: values, extensionMap: thisMessage.extensionMap, fieldNumber: fieldNumber)
case let values as [Float]:
thisMessage.extensionMap[fieldNumber] = mergeRepeatedExtensionFields(otherList: values, extensionMap: thisMessage.extensionMap, fieldNumber: fieldNumber)
case let values as [Double]:
thisMessage.extensionMap[fieldNumber] = mergeRepeatedExtensionFields(otherList: values, extensionMap: thisMessage.extensionMap, fieldNumber: fieldNumber)
case let values as [String]:
thisMessage.extensionMap[fieldNumber] = mergeRepeatedExtensionFields(otherList: values, extensionMap: thisMessage.extensionMap, fieldNumber: fieldNumber)
case let values as Array<Data>:
thisMessage.extensionMap[fieldNumber] = mergeRepeatedExtensionFields(otherList: values, extensionMap: thisMessage.extensionMap, fieldNumber: fieldNumber)
case let values as [GeneratedMessage]:
thisMessage.extensionMap[fieldNumber] = mergeRepeatedExtensionFields(otherList: values, extensionMap: thisMessage.extensionMap, fieldNumber: fieldNumber)
default:
break
}
}
else
{
thisMessage.extensionMap[fieldNumber] = value
}
}
}
}
}