Message+TextFormatAdditions.swift 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114
  1. // Sources/SwiftProtobuf/Message+TextFormatAdditions.swift - Text format primitive types
  2. //
  3. // Copyright (c) 2014 - 2016 Apple Inc. and the project authors
  4. // Licensed under Apache License v2.0 with Runtime Library Exception
  5. //
  6. // See LICENSE.txt for license information:
  7. // https://github.com/apple/swift-protobuf/blob/main/LICENSE.txt
  8. //
  9. // -----------------------------------------------------------------------------
  10. ///
  11. /// Extensions to `Message` to support text format encoding/decoding.
  12. ///
  13. // -----------------------------------------------------------------------------
  14. import Foundation
  15. /// Text format encoding and decoding methods for messages.
  16. extension Message {
  17. /// Returns a string containing the Protocol Buffer text format serialization
  18. /// of the message.
  19. ///
  20. /// Unlike binary encoding, presence of required fields is not enforced when
  21. /// serializing to text format.
  22. ///
  23. /// - Returns: A string containing the text format serialization of the
  24. /// message.
  25. public func textFormatString() -> String {
  26. // This is implemented as a separate zero-argument function
  27. // to preserve binary compatibility.
  28. textFormatString(options: TextFormatEncodingOptions())
  29. }
  30. /// Returns a string containing the Protocol Buffer text format serialization
  31. /// of the message.
  32. ///
  33. /// Unlike binary encoding, presence of required fields is not enforced when
  34. /// serializing to text format.
  35. ///
  36. /// - Returns: A string containing the text format serialization of the message.
  37. /// - Parameters:
  38. /// - options: The TextFormatEncodingOptions to use.
  39. public func textFormatString(
  40. options: TextFormatEncodingOptions
  41. ) -> String {
  42. var visitor = TextFormatEncodingVisitor(message: self, options: options)
  43. if let any = self as? Google_Protobuf_Any {
  44. any._storage.textTraverse(visitor: &visitor)
  45. } else {
  46. // Although the general traversal/encoding infrastructure supports
  47. // throwing errors (needed for JSON/Binary WKTs support, binary format
  48. // missing required fields); TextEncoding never actually does throw.
  49. try! traverse(visitor: &visitor)
  50. }
  51. return visitor.result
  52. }
  53. /// Creates a new message by decoding the given string containing a
  54. /// serialized message in Protocol Buffer text format.
  55. ///
  56. /// - Parameters:
  57. /// - textFormatString: The text format string to decode.
  58. /// - extensions: An ``ExtensionMap`` used to look up and decode any
  59. /// extensions in this message or messages nested within this message's
  60. /// fields.
  61. /// - Throws: ``SwiftProtobufError`` on failure.
  62. // TODO: delete this (and keep the one with the extra param instead) when we break API
  63. public init(
  64. textFormatString: String,
  65. extensions: (any ExtensionMap)? = nil
  66. ) throws {
  67. try self.init(
  68. textFormatString: textFormatString,
  69. options: TextFormatDecodingOptions(),
  70. extensions: extensions
  71. )
  72. }
  73. /// Creates a new message by decoding the given string containing a
  74. /// serialized message in Protocol Buffer text format.
  75. ///
  76. /// - Parameters:
  77. /// - textFormatString: The text format string to decode.
  78. /// - options: The ``TextFormatDecodingOptions`` to use.
  79. /// - extensions: An ``ExtensionMap`` used to look up and decode any
  80. /// extensions in this message or messages nested within this message's
  81. /// fields.
  82. /// - Throws: ``TextFormatDecodingError`` on failure.
  83. public init(
  84. textFormatString: String,
  85. options: TextFormatDecodingOptions = TextFormatDecodingOptions(),
  86. extensions: (any ExtensionMap)? = nil
  87. ) throws {
  88. self.init()
  89. if !textFormatString.isEmpty {
  90. if let data = textFormatString.data(using: String.Encoding.utf8) {
  91. try data.withUnsafeBytes { (body: UnsafeRawBufferPointer) in
  92. if let baseAddress = body.baseAddress, body.count > 0 {
  93. var decoder = try TextFormatDecoder(
  94. messageType: Self.self,
  95. utf8Pointer: baseAddress,
  96. count: body.count,
  97. options: options,
  98. extensions: extensions
  99. )
  100. try decodeMessage(decoder: &decoder)
  101. if !decoder.complete {
  102. throw TextFormatDecodingError.trailingGarbage
  103. }
  104. }
  105. }
  106. }
  107. }
  108. }
  109. }