Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 4bad1f05 authored by Treehugger Robot's avatar Treehugger Robot Committed by Android (Google) Code Review
Browse files

Merge "FTL: Add FTL_EXPECT" into main

parents 439ddfbd 1f39c3d3
Loading
Loading
Loading
Loading
+30 −0
Original line number Diff line number Diff line
@@ -69,6 +69,36 @@
    exp_.value();                                                         \
  })

// Given an expression `expr` that evaluates to an ftl::Expected<T, E> result (R for short),
// FTL_EXPECT unwraps T out of R, or bails out of the enclosing function F if R has an error E.
// While FTL_TRY bails out with R, FTL_EXPECT bails out with E, which is useful when F does not
// need to propagate R because T is not relevant to the caller.
//
// Example usage:
//
//   using StringExp = ftl::Expected<std::string, std::errc>;
//
//   std::errc repeat(StringExp exp, std::string& out) {
//     const std::string str = FTL_EXPECT(exp);
//     out = str + str;
//     return std::errc::operation_in_progress;
//   }
//
//   std::string str;
//   assert(std::errc::operation_in_progress == repeat(StringExp("ha"s), str));
//   assert("haha"s == str);
//   assert(std::errc::bad_message == repeat(ftl::Unexpected(std::errc::bad_message), str));
//   assert("haha"s == str);
//
#define FTL_EXPECT(expr)              \
  ({                                  \
    auto exp_ = (expr);               \
    if (!exp_.has_value()) {          \
      return std::move(exp_.error()); \
    }                                 \
    exp_.value();                     \
  })

namespace android::ftl {

// Superset of base::expected<T, E> with monadic operations.
+33 −6
Original line number Diff line number Diff line
@@ -79,16 +79,28 @@ TEST(Expected, ValueOpt) {

namespace {

IntExp increment(IntExp exp) {
IntExp increment_try(IntExp exp) {
  const int i = FTL_TRY(exp);
  return IntExp(i + 1);
}

StringExp repeat(StringExp exp) {
std::errc increment_expect(IntExp exp, int& out) {
  const int i = FTL_EXPECT(exp);
  out = i + 1;
  return std::errc::operation_in_progress;
}

StringExp repeat_try(StringExp exp) {
  const std::string str = FTL_TRY(exp);
  return StringExp(str + str);
}

std::errc repeat_expect(StringExp exp, std::string& out) {
  const std::string str = FTL_EXPECT(exp);
  out = str + str;
  return std::errc::operation_in_progress;
}

void uppercase(char& c, ftl::Optional<char> opt) {
  c = std::toupper(FTL_TRY(std::move(opt).ok_or(ftl::Unit())));
}
@@ -97,13 +109,13 @@ void uppercase(char& c, ftl::Optional<char> opt) {

// Keep in sync with example usage in header file.
TEST(Expected, Try) {
  EXPECT_EQ(IntExp(100), increment(IntExp(99)));
  EXPECT_TRUE(repeat(ftl::Unexpected(std::errc::value_too_large)).has_error([](std::errc e) {
  EXPECT_EQ(IntExp(100), increment_try(IntExp(99)));
  EXPECT_TRUE(increment_try(ftl::Unexpected(std::errc::value_too_large)).has_error([](std::errc e) {
    return e == std::errc::value_too_large;
  }));

  EXPECT_EQ(StringExp("haha"s), repeat(StringExp("ha"s)));
  EXPECT_TRUE(repeat(ftl::Unexpected(std::errc::bad_message)).has_error([](std::errc e) {
  EXPECT_EQ(StringExp("haha"s), repeat_try(StringExp("ha"s)));
  EXPECT_TRUE(repeat_try(ftl::Unexpected(std::errc::bad_message)).has_error([](std::errc e) {
    return e == std::errc::bad_message;
  }));

@@ -115,4 +127,19 @@ TEST(Expected, Try) {
  EXPECT_EQ(c, 'A');
}

TEST(Expected, Expect) {
  int i = 0;
  EXPECT_EQ(std::errc::operation_in_progress, increment_expect(IntExp(99), i));
  EXPECT_EQ(100, i);
  EXPECT_EQ(std::errc::value_too_large,
            increment_expect(ftl::Unexpected(std::errc::value_too_large), i));
  EXPECT_EQ(100, i);

  std::string str;
  EXPECT_EQ(std::errc::operation_in_progress, repeat_expect(StringExp("ha"s), str));
  EXPECT_EQ("haha"s, str);
  EXPECT_EQ(std::errc::bad_message, repeat_expect(ftl::Unexpected(std::errc::bad_message), str));
  EXPECT_EQ("haha"s, str);
}

}  // namespace android::test