Last active
December 20, 2021 20:57
-
-
Save kean/118ae053c5d610069a8e60d37e2d999b to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import UIKit | |
// Almost pseudocode, but should be possible to write in proper Swift | |
// MARK: High-Level APIs | |
// Decodes the document. By default, ignores errors and warnings. | |
func decode(data: Data, isStrict: Bool = false) -> throws OpenAPI.Document { | |
let parser = JSONDecoder().decoder(DocumentParser.self, from: data) | |
// Or maybe be even more granular: "strict", "ignoreWarnings", "ignoreAll"? | |
if isSrict && (!document.errors.isEmpty || !document.warnings.isEmpty) { | |
throw DocumentError(document.errors, document.warnigs) | |
} | |
// In non-strict, return a document even if there were errors (e.g. failed to | |
// parse one of the schemas completely) or warnings (e.g. a schemas with | |
// type "string" has properties from "array") | |
return parser.document | |
} | |
func validate(data: Data) -> ([Errror, Warnings] { | |
let document = JSONDecoder().decoder(DocumentDecoder.self, from: data) | |
return (document.errors, document.warnings) | |
} | |
// MARK: Parsers | |
struct DocumentParser: Decodable { | |
// Schemas that were parsed succesfully | |
let schemas: [OpenAPI.Schema] | |
// Errors encountered during schemas parsing | |
var errors: [Error] | |
// Warnings encountered during schemas parsing | |
var warnings: [Warning] | |
init(from decoder: Decoder) { | |
// .. | |
let schemas = try decoder.decode(DecodableResult<SchemaParser>.self, forKey: "schemas") | |
self.schemas = schemas.compactMap { $0.result.value } | |
self.errors = schemas.compactMap { $0.result.error } | |
self.warnings = schemas.compactMap { $0.result.value }.flatMap { $0.warnings } | |
// perform validations across schemas if needed, e.g. duplicate names | |
self.warnings = ... | |
} | |
} | |
struct SchemaParser: Decodable { | |
let schema: OpenAPI.Schema | |
let warnings: [Warning] | |
init(from decoder: Decoder) { | |
// decode and throw if there are critical errors | |
// entity could probably decode itself | |
self.schema = ... | |
// perform validations | |
self.warnings = [...] | |
} | |
} | |
// A critical errors, e.g. failed to parse one of the schemas completely | |
struct Error {} | |
// A warning, e.g. a schemas with type "string" has properties from "array" | |
struct Warning {} | |
// Catches errors and saves them a results instead of throwing | |
struct DecodableResult<T: Decodable>: Decodable { | |
let result: Result<T, Errors>? | |
init(from decoder: Decoder) throws { | |
do { | |
let container = try decoder.singleValueContainer() | |
self.value = .success(try container.decode(T.self)) | |
} catch { error as Warnings | |
self.result =. failure(error) | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment