Skip to content

Commit 120f586

Browse files
authored
Add support for integer based enums (#95)
* Add support for int enums * Swift format
1 parent 21cea81 commit 120f586

3 files changed

Lines changed: 78 additions & 9 deletions

File tree

Sources/SotoCodeGeneratorLib/AwsService+shapes.swift

Lines changed: 49 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,11 @@ extension AwsService {
2828
model
2929
.select(type: EnumShape.self)
3030
.compactMap { self.generateEnumContext($0.value, shapeName: $0.key.shapeName) }
31-
let enums = (traitEnums + shapeEnums).sorted { $0.name < $1.name }
31+
let intEnums: [EnumContext] =
32+
model
33+
.select(type: IntEnumShape.self)
34+
.compactMap { self.generateIntEnumContext($0.value, shapeName: $0.key.shapeName) }
35+
let enums = (traitEnums + shapeEnums + intEnums).sorted { $0.name < $1.name }
3236
var shapeContexts: [ShapesContext.ShapeType] = enums.map { .enum($0) }
3337

3438
// generate structures
@@ -81,7 +85,8 @@ extension AwsService {
8185
return EnumContext(
8286
name: shapeName.toSwiftClassCase(),
8387
documentation: processDocs(from: shape),
84-
values: valueContexts,
88+
stringValues: .init(values: valueContexts),
89+
intValues: nil,
8590
isExtensible: shape.hasTrait(type: SotoExtensibleEnumTrait.self)
8691
)
8792
}
@@ -103,9 +108,8 @@ extension AwsService {
103108
switch enumValueTrait.value {
104109
case .string(let name):
105110
value = name
106-
case .integer(let integer):
107-
value = integer.description
108-
fatalError("intEnum is currently not supported")
111+
case .integer:
112+
fatalError("String enumerations shouldn't have integer based values")
109113
}
110114
} else {
111115
value = enumerated.element.key
@@ -120,7 +124,46 @@ extension AwsService {
120124
return EnumContext(
121125
name: shapeName.toSwiftClassCase(),
122126
documentation: processDocs(from: enumShape),
123-
values: valueContexts.sorted { $0.case < $1.case },
127+
stringValues: .init(values: valueContexts.sorted { $0.case < $1.case }),
128+
intValues: nil,
129+
isExtensible: enumShape.hasTrait(type: SotoExtensibleEnumTrait.self)
130+
)
131+
}
132+
133+
/// Generate the context information for outputting an enum from strings with enum traits
134+
func generateIntEnumContext(_ enumShape: IntEnumShape, shapeName: String) -> EnumContext? {
135+
let usedInInput = enumShape.hasTrait(type: SotoInputShapeTrait.self)
136+
let usedInOutput = enumShape.hasTrait(type: SotoOutputShapeTrait.self)
137+
guard usedInInput || usedInOutput else { return nil }
138+
guard let members = enumShape.members else { return nil }
139+
// Operations
140+
let valueContexts: [IntEnumMemberContext] = members.enumerated().map { enumerated -> IntEnumMemberContext in
141+
var key = enumerated.element.key.toSwiftEnumCase()
142+
if key.allLetterIsNumeric() {
143+
key = "\(shapeName.toSwiftVariableCase())\(key)"
144+
}
145+
let value: Int
146+
let enumValueTrait = enumerated.element.value.trait(type: EnumValueTrait.self)
147+
switch enumValueTrait?.value {
148+
case .string:
149+
fatalError("Int enumerations shouldn't have string based values")
150+
case .integer(let integer):
151+
value = integer
152+
case .none:
153+
fatalError("Int enumerations require integer value")
154+
}
155+
let documentation = enumerated.element.value.trait(type: DocumentationTrait.self)
156+
return IntEnumMemberContext(
157+
case: key,
158+
documentation: documentation.map { processDocs($0.value) } ?? [],
159+
rawValue: value
160+
)
161+
}
162+
return EnumContext(
163+
name: shapeName.toSwiftClassCase(),
164+
documentation: processDocs(from: enumShape),
165+
stringValues: nil,
166+
intValues: .init(values: valueContexts.sorted { $0.case < $1.case }),
124167
isExtensible: enumShape.hasTrait(type: SotoExtensibleEnumTrait.self)
125168
)
126169
}

Sources/SotoCodeGeneratorLib/AwsService.swift

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -859,9 +859,16 @@ extension AwsService {
859859
}
860860

861861
struct EnumContext {
862+
struct IntValues {
863+
let values: [IntEnumMemberContext]
864+
}
865+
struct StringValues {
866+
let values: [EnumMemberContext]
867+
}
862868
let name: String
863869
let documentation: [String.SubSequence]
864-
let values: [EnumMemberContext]
870+
let stringValues: StringValues?
871+
let intValues: IntValues?
865872
let isExtensible: Bool
866873
}
867874

@@ -871,6 +878,12 @@ extension AwsService {
871878
let rawValue: String
872879
}
873880

881+
struct IntEnumMemberContext {
882+
let `case`: String
883+
let documentation: [String.SubSequence]
884+
let rawValue: Int
885+
}
886+
874887
struct ArrayEncodingPropertiesContext: EncodingPropertiesContext {
875888
let name: String
876889
let member: String

Sources/SotoCodeGeneratorLib/Templates/enum.swift

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,15 +23,16 @@ extension Templates {
2323
self.rawValue = rawValue
2424
}
2525
26-
{{#values}}
26+
{{#stringValues.values}}
2727
{{#documentation}}
2828
{{>comment}}
2929
{{/documentation}}
3030
{{scope}} static var {{case}}: Self { .init(rawValue: "{{rawValue}}") }
31-
{{/values}}
31+
{{/stringValues.values}}
3232
}
3333
{{/isExtensible}}
3434
{{^isExtensible}}
35+
{{#stringValues}}
3536
{{scope}} enum {{name}}: String, CustomStringConvertible, Codable, Sendable, CodingKeyRepresentable {
3637
{{#values}}
3738
{{#documentation}}
@@ -41,6 +42,18 @@ extension Templates {
4142
{{/values}}
4243
{{scope}} var description: String { return self.rawValue }
4344
}
45+
{{/stringValues}}
46+
{{#intValues}}
47+
{{scope}} enum {{name}}: Int, CustomStringConvertible, Codable, Sendable, CodingKeyRepresentable {
48+
{{#values}}
49+
{{#documentation}}
50+
{{>comment}}
51+
{{/documentation}}
52+
case {{case}} = {{rawValue}}
53+
{{/values}}
54+
{{scope}} var description: String { return "\\(self.rawValue)" }
55+
}
56+
{{/intValues}}
4457
{{/isExtensible}}
4558
4659
"""

0 commit comments

Comments
 (0)