@@ -19,15 +19,6 @@ enum CodableEnum: String, Codable, Equatable {
19
19
case abc
20
20
case def
21
21
case ghi
22
-
23
- public static func == ( lhs: Self , rhs: Self ) -> Bool {
24
- switch ( lhs, rhs) {
25
- case ( . abc, . abc) : return true
26
- case ( . def, . def) : return true
27
- case ( . ghi, . ghi) : return true
28
- default : return false
29
- }
30
- }
31
22
}
32
23
33
24
struct CodableStruct : Codable , Equatable {
@@ -501,4 +492,83 @@ final class TOMLKitTests: XCTestCase {
501
492
let _ = try udc. nestedUnkeyedContainer ( )
502
493
XCTAssertEqual ( udc. currentIndex, 1 )
503
494
}
495
+
496
+ // Tests for a bug where not-decoded keys would carry over from unsuccessful
497
+ // decoding attempts, breaking the common 'try one thing then retry another'
498
+ // decoding pattern. This bug was specific to decoders with
499
+ // `strictDecoding: true`.
500
+ func testRetryKeyedOrDictionary( ) throws {
501
+ enum StructOrDictionary : Decodable , Equatable {
502
+ case `struct`( value: Int )
503
+ case dictionary( [ String : Int ] )
504
+
505
+ enum CodingKeys : String , CodingKey {
506
+ case value
507
+ }
508
+
509
+ init ( from decoder: Decoder ) throws {
510
+ if let container = try ? decoder. container ( keyedBy: CodingKeys . self) {
511
+ if let value = try ? container. decode ( Int . self, forKey: . value) {
512
+ self = . struct( value: value)
513
+ }
514
+ }
515
+
516
+ if let container = try ? decoder. singleValueContainer ( ) {
517
+ self = try . dictionary( container. decode ( [ String : Int ] . self) )
518
+ } else {
519
+ throw DecodingError . dataCorrupted ( . init(
520
+ codingPath: [ ] ,
521
+ debugDescription: " Expected int or keyedInt "
522
+ ) )
523
+ }
524
+ }
525
+ }
526
+
527
+ let toml = " other_value = 1 "
528
+
529
+ // Before the bug got fixed, this line would throw an unused key error.
530
+ let value = try TOMLDecoder ( strictDecoding: true ) . decode ( StructOrDictionary . self, from: toml)
531
+
532
+ // We don't actually expect this to fail, it's not the point of the test, but
533
+ // might as well assert it just in case.
534
+ XCTAssertEqual ( value, . dictionary( [ " other_value " : 1 ] ) )
535
+ }
536
+
537
+ // This is related to the test above, but tests for a different aspect of the
538
+ // bug (I originally fixed one but not the other so they are kind of independent).
539
+ func testRetryKeyedOrInt( ) throws {
540
+ struct SimpleCodableStruct : Codable , Equatable {
541
+ var value : Int
542
+ }
543
+
544
+ enum SimpleOrComplex : Decodable , Equatable {
545
+ case simple( SimpleCodableStruct )
546
+ case complex( CodableStruct )
547
+
548
+ init ( from decoder: Decoder ) throws {
549
+ if let container = try ? decoder. singleValueContainer ( ) {
550
+ if let value = try ? container. decode ( CodableStruct . self) {
551
+ self = . complex( value)
552
+ return
553
+ } else if let value = try ? container. decode ( SimpleCodableStruct . self) {
554
+ self = . simple( value)
555
+ return
556
+ }
557
+ }
558
+ throw DecodingError . dataCorrupted ( . init(
559
+ codingPath: [ ] ,
560
+ debugDescription: " Expected CodableStruct or SimpleCodableStruct "
561
+ ) )
562
+ }
563
+ }
564
+
565
+ let toml = " value = 2 "
566
+
567
+ // Before the bug got fixed, this line would throw an unused key error.
568
+ let value = try TOMLDecoder ( strictDecoding: true ) . decode ( SimpleOrComplex . self, from: toml)
569
+
570
+ // We don't actually expect this to fail, it's not the point of the test, but
571
+ // might as well assert it just in case.
572
+ XCTAssertEqual ( value, . simple( SimpleCodableStruct ( value: 2 ) ) )
573
+ }
504
574
}
0 commit comments