// Sources/SwiftProtobuf/Message+TextFormatAdditions.swift - Text format primitive types // // Copyright (c) 2014 - 2016 Apple Inc. and the project authors // Licensed under Apache License v2.0 with Runtime Library Exception // // See LICENSE.txt for license information: // https://github.com/apple/swift-protobuf/blob/main/LICENSE.txt // // ----------------------------------------------------------------------------- /// /// Extensions to `Message` to support text format encoding/decoding. /// // ----------------------------------------------------------------------------- import Foundation /// Text format encoding and decoding methods for messages. extension Message { /// Returns a string containing the Protocol Buffer text format serialization /// of the message. /// /// Unlike binary encoding, presence of required fields is not enforced when /// serializing to text format. /// /// - Returns: A string containing the text format serialization of the /// message. public func textFormatString() -> String { // This is implemented as a separate zero-argument function // to preserve binary compatibility. textFormatString(options: TextFormatEncodingOptions()) } /// Returns a string containing the Protocol Buffer text format serialization /// of the message. /// /// Unlike binary encoding, presence of required fields is not enforced when /// serializing to text format. /// /// - Returns: A string containing the text format serialization of the message. /// - Parameters: /// - options: The TextFormatEncodingOptions to use. public func textFormatString( options: TextFormatEncodingOptions ) -> String { var visitor = TextFormatEncodingVisitor(message: self, options: options) if let any = self as? Google_Protobuf_Any { any._storage.textTraverse(visitor: &visitor) } else { // Although the general traversal/encoding infrastructure supports // throwing errors (needed for JSON/Binary WKTs support, binary format // missing required fields); TextEncoding never actually does throw. try! traverse(visitor: &visitor) } return visitor.result } /// Creates a new message by decoding the given string containing a /// serialized message in Protocol Buffer text format. /// /// - Parameters: /// - textFormatString: The text format string to decode. /// - extensions: An ``ExtensionMap`` used to look up and decode any /// extensions in this message or messages nested within this message's /// fields. /// - Throws: ``SwiftProtobufError`` on failure. // TODO: delete this (and keep the one with the extra param instead) when we break API public init( textFormatString: String, extensions: (any ExtensionMap)? = nil ) throws { try self.init( textFormatString: textFormatString, options: TextFormatDecodingOptions(), extensions: extensions ) } /// Creates a new message by decoding the given string containing a /// serialized message in Protocol Buffer text format. /// /// - Parameters: /// - textFormatString: The text format string to decode. /// - options: The ``TextFormatDecodingOptions`` to use. /// - extensions: An ``ExtensionMap`` used to look up and decode any /// extensions in this message or messages nested within this message's /// fields. /// - Throws: ``TextFormatDecodingError`` on failure. public init( textFormatString: String, options: TextFormatDecodingOptions = TextFormatDecodingOptions(), extensions: (any ExtensionMap)? = nil ) throws { self.init() if !textFormatString.isEmpty { if let data = textFormatString.data(using: String.Encoding.utf8) { try data.withUnsafeBytes { (body: UnsafeRawBufferPointer) in if let baseAddress = body.baseAddress, body.count > 0 { var decoder = try TextFormatDecoder( messageType: Self.self, utf8Pointer: baseAddress, count: body.count, options: options, extensions: extensions ) try decodeMessage(decoder: &decoder) if !decoder.complete { throw TextFormatDecodingError.trailingGarbage } } } } } } }