Message.swift 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197
  1. /*
  2. *
  3. * Copyright 2016, Google Inc.
  4. * All rights reserved.
  5. *
  6. * Redistribution and use in source and binary forms, with or without
  7. * modification, are permitted provided that the following conditions are
  8. * met:
  9. *
  10. * * Redistributions of source code must retain the above copyright
  11. * notice, this list of conditions and the following disclaimer.
  12. * * Redistributions in binary form must reproduce the above
  13. * copyright notice, this list of conditions and the following disclaimer
  14. * in the documentation and/or other materials provided with the
  15. * distribution.
  16. * * Neither the name of Google Inc. nor the names of its
  17. * contributors may be used to endorse or promote products derived from
  18. * this software without specific prior written permission.
  19. *
  20. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  21. * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  22. * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
  23. * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
  24. * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  25. * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
  26. * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
  27. * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
  28. * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  29. * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
  30. * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  31. *
  32. */
  33. import Foundation
  34. /// zigzag-encode 32-bit integers
  35. func zigzag(_ n:Int32) -> (Int32) {
  36. return (n << 1) ^ (n >> 31)
  37. }
  38. /// zigzag-encode 64-bit integers
  39. func zigzag(_ n:Int64) -> (Int64) {
  40. return (n << 1) ^ (n >> 63)
  41. }
  42. /// A representation of a protocol buffer message that can be used to read and build protobufs
  43. public class Message {
  44. var descriptor: MessageDescriptor
  45. var fields: [Field]
  46. init(descriptor: MessageDescriptor, fields: [Field]) {
  47. self.descriptor = descriptor
  48. self.fields = fields
  49. }
  50. /// add a field and perform the specified action
  51. public func addField(_ name: String, action:((Field) -> Void)) {
  52. // look up the field descriptor
  53. for fieldDescriptor in descriptor.fieldDescriptors {
  54. if (fieldDescriptor.name == name) {
  55. // create a field with that descriptor
  56. let field = Field(descriptor:fieldDescriptor)
  57. // add it to self.fields
  58. self.fields.append(field)
  59. action(field)
  60. }
  61. }
  62. }
  63. /// add a field and set it to the specified value
  64. public func addField(_ name: String, value: Any) {
  65. // look up the field descriptor
  66. for fieldDescriptor in descriptor.fieldDescriptors {
  67. if (fieldDescriptor.name == name) {
  68. // create a field with that descriptor
  69. let field = Field(descriptor:fieldDescriptor)
  70. // add it to self.fields
  71. self.fields.append(field)
  72. field.value = value
  73. }
  74. }
  75. }
  76. public func fieldCount() -> Int {
  77. return fields.count
  78. }
  79. /// get one field with the specified name
  80. public func oneField(_ name: String) -> Field? {
  81. for field in fields {
  82. if field.name() == name {
  83. return field
  84. }
  85. }
  86. return nil
  87. }
  88. /// perform an action on one field with the specified name
  89. public func forOneField(_ name: String, action:((Field) -> Void)) {
  90. for field in fields {
  91. if field.name() == name {
  92. action(field)
  93. break
  94. }
  95. }
  96. }
  97. /// perform an action on each field with the specified name
  98. public func forEachField(_ name:String, action:(Field) -> (Void)) {
  99. for field in fields {
  100. if field.name() == name {
  101. action(field)
  102. }
  103. }
  104. }
  105. /// perform an action on each field following the specified path of field names
  106. public func forEachField(_ path:[String], action:(Field) -> (Void)) {
  107. for field in fields {
  108. if field.name() == path[0] {
  109. if path.count == 1 {
  110. action(field)
  111. } else {
  112. var subpath = path
  113. subpath.removeFirst()
  114. field.message().forEachField(subpath, action:action)
  115. }
  116. }
  117. }
  118. }
  119. /// display a message for testing and debugging
  120. public func display() {
  121. for field in fields {
  122. field.display(indent:"")
  123. }
  124. }
  125. /// generate the binary protocol buffer representation of a message
  126. public func data() -> (Data) {
  127. let data = NSMutableData()
  128. for field in fields {
  129. data.appendVarint(field.tag() << 3 + field.wireType().rawValue)
  130. switch field.type() {
  131. case .double:
  132. data.appendDouble(field.double())
  133. case .float:
  134. data.appendFloat(field.float())
  135. case .int64:
  136. data.appendVarint(field.integer())
  137. case .uint64:
  138. data.appendVarint(field.integer())
  139. case .int32:
  140. data.appendVarint(field.integer())
  141. case .fixed64:
  142. data.appendInt64(field.integer())
  143. case .fixed32:
  144. data.appendInt32(field.integer())
  145. case .bool:
  146. data.appendVarint(field.bool() ? 1 : 0)
  147. case .string:
  148. var buf = [UInt8](field.string().utf8)
  149. data.appendVarint(buf.count)
  150. data.append(&buf, length: buf.count)
  151. case .group:
  152. assert(false)
  153. case .message:
  154. let messageData = field.message().data()
  155. data.appendVarint(messageData.count)
  156. messageData.withUnsafeBytes({ (bytes) in
  157. data.append(bytes, length: messageData.count)
  158. })
  159. case .bytes:
  160. let messageData = field.data()
  161. data.appendVarint(messageData.count)
  162. messageData.withUnsafeBytes({ (bytes) in
  163. data.append(bytes, length: messageData.count)
  164. })
  165. case .uint32:
  166. data.appendVarint(field.integer())
  167. case .enumeration:
  168. data.appendVarint(field.integer())
  169. case .sfixed32:
  170. data.appendInt32(field.integer())
  171. case .sfixed64:
  172. data.appendInt64(field.integer())
  173. case .sint32:
  174. data.appendVarint(Int(zigzag(Int32(field.integer()))))
  175. case .sint64:
  176. data.appendVarint(Int(zigzag(Int64(field.integer()))))
  177. }
  178. }
  179. return data as Data
  180. }
  181. }