ProtobufMessage.swift 6.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166
  1. // ProtobufRuntime/Sources/Protobuf/ProtobufMessage.swift - Message support
  2. //
  3. // This source file is part of the Swift.org open source project
  4. //
  5. // Copyright (c) 2014 - 2016 Apple Inc. and the Swift project authors
  6. // Licensed under Apache License v2.0 with Runtime Library Exception
  7. //
  8. // See http://swift.org/LICENSE.txt for license information
  9. // See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
  10. //
  11. // -----------------------------------------------------------------------------
  12. ///
  13. /// All messages implement some of these protocols: Generated messages output
  14. /// by protoc implement ProtobufGeneratedMessageType, hand-coded messages often
  15. /// implement ProtobufAbstractMessage. The protocol heirarchy here is
  16. /// a little involved due to the variety of requirements and the need to
  17. /// mix in JSON and binary support (see ProtobufBinaryTypes and ProtobufJSONTypes
  18. /// for extensions that support binary and JSON coding).
  19. ///
  20. // -----------------------------------------------------------------------------
  21. import Swift
  22. ///
  23. /// See ProtobufBinaryTypes and ProtobufJSONTypes for extensions
  24. /// to these protocols for supporting binary and JSON coding.
  25. ///
  26. ///
  27. /// The core protocol implemented by all messages, whether generated
  28. /// or hand-coded.
  29. ///
  30. /// In particular, this has no associated types or self references
  31. /// so can be used as a variable or argument type.
  32. ///
  33. public protocol ProtobufMessageBase: CustomDebugStringConvertible, ProtobufTraversable {
  34. init()
  35. // Basic facts about this class and the proto message it was generated from
  36. // Used by various encoders and decoders
  37. var swiftClassName: String { get }
  38. var protoMessageName: String { get }
  39. var protoPackageName: String { get }
  40. var anyTypePrefix: String { get }
  41. var anyTypeURL: String { get }
  42. var jsonFieldNames: [String: Int] {get}
  43. var protoFieldNames: [String: Int] {get}
  44. /// Decode a field identified by a field number (as given in the .proto file).
  45. ///
  46. /// This is the core method used by the deserialization machinery.
  47. ///
  48. /// Note that this is not specific to protobuf encoding; formats
  49. /// that use textual identifiers translate those to protoFieldNumbers and
  50. /// then invoke this to decode the field value.
  51. mutating func decodeField(setter: inout ProtobufFieldDecoder, protoFieldNumber: Int) throws -> Bool
  52. // The corresponding serialization support is the traverse() method
  53. // declared in ProtobufTraversable
  54. // Decode from an Any (which might itself have been decoded from JSON,
  55. // protobuf, or another Any)
  56. init(any: Google_Protobuf_Any) throws
  57. /// Serialize as an Any object in JSON format
  58. /// For generated message types, this generates the same JSON object
  59. /// as serializeJSON() except it adds an additional `@type` field.
  60. func serializeAnyJSON() throws -> String
  61. // Standard utility properties and methods.
  62. // Most of these are simple wrappers on top of the visitor machinery.
  63. // They are implemented in the protocol, not in the generated structs,
  64. // so can be overridden in user code by defining custom extensions to
  65. // the generated struct.
  66. var isEmpty: Bool { get }
  67. var hashValue: Int { get }
  68. var debugDescription: String { get }
  69. var customMirror: Mirror { get }
  70. }
  71. public extension ProtobufMessageBase {
  72. var hashValue: Int {return ProtobufHashVisitor(message: self).hashValue}
  73. var debugDescription: String {return ProtobufDebugDescriptionVisitor(message: self).description}
  74. var customMirror: Mirror {return ProtobufMirrorVisitor(message: self).mirror}
  75. // TODO: Add an option to the generator to override this in particular messages.
  76. // TODO: It would be nice if this could default to "" instead; that would save ~20
  77. // bytes on every serialized Any.
  78. var anyTypePrefix: String {return "type.googleapis.com"}
  79. var anyTypeURL: String {
  80. var url = anyTypePrefix
  81. if anyTypePrefix == "" || anyTypePrefix.characters.last! != "/" {
  82. url += "/"
  83. }
  84. if protoPackageName != "" {
  85. url += protoPackageName
  86. url += "."
  87. }
  88. url += protoMessageName
  89. return url
  90. }
  91. }
  92. ///
  93. /// ProtobufMessage which extends ProtobufMessageBase with some
  94. /// additional requirements, including serialization extensions.
  95. /// This is used directly by hand-coded message implementations.
  96. ///
  97. public protocol ProtobufMessage: ProtobufMessageBase, ProtobufBinaryMessageBase, ProtobufJSONMessageBase, CustomReflectable {
  98. }
  99. public protocol ProtobufAbstractMessage: ProtobufMessage, Hashable, ProtobufMapValueType {
  100. func isEqualTo(other: Self) -> Bool
  101. }
  102. public extension ProtobufAbstractMessage {
  103. static func isEqual(_ lhs: Self, _ rhs: Self) -> Bool {
  104. return lhs == rhs
  105. }
  106. public init(any: Google_Protobuf_Any) throws {
  107. self.init()
  108. try any.unpackTo(target: &self)
  109. }
  110. }
  111. public func ==<M: ProtobufAbstractMessage>(lhs: M, rhs: M) -> Bool {
  112. return lhs.isEqualTo(other: rhs)
  113. }
  114. ///
  115. /// Base type for Generated message types
  116. ///
  117. /// This provides some basic indirection so end users can override
  118. /// generated methods.
  119. ///
  120. public protocol ProtobufGeneratedMessage: ProtobufAbstractMessage {
  121. // The compiler actually generates the following methods.
  122. // Default implementations below redirect the standard names.
  123. // This allows developers to override the standard names to
  124. // customize the behavior.
  125. mutating func _protoc_generated_decodeField(setter: inout ProtobufFieldDecoder, protoFieldNumber: Int) throws -> Bool
  126. func _protoc_generated_traverse(visitor: inout ProtobufVisitor) throws
  127. func _protoc_generated_isEqualTo(other: Self) -> Bool
  128. var _protoc_generated_isEmpty: Bool { get }
  129. }
  130. public extension ProtobufGeneratedMessage {
  131. // Default implementations simply redirect to the generated versions.
  132. public func traverse(visitor: inout ProtobufVisitor) throws {
  133. try _protoc_generated_traverse(visitor: &visitor)
  134. }
  135. mutating func decodeField(setter: inout ProtobufFieldDecoder, protoFieldNumber: Int) throws -> Bool {
  136. return try _protoc_generated_decodeField(setter: &setter, protoFieldNumber: protoFieldNumber)
  137. }
  138. func isEqualTo(other: Self) -> Bool {
  139. return _protoc_generated_isEqualTo(other: other)
  140. }
  141. var isEmpty: Bool { get { return _protoc_generated_isEmpty } }
  142. }
  143. // TODO: This is a transition aid, remove this in August 2016.
  144. public typealias ProtobufGeneratedMessageType = ProtobufGeneratedMessage