forked from loafle/openapi-generator-original
[Swift3] Don't crash on invalid responses (#4547)
* [Swift 3] Return an error when dealing with invalid responses, instead of crashing. Compatiblity: ErrorResponse.Error becomes ErrorResponse.HttpError * Cleanup and work around existing swift3 generator bug/missing feature * Generate PetStore samples for swift3
This commit is contained in:
committed by
wing328
parent
5f6dcf07b2
commit
2faad6497d
@@ -92,7 +92,7 @@ open class AlamofireRequestBuilder<T>: RequestBuilder<T> {
|
||||
}
|
||||
self.processRequest(request: upload, managerId, completion)
|
||||
case .failure(let encodingError):
|
||||
completion(nil, ErrorResponse(statusCode: 415, data: nil, error: encodingError))
|
||||
completion(nil, ErrorResponse.HttpError(statusCode: 415, data: nil, error: encodingError))
|
||||
}
|
||||
})
|
||||
} else {
|
||||
@@ -124,7 +124,7 @@ open class AlamofireRequestBuilder<T>: RequestBuilder<T> {
|
||||
if stringResponse.result.isFailure {
|
||||
completion(
|
||||
nil,
|
||||
ErrorResponse(statusCode: stringResponse.response?.statusCode ?? 500, data: stringResponse.data, error: stringResponse.result.error as Error!)
|
||||
ErrorResponse.HttpError(statusCode: stringResponse.response?.statusCode ?? 500, data: stringResponse.data, error: stringResponse.result.error as Error!)
|
||||
)
|
||||
return
|
||||
}
|
||||
@@ -144,7 +144,7 @@ open class AlamofireRequestBuilder<T>: RequestBuilder<T> {
|
||||
if voidResponse.result.isFailure {
|
||||
completion(
|
||||
nil,
|
||||
ErrorResponse(statusCode: voidResponse.response?.statusCode ?? 500, data: voidResponse.data, error: voidResponse.result.error!)
|
||||
ErrorResponse.HttpError(statusCode: voidResponse.response?.statusCode ?? 500, data: voidResponse.data, error: voidResponse.result.error!)
|
||||
)
|
||||
return
|
||||
}
|
||||
@@ -163,7 +163,7 @@ open class AlamofireRequestBuilder<T>: RequestBuilder<T> {
|
||||
if (dataResponse.result.isFailure) {
|
||||
completion(
|
||||
nil,
|
||||
ErrorResponse(statusCode: dataResponse.response?.statusCode ?? 500, data: dataResponse.data, error: dataResponse.result.error!)
|
||||
ErrorResponse.HttpError(statusCode: dataResponse.response?.statusCode ?? 500, data: dataResponse.data, error: dataResponse.result.error!)
|
||||
)
|
||||
return
|
||||
}
|
||||
@@ -181,7 +181,7 @@ open class AlamofireRequestBuilder<T>: RequestBuilder<T> {
|
||||
cleanupRequest()
|
||||
|
||||
if response.result.isFailure {
|
||||
completion(nil, ErrorResponse(statusCode: response.response?.statusCode ?? 500, data: response.data, error: response.result.error!))
|
||||
completion(nil, ErrorResponse.HttpError(statusCode: response.response?.statusCode ?? 500, data: response.data, error: response.result.error!))
|
||||
return
|
||||
}
|
||||
|
||||
@@ -197,8 +197,11 @@ open class AlamofireRequestBuilder<T>: RequestBuilder<T> {
|
||||
return
|
||||
}
|
||||
if let json: Any = response.result.value {
|
||||
let body = Decoders.decode(clazz: T.self, source: json as AnyObject)
|
||||
completion(Response(response: response.response!, body: body), nil)
|
||||
let decoded = Decoders.decode(clazz: T.self, source: json as AnyObject)
|
||||
switch decoded {
|
||||
case let .success(object): completion(Response(response: response.response!, body: object), nil)
|
||||
case let .failure(error): completion(nil, ErrorResponse.DecodeError(response: response.data, decodeError: error))
|
||||
}
|
||||
return
|
||||
} else if "" is T {
|
||||
// swagger-parser currently doesn't support void, which will be fixed in future swagger-parser release
|
||||
@@ -207,7 +210,7 @@ open class AlamofireRequestBuilder<T>: RequestBuilder<T> {
|
||||
return
|
||||
}
|
||||
|
||||
completion(nil, ErrorResponse(statusCode: 500, data: nil, error: NSError(domain: "localhost", code: 500, userInfo: ["reason": "unreacheable code"])))
|
||||
completion(nil, ErrorResponse.HttpError(statusCode: 500, data: nil, error: NSError(domain: "localhost", code: 500, userInfo: ["reason": "unreacheable code"])))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -10,10 +10,9 @@ protocol JSONEncodable {
|
||||
func encodeToJSON() -> Any
|
||||
}
|
||||
|
||||
public struct ErrorResponse : Error {
|
||||
public let statusCode: Int
|
||||
public let data: Data?
|
||||
public let error: Error
|
||||
public enum ErrorResponse : Error {
|
||||
case HttpError(statusCode: Int, data: Data?, error: Error)
|
||||
case DecodeError(response: Data?, decodeError: DecodeError)
|
||||
}
|
||||
|
||||
open class Response<T> {
|
||||
@@ -37,90 +36,181 @@ open class Response<T> {
|
||||
}
|
||||
}
|
||||
|
||||
public enum Decoded<ValueType> {
|
||||
case success(ValueType)
|
||||
case failure(DecodeError)
|
||||
}
|
||||
|
||||
public extension Decoded {
|
||||
var value: ValueType? {
|
||||
switch self {
|
||||
case let .success(value):
|
||||
return value
|
||||
break
|
||||
case .failure:
|
||||
return nil
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public enum DecodeError {
|
||||
case typeMismatch(expected: String, actual: String)
|
||||
case missingKey(key: String)
|
||||
case parseError(message: String)
|
||||
}
|
||||
|
||||
private var once = Int()
|
||||
class Decoders {
|
||||
static fileprivate var decoders = Dictionary<String, ((AnyObject) -> AnyObject)>()
|
||||
|
||||
static func addDecoder<T>(clazz: T.Type, decoder: @escaping ((AnyObject) -> T)) {
|
||||
|
||||
static func addDecoder<T>(clazz: T.Type, decoder: @escaping ((AnyObject) -> Decoded<T>)) {
|
||||
let key = "\(T.self)"
|
||||
decoders[key] = { decoder($0) as AnyObject }
|
||||
}
|
||||
|
||||
static func decode<T>(clazz: T.Type, discriminator: String, source: AnyObject) -> T {
|
||||
static func decode<T>(clazz: T.Type, discriminator: String, source: AnyObject) -> Decoded<T> {
|
||||
let key = discriminator;
|
||||
if let decoder = decoders[key] {
|
||||
return decoder(source) as! T
|
||||
if let decoder = decoders[key], let value = decoder(source) as? Decoded<T> {
|
||||
return value
|
||||
} else {
|
||||
fatalError("Source \(source) is not convertible to type \(clazz): Maybe swagger file is insufficient")
|
||||
return .failure(.typeMismatch(expected: String(describing: clazz), actual: String(describing: source)))
|
||||
}
|
||||
}
|
||||
|
||||
static func decode<T>(clazz: [T].Type, source: AnyObject) -> [T] {
|
||||
let array = source as! [AnyObject]
|
||||
return array.map { Decoders.decode(clazz: T.self, source: $0) }
|
||||
}
|
||||
|
||||
static func decode<T, Key: Hashable>(clazz: [Key:T].Type, source: AnyObject) -> [Key:T] {
|
||||
let sourceDictionary = source as! [Key: AnyObject]
|
||||
var dictionary = [Key:T]()
|
||||
for (key, value) in sourceDictionary {
|
||||
dictionary[key] = Decoders.decode(clazz: T.self, source: value)
|
||||
static func decode<T>(clazz: [T].Type, source: AnyObject) -> Decoded<[T]> {
|
||||
if let sourceArray = source as? [AnyObject] {
|
||||
var values = [T]()
|
||||
for sourceValue in sourceArray {
|
||||
switch Decoders.decode(clazz: T.self, source: sourceValue) {
|
||||
case let .success(value):
|
||||
values.append(value)
|
||||
case let .failure(error):
|
||||
return .failure(error)
|
||||
break
|
||||
}
|
||||
}
|
||||
return .success(values)
|
||||
} else {
|
||||
return .failure(.typeMismatch(expected: String(describing: clazz), actual: String(describing: source)))
|
||||
}
|
||||
return dictionary
|
||||
}
|
||||
|
||||
static func decode<T>(clazz: T.Type, source: AnyObject) -> T {
|
||||
static func decode<T, Key: Hashable>(clazz: [Key:T].Type, source: AnyObject) -> Decoded<[Key:T]> {
|
||||
if let sourceDictionary = source as? [Key: AnyObject] {
|
||||
var dictionary = [Key:T]()
|
||||
for (key, value) in sourceDictionary {
|
||||
switch Decoders.decode(clazz: T.self, source: value) {
|
||||
case let .success(value):
|
||||
dictionary[key] = value
|
||||
break
|
||||
case let .failure(error):
|
||||
return .failure(error)
|
||||
}
|
||||
}
|
||||
return .success(dictionary)
|
||||
} else {
|
||||
return .failure(.typeMismatch(expected: String(describing: clazz), actual: String(describing: source)))
|
||||
}
|
||||
}
|
||||
|
||||
static func decodeOptional<T: RawRepresentable>(clazz: T.Type, source: AnyObject?) -> Decoded<T?> {
|
||||
if let value = source as? T.RawValue {
|
||||
if let enumValue = T.init(rawValue: value) {
|
||||
return .success(enumValue)
|
||||
} else {
|
||||
return .failure(.typeMismatch(expected: "A value from the enumeration \(T.self)", actual: "\(value)"))
|
||||
}
|
||||
} else {
|
||||
return .failure(.typeMismatch(expected: "\(T.RawValue.self) matching a case from the enumeration \(T.self)", actual: String(describing: type(of: source))))
|
||||
}
|
||||
}
|
||||
|
||||
static func decode<T>(clazz: T.Type, source: AnyObject) -> Decoded<T> {
|
||||
initialize()
|
||||
if T.self is Int32.Type && source is NSNumber {
|
||||
return source.int32Value as! T;
|
||||
if let value = source.int32Value as? T, source is NSNumber, T.self is Int32.Type {
|
||||
return .success(value)
|
||||
}
|
||||
if T.self is Int64.Type && source is NSNumber {
|
||||
return source.int64Value as! T;
|
||||
if let value = source.int32Value as? T, source is NSNumber, T.self is Int64.Type {
|
||||
return .success(value)
|
||||
}
|
||||
if T.self is UUID.Type && source is String {
|
||||
return UUID(uuidString: source as! String) as! T
|
||||
if let intermediate = source as? String, let value = UUID(uuidString: intermediate) as? T, source is String, T.self is UUID.Type {
|
||||
return .success(value)
|
||||
}
|
||||
if source is T {
|
||||
return source as! T
|
||||
if let value = source as? T {
|
||||
return .success(value)
|
||||
}
|
||||
if T.self is Data.Type && source is String {
|
||||
return Data(base64Encoded: source as! String) as! T
|
||||
if let intermediate = source as? String, let value = Data(base64Encoded: intermediate) as? T {
|
||||
return .success(value)
|
||||
}
|
||||
|
||||
let key = "\(T.self)"
|
||||
if let decoder = decoders[key] {
|
||||
return decoder(source) as! T
|
||||
if let decoder = decoders[key], let value = decoder(source) as? Decoded<T> {
|
||||
return value
|
||||
} else {
|
||||
fatalError("Source \(source) is not convertible to type \(clazz): Maybe swagger file is insufficient")
|
||||
return .failure(.typeMismatch(expected: String(describing: clazz), actual: String(describing: source)))
|
||||
}
|
||||
}
|
||||
|
||||
static func decodeOptional<T>(clazz: T.Type, source: AnyObject?) -> T? {
|
||||
if source is NSNull {
|
||||
return nil
|
||||
}
|
||||
return source.map { (source: AnyObject) -> T in
|
||||
Decoders.decode(clazz: clazz, source: source)
|
||||
//Convert a Decoded so that its value is optional. DO WE STILL NEED THIS?
|
||||
static func toOptional<T>(decoded: Decoded<T>) -> Decoded<T?> {
|
||||
return .success(decoded.value)
|
||||
}
|
||||
|
||||
static func decodeOptional<T>(clazz: T.Type, source: AnyObject?) -> Decoded<T?> {
|
||||
if let source = source, !(source is NSNull) {
|
||||
switch Decoders.decode(clazz: clazz, source: source) {
|
||||
case let .success(value): return .success(value)
|
||||
case let .failure(error): return .failure(error)
|
||||
}
|
||||
} else {
|
||||
return .success(nil)
|
||||
}
|
||||
}
|
||||
|
||||
static func decodeOptional<T>(clazz: [T].Type, source: AnyObject?) -> [T]? {
|
||||
if source is NSNull {
|
||||
return nil
|
||||
}
|
||||
return source.map { (someSource: AnyObject) -> [T] in
|
||||
Decoders.decode(clazz: clazz, source: someSource)
|
||||
static func decodeOptional<T>(clazz: [T].Type, source: AnyObject?) -> Decoded<[T]?> {
|
||||
if let source = source as? [AnyObject] {
|
||||
var values = [T]()
|
||||
for sourceValue in source {
|
||||
switch Decoders.decode(clazz: T.self, source: sourceValue) {
|
||||
case let .success(value): values.append(value)
|
||||
case let .failure(error): return .failure(error)
|
||||
}
|
||||
}
|
||||
return .success(values)
|
||||
} else {
|
||||
return .success(nil)
|
||||
}
|
||||
}
|
||||
|
||||
static func decodeOptional<T, Key: Hashable>(clazz: [Key:T].Type, source: AnyObject?) -> [Key:T]? {
|
||||
if source is NSNull {
|
||||
return nil
|
||||
}
|
||||
return source.map { (someSource: AnyObject) -> [Key:T] in
|
||||
Decoders.decode(clazz: clazz, source: someSource)
|
||||
static func decodeOptional<T, Key: Hashable>(clazz: [Key:T].Type, source: AnyObject?) -> Decoded<[Key:T]?> {
|
||||
if let sourceDictionary = source as? [Key: AnyObject] {
|
||||
var dictionary = [Key:T]()
|
||||
for (key, value) in sourceDictionary {
|
||||
switch Decoders.decode(clazz: T.self, source: value) {
|
||||
case let .success(value): dictionary[key] = value
|
||||
case let .failure(error): return .failure(error)
|
||||
}
|
||||
}
|
||||
return .success(dictionary)
|
||||
} else {
|
||||
return .success(nil)
|
||||
}
|
||||
}
|
||||
|
||||
static func decodeOptional<T: RawRepresentable, U: AnyObject where T.RawValue == U>(clazz: T, source: AnyObject) -> Decoded<T?> {
|
||||
if let value = source as? U {
|
||||
if let enumValue = T.init(rawValue: value) {
|
||||
return .success(enumValue)
|
||||
} else {
|
||||
return .failure(.typeMismatch(expected: "A value from the enumeration \(T.self)", actual: "\(value)"))
|
||||
}
|
||||
} else {
|
||||
return .failure(.typeMismatch(expected: "String", actual: String(describing: type(of: source))))
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private static var __once: () = {
|
||||
let formatters = [
|
||||
@@ -136,88 +226,97 @@ class Decoders {
|
||||
return formatter
|
||||
}
|
||||
// Decoder for Date
|
||||
Decoders.addDecoder(clazz: Date.self) { (source: AnyObject) -> Date in
|
||||
Decoders.addDecoder(clazz: Date.self) { (source: AnyObject) -> Decoded<Date> in
|
||||
if let sourceString = source as? String {
|
||||
for formatter in formatters {
|
||||
if let date = formatter.date(from: sourceString) {
|
||||
return date
|
||||
return .success(date)
|
||||
}
|
||||
}
|
||||
}
|
||||
if let sourceInt = source as? Int64 {
|
||||
if let sourceInt = source as? Int {
|
||||
// treat as a java date
|
||||
return Date(timeIntervalSince1970: Double(sourceInt / 1000) )
|
||||
return .success(Date(timeIntervalSince1970: Double(sourceInt / 1000) ))
|
||||
}
|
||||
if source is String || source is Int {
|
||||
return .failure(.parseError(message: "Could not decode date"))
|
||||
} else {
|
||||
return .failure(.typeMismatch(expected: "String or Int", actual: "\(source)"))
|
||||
}
|
||||
fatalError("formatter failed to parse \(source)")
|
||||
}
|
||||
|
||||
|
||||
// Decoder for ISOFullDate
|
||||
Decoders.addDecoder(clazz: ISOFullDate.self) { (source: AnyObject) -> ISOFullDate in
|
||||
Decoders.addDecoder(clazz: ISOFullDate.self) { (source: AnyObject) -> Decoded<ISOFullDate> in
|
||||
if let string = source as? String,
|
||||
let isoDate = ISOFullDate.from(string: string) {
|
||||
return isoDate
|
||||
return .success(isoDate)
|
||||
} else {
|
||||
return .failure(.typeMismatch(expected: "ISO date", actual: "\(source)"))
|
||||
}
|
||||
fatalError("formatter failed to parse \(source)")
|
||||
} {{#models}}{{#model}}
|
||||
|
||||
{{^isArrayModel}}
|
||||
// Decoder for [{{{classname}}}]
|
||||
Decoders.addDecoder(clazz: [{{{classname}}}].self) { (source: AnyObject) -> [{{{classname}}}] in
|
||||
Decoders.addDecoder(clazz: [{{{classname}}}].self) { (source: AnyObject) -> Decoded<[{{{classname}}}]> in
|
||||
return Decoders.decode(clazz: [{{{classname}}}].self, source: source)
|
||||
}
|
||||
// Decoder for {{{classname}}}
|
||||
Decoders.addDecoder(clazz: {{{classname}}}.self) { (source: AnyObject) -> {{{classname}}} in
|
||||
{{#isArrayModel}}
|
||||
let sourceArray = source as! [AnyObject]
|
||||
return sourceArray.map({ Decoders.decode(clazz: {{{arrayModelType}}}.self, source: $0) })
|
||||
{{/isArrayModel}}
|
||||
{{^isArrayModel}}
|
||||
Decoders.addDecoder(clazz: {{{classname}}}.self) { (source: AnyObject) -> Decoded<{{{classname}}}> in
|
||||
{{#isEnum}}
|
||||
if let source = source as? {{dataType}} {
|
||||
if let result = {{classname}}(rawValue: source) {
|
||||
return result
|
||||
}
|
||||
}
|
||||
fatalError("Source \(source) is not convertible to enum type {{classname}}: Maybe swagger file is insufficient")
|
||||
//TODO: I don't think we need this anymore
|
||||
return Decoders.decode(clazz: {{{classname}}}.self, source: source)
|
||||
{{/isEnum}}
|
||||
{{^isEnum}}
|
||||
{{#allVars.isEmpty}}
|
||||
if let source = source as? {{dataType}} {
|
||||
return source
|
||||
return .success(source)
|
||||
} else {
|
||||
return .failure(.typeMismatch(expected: "Typealias {{classname}}", actual: "\(source)"))
|
||||
}
|
||||
fatalError("Source \(source) is not convertible to typealias {{classname}}: Maybe swagger file is insufficient")
|
||||
{{/allVars.isEmpty}}
|
||||
{{^allVars.isEmpty}}
|
||||
let sourceDictionary = source as! [AnyHashable: Any]
|
||||
if let sourceDictionary = source as? [AnyHashable: Any] {
|
||||
{{#discriminator}}
|
||||
// Check discriminator to support inheritance
|
||||
if let discriminator = sourceDictionary["{{discriminator}}"] as? String, discriminator != "{{classname}}"{
|
||||
return Decoders.decode(clazz: {{classname}}.self, discriminator: discriminator, source: source)
|
||||
}
|
||||
// Check discriminator to support inheritance
|
||||
if let discriminator = sourceDictionary["{{discriminator}}"] as? String, discriminator != "{{classname}}"{
|
||||
return Decoders.decode(clazz: {{classname}}.self, discriminator: discriminator, source: source)
|
||||
}
|
||||
{{/discriminator}}
|
||||
|
||||
{{#unwrapRequired}}
|
||||
let instance = {{classname}}({{#requiredVars}}{{^-first}}, {{/-first}}{{#isEnum}}{{name}}: {{classname}}.{{datatypeWithEnum}}(rawValue: (sourceDictionary["{{baseName}}"] as! {{datatype}}))! {{/isEnum}}{{^isEnum}}{{name}}: Decoders.decode(clazz: {{{baseType}}}.self, source: sourceDictionary["{{baseName}}"]! as AnyObject){{/isEnum}}{{/requiredVars}})
|
||||
{{#optionalVars}}{{#isEnum}}
|
||||
if let {{name}} = sourceDictionary["{{baseName}}"] as? {{datatype}} { {{^isContainer}}
|
||||
instance.{{name}} = {{classname}}.{{datatypeWithEnum}}(rawValue: ({{name}})){{/isContainer}}{{#isListContainer}}
|
||||
instance.{{name}} = {{name}}.map ({ {{classname}}.{{enumName}}(rawValue: $0)! }){{/isListContainer}}
|
||||
}{{/isEnum}}{{^isEnum}}
|
||||
instance.{{name}} = Decoders.decodeOptional(clazz: {{{baseType}}}.self, source: sourceDictionary["{{baseName}}"] as AnyObject?){{/isEnum}}
|
||||
{{#requiredVars}}
|
||||
guard let {{name}}Source = sourceDictionary["{{baseName}}"] as AnyObject? else {
|
||||
return .failure(.missingKey(key: "{{baseName}}"))
|
||||
}
|
||||
guard let {{name}} = Decoders.decode(clazz: {{#isEnum}}{{^isListContainer}}{{classname}}.{{enumName}}.self{{/isListContainer}}{{#isListContainer}}Array<{{classname}}.{{enumName}}>.self{{/isListContainer}}{{/isEnum}}{{^isEnum}}{{{datatype}}}.self{{/isEnum}}.self, source: {{name}}Source).value else {
|
||||
return .failure(.typeMismatch(expected: "{{classname}}", actual: "\({{name}}Source)"))
|
||||
}
|
||||
{{/requiredVars}}
|
||||
let instance = {{classname}}({{#requiredVars}}{{^-first}}, {{/-first}}{{name}}: {{name}}{{/requiredVars}})
|
||||
{{#optionalVars}}
|
||||
switch Decoders.decodeOptional(clazz: {{#isEnum}}{{^isListContainer}}{{classname}}.{{enumName}}.self{{/isListContainer}}{{#isListContainer}}Array<{{classname}}.{{enumName}}>.self{{/isListContainer}}{{/isEnum}}{{^isEnum}}{{{datatype}}}.self{{/isEnum}}, source: sourceDictionary["{{baseName}}"] as AnyObject?) {
|
||||
case let .success(value): instance.{{name}} = value
|
||||
case let .failure(error): return .failure(error)
|
||||
}
|
||||
{{/optionalVars}}
|
||||
{{/unwrapRequired}}
|
||||
{{^unwrapRequired}}
|
||||
let instance = {{classname}}(){{#allVars}}{{#isEnum}}
|
||||
if let {{name}} = sourceDictionary["{{baseName}}"] as? {{datatype}} { {{^isContainer}}
|
||||
instance.{{name}} = {{classname}}.{{datatypeWithEnum}}(rawValue: ({{name}})){{/isContainer}}{{#isListContainer}}
|
||||
instance.{{name}} = {{name}}.map ({ {{classname}}.{{enumName}}(rawValue: $0)! }){{/isListContainer}}{{#isMapContainer}}//TODO: handle enum map scenario{{/isMapContainer}}
|
||||
}{{/isEnum}}
|
||||
{{^isEnum}}instance.{{name}} = Decoders.decodeOptional(clazz: {{{baseType}}}.self, source: sourceDictionary["{{baseName}}"] as AnyObject?){{/isEnum}}{{/allVars}}
|
||||
let instance = {{classname}}(){{#allVars}}
|
||||
switch Decoders.decodeOptional(clazz: {{#isEnum}}{{^isListContainer}}{{classname}}.{{enumName}}.self{{/isListContainer}}{{#isListContainer}}Array<{{classname}}.{{enumName}}>.self{{/isListContainer}}{{/isEnum}}{{^isEnum}}{{{datatype}}}.self{{/isEnum}}, source: sourceDictionary["{{baseName}}"] as AnyObject?) {
|
||||
{{#isEnum}}{{#isMapContainer}}/*{{/isMapContainer}}{{/isEnum}}
|
||||
case let .success(value): instance.{{name}} = value
|
||||
case let .failure(error): return .failure(error)
|
||||
{{#isEnum}}{{#isMapContainer}}*/ default: break //TODO: handle enum map scenario{{/isMapContainer}}{{/isEnum}}
|
||||
}
|
||||
{{/allVars}}
|
||||
{{/unwrapRequired}}
|
||||
return instance
|
||||
return .success(instance)
|
||||
} else {
|
||||
return .failure(.typeMismatch(expected: "{{classname}}", actual: "\(source)"))
|
||||
}
|
||||
{{/allVars.isEmpty}}
|
||||
{{/isEnum}}
|
||||
{{/isArrayModel}}
|
||||
}{{/model}}
|
||||
}{{/isArrayModel}}{{/model}}
|
||||
{{/models}}
|
||||
}()
|
||||
|
||||
|
||||
Reference in New Issue
Block a user