Fix enum decoding (#39)

Fixes an issue where `5.0` in Pkl can possibly be cast to `Int`
This commit is contained in:
Daniel Chao 2025-02-03 10:50:36 -08:00 committed by GitHub
parent f0bd189f48
commit b253e83f7b
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
5 changed files with 57 additions and 11 deletions

View File

@ -15,7 +15,7 @@ extension UnionTypes {
public init(from decoder: Decoder) throws {
let decoded = try decoder.singleValueContainer().decode(PklSwift.PklAny.self).value
switch decoded {
switch decoded?.base {
case let decoded as Banana:
self = Fruit.banana(decoded)
case let decoded as Grape:
@ -47,7 +47,7 @@ extension UnionTypes {
public init(from decoder: Decoder) throws {
let decoded = try decoder.singleValueContainer().decode(PklSwift.PklAny.self).value
switch decoded {
switch decoded?.base {
case let decoded as Zebra:
self = ZebraOrDonkey.zebra(decoded)
case let decoded as Donkey:
@ -81,7 +81,7 @@ extension UnionTypes {
public init(from decoder: Decoder) throws {
let decoded = try decoder.singleValueContainer().decode(PklSwift.PklAny.self).value
switch decoded {
switch decoded?.base {
case let decoded as any Animal:
self = AnimalOrString.animal(decoded)
case let decoded as String:
@ -107,6 +107,29 @@ extension UnionTypes {
}
}
public enum IntOrFloat: Decodable, Hashable {
case int(Int)
case float64(Float64)
public init(from decoder: Decoder) throws {
let decoded = try decoder.singleValueContainer().decode(PklSwift.PklAny.self).value
switch decoded?.base {
case let decoded as Int:
self = IntOrFloat.int(decoded)
case let decoded as Float64:
self = IntOrFloat.float64(decoded)
default:
throw DecodingError.typeMismatch(
IntOrFloat.self,
.init(
codingPath: decoder.codingPath,
debugDescription: "Expected type IntOrFloat, but got \(String(describing: decoded))"
)
)
}
}
}
public struct Module: PklRegisteredType, Decodable, Hashable {
public static let registeredIdentifier: String = "UnionTypes"
@ -132,6 +155,12 @@ extension UnionTypes {
public var animalOrString2: AnimalOrString
public var intOrFloat1: IntOrFloat
public var intOrFloat2: IntOrFloat
public var intOrFloat3: IntOrFloat
public init(
fruit1: Fruit,
fruit2: Fruit,
@ -143,7 +172,10 @@ extension UnionTypes {
animal1: ZebraOrDonkey,
animal2: ZebraOrDonkey,
animalOrString1: AnimalOrString,
animalOrString2: AnimalOrString
animalOrString2: AnimalOrString,
intOrFloat1: IntOrFloat,
intOrFloat2: IntOrFloat,
intOrFloat3: IntOrFloat
) {
self.fruit1 = fruit1
self.fruit2 = fruit2
@ -156,6 +188,9 @@ extension UnionTypes {
self.animal2 = animal2
self.animalOrString1 = animalOrString1
self.animalOrString2 = animalOrString2
self.intOrFloat1 = intOrFloat1
self.intOrFloat2 = intOrFloat2
self.intOrFloat3 = intOrFloat3
}
}

View File

@ -52,4 +52,12 @@ typealias AnimalOrString = Animal|String
animalOrString1: AnimalOrString = new Zebra {}
animalOrString2: AnimalOrString = "Zebra"
animalOrString2: AnimalOrString = "Zebra"
typealias IntOrFloat = Int | Float
intOrFloat1: IntOrFloat = 5.0
intOrFloat2: IntOrFloat = 5.5
intOrFloat3: IntOrFloat = 5

View File

@ -160,7 +160,10 @@ class FixturesTest: XCTestCase {
animal1: .zebra(UnionTypes.Zebra(name: "Zebra")),
animal2: .donkey(UnionTypes.Donkey(name: "Donkey")),
animalOrString1: .animal(UnionTypes.Zebra(name: "Zebra")),
animalOrString2: .string("Zebra")
animalOrString2: .string("Zebra"),
intOrFloat1: .float64(5.0),
intOrFloat2: .float64(5.5),
intOrFloat3: .int(5)
))
}
}

View File

@ -20,7 +20,7 @@ extension Enums {
public init(from decoder: Decoder) throws {
let decoded = try decoder.singleValueContainer().decode(PklSwift.PklAny.self).value
switch decoded {
switch decoded?.base {
case let decoded as Horse:
self = Animal.horse(decoded)
case let decoded as Zebra:
@ -46,7 +46,7 @@ extension Enums {
public init(from decoder: Decoder) throws {
let decoded = try decoder.singleValueContainer().decode(PklSwift.PklAny.self).value
switch decoded {
switch decoded?.base {
case let decoded as [String: String]:
self = DictOrArray.dictionaryStringString(decoded)
case let decoded as [String]:
@ -70,7 +70,7 @@ extension Enums {
public init(from decoder: Decoder) throws {
let decoded = try decoder.singleValueContainer().decode(PklSwift.PklAny.self).value
switch decoded {
switch decoded?.base {
case let decoded as Horse:
self = HorseOrBug.horse(decoded)
case let decoded as String:
@ -95,7 +95,7 @@ extension Enums {
public init(from decoder: Decoder) throws {
let decoded = try decoder.singleValueContainer().decode(PklSwift.PklAny.self).value
switch decoded {
switch decoded?.base {
case let decoded as Horse?:
self = MaybeHorseOrDefinitelyZebra.horse(decoded)
case let decoded as Zebra:

View File

@ -89,7 +89,7 @@ local enumContents =
}
"\(module.indent)public init(from decoder: Decoder) throws {"
"\(module.indent.repeat(2))let decoded = try decoder.singleValueContainer().decode(PklSwift.PklAny.self).value"
"\(module.indent.repeat(2))switch decoded {"
"\(module.indent.repeat(2))switch decoded?.base {"
for (member in enumNormalMembers) {
"\(module.indent.repeat(2))case let decoded as \(member.renderedType):"
"\(module.indent.repeat(3))self = \(module.mapping.name).\(member.name)(decoded)"