Skip to content

Commit 84c138d

Browse files
authored
Merge pull request #77 from MercuryTechnologies/tad/swift-sum-types
swift: add Codable implementation for sum-of-product types
2 parents a37fe36 + bb72de5 commit 84c138d

File tree

21 files changed

+695
-15
lines changed

21 files changed

+695
-15
lines changed
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
@Serializable
2+
sealed class Enum : Parcelable

.golden/kotlinEnumSumOfProductWithTaggedObjectStyleSpec/golden

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,4 +10,9 @@ sealed class Enum : Parcelable {
1010
@Serializable
1111
@SerialName("dataCons1")
1212
data class DataCons1(val contents: Record1) : Enum()
13+
14+
@Parcelize
15+
@Serializable
16+
@SerialName("dataCons2")
17+
data object DataCons2 : Enum()
1318
}
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
@Parcelize
2+
@Serializable
3+
data class Record0(
4+
val record0Field0: Int,
5+
val record0Field1: Int,
6+
) : Parcelable
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
@Parcelize
2+
@Serializable
3+
data class Record1(
4+
val record1Field0: Int,
5+
val record1Field1: Int,
6+
) : Parcelable

.golden/swiftEnumSumOfProductDocSpec/golden

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,4 +4,37 @@ enum Enum: CaseIterable, Hashable, Codable {
44
case dataCons0(Record0)
55
/// Another constructor.
66
case dataCons1(Record1)
7+
8+
enum CodingKeys: String, CodingKey {
9+
case tag
10+
case contents
11+
}
12+
13+
init(from decoder: any Decoder) throws {
14+
let container = try decoder.container(keyedBy: CodingKeys.self)
15+
let discriminator = try container.decode(String.self, forKey: .tag)
16+
switch discriminator {
17+
case "dataCons0":
18+
self = .dataCons0(try container.decode(Record0.self, forKey: .contents))
19+
case "dataCons1":
20+
self = .dataCons1(try container.decode(Record1.self, forKey: .contents))
21+
default:
22+
throw DecodingError.typeMismatch(
23+
CodingKeys.self,
24+
.init(codingPath: decoder.codingPath, debugDescription: "Can't decode unknown tag: Enum.\(discriminator)")
25+
)
26+
}
27+
}
28+
29+
func encode(to encoder: any Encoder) throws {
30+
var container = encoder.container(keyedBy: CodingKeys.self)
31+
switch (self) {
32+
case let .dataCons0(contents):
33+
try container.encode("dataCons0", forKey: .tag)
34+
try container.encode(contents, forKey: .contents)
35+
case let .dataCons1(contents):
36+
try container.encode("dataCons1", forKey: .tag)
37+
try container.encode(contents, forKey: .contents)
38+
}
39+
}
740
}
Lines changed: 45 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,48 @@
1-
enum Enum: CaseIterable, Hashable, Codable {
1+
enum Enum: Hashable, Codable {
22
case dataCons0(_ enumField0: Int, _ enumField1: Int)
33
case dataCons1(_ enumField2: String, _ enumField3: String)
4+
5+
enum CodingKeys: String, CodingKey {
6+
case tag
7+
case enumField0
8+
case enumField1
9+
case enumField2
10+
case enumField3
11+
}
12+
13+
init(from decoder: any Decoder) throws {
14+
let container = try decoder.container(keyedBy: CodingKeys.self)
15+
let discriminator = try container.decode(String.self, forKey: .tag)
16+
switch discriminator {
17+
case "dataCons0":
18+
self = .dataCons0(
19+
try container.decode(Int.self, forKey: .enumField0),
20+
try container.decode(Int.self, forKey: .enumField1)
21+
)
22+
case "dataCons1":
23+
self = .dataCons1(
24+
try container.decode(String.self, forKey: .enumField2),
25+
try container.decode(String.self, forKey: .enumField3)
26+
)
27+
default:
28+
throw DecodingError.typeMismatch(
29+
CodingKeys.self,
30+
.init(codingPath: decoder.codingPath, debugDescription: "Can't decode unknown tag: Enum.\(discriminator)")
31+
)
32+
}
33+
}
34+
35+
func encode(to encoder: any Encoder) throws {
36+
var container = encoder.container(keyedBy: CodingKeys.self)
37+
switch (self) {
38+
case let .dataCons0:
39+
try container.encode("dataCons0", forKey: .tag)
40+
try container.encode(enumField0, forKey: .enumField0)
41+
try container.encode(enumField1, forKey: .enumField1)
42+
case let .dataCons1:
43+
try container.encode("dataCons1", forKey: .tag)
44+
try container.encode(enumField2, forKey: .enumField2)
45+
try container.encode(enumField3, forKey: .enumField3)
46+
}
47+
}
448
}
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,36 @@
11
enum Enum: CaseIterable, Hashable, Codable {
22
case dataCons0(Record0)
33
case dataCons1(Record1)
4+
5+
enum CodingKeys: String, CodingKey {
6+
case tag
7+
}
8+
9+
init(from decoder: any Decoder) throws {
10+
let container = try decoder.container(keyedBy: CodingKeys.self)
11+
let discriminator = try container.decode(String.self, forKey: .tag)
12+
switch discriminator {
13+
case "dataCons0":
14+
self = .dataCons0(try Record0.init(from: decoder))
15+
case "dataCons1":
16+
self = .dataCons1(try Record1.init(from: decoder))
17+
default:
18+
throw DecodingError.typeMismatch(
19+
CodingKeys.self,
20+
.init(codingPath: decoder.codingPath, debugDescription: "Can't decode unknown tag: Enum.\(discriminator)")
21+
)
22+
}
23+
}
24+
25+
func encode(to encoder: any Encoder) throws {
26+
var container = encoder.container(keyedBy: CodingKeys.self)
27+
switch (self) {
28+
case let .dataCons0(value):
29+
try container.encode("dataCons0", forKey: .tag)
30+
try value.encode(to: encoder)
31+
case let .dataCons1(value):
32+
try container.encode("dataCons1", forKey: .tag)
33+
try value.encode(to: encoder)
34+
}
35+
}
436
}
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
enum Enum: Codable {
2+
case dataCons0(Record0)
3+
case dataCons1(Record1)
4+
case dataCons2
5+
case _unknown
6+
7+
enum CodingKeys: String, CodingKey {
8+
case tag
9+
}
10+
11+
init(from decoder: any Decoder) throws {
12+
let container = try decoder.container(keyedBy: CodingKeys.self)
13+
let discriminator = try container.decode(String.self, forKey: .tag)
14+
switch discriminator {
15+
case "dataCons0":
16+
self = .dataCons0(try Record0.init(from: decoder))
17+
case "dataCons1":
18+
self = .dataCons1(try Record1.init(from: decoder))
19+
case "dataCons2":
20+
self = .dataCons2
21+
default:
22+
self = ._unknown
23+
}
24+
}
25+
26+
func encode(to encoder: any Encoder) throws {
27+
var container = encoder.container(keyedBy: CodingKeys.self)
28+
switch (self) {
29+
case let .dataCons0(value):
30+
try container.encode("dataCons0", forKey: .tag)
31+
try value.encode(to: encoder)
32+
case let .dataCons1(value):
33+
try container.encode("dataCons1", forKey: .tag)
34+
try value.encode(to: encoder)
35+
case .dataCons2:
36+
try container.encode("dataCons2", forKey: .tag)
37+
case ._unknown:
38+
throw EncodingError.invalidValue(
39+
self,
40+
.init(codingPath: encoder.codingPath, debugDescription: "Can't encode value: Enum._unknown")
41+
)
42+
}
43+
}
44+
}
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
enum Enum: Codable {
2+
case dataCons0(Record0)
3+
case dataCons1(Record1)
4+
case dataCons2
5+
6+
enum CodingKeys: String, CodingKey {
7+
case tag
8+
case contents
9+
}
10+
11+
init(from decoder: any Decoder) throws {
12+
let container = try decoder.container(keyedBy: CodingKeys.self)
13+
let discriminator = try container.decode(String.self, forKey: .tag)
14+
switch discriminator {
15+
case "dataCons0":
16+
self = .dataCons0(try container.decode(Record0.self, forKey: .contents))
17+
case "dataCons1":
18+
self = .dataCons1(try container.decode(Record1.self, forKey: .contents))
19+
case "dataCons2":
20+
self = .dataCons2
21+
default:
22+
throw DecodingError.typeMismatch(
23+
CodingKeys.self,
24+
.init(codingPath: decoder.codingPath, debugDescription: "Can't decode unknown tag: Enum.\(discriminator)")
25+
)
26+
}
27+
}
28+
29+
func encode(to encoder: any Encoder) throws {
30+
var container = encoder.container(keyedBy: CodingKeys.self)
31+
switch (self) {
32+
case let .dataCons0(contents):
33+
try container.encode("dataCons0", forKey: .tag)
34+
try container.encode(contents, forKey: .contents)
35+
case let .dataCons1(contents):
36+
try container.encode("dataCons1", forKey: .tag)
37+
try container.encode(contents, forKey: .contents)
38+
case .dataCons2:
39+
try container.encode("dataCons2", forKey: .tag)
40+
}
41+
}
42+
}
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
struct Record0: Codable {
2+
var record0Field0: Int
3+
var record0Field1: Int
4+
}

0 commit comments

Comments
 (0)