enumの値チェック
enumをrawValueから生成するときに、値を制限したいことはよくあると思います。
Himotokiと組み合わせることを前提に、rawValueが不正だった場合に詳細なエラーメッセージを含むDecodeError.TypeMismatch
をthrowするinitializerを作ったので共有します。
なおRawValueがIntの場合限定です。有効範囲を0から11として無理やりinitializerを呼んでみて、ダメだったらエラーにするというなんとも無理やりな実装です。
こんな風に使います。
enum Status: Int { case Initial = 0, Active = 1, Inactive = 2 } struct Bar: Decodable { let status: Status static func decode(e: Extractor) throws -> Bar { return Bar( status: try Status(int: try e <| "status", keyPath: "status") ) } }
以下、init(int:)
の実装です。
import Foundation import Himotoki extension RawRepresentable where Self.RawValue == Int { /// Failable initializer for any RawRepresentable(such as enum) types /// If passed rawValue didn't match expectation, /// throws detailed error with `expected` and passed in `keyPath`. /// /// - parameter int: the rawValue /// - parameter keyPath: /// - throws: DecodeError.TypeMismatch /// - seealso: for Error type, see Himotoki init(int: Self.RawValue, keyPath: KeyPath = "") throws { guard let _ = Self(rawValue: int) else { throw DecodeError.TypeMismatch(expected: expectedIntValues(Self.self), actual: "\(int)", keyPath: keyPath) } self.init(rawValue: int)! } init?(optionalInt: Self.RawValue?, keyPath: KeyPath = "") throws { guard let int = optionalInt else { return nil } try self.init(int: int) } } private func expectedIntValues<T: RawRepresentable where T.RawValue == Int> (type: T.Type) -> String { return (0...11) /// Note: Assuming that the valid rawValues are between 0 to 11 . .flatMap{type.init(rawValue: $0)} .reduce("") {acc, e in "\(acc == "" ? "" : acc+",")\(e.rawValue)"} }
フィードバックいただけると嬉しいです。