/src/swift-protobuf/Sources/SwiftProtobuf/Message+TextFormatAdditions.swift
Line | Count | Source |
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 | | |
15 | | #if canImport(FoundationEssentials) |
16 | | import FoundationEssentials |
17 | | #else |
18 | | import Foundation |
19 | | #endif |
20 | | |
21 | | /// Text format encoding and decoding methods for messages. |
22 | | extension Message { |
23 | | /// Returns a string containing the Protocol Buffer text format serialization |
24 | | /// of the message. |
25 | | /// |
26 | | /// Unlike binary encoding, presence of required fields is not enforced when |
27 | | /// serializing to text format. |
28 | | /// |
29 | | /// - Returns: A string containing the text format serialization of the |
30 | | /// message. |
31 | 0 | public func textFormatString() -> String { |
32 | 0 | // This is implemented as a separate zero-argument function |
33 | 0 | // to preserve binary compatibility. |
34 | 0 | textFormatString(options: TextFormatEncodingOptions()) |
35 | 0 | } |
36 | | |
37 | | /// Returns a string containing the Protocol Buffer text format serialization |
38 | | /// of the message. |
39 | | /// |
40 | | /// Unlike binary encoding, presence of required fields is not enforced when |
41 | | /// serializing to text format. |
42 | | /// |
43 | | /// - Returns: A string containing the text format serialization of the message. |
44 | | /// - Parameters: |
45 | | /// - options: The TextFormatEncodingOptions to use. |
46 | | public func textFormatString( |
47 | | options: TextFormatEncodingOptions |
48 | 19.2k | ) -> String { |
49 | 19.2k | var visitor = TextFormatEncodingVisitor(message: self, options: options) |
50 | 19.2k | if let any = self as? Google_Protobuf_Any { |
51 | 0 | any._storage.textTraverse(visitor: &visitor) |
52 | 19.2k | } else { |
53 | 19.2k | // Although the general traversal/encoding infrastructure supports |
54 | 19.2k | // throwing errors (needed for JSON/Binary WKTs support, binary format |
55 | 19.2k | // missing required fields); TextEncoding never actually does throw. |
56 | 19.2k | try! traverse(visitor: &visitor) |
57 | 19.2k | } |
58 | 19.2k | return visitor.result |
59 | 19.2k | } |
60 | | |
61 | | /// Creates a new message by decoding the given string containing a |
62 | | /// serialized message in Protocol Buffer text format. |
63 | | /// |
64 | | /// - Parameters: |
65 | | /// - textFormatString: The text format string to decode. |
66 | | /// - extensions: An ``ExtensionMap`` used to look up and decode any |
67 | | /// extensions in this message or messages nested within this message's |
68 | | /// fields. |
69 | | /// - Throws: ``SwiftProtobufError`` on failure. |
70 | | // TODO: delete this (and keep the one with the extra param instead) when we break API |
71 | | public init( |
72 | | textFormatString: String, |
73 | | extensions: (any ExtensionMap)? = nil |
74 | 0 | ) throws { |
75 | 0 | try self.init( |
76 | 0 | textFormatString: textFormatString, |
77 | 0 | options: TextFormatDecodingOptions(), |
78 | 0 | extensions: extensions |
79 | 0 | ) |
80 | 0 | } |
81 | | |
82 | | /// Creates a new message by decoding the given string containing a |
83 | | /// serialized message in Protocol Buffer text format. |
84 | | /// |
85 | | /// - Parameters: |
86 | | /// - textFormatString: The text format string to decode. |
87 | | /// - options: The ``TextFormatDecodingOptions`` to use. |
88 | | /// - extensions: An ``ExtensionMap`` used to look up and decode any |
89 | | /// extensions in this message or messages nested within this message's |
90 | | /// fields. |
91 | | /// - Throws: ``TextFormatDecodingError`` on failure. |
92 | | public init( |
93 | | textFormatString: String, |
94 | | options: TextFormatDecodingOptions = TextFormatDecodingOptions(), |
95 | | extensions: (any ExtensionMap)? = nil |
96 | 36.7k | ) throws { |
97 | 36.7k | self.init() |
98 | 36.7k | if !textFormatString.isEmpty { |
99 | 36.7k | if let data = textFormatString.data(using: String.Encoding.utf8) { |
100 | 36.7k | try data.withUnsafeBytes { (body: UnsafeRawBufferPointer) in |
101 | 36.7k | if let baseAddress = body.baseAddress, body.count > 0 { |
102 | 36.7k | var decoder = try TextFormatDecoder( |
103 | 36.7k | messageType: Self.self, |
104 | 36.7k | utf8Pointer: baseAddress, |
105 | 36.7k | count: body.count, |
106 | 36.7k | options: options, |
107 | 36.7k | extensions: extensions |
108 | 36.7k | ) |
109 | 36.7k | try decodeMessage(decoder: &decoder) |
110 | 19.2k | if !decoder.complete { |
111 | 0 | throw TextFormatDecodingError.trailingGarbage |
112 | 19.2k | } |
113 | 19.2k | } |
114 | 19.2k | } |
115 | 19.2k | } |
116 | 19.2k | } |
117 | 19.2k | } |
118 | | } |