Skip to content

Commit

Permalink
Input-errors are now thrown as an array of errors.
Browse files Browse the repository at this point in the history
  • Loading branch information
Evertt committed May 20, 2016
1 parent d618ca4 commit eee4884
Showing 1 changed file with 34 additions and 16 deletions.
50 changes: 34 additions & 16 deletions Sources/Unbox.swift
Original file line number Diff line number Diff line change
Expand Up @@ -85,28 +85,39 @@ public func Unbox<T: UnboxableWithContext>(data: NSData, context: T.ContextType,

// MARK: - Error type

public enum InvalidInputError: ErrorType, CustomStringConvertible {
public var description: String {
switch self {
case .MissingKey(let key):
return "missing key (\(key))"
case .InvalidValue(let key, let valueDescription):
return "invalid value (\(valueDescription)) for key (\(key))"
}
}

/// Thrown when a required key was missing in an unboxed dictionary. Contains the missing key.
case MissingKey(String)
/// Thrown when a required key contained an invalid value in an unboxed dictionary. Contains the invalid
/// key and a description of the invalid data.
case InvalidValue(String, String)
}

/// Enum describing errors that can occur during unboxing. Use the throwing functions to receive any errors.
public enum UnboxError: ErrorType, CustomStringConvertible {
public var description: String {
let baseDescription = "[Unbox error] "

switch self {
case .MissingKey(let key):
return baseDescription + "Missing key (\(key))"
case .InvalidValue(let key, let valueDescription):
return baseDescription + "Invalid value (\(valueDescription)) for key (\(key))"
case .InvalidInput(let errors):
return baseDescription + errors.map{"\($0)"}.joinWithSeparator(", ")
case .InvalidData:
return baseDescription + "Invalid NSData"
case .CustomUnboxingFailed:
return baseDescription + "A custom unboxing closure returned nil"
}
}

/// Thrown when a required key was missing in an unboxed dictionary. Contains the missing key.
case MissingKey(String)
/// Thrown when a required key contained an invalid value in an unboxed dictionary. Contains the invalid
/// key and a description of the invalid data.
case InvalidValue(String, String)
case InvalidInput([InvalidInputError])
/// Thrown when a piece of data (NSData) could not be unboxed because it was considered invalid
case InvalidData
/// Thrown when a custom unboxing closure returned nil
Expand Down Expand Up @@ -303,11 +314,11 @@ public class Unboxer {
/// The underlying JSON dictionary that is being unboxed
public let dictionary: UnboxableDictionary
/// Whether the Unboxer has failed, and a `nil` value will be returned from the `Unbox()` function that triggered it.
public var hasFailed: Bool { return self.failureInfo != nil }
public var hasFailed: Bool { return !self.failureInfo.isEmpty }
/// Any contextual object that was supplied when unboxing was started
public let context: Any?

private var failureInfo: (key: String, value: Any?)?
private var failureInfo = [(key: String, value: Any?)]()

// MARK: - Private initializer

Expand Down Expand Up @@ -539,7 +550,7 @@ public class Unboxer {

/// Make this Unboxer fail for a certain key and invalid value. This will cause the `Unbox()` function that triggered this Unboxer to return `nil`.
public func failForInvalidValue(invalidValue: Any?, forKey key: String) {
self.failureInfo = (key, invalidValue)
self.failureInfo.append((key, invalidValue))
}
}

Expand Down Expand Up @@ -710,15 +721,22 @@ private extension Unboxer {
}

func throwIfFailed() throws {
guard let failureInfo = self.failureInfo else {
guard !failureInfo.isEmpty else {
return
}

if let failedValue: Any = failureInfo.value {
throw UnboxError.InvalidValue(failureInfo.key, "\(failedValue)")
var inputErrors = [InvalidInputError]()

for failure in failureInfo {
if let failedValue: Any = failure.value {
inputErrors.append(.InvalidValue(failure.key, "\(failedValue)"))
}
else {
inputErrors.append(.MissingKey(failure.key))
}
}

throw UnboxError.MissingKey(failureInfo.key)
throw UnboxError.InvalidInput(inputErrors)
}
}

Expand Down

0 comments on commit eee4884

Please sign in to comment.