@@ -190,7 +190,7 @@ fileprivate class _JSONEncoder : Encoder {
190
190
/// Returns whether a new element can be encoded at this coding path.
191
191
///
192
192
/// `true` if an element has not yet been encoded at this coding path; `false` otherwise.
193
- var canEncodeNewElement : Bool {
193
+ var canEncodeNewValue : Bool {
194
194
// Every time a new value gets encoded, the key it's encoded for is pushed onto the coding path (even if it's a nil key from an unkeyed container).
195
195
// At the same time, every time a container is requested, a new value gets pushed onto the storage stack.
196
196
// If there are more values on the storage stack than on the coding path, it means the value is requesting more than one container, which violates the precondition.
@@ -200,39 +200,43 @@ fileprivate class _JSONEncoder : Encoder {
200
200
return self . storage. count == self . codingPath. count
201
201
}
202
202
203
- /// Asserts that a new container can be requested at this coding path.
204
- /// `preconditionFailure()`s if one cannot be requested.
205
- func assertCanRequestNewContainer( ) {
206
- guard self . canEncodeNewElement else {
207
- let previousContainerType : String
208
- if self . storage. containers. last is NSDictionary {
209
- previousContainerType = " keyed "
210
- } else if self . storage. containers. last is NSArray {
211
- previousContainerType = " unkeyed "
212
- } else {
213
- previousContainerType = " single value "
203
+ // MARK: - Encoder Methods
204
+ func container< Key> ( keyedBy: Key . Type ) -> KeyedEncodingContainer < Key > {
205
+ // If an existing keyed container was already requested, return that one.
206
+ let topContainer : NSMutableDictionary
207
+ if self . canEncodeNewValue {
208
+ // We haven't yet pushed a container at this level; do so here.
209
+ topContainer = self . storage. pushKeyedContainer ( )
210
+ } else {
211
+ guard let container = self . storage. containers. last as? NSMutableDictionary else {
212
+ preconditionFailure ( " Attempt to push new keyed encoding container when already previously encoded at this path. " )
214
213
}
215
214
216
- preconditionFailure ( " Attempt to encode with new container when already encoded with \( previousContainerType ) container. " )
215
+ topContainer = container
217
216
}
218
- }
219
217
220
- // MARK: - Encoder Methods
221
- func container< Key> ( keyedBy: Key . Type ) -> KeyedEncodingContainer < Key > {
222
- assertCanRequestNewContainer ( )
223
- let topContainer = self . storage. pushKeyedContainer ( )
224
218
let container = _JSONKeyedEncodingContainer < Key > ( referencing: self , codingPath: self . codingPath, wrapping: topContainer)
225
219
return KeyedEncodingContainer ( container)
226
220
}
227
221
228
222
func unkeyedContainer( ) -> UnkeyedEncodingContainer {
229
- assertCanRequestNewContainer ( )
230
- let topContainer = self . storage. pushUnkeyedContainer ( )
223
+ // If an existing unkeyed container was already requested, return that one.
224
+ let topContainer : NSMutableArray
225
+ if self . canEncodeNewValue {
226
+ // We haven't yet pushed a container at this level; do so here.
227
+ topContainer = self . storage. pushUnkeyedContainer ( )
228
+ } else {
229
+ guard let container = self . storage. containers. last as? NSMutableArray else {
230
+ preconditionFailure ( " Attempt to push new unkeyed encoding container when already previously encoded at this path. " )
231
+ }
232
+
233
+ topContainer = container
234
+ }
235
+
231
236
return _JSONUnkeyedEncodingContainer ( referencing: self , codingPath: self . codingPath, wrapping: topContainer)
232
237
}
233
238
234
239
func singleValueContainer( ) -> SingleValueEncodingContainer {
235
- assertCanRequestNewContainer ( )
236
240
return self
237
241
}
238
242
}
@@ -474,106 +478,89 @@ fileprivate struct _JSONUnkeyedEncodingContainer : UnkeyedEncodingContainer {
474
478
}
475
479
476
480
extension _JSONEncoder : SingleValueEncodingContainer {
477
- // MARK: - Utility Methods
478
-
479
- /// Asserts that a single value can be encoded at the current coding path (i.e. that one has not already been encoded through this container).
480
- /// `preconditionFailure()`s if one cannot be encoded.
481
- ///
482
- /// This is similar to assertCanRequestNewContainer above.
483
- func assertCanEncodeSingleValue( ) {
484
- guard self . canEncodeNewElement else {
485
- let previousContainerType : String
486
- if self . storage. containers. last is NSDictionary {
487
- previousContainerType = " keyed "
488
- } else if self . storage. containers. last is NSArray {
489
- previousContainerType = " unkeyed "
490
- } else {
491
- preconditionFailure ( " Attempt to encode multiple values in a single value container. " )
492
- }
481
+ // MARK: - SingleValueEncodingContainer Methods
493
482
494
- preconditionFailure ( " Attempt to encode with new container when already encoded with \( previousContainerType ) container. " )
495
- }
483
+ func assertCanEncodeNewValue ( ) {
484
+ precondition ( self . canEncodeNewValue , " Attempt to encode value through single value container when previously value already encoded. " )
496
485
}
497
486
498
- // MARK: - SingleValueEncodingContainer Methods
499
-
500
487
func encodeNil( ) throws {
501
- assertCanEncodeSingleValue ( )
488
+ assertCanEncodeNewValue ( )
502
489
self . storage. push ( container: NSNull ( ) )
503
490
}
504
491
505
492
func encode( _ value: Bool ) throws {
506
- assertCanEncodeSingleValue ( )
493
+ assertCanEncodeNewValue ( )
507
494
self . storage. push ( container: box ( value) )
508
495
}
509
496
510
497
func encode( _ value: Int ) throws {
511
- assertCanEncodeSingleValue ( )
498
+ assertCanEncodeNewValue ( )
512
499
self . storage. push ( container: box ( value) )
513
500
}
514
501
515
502
func encode( _ value: Int8 ) throws {
516
- assertCanEncodeSingleValue ( )
503
+ assertCanEncodeNewValue ( )
517
504
self . storage. push ( container: box ( value) )
518
505
}
519
506
520
507
func encode( _ value: Int16 ) throws {
521
- assertCanEncodeSingleValue ( )
508
+ assertCanEncodeNewValue ( )
522
509
self . storage. push ( container: box ( value) )
523
510
}
524
511
525
512
func encode( _ value: Int32 ) throws {
526
- assertCanEncodeSingleValue ( )
513
+ assertCanEncodeNewValue ( )
527
514
self . storage. push ( container: box ( value) )
528
515
}
529
516
530
517
func encode( _ value: Int64 ) throws {
531
- assertCanEncodeSingleValue ( )
518
+ assertCanEncodeNewValue ( )
532
519
self . storage. push ( container: box ( value) )
533
520
}
534
521
535
522
func encode( _ value: UInt ) throws {
536
- assertCanEncodeSingleValue ( )
523
+ assertCanEncodeNewValue ( )
537
524
self . storage. push ( container: box ( value) )
538
525
}
539
526
540
527
func encode( _ value: UInt8 ) throws {
541
- assertCanEncodeSingleValue ( )
528
+ assertCanEncodeNewValue ( )
542
529
self . storage. push ( container: box ( value) )
543
530
}
544
531
545
532
func encode( _ value: UInt16 ) throws {
546
- assertCanEncodeSingleValue ( )
533
+ assertCanEncodeNewValue ( )
547
534
self . storage. push ( container: box ( value) )
548
535
}
549
536
550
537
func encode( _ value: UInt32 ) throws {
551
- assertCanEncodeSingleValue ( )
538
+ assertCanEncodeNewValue ( )
552
539
self . storage. push ( container: box ( value) )
553
540
}
554
541
555
542
func encode( _ value: UInt64 ) throws {
556
- assertCanEncodeSingleValue ( )
543
+ assertCanEncodeNewValue ( )
557
544
self . storage. push ( container: box ( value) )
558
545
}
559
546
560
547
func encode( _ value: String ) throws {
561
- assertCanEncodeSingleValue ( )
548
+ assertCanEncodeNewValue ( )
562
549
self . storage. push ( container: box ( value) )
563
550
}
564
551
565
552
func encode( _ value: Float ) throws {
566
- assertCanEncodeSingleValue ( )
553
+ assertCanEncodeNewValue ( )
567
554
try self . storage. push ( container: box ( value) )
568
555
}
569
556
570
557
func encode( _ value: Double ) throws {
571
- assertCanEncodeSingleValue ( )
558
+ assertCanEncodeNewValue ( )
572
559
try self . storage. push ( container: box ( value) )
573
560
}
574
561
575
562
func encode< T : Encodable > ( _ value: T ) throws {
576
- assertCanEncodeSingleValue ( )
563
+ assertCanEncodeNewValue ( )
577
564
try self . storage. push ( container: box ( value) )
578
565
}
579
566
}
@@ -763,7 +750,7 @@ fileprivate class _JSONReferencingEncoder : _JSONEncoder {
763
750
764
751
// MARK: - Coding Path Operations
765
752
766
- override var canEncodeNewElement : Bool {
753
+ override var canEncodeNewValue : Bool {
767
754
// With a regular encoder, the storage and coding path grow together.
768
755
// A referencing encoder, however, inherits its parents coding path, as well as the key it was created for.
769
756
// We have to take this into account.
0 commit comments