Coverage Report

Created: 2026-08-14 06:30

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/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
}