Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 12 additions & 0 deletions bin/configs/swift5-frozenEnums.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
generatorName: swift5
outputDir: samples/client/petstore/swift5/frozenEnums
inputSpec: modules/openapi-generator/src/test/resources/2_0/swift/petstore-with-fake-endpoints-models-for-testing.yaml
templateDir: modules/openapi-generator/src/main/resources/swift5
generateAliasAsModel: true
additionalProperties:
podAuthors: ""
podSummary: PetstoreClient
sortParamsByRequiredFlag: false
generateFrozenEnums: false
projectName: PetstoreClient
podHomepage: https://github.com/openapitools/openapi-generator
1 change: 1 addition & 0 deletions docs/generators/swift5.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ These options may be applied as additional-properties (cli) or configOptions (pl
|apiNamePrefix|Prefix that will be appended to all API names ('tags'). Default: empty string. e.g. Pet => Pet.| |null|
|disallowAdditionalPropertiesIfNotPresent|If false, the 'additionalProperties' implementation (set to true by default) is compliant with the OAS and JSON schema specifications. If true (default), keep the old (incorrect) behaviour that 'additionalProperties' is set to false by default.|<dl><dt>**false**</dt><dd>The 'additionalProperties' implementation is compliant with the OAS and JSON schema specifications.</dd><dt>**true**</dt><dd>Keep the old (incorrect) behaviour that 'additionalProperties' is set to false by default.</dd></dl>|true|
|ensureUniqueParams|Whether to ensure parameter names are unique in an operation (rename parameters that are not).| |true|
|generateFrozenEnums|Generate model enums that are "frozen". A frozen enum strictly represents the cases described in the spec, and nothing else. A non-frozen enum includes an unknown case that can represent future cases not yet described in the spec. (default: true)| |true|
|generateModelAdditionalProperties|Generate model additional properties (default: true)| |true|
|hashableModels|Make hashable models (default: true)| |true|
|hideGenerationTimestamp|Hides the generation timestamp when files are generated.| |true|
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@ public class Swift5ClientCodegen extends DefaultCodegen implements CodegenConfig
public static final String SWIFT_PACKAGE_PATH = "swiftPackagePath";
public static final String USE_CLASSES = "useClasses";
public static final String USE_BACKTICK_ESCAPES = "useBacktickEscapes";
public static final String GENERATE_FROZEN_ENUMS = "generateFrozenEnums";
public static final String GENERATE_MODEL_ADDITIONAL_PROPERTIES = "generateModelAdditionalProperties";
public static final String HASHABLE_MODELS = "hashableModels";
public static final String MAP_FILE_BINARY_TO_DATA = "mapFileBinaryToData";
Expand All @@ -90,6 +91,7 @@ public class Swift5ClientCodegen extends DefaultCodegen implements CodegenConfig
protected boolean useClasses = false;
protected boolean useBacktickEscapes = false;
protected boolean generateModelAdditionalProperties = true;
protected boolean generateFrozenEnums = true;
protected boolean hashableModels = true;
protected boolean mapFileBinaryToData = false;
protected String[] responseAs = new String[0];
Expand Down Expand Up @@ -281,6 +283,9 @@ public Swift5ClientCodegen() {
cliOptions.add(new CliOption(USE_BACKTICK_ESCAPES,
"Escape reserved words using backticks (default: false)")
.defaultValue(Boolean.FALSE.toString()));
cliOptions.add(new CliOption(GENERATE_FROZEN_ENUMS,
"Generate frozen enums (default: true)")
.defaultValue(Boolean.TRUE.toString()));
cliOptions.add(new CliOption(GENERATE_MODEL_ADDITIONAL_PROPERTIES,
"Generate model additional properties (default: true)")
.defaultValue(Boolean.TRUE.toString()));
Expand Down Expand Up @@ -485,6 +490,13 @@ public void processOpts() {
setUseBacktickEscapes(convertPropertyToBooleanAndWriteBack(USE_BACKTICK_ESCAPES));
}

// Setup generateFrozenEnums option. If true, enums will strictly include
// cases matching the spec. If false, enums will also include an extra "unknown" case.
if (additionalProperties.containsKey(GENERATE_FROZEN_ENUMS)) {
setGenerateFrozenEnums(convertPropertyToBooleanAndWriteBack(GENERATE_FROZEN_ENUMS));
}
additionalProperties.put(GENERATE_FROZEN_ENUMS, generateFrozenEnums);

if (additionalProperties.containsKey(GENERATE_MODEL_ADDITIONAL_PROPERTIES)) {
setGenerateModelAdditionalProperties(convertPropertyToBooleanAndWriteBack(GENERATE_MODEL_ADDITIONAL_PROPERTIES));
}
Expand Down Expand Up @@ -559,6 +571,9 @@ public void processOpts() {
supportingFiles.add(new SupportingFile("Extensions.mustache",
sourceFolder,
"Extensions.swift"));
supportingFiles.add(new SupportingFile("Protocols.mustache",
sourceFolder,
"Protocols.swift"));
supportingFiles.add(new SupportingFile("APIs.mustache",
sourceFolder,
"APIs.swift"));
Expand Down Expand Up @@ -943,6 +958,10 @@ public void setUseBacktickEscapes(boolean useBacktickEscapes) {
this.useBacktickEscapes = useBacktickEscapes;
}

public void setGenerateFrozenEnums(boolean generateFrozenEnums) {
this.generateFrozenEnums = generateFrozenEnums;
}

public void setGenerateModelAdditionalProperties(boolean generateModelAdditionalProperties) {
this.generateModelAdditionalProperties = generateModelAdditionalProperties;
}
Expand Down Expand Up @@ -1091,6 +1110,13 @@ public void postProcessModelProperty(CodegenModel model, CodegenProperty propert
// which provide Objective-C compatibility.
property.vendorExtensions.put("x-swift-optional-scalar", true);
}

if (property.isEnum) {
// A non-frozen (with the "unknown" case) enum is only possible with String or Int raw types.
if (property.dataType.equals("String") || property.dataType.equals("Int")) {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since now we are going to assign values to the enums, can we remove this?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe. Let me push the next update. I think we'll want to know the enum's type in order to assign a default value that is correct.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there any enum type that we don't support?
I think there is an easier way to do this, by removing this block of code and do this type check in the mustache files.
I think there are checks like isString, isInt, isDouble, isNumber, but I need to check tomorrow, because I'm not 100% sure.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@4brunu You are correct. I had tried this earlier, but was using the mustache clauses incorrectly. I made the change to remove the custom vendor extensions and use the built-in type checks. I think we should be good now

property.vendorExtensions.put("x-non-frozen-enum-capable", true);
}
}
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -206,3 +206,21 @@ extension Set: RequestDecodable where Element: Content {
extension Set: Content where Element: Content { }

extension AnyCodable: Content {}{{/useVapor}}

extension CaseIterableDefaultsLast {
/// Initializes an enum such that if a known raw value is found, then it is decoded.
/// Otherwise the last case ("unknown") is used.
/// - Parameter decoder: A decoder.
public init(from decoder: Decoder) throws {
if let value = try Self(rawValue: decoder.singleValueContainer().decode(RawValue.self)) {
self = value
} else if let lastValue = Self.allCases.last {
self = lastValue
} else {
throw DecodingError.valueNotFound(
Self.Type.self,
.init(codingPath: decoder.codingPath, debugDescription: "CaseIterableDefaultsLast")
)
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
// Protocols.swift
//
// Generated by openapi-generator
// https://openapi-generator.tech
//

/// An enum where the last case value is "unknown" and can be used as a default catch-all.
public protocol CaseIterableDefaultsLast: Decodable & CaseIterable & RawRepresentable
where RawValue: Decodable, AllCases: BidirectionalCollection {}
Original file line number Diff line number Diff line change
@@ -1,7 +1,12 @@
{{#nonPublicApi}}internal{{/nonPublicApi}}{{^nonPublicApi}}public{{/nonPublicApi}} enum {{classname}}: {{dataType}}, {{#useVapor}}Content, Hashable{{/useVapor}}{{^useVapor}}Codable{{/useVapor}}, CaseIterable {
{{#nonPublicApi}}internal{{/nonPublicApi}}{{^nonPublicApi}}public{{/nonPublicApi}} enum {{classname}}: {{dataType}}, {{#useVapor}}Content, Hashable{{/useVapor}}{{^useVapor}}Codable{{/useVapor}}, CaseIterable{{^generateFrozenEnums}}{{#vendorExtensions.x-non-frozen-enum-capable}}, CaseIterableDefaultsLast{{/vendorExtensions.x-non-frozen-enum-capable}}{{/generateFrozenEnums}} {
{{#allowableValues}}
{{#enumVars}}
case {{{name}}} = {{{value}}}
{{/enumVars}}
{{/allowableValues}}
{{^generateFrozenEnums}}
{{#vendorExtensions.x-non-frozen-enum-capable}}
case unknown

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@jarrodparkes I'm afraid this will conflict with an Enum case that is already unknown, for example, in my project some of the Enum's already have a unknown case.
Here are some alternative names:

  • unknownDefault (@unknown default)
  • openApiUnknown
  • {projectName}Unknown

Do you have other suggestions?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@4brunu good call. of your options, I like unknownDefault personally

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@4brunu updated

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry for didn't put more thought into it, but since I discover that the raw value name is the case name, maybe we should name the enum something a bit more complex to be extra sure that we avoid conflicts.

What do you think of the following suggestions?

  • {projectName}UnknownDefault
  • unknownDefault{projectName}
  • openApiUnknownDefault
  • unknownDefaultOpenApi

Do you have other suggestions?

I also like the unknownDefault because of the pattern in Swift @unknown default, but maybe we should try harder to avoid conflicts?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeh, probably so. I like unknownDefaultOpenApi. And now that I think about it, enum cases that are multiword strings, normally use snake_case. With that in mind, I can also set String raw value to "unknown_default_open_api"

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good to me 👍

{{/vendorExtensions.x-non-frozen-enum-capable}}
{{/generateFrozenEnums}}
}
Original file line number Diff line number Diff line change
@@ -1,7 +1,12 @@
{{#nonPublicApi}}internal{{/nonPublicApi}}{{^nonPublicApi}}public{{/nonPublicApi}} enum {{enumName}}: {{^isContainer}}{{dataType}}{{/isContainer}}{{#isContainer}}String{{/isContainer}}, {{#useVapor}}Content, Hashable{{/useVapor}}{{^useVapor}}Codable{{/useVapor}}, CaseIterable {
{{#nonPublicApi}}internal{{/nonPublicApi}}{{^nonPublicApi}}public{{/nonPublicApi}} enum {{enumName}}: {{^isContainer}}{{dataType}}{{/isContainer}}{{#isContainer}}String{{/isContainer}}, {{#useVapor}}Content, Hashable{{/useVapor}}{{^useVapor}}Codable{{/useVapor}}, CaseIterable{{^generateFrozenEnums}}{{#vendorExtensions.x-non-frozen-enum-capable}}, CaseIterableDefaultsLast{{/vendorExtensions.x-non-frozen-enum-capable}}{{/generateFrozenEnums}} {
{{#allowableValues}}
{{#enumVars}}
case {{{name}}} = {{{value}}}
{{/enumVars}}
{{/allowableValues}}
{{^generateFrozenEnums}}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@jarrodparkes please apply all the feedback from modelEnum.mustache also to this class

{{#vendorExtensions.x-non-frozen-enum-capable}}
case unknown

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@jarrodparkes same here

{{/vendorExtensions.x-non-frozen-enum-capable}}
{{/generateFrozenEnums}}
}
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ public class Swift5OptionsProvider implements OptionsProvider {
public static final String REMOVE_MIGRATION_PROJECT_NAME_CLASS_VALUE = "false";
public static final String SWIFT_USE_API_NAMESPACE_VALUE = "swiftUseApiNamespace";
public static final String USE_BACKTICKS_ESCAPES_VALUE = "false";
public static final String GENERATE_FROZEN_ENUMS_VALUE = "true";
public static final String GENERATE_MODEL_ADDITIONAL_PROPERTIES_VALUE = "true";
public static final String HASHABLE_MODELS_VALUE = "true";
public static final String ALLOW_UNICODE_IDENTIFIERS_VALUE = "false";
Expand Down Expand Up @@ -95,6 +96,7 @@ public Map<String, String> createOptions() {
.put(CodegenConstants.DISALLOW_ADDITIONAL_PROPERTIES_IF_NOT_PRESENT, "true")
.put(Swift5ClientCodegen.USE_SPM_FILE_STRUCTURE, USE_SPM_FILE_STRUCTURE_VALUE)
.put(Swift5ClientCodegen.SWIFT_PACKAGE_PATH, SWIFT_PACKAGE_PATH_VALUE)
.put(Swift5ClientCodegen.GENERATE_FROZEN_ENUMS, GENERATE_FROZEN_ENUMS_VALUE)
.put(Swift5ClientCodegen.GENERATE_MODEL_ADDITIONAL_PROPERTIES, GENERATE_MODEL_ADDITIONAL_PROPERTIES_VALUE)
.put(Swift5ClientCodegen.HASHABLE_MODELS, HASHABLE_MODELS_VALUE)
.put(Swift5ClientCodegen.MAP_FILE_BINARY_TO_DATA, "false")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ protected void verifyOptions() {
verify(clientCodegen).setPrependFormOrBodyParameters(Boolean.valueOf(Swift5OptionsProvider.PREPEND_FORM_OR_BODY_PARAMETERS_VALUE));
verify(clientCodegen).setReadonlyProperties(Boolean.parseBoolean(Swift5OptionsProvider.READONLY_PROPERTIES_VALUE));
verify(clientCodegen).setRemoveMigrationProjectNameClass(Boolean.parseBoolean(Swift5OptionsProvider.REMOVE_MIGRATION_PROJECT_NAME_CLASS_VALUE));
verify(clientCodegen).setGenerateFrozenEnums(Boolean.parseBoolean(Swift5OptionsProvider.GENERATE_FROZEN_ENUMS_VALUE));
verify(clientCodegen).setGenerateModelAdditionalProperties(Boolean.parseBoolean(Swift5OptionsProvider.GENERATE_MODEL_ADDITIONAL_PROPERTIES_VALUE));
verify(clientCodegen).setHashableModels(Boolean.parseBoolean(Swift5OptionsProvider.HASHABLE_MODELS_VALUE));
}
Expand Down
1 change: 1 addition & 0 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -1434,6 +1434,7 @@
<module>samples/client/petstore/swift5/combineLibrary</module>
<module>samples/client/petstore/swift5/default</module>
<module>samples/client/petstore/swift5/deprecated</module>
<module>samples/client/petstore/swift5/frozenEnums</module>
<module>samples/client/petstore/swift5/nonPublicApi</module>
<module>samples/client/petstore/swift5/objcCompatible</module>
<module>samples/client/petstore/swift5/promisekitLibrary</module>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ PetstoreClient/Classes/OpenAPIs/Models/TypeHolderDefault.swift
PetstoreClient/Classes/OpenAPIs/Models/TypeHolderExample.swift
PetstoreClient/Classes/OpenAPIs/Models/User.swift
PetstoreClient/Classes/OpenAPIs/OpenISO8601DateFormatter.swift
PetstoreClient/Classes/OpenAPIs/Protocols.swift
PetstoreClient/Classes/OpenAPIs/SynchronizedDictionary.swift
README.md
docs/AdditionalPropertiesClass.md
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -156,3 +156,21 @@ extension HTTPURLResponse {
return (200 ..< 300).contains(statusCode)
}
}

extension CaseIterableDefaultsLast {
/// Initializes an enum such that if a known raw value is found, then it is decoded.
/// Otherwise the last case ("unknown") is used.
/// - Parameter decoder: A decoder.
public init(from decoder: Decoder) throws {
if let value = try Self(rawValue: decoder.singleValueContainer().decode(RawValue.self)) {
self = value
} else if let lastValue = Self.allCases.last {
self = lastValue
} else {
throw DecodingError.valueNotFound(
Self.Type.self,
.init(codingPath: decoder.codingPath, debugDescription: "CaseIterableDefaultsLast")
)
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
// Protocols.swift
//
// Generated by openapi-generator
// https://openapi-generator.tech
//

/// An enum where the last case value is "unknown" and can be used as a default catch-all.
public protocol CaseIterableDefaultsLast: Decodable & CaseIterable & RawRepresentable
where RawValue: Decodable, AllCases: BidirectionalCollection {}
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ PetstoreClient/Classes/OpenAPIs/Models/TypeHolderDefault.swift
PetstoreClient/Classes/OpenAPIs/Models/TypeHolderExample.swift
PetstoreClient/Classes/OpenAPIs/Models/User.swift
PetstoreClient/Classes/OpenAPIs/OpenISO8601DateFormatter.swift
PetstoreClient/Classes/OpenAPIs/Protocols.swift
PetstoreClient/Classes/OpenAPIs/SynchronizedDictionary.swift
PetstoreClient/Classes/OpenAPIs/URLSessionImplementations.swift
README.md
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -156,3 +156,21 @@ extension HTTPURLResponse {
return (200 ..< 300).contains(statusCode)
}
}

extension CaseIterableDefaultsLast {
/// Initializes an enum such that if a known raw value is found, then it is decoded.
/// Otherwise the last case ("unknown") is used.
/// - Parameter decoder: A decoder.
public init(from decoder: Decoder) throws {
if let value = try Self(rawValue: decoder.singleValueContainer().decode(RawValue.self)) {
self = value
} else if let lastValue = Self.allCases.last {
self = lastValue
} else {
throw DecodingError.valueNotFound(
Self.Type.self,
.init(codingPath: decoder.codingPath, debugDescription: "CaseIterableDefaultsLast")
)
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
// Protocols.swift
//
// Generated by openapi-generator
// https://openapi-generator.tech
//

/// An enum where the last case value is "unknown" and can be used as a default catch-all.
public protocol CaseIterableDefaultsLast: Decodable & CaseIterable & RawRepresentable
where RawValue: Decodable, AllCases: BidirectionalCollection {}
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ PetstoreClient/Classes/OpenAPIs/Models/TypeHolderDefault.swift
PetstoreClient/Classes/OpenAPIs/Models/TypeHolderExample.swift
PetstoreClient/Classes/OpenAPIs/Models/User.swift
PetstoreClient/Classes/OpenAPIs/OpenISO8601DateFormatter.swift
PetstoreClient/Classes/OpenAPIs/Protocols.swift
PetstoreClient/Classes/OpenAPIs/SynchronizedDictionary.swift
PetstoreClient/Classes/OpenAPIs/URLSessionImplementations.swift
README.md
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -156,3 +156,21 @@ extension HTTPURLResponse {
return (200 ..< 300).contains(statusCode)
}
}

extension CaseIterableDefaultsLast {
/// Initializes an enum such that if a known raw value is found, then it is decoded.
/// Otherwise the last case ("unknown") is used.
/// - Parameter decoder: A decoder.
public init(from decoder: Decoder) throws {
if let value = try Self(rawValue: decoder.singleValueContainer().decode(RawValue.self)) {
self = value
} else if let lastValue = Self.allCases.last {
self = lastValue
} else {
throw DecodingError.valueNotFound(
Self.Type.self,
.init(codingPath: decoder.codingPath, debugDescription: "CaseIterableDefaultsLast")
)
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
// Protocols.swift
//
// Generated by openapi-generator
// https://openapi-generator.tech
//

/// An enum where the last case value is "unknown" and can be used as a default catch-all.
public protocol CaseIterableDefaultsLast: Decodable & CaseIterable & RawRepresentable
where RawValue: Decodable, AllCases: BidirectionalCollection {}
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@ PetstoreClient/Classes/OpenAPIs/Models/TypeHolderExample.swift
PetstoreClient/Classes/OpenAPIs/Models/User.swift
PetstoreClient/Classes/OpenAPIs/Models/XmlItem.swift
PetstoreClient/Classes/OpenAPIs/OpenISO8601DateFormatter.swift
PetstoreClient/Classes/OpenAPIs/Protocols.swift
PetstoreClient/Classes/OpenAPIs/SynchronizedDictionary.swift
PetstoreClient/Classes/OpenAPIs/URLSessionImplementations.swift
README.md
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -156,3 +156,21 @@ extension HTTPURLResponse {
return (200 ..< 300).contains(statusCode)
}
}

extension CaseIterableDefaultsLast {
/// Initializes an enum such that if a known raw value is found, then it is decoded.
/// Otherwise the last case ("unknown") is used.
/// - Parameter decoder: A decoder.
public init(from decoder: Decoder) throws {
if let value = try Self(rawValue: decoder.singleValueContainer().decode(RawValue.self)) {
self = value
} else if let lastValue = Self.allCases.last {
self = lastValue
} else {
throw DecodingError.valueNotFound(
Self.Type.self,
.init(codingPath: decoder.codingPath, debugDescription: "CaseIterableDefaultsLast")
)
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
// Protocols.swift
//
// Generated by openapi-generator
// https://openapi-generator.tech
//

/// An enum where the last case value is "unknown" and can be used as a default catch-all.
public protocol CaseIterableDefaultsLast: Decodable & CaseIterable & RawRepresentable
where RawValue: Decodable, AllCases: BidirectionalCollection {}
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ PetstoreClient/Classes/OpenAPIs/Models/Pet.swift
PetstoreClient/Classes/OpenAPIs/Models/Tag.swift
PetstoreClient/Classes/OpenAPIs/Models/User.swift
PetstoreClient/Classes/OpenAPIs/OpenISO8601DateFormatter.swift
PetstoreClient/Classes/OpenAPIs/Protocols.swift
PetstoreClient/Classes/OpenAPIs/SynchronizedDictionary.swift
PetstoreClient/Classes/OpenAPIs/URLSessionImplementations.swift
README.md
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -156,3 +156,21 @@ extension HTTPURLResponse {
return (200 ..< 300).contains(statusCode)
}
}

extension CaseIterableDefaultsLast {
/// Initializes an enum such that if a known raw value is found, then it is decoded.
/// Otherwise the last case ("unknown") is used.
/// - Parameter decoder: A decoder.
public init(from decoder: Decoder) throws {
if let value = try Self(rawValue: decoder.singleValueContainer().decode(RawValue.self)) {
self = value
} else if let lastValue = Self.allCases.last {
self = lastValue
} else {
throw DecodingError.valueNotFound(
Self.Type.self,
.init(codingPath: decoder.codingPath, debugDescription: "CaseIterableDefaultsLast")
)
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
// Protocols.swift
//
// Generated by openapi-generator
// https://openapi-generator.tech
//

/// An enum where the last case value is "unknown" and can be used as a default catch-all.
public protocol CaseIterableDefaultsLast: Decodable & CaseIterable & RawRepresentable
where RawValue: Decodable, AllCases: BidirectionalCollection {}
Loading