Skip to content

Commit efe0ff8

Browse files
Itai FerberDougGregor
authored andcommitted
Fix container assertion in referencing encoders
(cherry picked from commit 3a6dbeb)
1 parent 32de06b commit efe0ff8

File tree

2 files changed

+36
-0
lines changed

2 files changed

+36
-0
lines changed

stdlib/public/SDK/Foundation/JSONEncoder.swift

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -708,6 +708,24 @@ fileprivate class _JSONReferencingEncoder : _JSONEncoder {
708708
super.init(options: encoder.options, codingPath: encoder.codingPath)
709709
}
710710

711+
// MARK: - Overridden Implementations
712+
713+
/// Asserts that we can add a new container at this coding path. See _JSONEncoder.assertCanRequestNewContainer for the logic behind this.
714+
/// This differs from super's implementation only in the condition: we need to account for the fact that we copied our reference's coding path, but not its list of containers, so the counts are mismatched.
715+
override func assertCanRequestNewContainer() {
716+
guard self.storage.count == self.codingPath.count - self.encoder.codingPath.count else {
717+
let previousContainerType: String
718+
if self.storage.containers.last is NSDictionary {
719+
previousContainerType = "keyed"
720+
} else if self.storage.containers.last is NSArray {
721+
previousContainerType = "unkeyed"
722+
} else {
723+
previousContainerType = "single value"
724+
}
725+
726+
preconditionFailure("Attempt to encode with new container when already encoded with \(previousContainerType) container.")
727+
}
728+
}
711729

712730
// MARK: - Deinitialization
713731

stdlib/public/SDK/Foundation/PlistEncoder.swift

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -518,6 +518,24 @@ fileprivate class _PlistReferencingEncoder : _PlistEncoder {
518518
super.init(options: encoder.options, codingPath: encoder.codingPath)
519519
}
520520

521+
// MARK: - Overridden Implementations
522+
523+
/// Asserts that we can add a new container at this coding path. See _PlistEncoder.assertCanRequestNewContainer for the logic behind this.
524+
/// This differs from super's implementation only in the condition: we need to account for the fact that we copied our reference's coding path, but not its list of containers, so the counts are mismatched.
525+
override func assertCanRequestNewContainer() {
526+
guard self.storage.count == self.codingPath.count - self.encoder.codingPath.count else {
527+
let previousContainerType: String
528+
if self.storage.containers.last is NSDictionary {
529+
previousContainerType = "keyed"
530+
} else if self.storage.containers.last is NSArray {
531+
previousContainerType = "unkeyed"
532+
} else {
533+
previousContainerType = "single value"
534+
}
535+
536+
preconditionFailure("Attempt to encode with new container when already encoded with \(previousContainerType) container.")
537+
}
538+
}
521539

522540
// MARK: - Deinitialization
523541

0 commit comments

Comments
 (0)