Coverage Report

Created: 2026-02-14 07:18

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/swift-protobuf/Sources/SwiftProtobuf/BinaryEncodingSizeVisitor.swift
Line
Count
Source
1
// Sources/SwiftProtobuf/BinaryEncodingSizeVisitor.swift - Binary size calculation 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
/// Visitor used during binary encoding that precalcuates the size of a
12
/// serialized message.
13
///
14
// -----------------------------------------------------------------------------
15
16
import Foundation
17
18
/// Visitor that calculates the binary-encoded size of a message so that a
19
/// properly sized `Data` or `UInt8` array can be pre-allocated before
20
/// serialization.
21
internal struct BinaryEncodingSizeVisitor: Visitor {
22
23
    /// Accumulates the required size of the message during traversal.
24
113M
    var serializedSize: Int = 0
25
26
110M
    init() {}
27
28
894k
    mutating func visitUnknown(bytes: Data) throws {
29
894k
        serializedSize += bytes.count
30
894k
    }
31
32
191k
    mutating func visitSingularFloatField(value: Float, fieldNumber: Int) throws {
33
191k
        let tagSize = FieldTag(fieldNumber: fieldNumber, wireFormat: .fixed32).encodedSize
34
191k
        serializedSize += tagSize + MemoryLayout<Float>.size
35
191k
    }
36
37
103k
    mutating func visitSingularDoubleField(value: Double, fieldNumber: Int) throws {
38
103k
        let tagSize = FieldTag(fieldNumber: fieldNumber, wireFormat: .fixed64).encodedSize
39
103k
        serializedSize += tagSize + MemoryLayout<Double>.size
40
103k
    }
41
42
968k
    mutating func visitSingularInt32Field(value: Int32, fieldNumber: Int) throws {
43
968k
        try visitSingularInt64Field(value: Int64(value), fieldNumber: fieldNumber)
44
968k
    }
45
46
1.35M
    mutating func visitSingularInt64Field(value: Int64, fieldNumber: Int) throws {
47
1.35M
        let tagSize = FieldTag(fieldNumber: fieldNumber, wireFormat: .varint).encodedSize
48
1.35M
        serializedSize += tagSize + Varint.encodedSize(of: value)
49
1.35M
    }
50
51
396k
    mutating func visitSingularUInt32Field(value: UInt32, fieldNumber: Int) throws {
52
396k
        try visitSingularUInt64Field(value: UInt64(value), fieldNumber: fieldNumber)
53
396k
    }
54
55
734k
    mutating func visitSingularUInt64Field(value: UInt64, fieldNumber: Int) throws {
56
734k
        let tagSize = FieldTag(fieldNumber: fieldNumber, wireFormat: .varint).encodedSize
57
734k
        serializedSize += tagSize + Varint.encodedSize(of: value)
58
734k
    }
59
60
353k
    mutating func visitSingularSInt32Field(value: Int32, fieldNumber: Int) throws {
61
353k
        let tagSize = FieldTag(fieldNumber: fieldNumber, wireFormat: .varint).encodedSize
62
353k
        serializedSize += tagSize + Varint.encodedSize(of: ZigZag.encoded(value))
63
353k
    }
64
65
417k
    mutating func visitSingularSInt64Field(value: Int64, fieldNumber: Int) throws {
66
417k
        let tagSize = FieldTag(fieldNumber: fieldNumber, wireFormat: .varint).encodedSize
67
417k
        serializedSize += tagSize + Varint.encodedSize(of: ZigZag.encoded(value))
68
417k
    }
69
70
666k
    mutating func visitSingularFixed32Field(value: UInt32, fieldNumber: Int) throws {
71
666k
        let tagSize = FieldTag(fieldNumber: fieldNumber, wireFormat: .fixed32).encodedSize
72
666k
        serializedSize += tagSize + MemoryLayout<UInt32>.size
73
666k
    }
74
75
760k
    mutating func visitSingularFixed64Field(value: UInt64, fieldNumber: Int) throws {
76
760k
        let tagSize = FieldTag(fieldNumber: fieldNumber, wireFormat: .fixed64).encodedSize
77
760k
        serializedSize += tagSize + MemoryLayout<UInt64>.size
78
760k
    }
79
80
1.36M
    mutating func visitSingularSFixed32Field(value: Int32, fieldNumber: Int) throws {
81
1.36M
        let tagSize = FieldTag(fieldNumber: fieldNumber, wireFormat: .fixed32).encodedSize
82
1.36M
        serializedSize += tagSize + MemoryLayout<Int32>.size
83
1.36M
    }
84
85
959k
    mutating func visitSingularSFixed64Field(value: Int64, fieldNumber: Int) throws {
86
959k
        let tagSize = FieldTag(fieldNumber: fieldNumber, wireFormat: .fixed64).encodedSize
87
959k
        serializedSize += tagSize + MemoryLayout<Int64>.size
88
959k
    }
89
90
750k
    mutating func visitSingularBoolField(value: Bool, fieldNumber: Int) throws {
91
750k
        let tagSize = FieldTag(fieldNumber: fieldNumber, wireFormat: .varint).encodedSize
92
750k
        serializedSize += tagSize + 1
93
750k
    }
94
95
312k
    mutating func visitSingularStringField(value: String, fieldNumber: Int) throws {
96
312k
        let tagSize = FieldTag(fieldNumber: fieldNumber, wireFormat: .lengthDelimited).encodedSize
97
312k
        let count = value.utf8.count
98
312k
        serializedSize += tagSize + Varint.encodedSize(of: Int64(count)) + count
99
312k
    }
100
101
183k
    mutating func visitSingularBytesField(value: Data, fieldNumber: Int) throws {
102
183k
        let tagSize = FieldTag(fieldNumber: fieldNumber, wireFormat: .lengthDelimited).encodedSize
103
183k
        let count = value.count
104
183k
        serializedSize += tagSize + Varint.encodedSize(of: Int64(count)) + count
105
183k
    }
106
107
    // The default impls for visitRepeated*Field would work, but by implementing
108
    // these directly, the calculation for the tag overhead can be optimized and
109
    // the fixed width fields can be simple multiplication.
110
111
77.2k
    mutating func visitRepeatedFloatField(value: [Float], fieldNumber: Int) throws {
112
77.2k
        assert(!value.isEmpty)
113
77.2k
        let tagSize = FieldTag(fieldNumber: fieldNumber, wireFormat: .fixed32).encodedSize
114
77.2k
        serializedSize += tagSize * value.count + MemoryLayout<Float>.size * value.count
115
77.2k
    }
116
117
43.0k
    mutating func visitRepeatedDoubleField(value: [Double], fieldNumber: Int) throws {
118
43.0k
        assert(!value.isEmpty)
119
43.0k
        let tagSize = FieldTag(fieldNumber: fieldNumber, wireFormat: .fixed64).encodedSize
120
43.0k
        serializedSize += tagSize * value.count + MemoryLayout<Double>.size * value.count
121
43.0k
    }
122
123
56.1k
    mutating func visitRepeatedInt32Field(value: [Int32], fieldNumber: Int) throws {
124
56.1k
        assert(!value.isEmpty)
125
56.1k
        let tagSize = FieldTag(fieldNumber: fieldNumber, wireFormat: .varint).encodedSize
126
310k
        let dataSize = value.reduce(0) { $0 + Varint.encodedSize(of: $1) }
127
56.1k
        serializedSize += tagSize * value.count + dataSize
128
56.1k
    }
129
130
40.7k
    mutating func visitRepeatedInt64Field(value: [Int64], fieldNumber: Int) throws {
131
40.7k
        assert(!value.isEmpty)
132
40.7k
        let tagSize = FieldTag(fieldNumber: fieldNumber, wireFormat: .varint).encodedSize
133
420k
        let dataSize = value.reduce(0) { $0 + Varint.encodedSize(of: $1) }
134
40.7k
        serializedSize += tagSize * value.count + dataSize
135
40.7k
    }
136
137
107k
    mutating func visitRepeatedUInt32Field(value: [UInt32], fieldNumber: Int) throws {
138
107k
        assert(!value.isEmpty)
139
107k
        let tagSize = FieldTag(fieldNumber: fieldNumber, wireFormat: .varint).encodedSize
140
838k
        let dataSize = value.reduce(0) { $0 + Varint.encodedSize(of: $1) }
141
107k
        serializedSize += tagSize * value.count + dataSize
142
107k
    }
143
144
46.1k
    mutating func visitRepeatedUInt64Field(value: [UInt64], fieldNumber: Int) throws {
145
46.1k
        assert(!value.isEmpty)
146
46.1k
        let tagSize = FieldTag(fieldNumber: fieldNumber, wireFormat: .varint).encodedSize
147
1.98M
        let dataSize = value.reduce(0) { $0 + Varint.encodedSize(of: $1) }
148
46.1k
        serializedSize += tagSize * value.count + dataSize
149
46.1k
    }
150
151
44.0k
    mutating func visitRepeatedSInt32Field(value: [Int32], fieldNumber: Int) throws {
152
44.0k
        assert(!value.isEmpty)
153
44.0k
        let tagSize = FieldTag(fieldNumber: fieldNumber, wireFormat: .varint).encodedSize
154
906k
        let dataSize = value.reduce(0) { $0 + Varint.encodedSize(of: ZigZag.encoded($1)) }
155
44.0k
        serializedSize += tagSize * value.count + dataSize
156
44.0k
    }
157
158
71.2k
    mutating func visitRepeatedSInt64Field(value: [Int64], fieldNumber: Int) throws {
159
71.2k
        assert(!value.isEmpty)
160
71.2k
        let tagSize = FieldTag(fieldNumber: fieldNumber, wireFormat: .varint).encodedSize
161
2.47M
        let dataSize = value.reduce(0) { $0 + Varint.encodedSize(of: ZigZag.encoded($1)) }
162
71.2k
        serializedSize += tagSize * value.count + dataSize
163
71.2k
    }
164
165
56.9k
    mutating func visitRepeatedFixed32Field(value: [UInt32], fieldNumber: Int) throws {
166
56.9k
        assert(!value.isEmpty)
167
56.9k
        let tagSize = FieldTag(fieldNumber: fieldNumber, wireFormat: .fixed32).encodedSize
168
56.9k
        serializedSize += tagSize * value.count + MemoryLayout<UInt32>.size * value.count
169
56.9k
    }
170
171
11.5k
    mutating func visitRepeatedFixed64Field(value: [UInt64], fieldNumber: Int) throws {
172
11.5k
        assert(!value.isEmpty)
173
11.5k
        let tagSize = FieldTag(fieldNumber: fieldNumber, wireFormat: .fixed64).encodedSize
174
11.5k
        serializedSize += tagSize * value.count + MemoryLayout<UInt64>.size * value.count
175
11.5k
    }
176
177
35.0k
    mutating func visitRepeatedSFixed32Field(value: [Int32], fieldNumber: Int) throws {
178
35.0k
        assert(!value.isEmpty)
179
35.0k
        let tagSize = FieldTag(fieldNumber: fieldNumber, wireFormat: .fixed32).encodedSize
180
35.0k
        serializedSize += tagSize * value.count + MemoryLayout<Int32>.size * value.count
181
35.0k
    }
182
183
32.1k
    mutating func visitRepeatedSFixed64Field(value: [Int64], fieldNumber: Int) throws {
184
32.1k
        assert(!value.isEmpty)
185
32.1k
        let tagSize = FieldTag(fieldNumber: fieldNumber, wireFormat: .fixed64).encodedSize
186
32.1k
        serializedSize += tagSize * value.count + MemoryLayout<Int64>.size * value.count
187
32.1k
    }
188
189
39.8k
    mutating func visitRepeatedBoolField(value: [Bool], fieldNumber: Int) throws {
190
39.8k
        assert(!value.isEmpty)
191
39.8k
        let tagSize = FieldTag(fieldNumber: fieldNumber, wireFormat: .varint).encodedSize
192
39.8k
        serializedSize += tagSize * value.count + 1 * value.count
193
39.8k
    }
194
195
27.1k
    mutating func visitRepeatedStringField(value: [String], fieldNumber: Int) throws {
196
27.1k
        assert(!value.isEmpty)
197
27.1k
        let tagSize = FieldTag(fieldNumber: fieldNumber, wireFormat: .lengthDelimited).encodedSize
198
70.8k
        let dataSize = value.reduce(0) {
199
70.8k
            let count = $1.utf8.count
200
70.8k
            return $0 + Varint.encodedSize(of: Int64(count)) + count
201
70.8k
        }
202
27.1k
        serializedSize += tagSize * value.count + dataSize
203
27.1k
    }
204
205
61.8k
    mutating func visitRepeatedBytesField(value: [Data], fieldNumber: Int) throws {
206
61.8k
        assert(!value.isEmpty)
207
61.8k
        let tagSize = FieldTag(fieldNumber: fieldNumber, wireFormat: .lengthDelimited).encodedSize
208
108k
        let dataSize = value.reduce(0) {
209
108k
            let count = $1.count
210
108k
            return $0 + Varint.encodedSize(of: Int64(count)) + count
211
108k
        }
212
61.8k
        serializedSize += tagSize * value.count + dataSize
213
61.8k
    }
214
215
    // Packed field handling.
216
217
51.2k
    mutating func visitPackedFloatField(value: [Float], fieldNumber: Int) throws {
218
51.2k
        assert(!value.isEmpty)
219
51.2k
        let tagSize = FieldTag(fieldNumber: fieldNumber, wireFormat: .lengthDelimited).encodedSize
220
51.2k
        let dataSize = value.count * MemoryLayout<Float>.size
221
51.2k
        serializedSize += tagSize + Varint.encodedSize(of: Int64(dataSize)) + dataSize
222
51.2k
    }
223
224
54.5k
    mutating func visitPackedDoubleField(value: [Double], fieldNumber: Int) throws {
225
54.5k
        assert(!value.isEmpty)
226
54.5k
        let tagSize = FieldTag(fieldNumber: fieldNumber, wireFormat: .lengthDelimited).encodedSize
227
54.5k
        let dataSize = value.count * MemoryLayout<Double>.size
228
54.5k
        serializedSize += tagSize + Varint.encodedSize(of: Int64(dataSize)) + dataSize
229
54.5k
    }
230
231
21.9k
    mutating func visitPackedInt32Field(value: [Int32], fieldNumber: Int) throws {
232
21.9k
        assert(!value.isEmpty)
233
21.9k
        let tagSize = FieldTag(fieldNumber: fieldNumber, wireFormat: .lengthDelimited).encodedSize
234
2.24M
        let dataSize = value.reduce(0) { $0 + Varint.encodedSize(of: $1) }
235
21.9k
        serializedSize +=
236
21.9k
            tagSize + Varint.encodedSize(of: Int64(dataSize)) + dataSize
237
21.9k
    }
238
239
28.3k
    mutating func visitPackedInt64Field(value: [Int64], fieldNumber: Int) throws {
240
28.3k
        assert(!value.isEmpty)
241
28.3k
        let tagSize = FieldTag(fieldNumber: fieldNumber, wireFormat: .lengthDelimited).encodedSize
242
2.41M
        let dataSize = value.reduce(0) { $0 + Varint.encodedSize(of: $1) }
243
28.3k
        serializedSize +=
244
28.3k
            tagSize + Varint.encodedSize(of: Int64(dataSize)) + dataSize
245
28.3k
    }
246
247
39.2k
    mutating func visitPackedSInt32Field(value: [Int32], fieldNumber: Int) throws {
248
39.2k
        assert(!value.isEmpty)
249
39.2k
        let tagSize = FieldTag(fieldNumber: fieldNumber, wireFormat: .lengthDelimited).encodedSize
250
1.13M
        let dataSize = value.reduce(0) { $0 + Varint.encodedSize(of: ZigZag.encoded($1)) }
251
39.2k
        serializedSize +=
252
39.2k
            tagSize + Varint.encodedSize(of: Int64(dataSize)) + dataSize
253
39.2k
    }
254
255
58.8k
    mutating func visitPackedSInt64Field(value: [Int64], fieldNumber: Int) throws {
256
58.8k
        assert(!value.isEmpty)
257
58.8k
        let tagSize = FieldTag(fieldNumber: fieldNumber, wireFormat: .lengthDelimited).encodedSize
258
669k
        let dataSize = value.reduce(0) { $0 + Varint.encodedSize(of: ZigZag.encoded($1)) }
259
58.8k
        serializedSize +=
260
58.8k
            tagSize + Varint.encodedSize(of: Int64(dataSize)) + dataSize
261
58.8k
    }
262
263
44.1k
    mutating func visitPackedUInt32Field(value: [UInt32], fieldNumber: Int) throws {
264
44.1k
        assert(!value.isEmpty)
265
44.1k
        let tagSize = FieldTag(fieldNumber: fieldNumber, wireFormat: .lengthDelimited).encodedSize
266
2.44M
        let dataSize = value.reduce(0) { $0 + Varint.encodedSize(of: $1) }
267
44.1k
        serializedSize +=
268
44.1k
            tagSize + Varint.encodedSize(of: Int64(dataSize)) + dataSize
269
44.1k
    }
270
271
54.5k
    mutating func visitPackedUInt64Field(value: [UInt64], fieldNumber: Int) throws {
272
54.5k
        assert(!value.isEmpty)
273
54.5k
        let tagSize = FieldTag(fieldNumber: fieldNumber, wireFormat: .lengthDelimited).encodedSize
274
4.48M
        let dataSize = value.reduce(0) { $0 + Varint.encodedSize(of: $1) }
275
54.5k
        serializedSize +=
276
54.5k
            tagSize + Varint.encodedSize(of: Int64(dataSize)) + dataSize
277
54.5k
    }
278
279
85.6k
    mutating func visitPackedFixed32Field(value: [UInt32], fieldNumber: Int) throws {
280
85.6k
        assert(!value.isEmpty)
281
85.6k
        let tagSize = FieldTag(fieldNumber: fieldNumber, wireFormat: .lengthDelimited).encodedSize
282
85.6k
        let dataSize = value.count * MemoryLayout<UInt32>.size
283
85.6k
        serializedSize += tagSize + Varint.encodedSize(of: Int64(dataSize)) + dataSize
284
85.6k
    }
285
286
66.9k
    mutating func visitPackedFixed64Field(value: [UInt64], fieldNumber: Int) throws {
287
66.9k
        assert(!value.isEmpty)
288
66.9k
        let tagSize = FieldTag(fieldNumber: fieldNumber, wireFormat: .lengthDelimited).encodedSize
289
66.9k
        let dataSize = value.count * MemoryLayout<UInt64>.size
290
66.9k
        serializedSize += tagSize + Varint.encodedSize(of: Int64(dataSize)) + dataSize
291
66.9k
    }
292
293
35.1k
    mutating func visitPackedSFixed32Field(value: [Int32], fieldNumber: Int) throws {
294
35.1k
        assert(!value.isEmpty)
295
35.1k
        let tagSize = FieldTag(fieldNumber: fieldNumber, wireFormat: .lengthDelimited).encodedSize
296
35.1k
        let dataSize = value.count * MemoryLayout<Int32>.size
297
35.1k
        serializedSize += tagSize + Varint.encodedSize(of: Int64(dataSize)) + dataSize
298
35.1k
    }
299
300
56.5k
    mutating func visitPackedSFixed64Field(value: [Int64], fieldNumber: Int) throws {
301
56.5k
        assert(!value.isEmpty)
302
56.5k
        let tagSize = FieldTag(fieldNumber: fieldNumber, wireFormat: .lengthDelimited).encodedSize
303
56.5k
        let dataSize = value.count * MemoryLayout<Int64>.size
304
56.5k
        serializedSize += tagSize + Varint.encodedSize(of: Int64(dataSize)) + dataSize
305
56.5k
    }
306
307
26.2k
    mutating func visitPackedBoolField(value: [Bool], fieldNumber: Int) throws {
308
26.2k
        assert(!value.isEmpty)
309
26.2k
        let tagSize = FieldTag(fieldNumber: fieldNumber, wireFormat: .lengthDelimited).encodedSize
310
26.2k
        let dataSize = value.count
311
26.2k
        serializedSize += tagSize + Varint.encodedSize(of: Int64(dataSize)) + dataSize
312
26.2k
    }
313
314
    mutating func visitSingularEnumField<E: Enum>(
315
        value: E,
316
        fieldNumber: Int
317
850k
    ) throws {
318
850k
        let tagSize = FieldTag(
319
850k
            fieldNumber: fieldNumber,
320
850k
            wireFormat: .varint
321
850k
        ).encodedSize
322
850k
        serializedSize += tagSize
323
850k
        let dataSize = Varint.encodedSize(of: Int32(truncatingIfNeeded: value.rawValue))
324
850k
        serializedSize += dataSize
325
850k
    }
326
327
    mutating func visitRepeatedEnumField<E: Enum>(
328
        value: [E],
329
        fieldNumber: Int
330
48.0k
    ) throws {
331
48.0k
        assert(!value.isEmpty)
332
48.0k
        let tagSize = FieldTag(
333
48.0k
            fieldNumber: fieldNumber,
334
48.0k
            wireFormat: .varint
335
48.0k
        ).encodedSize
336
48.0k
        serializedSize += value.count * tagSize
337
752k
        let dataSize = value.reduce(0) {
338
752k
            $0 + Varint.encodedSize(of: Int32(truncatingIfNeeded: $1.rawValue))
339
752k
        }
340
48.0k
        serializedSize += dataSize
341
48.0k
    }
342
343
    mutating func visitPackedEnumField<E: Enum>(
344
        value: [E],
345
        fieldNumber: Int
346
84.9k
    ) throws {
347
84.9k
        assert(!value.isEmpty)
348
84.9k
        let tagSize = FieldTag(
349
84.9k
            fieldNumber: fieldNumber,
350
84.9k
            wireFormat: .varint
351
84.9k
        ).encodedSize
352
84.9k
        serializedSize += tagSize
353
345k
        let dataSize = value.reduce(0) {
354
345k
            $0 + Varint.encodedSize(of: Int32(truncatingIfNeeded: $1.rawValue))
355
345k
        }
356
84.9k
        serializedSize += Varint.encodedSize(of: Int64(dataSize)) + dataSize
357
84.9k
    }
358
359
    mutating func visitSingularMessageField<M: Message>(
360
        value: M,
361
        fieldNumber: Int
362
2.57M
    ) throws {
363
2.57M
        let tagSize = FieldTag(
364
2.57M
            fieldNumber: fieldNumber,
365
2.57M
            wireFormat: .lengthDelimited
366
2.57M
        ).encodedSize
367
2.57M
        let messageSize = try value.serializedDataSize()
368
2.57M
        serializedSize +=
369
2.57M
            tagSize + Varint.encodedSize(of: UInt64(messageSize)) + messageSize
370
2.57M
    }
371
372
    mutating func visitRepeatedMessageField<M: Message>(
373
        value: [M],
374
        fieldNumber: Int
375
380k
    ) throws {
376
380k
        assert(!value.isEmpty)
377
380k
        let tagSize = FieldTag(
378
380k
            fieldNumber: fieldNumber,
379
380k
            wireFormat: .lengthDelimited
380
380k
        ).encodedSize
381
380k
        serializedSize += value.count * tagSize
382
2.77M
        let dataSize = try value.reduce(0) {
383
2.77M
            let messageSize = try $1.serializedDataSize()
384
2.77M
            return $0 + Varint.encodedSize(of: UInt64(messageSize)) + messageSize
385
2.77M
        }
386
380k
        serializedSize += dataSize
387
380k
    }
388
389
47.9k
    mutating func visitSingularGroupField<G: Message>(value: G, fieldNumber: Int) throws {
390
47.9k
        // The wire format doesn't matter here because the encoded size of the
391
47.9k
        // integer won't change based on the low three bits.
392
47.9k
        let tagSize = FieldTag(
393
47.9k
            fieldNumber: fieldNumber,
394
47.9k
            wireFormat: .startGroup
395
47.9k
        ).encodedSize
396
47.9k
        serializedSize += 2 * tagSize
397
47.9k
        try value.traverse(visitor: &self)
398
47.9k
    }
399
400
    mutating func visitRepeatedGroupField<G: Message>(
401
        value: [G],
402
        fieldNumber: Int
403
21.8k
    ) throws {
404
21.8k
        assert(!value.isEmpty)
405
21.8k
        let tagSize = FieldTag(
406
21.8k
            fieldNumber: fieldNumber,
407
21.8k
            wireFormat: .startGroup
408
21.8k
        ).encodedSize
409
21.8k
        serializedSize += 2 * value.count * tagSize
410
45.1k
        for v in value {
411
45.1k
            try v.traverse(visitor: &self)
412
45.1k
        }
413
21.8k
    }
414
415
    mutating func visitMapField<KeyType, ValueType: MapValueType>(
416
        fieldType: _ProtobufMap<KeyType, ValueType>.Type,
417
        value: _ProtobufMap<KeyType, ValueType>.BaseType,
418
        fieldNumber: Int
419
1.14M
    ) throws {
420
1.14M
        let tagSize = FieldTag(
421
1.14M
            fieldNumber: fieldNumber,
422
1.14M
            wireFormat: .lengthDelimited
423
1.14M
        ).encodedSize
424
1.40M
        for (k, v) in value {
425
1.40M
            var sizer = BinaryEncodingSizeVisitor()
426
1.40M
            try KeyType.visitSingular(value: k, fieldNumber: 1, with: &sizer)
427
1.40M
            try ValueType.visitSingular(value: v, fieldNumber: 2, with: &sizer)
428
1.40M
            let entrySize = sizer.serializedSize
429
1.40M
            serializedSize += Varint.encodedSize(of: Int64(entrySize)) + entrySize
430
1.40M
        }
431
1.14M
        serializedSize += value.count * tagSize
432
1.14M
    }
433
434
    mutating func visitMapField<KeyType, ValueType>(
435
        fieldType: _ProtobufEnumMap<KeyType, ValueType>.Type,
436
        value: _ProtobufEnumMap<KeyType, ValueType>.BaseType,
437
        fieldNumber: Int
438
107k
    ) throws where ValueType.RawValue == Int {
439
107k
        let tagSize = FieldTag(
440
107k
            fieldNumber: fieldNumber,
441
107k
            wireFormat: .lengthDelimited
442
107k
        ).encodedSize
443
458k
        for (k, v) in value {
444
458k
            var sizer = BinaryEncodingSizeVisitor()
445
458k
            try KeyType.visitSingular(value: k, fieldNumber: 1, with: &sizer)
446
458k
            try sizer.visitSingularEnumField(value: v, fieldNumber: 2)
447
458k
            let entrySize = sizer.serializedSize
448
458k
            serializedSize += Varint.encodedSize(of: Int64(entrySize)) + entrySize
449
458k
        }
450
107k
        serializedSize += value.count * tagSize
451
107k
    }
452
453
    mutating func visitMapField<KeyType, ValueType>(
454
        fieldType: _ProtobufMessageMap<KeyType, ValueType>.Type,
455
        value: _ProtobufMessageMap<KeyType, ValueType>.BaseType,
456
        fieldNumber: Int
457
160k
    ) throws {
458
160k
        let tagSize = FieldTag(
459
160k
            fieldNumber: fieldNumber,
460
160k
            wireFormat: .lengthDelimited
461
160k
        ).encodedSize
462
1.18M
        for (k, v) in value {
463
1.18M
            var sizer = BinaryEncodingSizeVisitor()
464
1.18M
            try KeyType.visitSingular(value: k, fieldNumber: 1, with: &sizer)
465
1.18M
            try sizer.visitSingularMessageField(value: v, fieldNumber: 2)
466
1.18M
            let entrySize = sizer.serializedSize
467
1.18M
            serializedSize += Varint.encodedSize(of: Int64(entrySize)) + entrySize
468
1.18M
        }
469
160k
        serializedSize += value.count * tagSize
470
160k
    }
471
472
    mutating func visitExtensionFieldsAsMessageSet(
473
        fields: ExtensionFieldValueSet,
474
        start: Int,
475
        end: Int
476
2.09M
    ) throws {
477
2.09M
        var sizer = BinaryEncodingMessageSetSizeVisitor()
478
2.09M
        try fields.traverse(visitor: &sizer, start: start, end: end)
479
2.09M
        serializedSize += sizer.serializedSize
480
2.09M
    }
481
}
482
483
extension BinaryEncodingSizeVisitor {
484
485
    // Helper Visitor to compute the sizes when writing out the extensions as MessageSets.
486
    internal struct BinaryEncodingMessageSetSizeVisitor: SelectiveVisitor {
487
2.11M
        var serializedSize: Int = 0
488
489
2.09M
        init() {}
490
491
16.6k
        mutating func visitSingularMessageField<M: Message>(value: M, fieldNumber: Int) throws {
492
16.6k
            var groupSize = WireFormat.MessageSet.itemTagsEncodedSize
493
16.6k
494
16.6k
            groupSize += Varint.encodedSize(of: Int32(fieldNumber))
495
16.6k
496
16.6k
            let messageSize = try value.serializedDataSize()
497
16.6k
            groupSize += Varint.encodedSize(of: UInt64(messageSize)) + messageSize
498
16.6k
499
16.6k
            serializedSize += groupSize
500
16.6k
        }
501
502
        // SelectiveVisitor handles the rest.
503
    }
504
505
}