forked from thoughtbot/Argo
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Implement a Decoded type for error messaging
This introduces a `Decoded` type which is similar to a `Result` type. It has a success state and 2 failure states. One failure state occurs if there is a type mismatch and the other is for a missing key in the JSON. This custom type allows us to retain some information about why a decoding has failed. It also allows us to abstract the return type that the user wants. We have defined a global `decode` function for the user to use. It can return an optional type, ignoring the failure data, or return the `Decoded` type if the user would like to retain the error information. Other return types like `Result` could also easily be implemented in a particular project. The 2 different error states will function a bit differently. If the user wants an optional value from the decoding, indicated by `<|?` or `<||?` the `Decoded` type will allow failure only if the key is missing and not if the type is a mismatch.
- Loading branch information
Tony DiPasquale
committed
Mar 13, 2015
1 parent
3c65ba2
commit 9a2f1b6
Showing
24 changed files
with
192 additions
and
74 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
import Box | ||
|
||
public enum Decoded<T> { | ||
case Success(Box<T>) | ||
case TypeMismatch(String) | ||
case MissingKey(String) | ||
|
||
public var value: T? { | ||
switch self { | ||
case let .Success(box): return box.value | ||
default: return .None | ||
} | ||
} | ||
|
||
public static func optional<A>(p: Decoded<A>) -> Decoded<A?> { | ||
switch p { | ||
case let .Success(box): return .Success(Box(.Some(box.value))) | ||
case let .MissingKey(string): return .Success(Box(.None)) | ||
case let .TypeMismatch(string): return .TypeMismatch(string) | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
public func decode<T: JSONDecodable where T == T.DecodedType>(object: AnyObject) -> T? { | ||
return decode(object).value | ||
} | ||
|
||
public func decode<T: JSONDecodable where T == T.DecodedType>(object: AnyObject) -> [T]? { | ||
return decode(object).value | ||
} | ||
|
||
public func decode<T: JSONDecodable where T == T.DecodedType>(object: AnyObject) -> Decoded<T> { | ||
return T.decode(JSON.parse(object)) | ||
} | ||
|
||
public func decode<T: JSONDecodable where T == T.DecodedType>(object: AnyObject) -> Decoded<[T]> { | ||
return decodeArray(JSON.parse(object)) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,7 +1,7 @@ | ||
import Runes | ||
|
||
func flatReduce<S: SequenceType, U>(sequence: S, initial: U, combine: (U, S.Generator.Element) -> U?) -> U? { | ||
return reduce(sequence, initial) { accum, x in | ||
func flatReduce<S: SequenceType, U>(sequence: S, initial: U, combine: (U, S.Generator.Element) -> Decoded<U>) -> Decoded<U> { | ||
return reduce(sequence, pure(initial)) { accum, x in | ||
accum >>- { combine($0, x) } | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,7 +1,13 @@ | ||
import Runes | ||
|
||
func sequence<T>(xs: [T?]) -> [T]? { | ||
return reduce(xs, []) { accum, elem in | ||
func sequence<T>(xs: [Decoded<T>]) -> Decoded<[T]> { | ||
return reduce(xs, pure([])) { accum, elem in | ||
return curry(+) <^> accum <*> (pure <^> elem) | ||
} | ||
} | ||
|
||
func sequence<T>(xs: [String: Decoded<T>]) -> Decoded<[String: T]> { | ||
return reduce(xs, pure([:])) { accum, elem in | ||
return curry(+) <^> accum <*> ({ [elem.0: $0] } <^> elem.1) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
import Runes | ||
import Box | ||
|
||
public func >>-<A, B>(a: Decoded<A>, f: A -> Decoded<B>) -> Decoded<B> { | ||
switch a { | ||
case let .Success(box): return f(box.value) | ||
case let .MissingKey(string): return .MissingKey(string) | ||
case let .TypeMismatch(string): return .TypeMismatch(string) | ||
} | ||
} | ||
|
||
public func <^><A, B>(f: A -> B, a: Decoded<A>) -> Decoded<B> { | ||
switch a { | ||
case let .Success(box): return .Success(Box(f(box.value))) | ||
case let .MissingKey(string): return .MissingKey(string) | ||
case let .TypeMismatch(string): return .TypeMismatch(string) | ||
} | ||
} | ||
|
||
public func <*><A, B>(f: Decoded<A -> B>, a: Decoded<A>) -> Decoded<B> { | ||
switch f { | ||
case let .Success(box): return box.value <^> a | ||
case let .MissingKey(string): return .MissingKey(string) | ||
case let .TypeMismatch(string): return .TypeMismatch(string) | ||
} | ||
} | ||
|
||
public func pure<A>(a: A) -> Decoded<A> { | ||
return .Success(Box(a)) | ||
} |
Oops, something went wrong.