Skip to content

Instantly share code, notes, and snippets.

@zhjuncai
Forked from seanlilmateus/result.swift
Last active August 29, 2015 14:14
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save zhjuncai/22ab34649962cfe21a84 to your computer and use it in GitHub Desktop.
Save zhjuncai/22ab34649962cfe21a84 to your computer and use it in GitHub Desktop.
#!/usr/bin/env xcrun swift -i
import Foundation
enum Result<T, E> {
/*
We can't use this at the moment due to a LLVM Error:
error: unimplemented IR generation feature non-fixed multi-payload enum layout
LLVM ERROR: unimplemented IRGen feature! non-fixed multi-payload enum layout
case Success(T)
case Failure(E)
*/
case Success(@auto_closure() -> T)
case Failure(@auto_closure() -> E)
func isSuccess() -> Bool {
switch self {
case .Success: return true
default: return false
}
}
func isFailure() -> Bool {
return !self.isSuccess()
}
func success() -> T? {
switch self {
case .Success(let x): return Optional.Some(x())
default: return nil
}
}
func failure() -> E? {
switch self {
case .Failure(let e): return Optional.Some(e())
default: return nil
}
}
func map<U>(op: T -> U) -> Result<U, E> {
switch self {
case .Success(let x): return .Success(op(x()))
case .Failure(let x): return .Failure(x())
}
}
func mapFailure<F>(op: E -> F) -> Result<T,F> {
switch self {
case .Success(let t): return .Success(t)
case .Failure(let e): return .Failure(op(e()))
}
}
func and<U>(res: Result<U, E>) -> Result<U, E> {
switch self {
case .Success: return res
case .Failure(let e): return .Failure(e())
}
}
func andThen<U>(op: T -> Result<U, E>) -> Result<U, E> {
switch self {
case .Success(let t): return op(t())
case .Failure(let e): return .Failure(e)
}
}
func or(res: Result<T, E>) -> Result<T, E> {
switch self {
case .Success: return self
case .Failure: return res
}
}
func orElse<F>(op: E -> Result<T, F>) -> Result<T, F> {
switch self {
case .Success(let t): return .Success(t())
case .Failure(let e): return op(e())
}
}
func unwrapOr(optb: T) -> T {
switch self {
case .Success(let t): return t()
case .Failure: return optb
}
}
func unwrapOrElse(op: E -> T) -> T {
switch self {
case .Success(let t): return t()
case .Failure(let e): return op(e())
}
}
// Fails if the value is an `Failure`, with a custom failure message provided
// by the `Failure`'s value.
// caller line && file, otherwise would git the current line where the fatalError is called
func unwrap(file: StaticString = __FILE__, line: UWord = __LINE__) -> T {
switch self {
case .Success(let x): return x()
case .Failure(let e): fatalError("unexpectedly found a Failure while unwrapping a Result value", file:file, line:line)
}
}
// Fails if the value is an `Success`, with a custom failure message provided
// by the `Success`'s value.
// caller line && file, otherwise would git the current line where the fatalError is called
func unwrapError(file: StaticString = __FILE__, line: UWord = __LINE__) -> E {
switch self {
case .Failure(let e): return e()
case .Success(let x): fatalError("unexpectedly found a Success while unwrapping a Result value", file:file, line:line)
}
}
}
extension Result : Printable {
var description : String {
switch self {
case .Success(let x): return ".Success(\(x()))"
case .Failure(let e): return ".Failure(\(e()))"
}
}
}
extension Result : LogicValue {
func getLogicValue() -> Bool {
return self.isSuccess()
}
}
enum Version : Printable {
case Version1, Version2
var description : String {
switch self {
case .Version1: return "Version1"
case .Version2: return "Version2"
}
}
}
typealias IOResult = Result<NSData, NSError>
func readFile(path:String) -> IOResult {
var maybeError:NSError?
let url:NSURL = NSURL(string: path)
let handler:NSFileHandle? = NSFileHandle.fileHandleForReadingFromURL(url, error:&maybeError)
if let file = handler {
return .Success(file.availableData)
} else if let error = maybeError {
return .Failure(error)
} else { // should never happen, unless NSURL initialization fails...
let userInfo = ["reason":"An unknown error has occurred"]
return .Failure(NSError(domain: "SwiftIO", code: -2, userInfo: userInfo))
}
}
func parseVersion(header: [UInt8]) -> Result<Version, String> {
if header.count < 1 { return .Failure("invalid header length") }
switch header[0] {
case 1: return .Success(.Version1)
case 2: return .Success(.Version2)
default: return .Failure("invalid version")
}
}
// IOResult for reading files
let profile = readFile("\(NSHomeDirectory())/.profile")
let result:Result<String, NSError> = profile.map { x in NSString(data:x, encoding: NSUTF8StringEncoding) }
println(result.description)
// header parsing
let header = parseVersion([0, 2, 3, 4])
if let version = header.success() {
println("working with version: \(version)")
} else if let error = header.failure() {
println("error parsing header: \(error)")
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment