Skip to content

Instantly share code, notes, and snippets.

@rnapier
Last active August 21, 2020 14:00
Show Gist options
  • Star 4 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save rnapier/39007fd0fee47ca6966aafa86775ca46 to your computer and use it in GitHub Desktop.
Save rnapier/39007fd0fee47ca6966aafa86775ca46 to your computer and use it in GitHub Desktop.
AssertionFailure as a type
///
/// Boring setup. See below for the good parts
///
public class Logger {
public static let root = Logger(subsystem: .none, parent: nil)
public let subsystem: Subsystem
public let parent: Logger?
public init(subsystem: Subsystem, parent: Logger? = .root) {
self.subsystem = subsystem
self.parent = parent
}
// Fatals should go through something else like fatalError.
fileprivate func fatal(_ message: String, error: Error?, data: [String: Any] = [:], file: String = #file, line: Int = #line, function: String = #function) {
// Do what you want here
print("Logging: \(message)")
// All the gory internals of the logger....
// logInternal(message, data: add(error: error, to: data), level: .fatal, file: file, line: line, function: function)
// flush()
}
}
public struct Subsystem: Equatable, CustomStringConvertible {
public let name: String
public init(name: String) {
self.name = name
}
public var description: String { return name }
}
extension Subsystem {
public static var none: Subsystem { return Subsystem(name: "") }
}
public let Log = Logger.root
/// End boring setup.
///
/// The Good Parts
///
// WARNING: Constructing AssertionFailure calls assertionFailure()
struct AssertionFailure: Error {
let message: String
let file: StaticString
let line: Int
init(message: String, file: StaticString, line: Int) {
Swift.assertionFailure(message, file: file, line: UInt(line))
self.message = message
self.file = file
self.line = line
}
}
extension Logger {
@discardableResult
public func assertionFailure(_ message: String = "", error: Error? = nil, data: [String: Any] = [:], file: StaticString = #file, line: Int = #line, function: String = #function)
-> Error {
// First, log it (and flush all the destinations)
fatal(message, error: error, data: data, file: String(describing: file), line: line)
// And then either crash (assertionFailure) or return it as an Error (which can be thrown)
return AssertionFailure(message: message, file: file, line: line)
}
}
// We can throw AssertionFailures
throw Log.assertionFailure("Bad")
// Or use them as Error values
completion(.failure(Log.assertionFailure("Bad")))
// But also, they can be used without a logging system
throw AssertionFailure(message: "Bad")
// Probably possible to wrap `assert` in here somehow more directly.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment