mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-24 21:31:04 +00:00
Bug 1324829 - Add the mozilla::Result::andThen
method; r=froydnj
This commit is contained in:
parent
f40c749727
commit
a19333ea56
@ -26,6 +26,7 @@ namespace mozilla {
|
||||
struct Ok {};
|
||||
|
||||
template <typename E> class GenericErrorResult;
|
||||
template <typename V, typename E> class Result;
|
||||
|
||||
namespace detail {
|
||||
|
||||
@ -134,6 +135,12 @@ template <typename T> struct HasFreeLSB<T&> {
|
||||
static const bool value = HasFreeLSB<T*>::value;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct IsResult : FalseType { };
|
||||
|
||||
template <typename V, typename E>
|
||||
struct IsResult<Result<V, E>> : TrueType { };
|
||||
|
||||
} // namespace detail
|
||||
|
||||
/**
|
||||
@ -251,6 +258,44 @@ public:
|
||||
using RetResult = Result<decltype(f(*((V*) nullptr))), E>;
|
||||
return isOk() ? RetResult(f(unwrap())) : RetResult(unwrapErr());
|
||||
}
|
||||
|
||||
/**
|
||||
* Given a function V -> Result<W, E>, apply it to this result's success value
|
||||
* and return its result. If this result is an error value, then return a
|
||||
* copy.
|
||||
*
|
||||
* This is sometimes called "flatMap" or ">>=" in other contexts.
|
||||
*
|
||||
* `andThen`ing over success values invokes the function to produce a new
|
||||
* result:
|
||||
*
|
||||
* Result<const char*, Error> res("hello, andThen!");
|
||||
* Result<HtmlFreeString, Error> res2 = res.andThen([](const char* s) {
|
||||
* return containsHtmlTag(s)
|
||||
* ? Result<HtmlFreeString, Error>(Error("Invalid: contains HTML"))
|
||||
* : Result<HtmlFreeString, Error>(HtmlFreeString(s));
|
||||
* }
|
||||
* });
|
||||
* MOZ_ASSERT(res2.isOk());
|
||||
* MOZ_ASSERT(res2.unwrap() == HtmlFreeString("hello, andThen!");
|
||||
*
|
||||
* `andThen`ing over error results does not invoke the function, and just
|
||||
* produces a new copy of the error result:
|
||||
*
|
||||
* Result<int, const char*> res("some error");
|
||||
* auto res2 = res.andThen([](int x) { ... });
|
||||
* MOZ_ASSERT(res2.isErr());
|
||||
* MOZ_ASSERT(res.unwrapErr() == res2.unwrapErr());
|
||||
*/
|
||||
template<
|
||||
typename F,
|
||||
typename = typename EnableIf<
|
||||
detail::IsResult<decltype((*((F*) nullptr))(*((V*) nullptr)))>::value
|
||||
>::Type
|
||||
>
|
||||
auto andThen(F f) const -> decltype(f(*((V*) nullptr))) {
|
||||
return isOk() ? f(unwrap()) : GenericErrorResult<E>(unwrapErr());
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -200,6 +200,27 @@ MapTest()
|
||||
MOZ_RELEASE_ASSERT(res6.unwrap() == 5);
|
||||
}
|
||||
|
||||
static void
|
||||
AndThenTest()
|
||||
{
|
||||
// `andThen`ing over success results.
|
||||
Result<int, const char*> r1(10);
|
||||
Result<int, const char*> r2 = r1.andThen([](int x) {
|
||||
return Result<int, const char*>(x + 1);
|
||||
});
|
||||
MOZ_RELEASE_ASSERT(r2.isOk());
|
||||
MOZ_RELEASE_ASSERT(r2.unwrap() == 11);
|
||||
|
||||
// `andThen`ing over error results.
|
||||
Result<int, const char*> r3("error");
|
||||
Result<int, const char*> r4 = r3.andThen([](int x) {
|
||||
MOZ_RELEASE_ASSERT(false);
|
||||
return Result<int, const char*>(1);
|
||||
});
|
||||
MOZ_RELEASE_ASSERT(r4.isErr());
|
||||
MOZ_RELEASE_ASSERT(r3.unwrapErr() == r4.unwrapErr());
|
||||
}
|
||||
|
||||
/* * */
|
||||
|
||||
int main()
|
||||
@ -209,5 +230,6 @@ int main()
|
||||
EmptyValueTest();
|
||||
ReferenceTest();
|
||||
MapTest();
|
||||
AndThenTest();
|
||||
return 0;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user