Coverage Report

Created: 2021-09-03 06:06

/src/swift-protobuf/Sources/SwiftProtobuf/TextFormatEncodingVisitor.swift
Line
Count
Source (jump to first uncovered line)
1
// Sources/SwiftProtobuf/TextFormatEncodingVisitor.swift - Text format encoding support
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
/// Text format serialization engine.
12
///
13
// -----------------------------------------------------------------------------
14
15
import Foundation
16
17
private let mapNameResolver: [Int:StaticString] = [1: "key", 2: "value"]
18
19
/// Visitor that serializes a message into protobuf text format.
20
internal struct TextFormatEncodingVisitor: Visitor {
21
22
  private var encoder: TextFormatEncoder
23
  private var nameMap: _NameMap?
24
  private var nameResolver: [Int:StaticString]
25
  private var extensions: ExtensionFieldValueSet?
26
  private let options: TextFormatEncodingOptions
27
28
  /// The protobuf text produced by the visitor.
29
0
  var result: String {
30
0
    return encoder.stringResult
31
0
  }
32
33
  /// Creates a new visitor that serializes the given message to protobuf text
34
  /// format.
35
0
  init(message: Message, options: TextFormatEncodingOptions) {
36
0
    self.init(message: message, encoder: TextFormatEncoder(), options: options)
37
0
  }
38
39
  /// Creates a new visitor that serializes the given message to protobuf text
40
  /// format, using an existing encoder.
41
0
  private init(message: Message, encoder: TextFormatEncoder, options: TextFormatEncodingOptions) {
42
0
    let nameMap: _NameMap?
43
0
    if let nameProviding = message as? _ProtoNameProviding {
44
0
        nameMap = type(of: nameProviding)._protobuf_nameMap
45
0
    } else {
46
0
        nameMap = nil
47
0
    }
48
0
    let extensions = (message as? ExtensibleMessage)?._protobuf_extensionFieldValues
49
0
    self.init(nameMap: nameMap, nameResolver: [:], extensions: extensions, encoder: encoder, options: options)
50
0
  }
51
52
  private init(
53
    nameMap: _NameMap?,
54
    nameResolver: [Int:StaticString],
55
    extensions: ExtensionFieldValueSet?,
56
    encoder: TextFormatEncoder,
57
    options: TextFormatEncodingOptions
58
0
  ) {
59
0
    self.nameMap = nameMap
60
0
    self.nameResolver = nameResolver
61
0
    self.extensions = extensions
62
0
    self.encoder = encoder
63
0
    self.options = options
64
0
  }
65
66
  // TODO: This largely duplicates emitFieldName() below.
67
  // But, it's slower so we don't want to just have emitFieldName() use
68
  // formatFieldName().  Also, we need to measure whether the optimization
69
  // this provides to repeated fields is worth the effort; consider just
70
  // removing this and having repeated fields just re-run emitFieldName()
71
  // for each item.
72
0
  private func formatFieldName(lookingUp fieldNumber: Int) -> [UInt8] {
73
0
      var bytes = [UInt8]()
74
0
      if let protoName = nameMap?.names(for: fieldNumber)?.proto {
75
0
          bytes.append(contentsOf: protoName.utf8Buffer)
76
0
      } else if let protoName = nameResolver[fieldNumber] {
77
0
          let buff = UnsafeBufferPointer(start: protoName.utf8Start, count: protoName.utf8CodeUnitCount)
78
0
          bytes.append(contentsOf: buff)
79
0
      } else if let extensionName = extensions?[fieldNumber]?.protobufExtension.fieldName {
80
0
          bytes.append(UInt8(ascii: "["))
81
0
          bytes.append(contentsOf: extensionName.utf8)
82
0
          bytes.append(UInt8(ascii: "]"))
83
0
      } else {
84
0
          bytes.append(contentsOf: fieldNumber.description.utf8)
85
0
      }
86
0
      return bytes
87
0
  }
88
89
0
  private mutating func emitFieldName(lookingUp fieldNumber: Int) {
90
0
      if let protoName = nameMap?.names(for: fieldNumber)?.proto {
91
0
          encoder.emitFieldName(name: protoName.utf8Buffer)
92
0
      } else if let protoName = nameResolver[fieldNumber] {
93
0
          encoder.emitFieldName(name: protoName)
94
0
      } else if let extensionName = extensions?[fieldNumber]?.protobufExtension.fieldName {
95
0
          encoder.emitExtensionFieldName(name: extensionName)
96
0
      } else {
97
0
          encoder.emitFieldNumber(number: fieldNumber)
98
0
      }
99
0
  }
100
101
0
  mutating func visitUnknown(bytes: Data) throws {
102
0
      if options.printUnknownFields {
103
0
          try bytes.withUnsafeBytes { (body: UnsafeRawBufferPointer) -> () in
104
0
            if let baseAddress = body.baseAddress, body.count > 0 {
105
0
              // All fields will be directly handled, so there is no need for
106
0
              // the unknown field buffering/collection (when scannings to see
107
0
              // if something is a message, this would be extremely wasteful).
108
0
              var binaryOptions = BinaryDecodingOptions()
109
0
              binaryOptions.discardUnknownFields = true
110
0
              var decoder = BinaryDecoder(forReadingFrom: baseAddress,
111
0
                                          count: body.count,
112
0
                                          options: binaryOptions)
113
0
              try visitUnknown(decoder: &decoder)
114
0
            }
115
0
          }
116
0
      }
117
0
  }
118
119
  /// Helper for printing out unknowns.
120
  ///
121
  /// The implementation tries to be "helpful" and if a length delimited field
122
  /// appears to be a submessage, it prints it as such. However, that opens the
123
  /// door to someone sending a message with an unknown field that is a stack
124
  /// bomb, i.e. - it causes this code to recurse, exhausing the stack and
125
  /// thus opening up an attack vector. To keep this "help", but avoid the
126
  /// attack, a limit is placed on how many times it will recurse before just
127
  /// treating the length delimted fields as bytes and not trying to decode
128
  /// them.
129
  private mutating func visitUnknown(
130
    decoder: inout BinaryDecoder,
131
    recursionBudget: Int = 10
132
0
  ) throws {
133
0
      // This stack serves to avoid recursion for groups within groups within
134
0
      // groups..., this avoid the stack attack that the message detection
135
0
      // hits. No limit is placed on this because there is no stack risk with
136
0
      // recursion, and because if a limit was hit, there is no other way to
137
0
      // encode the group (the message field can just print as length
138
0
      // delimited, groups don't have an option like that).
139
0
      var groupFieldNumberStack: [Int] = []
140
0
141
0
      while let tag = try decoder.getTag() {
142
0
          switch tag.wireFormat {
143
0
          case .varint:
144
0
              encoder.emitFieldNumber(number: tag.fieldNumber)
145
0
              var value: UInt64 = 0
146
0
              encoder.startRegularField()
147
0
              try decoder.decodeSingularUInt64Field(value: &value)
148
0
              encoder.putUInt64(value: value)
149
0
              encoder.endRegularField()
150
0
          case .fixed64:
151
0
              encoder.emitFieldNumber(number: tag.fieldNumber)
152
0
              var value: UInt64 = 0
153
0
              encoder.startRegularField()
154
0
              try decoder.decodeSingularFixed64Field(value: &value)
155
0
              encoder.putUInt64Hex(value: value, digits: 16)
156
0
              encoder.endRegularField()
157
0
          case .lengthDelimited:
158
0
              encoder.emitFieldNumber(number: tag.fieldNumber)
159
0
              var bytes = Data()
160
0
              try decoder.decodeSingularBytesField(value: &bytes)
161
0
              bytes.withUnsafeBytes { (body: UnsafeRawBufferPointer) -> () in
162
0
                  if let baseAddress = body.baseAddress, body.count > 0 {
163
0
                      var encodeAsBytes: Bool
164
0
                      if (recursionBudget > 0) {
165
0
                          do {
166
0
                              // Walk all the fields to test if it looks like a message
167
0
                              var testDecoder = BinaryDecoder(forReadingFrom: baseAddress,
168
0
                                                              count: body.count,
169
0
                                                              parent: decoder)
170
0
                              while let _ = try testDecoder.nextFieldNumber() {
171
0
                              }
172
0
                              // No error?  Output the message body.
173
0
                              encodeAsBytes = false
174
0
                              var subDecoder = BinaryDecoder(forReadingFrom: baseAddress,
175
0
                                                             count: bytes.count,
176
0
                                                             parent: decoder)
177
0
                              encoder.startMessageField()
178
0
                              try visitUnknown(decoder: &subDecoder,
179
0
                                               recursionBudget: recursionBudget - 1)
180
0
                              encoder.endMessageField()
181
0
                          } catch {
182
0
                              encodeAsBytes = true
183
0
                          }
184
0
                      } else {
185
0
                          encodeAsBytes = true
186
0
                      }
187
0
                      if (encodeAsBytes) {
188
0
                        encoder.startRegularField()
189
0
                        encoder.putBytesValue(value: bytes)
190
0
                        encoder.endRegularField()
191
0
                      }
192
0
                  }
193
0
              }
194
0
          case .startGroup:
195
0
              encoder.emitFieldNumber(number: tag.fieldNumber)
196
0
              encoder.startMessageField()
197
0
              groupFieldNumberStack.append(tag.fieldNumber)
198
0
          case .endGroup:
199
0
              let groupFieldNumber = groupFieldNumberStack.popLast()
200
0
              // Unknown data is scanned and verified by the
201
0
              // binary parser, so this can never fail.
202
0
              assert(tag.fieldNumber == groupFieldNumber)
203
0
              encoder.endMessageField()
204
0
          case .fixed32:
205
0
              encoder.emitFieldNumber(number: tag.fieldNumber)
206
0
              var value: UInt32 = 0
207
0
              encoder.startRegularField()
208
0
              try decoder.decodeSingularFixed32Field(value: &value)
209
0
              encoder.putUInt64Hex(value: UInt64(value), digits: 8)
210
0
              encoder.endRegularField()
211
0
          }
212
0
      }
213
0
214
0
    // Unknown data is scanned and verified by the binary parser, so this can
215
0
    // never fail.
216
0
    assert(groupFieldNumberStack.isEmpty)
217
0
  }
218
219
  // Visitor.swift defines default versions for other singular field types
220
  // that simply widen and dispatch to one of the following.  Since Text format
221
  // does not distinguish e.g., Fixed64 vs. UInt64, this is sufficient.
222
223
0
  mutating func visitSingularFloatField(value: Float, fieldNumber: Int) throws {
224
0
      emitFieldName(lookingUp: fieldNumber)
225
0
      encoder.startRegularField()
226
0
      encoder.putFloatValue(value: value)
227
0
      encoder.endRegularField()
228
0
  }
229
230
0
  mutating func visitSingularDoubleField(value: Double, fieldNumber: Int) throws {
231
0
      emitFieldName(lookingUp: fieldNumber)
232
0
      encoder.startRegularField()
233
0
      encoder.putDoubleValue(value: value)
234
0
      encoder.endRegularField()
235
0
  }
236
237
0
  mutating func visitSingularInt64Field(value: Int64, fieldNumber: Int) throws {
238
0
      emitFieldName(lookingUp: fieldNumber)
239
0
      encoder.startRegularField()
240
0
      encoder.putInt64(value: value)
241
0
      encoder.endRegularField()
242
0
  }
243
244
0
  mutating func visitSingularUInt64Field(value: UInt64, fieldNumber: Int) throws {
245
0
      emitFieldName(lookingUp: fieldNumber)
246
0
      encoder.startRegularField()
247
0
      encoder.putUInt64(value: value)
248
0
      encoder.endRegularField()
249
0
  }
250
251
0
  mutating func visitSingularBoolField(value: Bool, fieldNumber: Int) throws {
252
0
      emitFieldName(lookingUp: fieldNumber)
253
0
      encoder.startRegularField()
254
0
      encoder.putBoolValue(value: value)
255
0
      encoder.endRegularField()
256
0
  }
257
258
0
  mutating func visitSingularStringField(value: String, fieldNumber: Int) throws {
259
0
      emitFieldName(lookingUp: fieldNumber)
260
0
      encoder.startRegularField()
261
0
      encoder.putStringValue(value: value)
262
0
      encoder.endRegularField()
263
0
  }
264
265
0
  mutating func visitSingularBytesField(value: Data, fieldNumber: Int) throws {
266
0
      emitFieldName(lookingUp: fieldNumber)
267
0
      encoder.startRegularField()
268
0
      encoder.putBytesValue(value: value)
269
0
      encoder.endRegularField()
270
0
  }
271
272
0
  mutating func visitSingularEnumField<E: Enum>(value: E, fieldNumber: Int) throws {
273
0
      emitFieldName(lookingUp: fieldNumber)
274
0
      encoder.startRegularField()
275
0
      encoder.putEnumValue(value: value)
276
0
      encoder.endRegularField()
277
0
  }
278
279
  mutating func visitSingularMessageField<M: Message>(value: M,
280
0
                                             fieldNumber: Int) throws {
281
0
      emitFieldName(lookingUp: fieldNumber)
282
0
283
0
      // Cache old encoder state
284
0
      let oldNameMap = self.nameMap
285
0
      let oldNameResolver = self.nameResolver
286
0
      let oldExtensions = self.extensions
287
0
      // Update encoding state for new message
288
0
      self.nameMap = (M.self as? _ProtoNameProviding.Type)?._protobuf_nameMap
289
0
      self.nameResolver = [:]
290
0
      self.extensions = (value as? ExtensibleMessage)?._protobuf_extensionFieldValues
291
0
      // Restore state before returning
292
0
      defer {
293
0
        self.extensions = oldExtensions
294
0
        self.nameResolver = oldNameResolver
295
0
        self.nameMap = oldNameMap
296
0
      }
297
0
      // Encode submessage
298
0
      encoder.startMessageField()
299
0
      if let any = value as? Google_Protobuf_Any {
300
0
          any.textTraverse(visitor: &self)
301
0
      } else {
302
0
          try! value.traverse(visitor: &self)
303
0
      }
304
0
      encoder.endMessageField()
305
0
  }
306
307
  // Emit the full "verbose" form of an Any.  This writes the typeURL
308
  // as a field name in `[...]` followed by the fields of the
309
  // contained message.
310
0
  internal mutating func visitAnyVerbose(value: Message, typeURL: String) {
311
0
      encoder.emitExtensionFieldName(name: typeURL)
312
0
      encoder.startMessageField()
313
0
      var visitor = TextFormatEncodingVisitor(message: value, encoder: encoder, options: options)
314
0
      if let any = value as? Google_Protobuf_Any {
315
0
          any.textTraverse(visitor: &visitor)
316
0
      } else {
317
0
          try! value.traverse(visitor: &visitor)
318
0
      }
319
0
      encoder = visitor.encoder
320
0
      encoder.endMessageField()
321
0
  }
322
323
  // Write a single special field called "#json".  This
324
  // is used for Any objects with undecoded JSON contents.
325
0
  internal mutating func visitAnyJSONDataField(value: Data) {
326
0
      encoder.indent()
327
0
      encoder.append(staticText: "#json: ")
328
0
      encoder.putBytesValue(value: value)
329
0
      encoder.append(staticText: "\n")
330
0
  }
331
332
  // The default implementations in Visitor.swift provide the correct
333
  // results, but we get significantly better performance by only doing
334
  // the name lookup once for the array, rather than once for each element:
335
336
0
  mutating func visitRepeatedFloatField(value: [Float], fieldNumber: Int) throws {
337
0
      assert(!value.isEmpty)
338
0
      let fieldName = formatFieldName(lookingUp: fieldNumber)
339
0
      for v in value {
340
0
          encoder.emitFieldName(name: fieldName)
341
0
          encoder.startRegularField()
342
0
          encoder.putFloatValue(value: v)
343
0
          encoder.endRegularField()
344
0
      }
345
0
  }
346
347
0
  mutating func visitRepeatedDoubleField(value: [Double], fieldNumber: Int) throws {
348
0
      assert(!value.isEmpty)
349
0
      let fieldName = formatFieldName(lookingUp: fieldNumber)
350
0
      for v in value {
351
0
          encoder.emitFieldName(name: fieldName)
352
0
          encoder.startRegularField()
353
0
          encoder.putDoubleValue(value: v)
354
0
          encoder.endRegularField()
355
0
      }
356
0
  }
357
358
0
  mutating func visitRepeatedInt32Field(value: [Int32], fieldNumber: Int) throws {
359
0
      assert(!value.isEmpty)
360
0
      let fieldName = formatFieldName(lookingUp: fieldNumber)
361
0
      for v in value {
362
0
          encoder.emitFieldName(name: fieldName)
363
0
          encoder.startRegularField()
364
0
          encoder.putInt64(value: Int64(v))
365
0
          encoder.endRegularField()
366
0
      }
367
0
  }
368
369
0
  mutating func visitRepeatedInt64Field(value: [Int64], fieldNumber: Int) throws {
370
0
      assert(!value.isEmpty)
371
0
      let fieldName = formatFieldName(lookingUp: fieldNumber)
372
0
      for v in value {
373
0
          encoder.emitFieldName(name: fieldName)
374
0
          encoder.startRegularField()
375
0
          encoder.putInt64(value: v)
376
0
          encoder.endRegularField()
377
0
      }
378
0
  }
379
380
0
  mutating func visitRepeatedUInt32Field(value: [UInt32], fieldNumber: Int) throws {
381
0
      assert(!value.isEmpty)
382
0
      let fieldName = formatFieldName(lookingUp: fieldNumber)
383
0
      for v in value {
384
0
          encoder.emitFieldName(name: fieldName)
385
0
          encoder.startRegularField()
386
0
          encoder.putUInt64(value: UInt64(v))
387
0
          encoder.endRegularField()
388
0
      }
389
0
  }
390
391
0
  mutating func visitRepeatedUInt64Field(value: [UInt64], fieldNumber: Int) throws {
392
0
      assert(!value.isEmpty)
393
0
      let fieldName = formatFieldName(lookingUp: fieldNumber)
394
0
      for v in value {
395
0
          encoder.emitFieldName(name: fieldName)
396
0
          encoder.startRegularField()
397
0
          encoder.putUInt64(value: v)
398
0
          encoder.endRegularField()
399
0
      }
400
0
  }
401
402
0
  mutating func visitRepeatedSInt32Field(value: [Int32], fieldNumber: Int) throws {
403
0
    try visitRepeatedInt32Field(value: value, fieldNumber: fieldNumber)
404
0
  }
405
0
  mutating func visitRepeatedSInt64Field(value: [Int64], fieldNumber: Int) throws {
406
0
    try visitRepeatedInt64Field(value: value, fieldNumber: fieldNumber)
407
0
  }
408
0
  mutating func visitRepeatedFixed32Field(value: [UInt32], fieldNumber: Int) throws {
409
0
    try visitRepeatedUInt32Field(value: value, fieldNumber: fieldNumber)
410
0
  }
411
0
  mutating func visitRepeatedFixed64Field(value: [UInt64], fieldNumber: Int) throws {
412
0
    try visitRepeatedUInt64Field(value: value, fieldNumber: fieldNumber)
413
0
  }
414
0
  mutating func visitRepeatedSFixed32Field(value: [Int32], fieldNumber: Int) throws {
415
0
    try visitRepeatedInt32Field(value: value, fieldNumber: fieldNumber)
416
0
  }
417
0
  mutating func visitRepeatedSFixed64Field(value: [Int64], fieldNumber: Int) throws {
418
0
    try visitRepeatedInt64Field(value: value, fieldNumber: fieldNumber)
419
0
  }
420
421
0
  mutating func visitRepeatedBoolField(value: [Bool], fieldNumber: Int) throws {
422
0
      assert(!value.isEmpty)
423
0
      let fieldName = formatFieldName(lookingUp: fieldNumber)
424
0
      for v in value {
425
0
          encoder.emitFieldName(name: fieldName)
426
0
          encoder.startRegularField()
427
0
          encoder.putBoolValue(value: v)
428
0
          encoder.endRegularField()
429
0
      }
430
0
  }
431
432
0
  mutating func visitRepeatedStringField(value: [String], fieldNumber: Int) throws {
433
0
      assert(!value.isEmpty)
434
0
      let fieldName = formatFieldName(lookingUp: fieldNumber)
435
0
      for v in value {
436
0
          encoder.emitFieldName(name: fieldName)
437
0
          encoder.startRegularField()
438
0
          encoder.putStringValue(value: v)
439
0
          encoder.endRegularField()
440
0
      }
441
0
  }
442
443
0
  mutating func visitRepeatedBytesField(value: [Data], fieldNumber: Int) throws {
444
0
      assert(!value.isEmpty)
445
0
      let fieldName = formatFieldName(lookingUp: fieldNumber)
446
0
      for v in value {
447
0
          encoder.emitFieldName(name: fieldName)
448
0
          encoder.startRegularField()
449
0
          encoder.putBytesValue(value: v)
450
0
          encoder.endRegularField()
451
0
      }
452
0
  }
453
454
0
  mutating func visitRepeatedEnumField<E: Enum>(value: [E], fieldNumber: Int) throws {
455
0
      assert(!value.isEmpty)
456
0
      let fieldName = formatFieldName(lookingUp: fieldNumber)
457
0
      for v in value {
458
0
          encoder.emitFieldName(name: fieldName)
459
0
          encoder.startRegularField()
460
0
          encoder.putEnumValue(value: v)
461
0
          encoder.endRegularField()
462
0
      }
463
0
  }
464
465
  // Messages and groups
466
  mutating func visitRepeatedMessageField<M: Message>(value: [M],
467
0
                                             fieldNumber: Int) throws {
468
0
      assert(!value.isEmpty)
469
0
      // Look up field name against outer message encoding state
470
0
      let fieldName = formatFieldName(lookingUp: fieldNumber)
471
0
      // Cache old encoder state
472
0
      let oldNameMap = self.nameMap
473
0
      let oldNameResolver = self.nameResolver
474
0
      let oldExtensions = self.extensions
475
0
      // Update encoding state for new message type
476
0
      self.nameMap = (M.self as? _ProtoNameProviding.Type)?._protobuf_nameMap
477
0
      self.nameResolver = [:]
478
0
      self.extensions = (value as? ExtensibleMessage)?._protobuf_extensionFieldValues
479
0
      // Iterate and encode each message
480
0
      for v in value {
481
0
          encoder.emitFieldName(name: fieldName)
482
0
          encoder.startMessageField()
483
0
          if let any = v as? Google_Protobuf_Any {
484
0
              any.textTraverse(visitor: &self)
485
0
          } else {
486
0
              try! v.traverse(visitor: &self)
487
0
          }
488
0
          encoder.endMessageField()
489
0
      }
490
0
      // Restore state
491
0
      self.extensions = oldExtensions
492
0
      self.nameResolver = oldNameResolver
493
0
      self.nameMap = oldNameMap
494
0
  }
495
496
  // Google's C++ implementation of Text format supports two formats
497
  // for repeated numeric fields: "short" format writes the list as a
498
  // single field with values enclosed in `[...]`, "long" format
499
  // writes a separate field name/value for each item.  They provide
500
  // an option for callers to select which output version they prefer.
501
502
  // Since this distinction mirrors the difference in Protobuf Binary
503
  // between "packed" and "non-packed", I've chosen to use the short
504
  // format for packed fields and the long version for repeated
505
  // fields.  This provides a clear visual distinction between these
506
  // fields (including proto3's default use of packed) without
507
  // introducing the baggage of a separate option.
508
509
  private mutating func _visitPacked<T>(
510
    value: [T], fieldNumber: Int,
511
    encode: (T, inout TextFormatEncoder) -> ()
512
0
  ) throws {
513
0
      assert(!value.isEmpty)
514
0
      emitFieldName(lookingUp: fieldNumber)
515
0
      encoder.startRegularField()
516
0
      var firstItem = true
517
0
      encoder.startArray()
518
0
      for v in value {
519
0
          if !firstItem {
520
0
              encoder.arraySeparator()
521
0
          }
522
0
          encode(v, &encoder)
523
0
          firstItem = false
524
0
      }
525
0
      encoder.endArray()
526
0
      encoder.endRegularField()
527
0
  }
528
529
0
  mutating func visitPackedFloatField(value: [Float], fieldNumber: Int) throws {
530
0
    try _visitPacked(value: value, fieldNumber: fieldNumber) {
531
0
      (v: Float, encoder: inout TextFormatEncoder) in
532
0
      encoder.putFloatValue(value: v)
533
0
    }
534
0
  }
535
536
0
  mutating func visitPackedDoubleField(value: [Double], fieldNumber: Int) throws {
537
0
    try _visitPacked(value: value, fieldNumber: fieldNumber) {
538
0
      (v: Double, encoder: inout TextFormatEncoder) in
539
0
      encoder.putDoubleValue(value: v)
540
0
    }
541
0
  }
542
543
0
  mutating func visitPackedInt32Field(value: [Int32], fieldNumber: Int) throws {
544
0
    try _visitPacked(value: value, fieldNumber: fieldNumber) {
545
0
      (v: Int32, encoder: inout TextFormatEncoder) in
546
0
      encoder.putInt64(value: Int64(v))
547
0
    }
548
0
  }
549
550
0
  mutating func visitPackedInt64Field(value: [Int64], fieldNumber: Int) throws {
551
0
    try _visitPacked(value: value, fieldNumber: fieldNumber) {
552
0
      (v: Int64, encoder: inout TextFormatEncoder) in
553
0
      encoder.putInt64(value: v)
554
0
    }
555
0
  }
556
557
0
  mutating func visitPackedUInt32Field(value: [UInt32], fieldNumber: Int) throws {
558
0
    try _visitPacked(value: value, fieldNumber: fieldNumber) {
559
0
      (v: UInt32, encoder: inout TextFormatEncoder) in
560
0
      encoder.putUInt64(value: UInt64(v))
561
0
    }
562
0
  }
563
564
0
  mutating func visitPackedUInt64Field(value: [UInt64], fieldNumber: Int) throws {
565
0
    try _visitPacked(value: value, fieldNumber: fieldNumber) {
566
0
      (v: UInt64, encoder: inout TextFormatEncoder) in
567
0
      encoder.putUInt64(value: v)
568
0
    }
569
0
  }
570
571
0
  mutating func visitPackedSInt32Field(value: [Int32], fieldNumber: Int) throws {
572
0
    try visitPackedInt32Field(value: value, fieldNumber: fieldNumber)
573
0
  }
574
575
0
  mutating func visitPackedSInt64Field(value: [Int64], fieldNumber: Int) throws {
576
0
    try visitPackedInt64Field(value: value, fieldNumber: fieldNumber)
577
0
  }
578
579
0
  mutating func visitPackedFixed32Field(value: [UInt32], fieldNumber: Int) throws {
580
0
    try visitPackedUInt32Field(value: value, fieldNumber: fieldNumber)
581
0
  }
582
583
0
  mutating func visitPackedFixed64Field(value: [UInt64], fieldNumber: Int) throws {
584
0
    try visitPackedUInt64Field(value: value, fieldNumber: fieldNumber)
585
0
  }
586
587
0
  mutating func visitPackedSFixed32Field(value: [Int32], fieldNumber: Int) throws {
588
0
    try visitPackedInt32Field(value: value, fieldNumber: fieldNumber)
589
0
  }
590
591
0
  mutating func visitPackedSFixed64Field(value: [Int64], fieldNumber: Int) throws {
592
0
    try visitPackedInt64Field(value: value, fieldNumber: fieldNumber)
593
0
  }
594
595
0
  mutating func visitPackedBoolField(value: [Bool], fieldNumber: Int) throws {
596
0
    try _visitPacked(value: value, fieldNumber: fieldNumber) {
597
0
      (v: Bool, encoder: inout TextFormatEncoder) in
598
0
      encoder.putBoolValue(value: v)
599
0
    }
600
0
  }
601
602
0
  mutating func visitPackedEnumField<E: Enum>(value: [E], fieldNumber: Int) throws {
603
0
    try _visitPacked(value: value, fieldNumber: fieldNumber) {
604
0
      (v: E, encoder: inout TextFormatEncoder) in
605
0
      encoder.putEnumValue(value: v)
606
0
    }
607
0
  }
608
609
  /// Helper to encapsulate the common structure of iterating over a map
610
  /// and encoding the keys and values.
611
  private mutating func _visitMap<K, V>(
612
    map: Dictionary<K, V>,
613
    fieldNumber: Int,
614
    isOrderedBefore: (K, K) -> Bool,
615
    coder: (inout TextFormatEncodingVisitor, K, V) throws -> ()
616
0
  ) throws {
617
0
      for (k,v) in map.sorted(by: { isOrderedBefore( $0.0, $1.0) }) {
618
0
          emitFieldName(lookingUp: fieldNumber)
619
0
          encoder.startMessageField()
620
0
          var visitor = TextFormatEncodingVisitor(nameMap: nil, nameResolver: mapNameResolver, extensions: nil, encoder: encoder, options: options)
621
0
          try coder(&visitor, k, v)
622
0
          encoder = visitor.encoder
623
0
          encoder.endMessageField()
624
0
      }
625
0
  }
626
627
  mutating func visitMapField<KeyType, ValueType: MapValueType>(
628
    fieldType: _ProtobufMap<KeyType, ValueType>.Type,
629
    value: _ProtobufMap<KeyType, ValueType>.BaseType,
630
    fieldNumber: Int
631
0
  ) throws {
632
0
      try _visitMap(map: value, fieldNumber: fieldNumber, isOrderedBefore: KeyType._lessThan) {
Unexecuted instantiation: $s13SwiftProtobuf25TextFormatEncodingVisitorV13visitMapField9fieldType5value0J6NumberyAA01_bH0Vyxq_Gm_SDy04BaseK0QzAKQy_GSitKAA0h3KeyK0RzAA0h5ValueK0R_r0_lFSbAL_ALtcxmcfu_
Unexecuted instantiation: $s13SwiftProtobuf25TextFormatEncodingVisitorV13visitMapField9fieldType5value0J6NumberyAA01_bH0Vyxq_Gm_SDy04BaseK0QzAKQy_GSitKAA0h3KeyK0RzAA0h5ValueK0R_r0_lFSbAL_ALtcxmcfu_SbAL_ALtcfu0_
633
0
          (visitor: inout TextFormatEncodingVisitor, key, value) throws -> () in
634
0
          try KeyType.visitSingular(value: key, fieldNumber: 1, with: &visitor)
635
0
          try ValueType.visitSingular(value: value, fieldNumber: 2, with: &visitor)
636
0
      }
637
0
  }
638
639
  mutating func visitMapField<KeyType, ValueType>(
640
    fieldType: _ProtobufEnumMap<KeyType, ValueType>.Type,
641
    value: _ProtobufEnumMap<KeyType, ValueType>.BaseType,
642
    fieldNumber: Int
643
0
  ) throws where ValueType.RawValue == Int {
644
0
      try _visitMap(map: value, fieldNumber: fieldNumber, isOrderedBefore: KeyType._lessThan) {
Unexecuted instantiation: $s13SwiftProtobuf25TextFormatEncodingVisitorV13visitMapField9fieldType5value0J6NumberyAA01_b4EnumH0Vyxq_Gm_SDy04BaseK0Qzq_GSitKAA0h3KeyK0RzAA0N0R_Si8RawValueRt_r0_lFSbAL_ALtcxmcfu_
Unexecuted instantiation: $s13SwiftProtobuf25TextFormatEncodingVisitorV13visitMapField9fieldType5value0J6NumberyAA01_b4EnumH0Vyxq_Gm_SDy04BaseK0Qzq_GSitKAA0h3KeyK0RzAA0N0R_Si8RawValueRt_r0_lFSbAL_ALtcxmcfu_SbAL_ALtcfu0_
645
0
          (visitor: inout TextFormatEncodingVisitor, key, value) throws -> () in
646
0
          try KeyType.visitSingular(value: key, fieldNumber: 1, with: &visitor)
647
0
          try visitor.visitSingularEnumField(value: value, fieldNumber: 2)
648
0
      }
649
0
  }
650
651
  mutating func visitMapField<KeyType, ValueType>(
652
    fieldType: _ProtobufMessageMap<KeyType, ValueType>.Type,
653
    value: _ProtobufMessageMap<KeyType, ValueType>.BaseType,
654
    fieldNumber: Int
655
0
  ) throws {
656
0
      try _visitMap(map: value, fieldNumber: fieldNumber, isOrderedBefore: KeyType._lessThan) {
Unexecuted instantiation: $s13SwiftProtobuf25TextFormatEncodingVisitorV13visitMapField9fieldType5value0J6NumberyAA01_b7MessageH0Vyxq_Gm_SDy04BaseK0Qzq_GSitKAA0h3KeyK0RzSHR_AA0N0R_r0_lFSbAL_ALtcxmcfu_
Unexecuted instantiation: $s13SwiftProtobuf25TextFormatEncodingVisitorV13visitMapField9fieldType5value0J6NumberyAA01_b7MessageH0Vyxq_Gm_SDy04BaseK0Qzq_GSitKAA0h3KeyK0RzSHR_AA0N0R_r0_lFSbAL_ALtcxmcfu_SbAL_ALtcfu0_
657
0
          (visitor: inout TextFormatEncodingVisitor, key, value) throws -> () in
658
0
          try KeyType.visitSingular(value: key, fieldNumber: 1, with: &visitor)
659
0
          try visitor.visitSingularMessageField(value: value, fieldNumber: 2)
660
0
      }
661
0
  }
662
}