Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Validate content type strings in validateDoc #471

41 changes: 32 additions & 9 deletions Sources/_OpenAPIGeneratorCore/Translator/Content/ContentType.swift
Original file line number Diff line number Diff line change
Expand Up @@ -143,23 +143,20 @@ struct ContentType: Hashable {
/// not be empty.
/// - Throws: If a malformed content type string is encountered.
init(string: String) throws {
struct InvalidContentTypeString: Error, LocalizedError, CustomStringConvertible {
var string: String
var description: String {
"Invalid content type string: '\(string)', must have 2 components separated by a slash."
}
var errorDescription: String? { description }
}
guard !string.isEmpty else { throw InvalidContentTypeString(string: "") }
guard !string.isEmpty else { throw ContentTypeError.emptyString(string) }
var semiComponents = string.split(separator: ";")
let typeAndSubtypeComponent = semiComponents.removeFirst()
self.originallyCasedParameterPairs = semiComponents.map { component in
component.split(separator: "=").map { $0.trimmingCharacters(in: .whitespacesAndNewlines) }
.joined(separator: "=")
}
let rawTypeAndSubtype = typeAndSubtypeComponent.trimmingCharacters(in: .whitespaces)
if rawTypeAndSubtype.isEmpty { throw ContentTypeError.whitespacesString(string) }
let typeAndSubtype = rawTypeAndSubtype.split(separator: "/").map(String.init)
guard typeAndSubtype.count == 2 else { throw InvalidContentTypeString(string: rawTypeAndSubtype) }
guard typeAndSubtype.count == 2 else {
if typeAndSubtype.count > 2 { throw ContentTypeError.excessiveComponents(rawTypeAndSubtype) }
throw ContentTypeError.genericError(rawTypeAndSubtype)
}
self.originallyCasedType = typeAndSubtype[0]
self.originallyCasedSubtype = typeAndSubtype[1]
}
Expand Down Expand Up @@ -229,6 +226,32 @@ struct ContentType: Hashable {
lhs.lowercasedTypeAndSubtype == rhs.lowercasedTypeAndSubtype
}

private enum ContentTypeError: Error, LocalizedError, CustomStringConvertible {
case emptyString(_ contentType: String)
case whitespacesString(_ contentType: String)
case excessiveComponents(_ contentType: String)
case genericError(_ contentType: String)

var description: String {
switch self {
case .emptyString(let contentTypeString):
return
"Invalid content type string: '\(contentTypeString)' is empty, must have 2 components separated by a slash '<type>/<subtype>'."
case .whitespacesString(let contentTypeString):
return
"Invalid content type string: '\(contentTypeString)' is formed of whitespaces, must have 2 components separated by a slash '<type>/<subtype>'."
case .excessiveComponents(let contentTypeString):
return
"Invalid content type string: '\(contentTypeString)' has an excessive number of components, must have 2 components separated by a slash '<type>/<subtype>'."
case .genericError(let contentTypeString):
return
"Invalid content type string: '\(contentTypeString)' must have 2 components separated by a slash '<type>/<subtype>'."
}
}

var errorDescription: String? { description }
}

func hash(into hasher: inout Hasher) { hasher.combine(lowercasedTypeAndSubtype) }
}

Expand Down