// Copyright © 2024 Ryan Booker. All rights reserved. import ArgumentParser import Foundation public enum Either<First, Second> { case first(First) case second(Second) public func reduce<T>( first firstResult: (First) -> T, second secondResult: (Second) -> T ) -> T { switch self { case let .first(value): firstResult(value) case let .second(error): secondResult(error) } } } extension Either: CustomStringConvertible where First: CustomStringConvertible, Second: CustomStringConvertible { public var description: String { reduce(first: \.description, second: \.description) } } extension Either: Decodable where First: Decodable, Second: Decodable { public init(from decoder: Decoder) throws { self = try tryBoth(decoder, first: First.init, second: Second.init) } } extension Either: ExpressibleByArgument where First: ExpressibleByArgument, Second: ExpressibleByArgument { public init?(argument: String) { if let value = First(argument: argument) { self = .first(value) } else if let value = Second(argument: argument) { self = .second(value) } else { return nil } } } public func tryBoth<A, First, Second>( _ value: A, first: (A) throws -> First, second: (A) throws -> Second ) throws -> Either<First, Second> { do { return try .first(first(value)) } catch let firstError { do { return try .second(second(value)) } catch let secondError { throw [firstError, secondError] } } } extension Array: Error where Element: Error {}