| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241 |
- /*
- *
- * Copyright 2016, Google Inc.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met:
- *
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * * Redistributions in binary form must reproduce the above
- * copyright notice, this list of conditions and the following disclaimer
- * in the documentation and/or other materials provided with the
- * distribution.
- * * Neither the name of Google Inc. nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- */
- import Foundation
- // A reader for protocol buffers. Used internally.
- class MessageReader {
- var fileDescriptorSet: FileDescriptorSet
- var messageName: String
- var data : Data
- var cursor : Int = 0
- init(_ fileDescriptorSet: FileDescriptorSet, messageName: String, data: Data) {
- self.fileDescriptorSet = fileDescriptorSet
- self.messageName = messageName
- self.data = data
- }
- func readMessage() -> Message? {
- if let descriptor = fileDescriptorSet.messageDescriptor(name: messageName) {
- return readMessage(range: NSRange(location: 0, length:data.count),
- descriptor:descriptor)
- } else {
- return nil
- }
- }
- private func nextUInt8() -> (UInt8) {
- var result: UInt8 = 0
- data.copyBytes(to: &result, from:cursor..<cursor+1)
- cursor += 1
- return result
- }
- private func nextUInt32() -> (UInt32) {
- var result: UInt32 = 0
- _ = data.copyBytes(to: UnsafeMutableBufferPointer(start: &result, count: 1), from:cursor..<cursor+4)
- cursor += 4
- return result
- }
- private func nextUInt64() -> (UInt64) {
- var result: UInt64 = 0
- _ = data.copyBytes(to: UnsafeMutableBufferPointer(start: &result, count: 1), from:cursor..<cursor+8)
- cursor += 8
- return result
- }
- private func nextInt32() -> (Int32) {
- var result: Int32 = 0
- _ = data.copyBytes(to: UnsafeMutableBufferPointer(start: &result, count: 1), from:cursor..<cursor+4)
- cursor += 4
- return result
- }
- private func nextInt64() -> (Int64) {
- var result: Int64 = 0
- _ = data.copyBytes(to: UnsafeMutableBufferPointer(start: &result, count: 1), from:cursor..<cursor+8)
- cursor += 8
- return result
- }
- private func nextDouble() -> (Double) {
- var result: Double = 0
- _ = data.copyBytes(to: UnsafeMutableBufferPointer(start: &result, count: 1), from:cursor..<cursor+8)
- cursor += 8
- return result
- }
- private func nextFloat() -> (Float) {
- var result: Float = 0
- _ = data.copyBytes(to: UnsafeMutableBufferPointer(start: &result, count: 1), from:cursor..<cursor+4)
- cursor += 4
- return result
- }
- private func nextVarint() -> (Int) {
- var sum : Int = 0
- var shift : Int = 0
- var b : Int = Int(self.nextUInt8())
- while (b & 0x80 != 0) {
- sum += (b & 0x7f) << shift
- shift += 7
- b = Int(self.nextUInt8())
- }
- sum += b << shift
- return sum
- }
- private func nextString(length: Int) -> (String) {
- var buffer = [UInt8](repeating: 0, count: length)
- data.copyBytes(to: &buffer, from:cursor..<cursor+length)
- self.cursor = self.cursor + length
- return String(bytes: buffer, encoding:String.Encoding.utf8)!
- }
- private func nextData(length: Int) -> (Data) {
- var buffer = [UInt8](repeating: 0, count: length)
- data.copyBytes(to: &buffer, from:cursor..<cursor+length)
- self.cursor = self.cursor + length
- return Data(bytes: &buffer, count: length)
- }
- private func readMessage(range: NSRange, descriptor : MessageDescriptor) -> Message {
- var fields = [Field]()
- while (cursor < range.location + range.length) {
- let s = self.nextVarint()
- let tag = s >> 3
- let wiretype = WireType(rawValue:s & 0x07)!
- let field = descriptor.fieldDescriptor(tag:tag)
- switch (wiretype) {
- case .varint:
- var value = self.nextVarint()
- if let field = field {
- if ((field.type == .sint32) || (field.type == .sint64)) {
- // zigzag decoding
- let sign = value & 0x01
- value = value >> 1
- if sign == 1 {
- value = -value - 1
- }
- }
- fields.append(
- Field(
- descriptor: field,
- value: value
- ))
- }
- case .fixed64:
- if let field = field {
- if field.type == .double {
- let value = self.nextDouble()
- fields.append(
- Field(
- descriptor: field,
- value: value))
- } else {
- let value = self.nextInt64()
- fields.append(
- Field(
- descriptor: field,
- value: value))
- }
- }
- case .lengthDelimited: // length-delimited
- let length = self.nextVarint()
- if let field = field {
- switch (field.type) {
- case .string:
- let value = self.nextString(length: length)
- fields.append(
- Field(
- descriptor: field,
- value: value))
- case .bytes:
- let value = self.nextData(length: length)
- fields.append(
- Field(
- descriptor: field,
- value: value))
- default:
- if let fieldDescriptor = fileDescriptorSet.messageDescriptor(name:field.type_name) {
- let value = readMessage(range:NSMakeRange(cursor, length),
- descriptor: fieldDescriptor)
- fields.append(
- Field(
- descriptor: field,
- value: value))
- } else {
- // skip unknown messages
- cursor += length
- }
- }
- } else {
- // skip unknown messages
- cursor += length
- }
- case .startGroup:
- break
- case .endGroup:
- break
- case .fixed32:
- if let field = field {
- if field.type == .float {
- let value = self.nextFloat()
- fields.append(
- Field(
- descriptor: field,
- value: value))
- } else {
- let value = self.nextInt32()
- fields.append(
- Field(
- descriptor: field,
- value: value))
- }
- }
- }
- }
- return Message(descriptor:descriptor, fields:fields)
- }
- }
|