@@ -17,6 +17,7 @@ import Foundation
17
17
18
18
/// Visitor that encodes a message graph in the protobuf binary wire format.
19
19
internal struct BinaryEncodingVisitor : Visitor {
20
+ private let options : BinaryEncodingOptions
20
21
21
22
var encoder : BinaryEncoder
22
23
@@ -26,8 +27,9 @@ internal struct BinaryEncodingVisitor: Visitor {
26
27
/// - Precondition: `pointer` must point to an allocated block of memory that
27
28
/// is large enough to hold the entire encoded message. For performance
28
29
/// reasons, the encoder does not make any attempts to verify this.
29
- init ( forWritingInto pointer: UnsafeMutableRawPointer ) {
30
- encoder = BinaryEncoder ( forWritingInto: pointer)
30
+ init ( forWritingInto pointer: UnsafeMutableRawPointer , options: BinaryEncodingOptions ) {
31
+ self . encoder = BinaryEncoder ( forWritingInto: pointer)
32
+ self . options = options
31
33
}
32
34
33
35
mutating func visitUnknown( bytes: Data ) throws {
@@ -258,49 +260,79 @@ internal struct BinaryEncodingVisitor: Visitor {
258
260
value: _ProtobufMap < KeyType , ValueType > . BaseType ,
259
261
fieldNumber: Int
260
262
) throws {
261
- for (k , v ) in value {
262
- encoder . startField ( fieldNumber: fieldNumber, wireFormat : . lengthDelimited )
263
- var sizer = BinaryEncodingSizeVisitor ( )
264
- try KeyType . visitSingular ( value: k , fieldNumber: 1 , with: & sizer)
265
- try ValueType . visitSingular ( value: v , fieldNumber: 2 , with: & sizer)
266
- let entrySize = sizer . serializedSize
267
- encoder . putVarInt ( value: entrySize )
268
- try KeyType . visitSingular ( value: k , fieldNumber: 1 , with: & self )
269
- try ValueType . visitSingular ( value : v , fieldNumber : 2 , with : & self )
270
- }
263
+ try iterateAndEncode (
264
+ map : value , fieldNumber: fieldNumber, isOrderedBefore : KeyType . _lessThan ,
265
+ encodeWithSizer : { sizer, key , value in
266
+ try KeyType . visitSingular ( value: key , fieldNumber: 1 , with: & sizer)
267
+ try ValueType . visitSingular ( value: value , fieldNumber: 2 , with: & sizer)
268
+ } , encodeWithVisitor : { visitor , key , value in
269
+ try KeyType . visitSingular ( value: key , fieldNumber : 1 , with : & visitor )
270
+ try ValueType . visitSingular ( value: value , fieldNumber: 2 , with: & visitor )
271
+ }
272
+ )
271
273
}
272
274
273
275
mutating func visitMapField< KeyType, ValueType> (
274
276
fieldType: _ProtobufEnumMap < KeyType , ValueType > . Type ,
275
277
value: _ProtobufEnumMap < KeyType , ValueType > . BaseType ,
276
278
fieldNumber: Int
277
279
) throws where ValueType. RawValue == Int {
278
- for (k , v ) in value {
279
- encoder . startField ( fieldNumber: fieldNumber, wireFormat : . lengthDelimited )
280
- var sizer = BinaryEncodingSizeVisitor ( )
281
- try KeyType . visitSingular ( value: k , fieldNumber: 1 , with: & sizer)
282
- try sizer. visitSingularEnumField ( value: v , fieldNumber: 2 )
283
- let entrySize = sizer . serializedSize
284
- encoder . putVarInt ( value: entrySize )
285
- try KeyType . visitSingular ( value: k , fieldNumber: 1 , with : & self )
286
- try visitSingularEnumField ( value : v , fieldNumber : 2 )
287
- }
280
+ try iterateAndEncode (
281
+ map : value , fieldNumber: fieldNumber, isOrderedBefore : KeyType . _lessThan ,
282
+ encodeWithSizer : { sizer, key , value in
283
+ try KeyType . visitSingular ( value: key , fieldNumber: 1 , with: & sizer)
284
+ try sizer. visitSingularEnumField ( value: value , fieldNumber: 2 )
285
+ } , encodeWithVisitor : { visitor , key , value in
286
+ try KeyType . visitSingular ( value: key , fieldNumber : 1 , with : & visitor )
287
+ try visitor . visitSingularEnumField ( value: value , fieldNumber: 2 )
288
+ }
289
+ )
288
290
}
289
291
290
292
mutating func visitMapField< KeyType, ValueType> (
291
293
fieldType: _ProtobufMessageMap < KeyType , ValueType > . Type ,
292
294
value: _ProtobufMessageMap < KeyType , ValueType > . BaseType ,
293
295
fieldNumber: Int
294
296
) throws {
295
- for (k, v) in value {
296
- encoder. startField ( fieldNumber: fieldNumber, wireFormat: . lengthDelimited)
297
- var sizer = BinaryEncodingSizeVisitor ( )
298
- try KeyType . visitSingular ( value: k, fieldNumber: 1 , with: & sizer)
299
- try sizer. visitSingularMessageField ( value: v, fieldNumber: 2 )
300
- let entrySize = sizer. serializedSize
301
- encoder. putVarInt ( value: entrySize)
302
- try KeyType . visitSingular ( value: k, fieldNumber: 1 , with: & self )
303
- try visitSingularMessageField ( value: v, fieldNumber: 2 )
297
+ try iterateAndEncode (
298
+ map: value, fieldNumber: fieldNumber, isOrderedBefore: KeyType . _lessThan,
299
+ encodeWithSizer: { sizer, key, value in
300
+ try KeyType . visitSingular ( value: key, fieldNumber: 1 , with: & sizer)
301
+ try sizer. visitSingularMessageField ( value: value, fieldNumber: 2 )
302
+ } , encodeWithVisitor: { visitor, key, value in
303
+ try KeyType . visitSingular ( value: key, fieldNumber: 1 , with: & visitor)
304
+ try visitor. visitSingularMessageField ( value: value, fieldNumber: 2 )
305
+ }
306
+ )
307
+ }
308
+
309
+ /// Helper to encapsulate the common structure of iterating over a map
310
+ /// and encoding the keys and values.
311
+ private mutating func iterateAndEncode< K, V> (
312
+ map: Dictionary < K , V > ,
313
+ fieldNumber: Int ,
314
+ isOrderedBefore: ( K , K ) -> Bool ,
315
+ encodeWithSizer: ( inout BinaryEncodingSizeVisitor , K , V ) throws -> ( ) ,
316
+ encodeWithVisitor: ( inout BinaryEncodingVisitor , K , V ) throws -> ( )
317
+ ) throws {
318
+ if options. useDeterministicOrdering {
319
+ for (k, v) in map. sorted ( by: { isOrderedBefore ( $0. 0 , $1. 0 ) } ) {
320
+ encoder. startField ( fieldNumber: fieldNumber, wireFormat: . lengthDelimited)
321
+ var sizer = BinaryEncodingSizeVisitor ( )
322
+ try encodeWithSizer ( & sizer, k, v)
323
+ let entrySize = sizer. serializedSize
324
+ encoder. putVarInt ( value: entrySize)
325
+ try encodeWithVisitor ( & self , k, v)
326
+ }
327
+ } else {
328
+ for (k, v) in map {
329
+ encoder. startField ( fieldNumber: fieldNumber, wireFormat: . lengthDelimited)
330
+ var sizer = BinaryEncodingSizeVisitor ( )
331
+ try encodeWithSizer ( & sizer, k, v)
332
+ let entrySize = sizer. serializedSize
333
+ encoder. putVarInt ( value: entrySize)
334
+ try encodeWithVisitor ( & self , k, v)
335
+ }
304
336
}
305
337
}
306
338
@@ -309,7 +341,7 @@ internal struct BinaryEncodingVisitor: Visitor {
309
341
start: Int ,
310
342
end: Int
311
343
) throws {
312
- var subVisitor = BinaryEncodingMessageSetVisitor ( encoder: encoder)
344
+ var subVisitor = BinaryEncodingMessageSetVisitor ( encoder: encoder, options : options )
313
345
try fields. traverse ( visitor: & subVisitor, start: start, end: end)
314
346
encoder = subVisitor. encoder
315
347
}
@@ -319,9 +351,12 @@ extension BinaryEncodingVisitor {
319
351
320
352
// Helper Visitor to when writing out the extensions as MessageSets.
321
353
internal struct BinaryEncodingMessageSetVisitor : SelectiveVisitor {
354
+ private let options : BinaryEncodingOptions
355
+
322
356
var encoder : BinaryEncoder
323
357
324
- init ( encoder: BinaryEncoder ) {
358
+ init ( encoder: BinaryEncoder , options: BinaryEncodingOptions ) {
359
+ self . options = options
325
360
self . encoder = encoder
326
361
}
327
362
@@ -338,7 +373,9 @@ extension BinaryEncodingVisitor {
338
373
let length = try value. serializedDataSize ( )
339
374
encoder. putVarInt ( value: length)
340
375
// Create the sub encoder after writing the length.
341
- var subVisitor = BinaryEncodingVisitor ( forWritingInto: encoder. pointer)
376
+ var subVisitor = BinaryEncodingVisitor (
377
+ forWritingInto: encoder. pointer, options: options
378
+ )
342
379
try value. traverse ( visitor: & subVisitor)
343
380
encoder. pointer = subVisitor. encoder. pointer
344
381
@@ -347,5 +384,4 @@ extension BinaryEncodingVisitor {
347
384
348
385
// SelectiveVisitor handles the rest.
349
386
}
350
-
351
387
}
0 commit comments