Android-cuttlefish cvd tool
Classes | Namespaces | Macros | Typedefs | Functions
result.h File Reference
#include <optional>
#include <ostream>
#include <sstream>
#include <string>
#include <type_traits>
#include <utility>
#include <vector>
#include <android-base/format.h>
#include <android-base/logging.h>
#include <android-base/result.h>
Include dependency graph for result.h:

Go to the source code of this file.

Classes

class  cuttlefish::StackTraceEntry
 
struct  fmt::formatter< cuttlefish::StackTraceEntry >
 
class  cuttlefish::StackTraceError
 
struct  fmt::formatter< cuttlefish::StackTraceError >
 

Namespaces

namespace  fmt
 
namespace  cuttlefish
 

Macros

#define CF_STACK_TRACE_ENTRY(expression)    StackTraceEntry(__FILE__, __LINE__, __PRETTY_FUNCTION__, __func__, expression)
 
#define CF_ERR(MSG)   (CF_STACK_TRACE_ENTRY("") << MSG)
 
#define CF_ERRNO(MSG)   (CF_STACK_TRACE_ENTRY("") << MSG)
 
#define CF_ERRF(MSG, ...)    (CF_STACK_TRACE_ENTRY("") << fmt::format(FMT_STRING(MSG), __VA_ARGS__))
 
#define CF_EXPECT_OVERLOAD(_1, _2, NAME, ...)   NAME
 
#define CF_EXPECT2(RESULT, MSG)
 
#define CF_EXPECT1(RESULT)   CF_EXPECT2(RESULT, "")
 
#define CF_EXPECT(...)    CF_EXPECT_OVERLOAD(__VA_ARGS__, CF_EXPECT2, CF_EXPECT1)(__VA_ARGS__)
 
#define CF_EXPECTF(RESULT, MSG, ...)    CF_EXPECT(RESULT, fmt::format(FMT_STRING(MSG), __VA_ARGS__))
 
#define CF_COMPARE_EXPECT4(COMPARE_OP, LHS_RESULT, RHS_RESULT, MSG)
 
#define CF_COMPARE_EXPECT3(COMPARE_OP, LHS_RESULT, RHS_RESULT)    CF_COMPARE_EXPECT4(COMPARE_OP, LHS_RESULT, RHS_RESULT, "")
 
#define CF_COMPARE_EXPECT_OVERLOAD(_1, _2, _3, _4, NAME, ...)   NAME
 
#define CF_COMPARE_EXPECT(...)
 
#define CF_EXPECT_EQ(LHS_RESULT, RHS_RESULT, ...)    CF_COMPARE_EXPECT(==, LHS_RESULT, RHS_RESULT, ##__VA_ARGS__)
 
#define CF_EXPECT_NE(LHS_RESULT, RHS_RESULT, ...)    CF_COMPARE_EXPECT(!=, LHS_RESULT, RHS_RESULT, ##__VA_ARGS__)
 
#define CF_EXPECT_LE(LHS_RESULT, RHS_RESULT, ...)    CF_COMPARE_EXPECT(<=, LHS_RESULT, RHS_RESULT, ##__VA_ARGS__)
 
#define CF_EXPECT_LT(LHS_RESULT, RHS_RESULT, ...)    CF_COMPARE_EXPECT(<, LHS_RESULT, RHS_RESULT, ##__VA_ARGS__)
 
#define CF_EXPECT_GE(LHS_RESULT, RHS_RESULT, ...)    CF_COMPARE_EXPECT(>=, LHS_RESULT, RHS_RESULT, ##__VA_ARGS__)
 
#define CF_EXPECT_GT(LHS_RESULT, RHS_RESULT, ...)    CF_COMPARE_EXPECT(>, LHS_RESULT, RHS_RESULT, ##__VA_ARGS__)
 

Typedefs

template<typename T >
using cuttlefish::Result = android::base::expected< T, StackTraceError >
 

Functions

template<typename T >
const T & fmt::runtime (const T &param)
 
std::string cuttlefish::ResultErrorFormat (bool color)
 
template<typename T >
cuttlefish::OutcomeDereference (std::optional< T > &&value)
 
template<typename T >
std::conditional_t< std::is_void_v< T >, bool, T > cuttlefish::OutcomeDereference (Result< T > &&result)
 
template<typename T >
std::enable_if< std::is_convertible_v< T, bool >, T >::type cuttlefish::OutcomeDereference (T &&value)
 
bool cuttlefish::TypeIsSuccess (bool value)
 
template<typename T >
bool cuttlefish::TypeIsSuccess (std::optional< T > &value)
 
template<typename T >
bool cuttlefish::TypeIsSuccess (Result< T > &value)
 
template<typename T >
bool cuttlefish::TypeIsSuccess (Result< T > &&value)
 
auto cuttlefish::ErrorFromType (bool)
 
template<typename T >
auto cuttlefish::ErrorFromType (std::optional< T >)
 
template<typename T >
auto cuttlefish::ErrorFromType (Result< T > &value)
 
template<typename T >
auto cuttlefish::ErrorFromType (Result< T > &&value)
 

Macro Definition Documentation

◆ CF_COMPARE_EXPECT

#define CF_COMPARE_EXPECT (   ...)
Value:
(__VA_ARGS__)
#define CF_COMPARE_EXPECT4(COMPARE_OP, LHS_RESULT, RHS_RESULT, MSG)
Definition: result.h:420
#define CF_COMPARE_EXPECT3(COMPARE_OP, LHS_RESULT, RHS_RESULT)
Definition: result.h:440
#define CF_COMPARE_EXPECT_OVERLOAD(_1, _2, _3, _4, NAME,...)
Definition: result.h:443

◆ CF_COMPARE_EXPECT3

#define CF_COMPARE_EXPECT3 (   COMPARE_OP,
  LHS_RESULT,
  RHS_RESULT 
)     CF_COMPARE_EXPECT4(COMPARE_OP, LHS_RESULT, RHS_RESULT, "")

◆ CF_COMPARE_EXPECT4

#define CF_COMPARE_EXPECT4 (   COMPARE_OP,
  LHS_RESULT,
  RHS_RESULT,
  MSG 
)
Value:
({ \
auto&& lhs_macro_intermediate_result = LHS_RESULT; \
auto&& rhs_macro_intermediate_result = RHS_RESULT; \
bool comparison_result = lhs_macro_intermediate_result COMPARE_OP \
rhs_macro_intermediate_result; \
if (!comparison_result) { \
auto current_entry = CF_STACK_TRACE_ENTRY(""); \
current_entry << "Expected \"" << #LHS_RESULT << "\" " << #COMPARE_OP \
<< " \"" << #RHS_RESULT << "\" but was " \
<< lhs_macro_intermediate_result << " vs " \
<< rhs_macro_intermediate_result << ". "; \
current_entry << MSG; \
auto error = ErrorFromType(false); \
error.PushEntry(std::move(current_entry)); \
return std::move(error); \
}; \
comparison_result; \
})
#define CF_STACK_TRACE_ENTRY(expression)
Definition: result.h:134
#define error(format, args...)
Definition: fec_private.h:201
auto ErrorFromType(Result< T > &&value)
Definition: result.h:357

◆ CF_COMPARE_EXPECT_OVERLOAD

#define CF_COMPARE_EXPECT_OVERLOAD (   _1,
  _2,
  _3,
  _4,
  NAME,
  ... 
)    NAME

◆ CF_ERR

#define CF_ERR (   MSG)    (CF_STACK_TRACE_ENTRY("") << MSG)

Error return macro that includes the location in the file in the error message. Use CF_ERRNO when including information from errno, otherwise use the base CF_ERR macro.

Example usage:

if (mkdir(path.c_str()) != 0) {
  return CF_ERRNO("mkdir(\"" << path << "\") failed: "
                  << strerror(errno));
}

This will return an error with the text

mkdir(...) failed: ...
  at path/to/file.cpp:50
  in Result<std::string> MyFunction()

◆ CF_ERRF

#define CF_ERRF (   MSG,
  ... 
)     (CF_STACK_TRACE_ENTRY("") << fmt::format(FMT_STRING(MSG), __VA_ARGS__))

◆ CF_ERRNO

#define CF_ERRNO (   MSG)    (CF_STACK_TRACE_ENTRY("") << MSG)

◆ CF_EXPECT

#define CF_EXPECT (   ...)     CF_EXPECT_OVERLOAD(__VA_ARGS__, CF_EXPECT2, CF_EXPECT1)(__VA_ARGS__)

Error propagation macro that can be used as an expression.

The first argument can be either a Result or a type that is convertible to a boolean. A successful result will return the value inside the result, or a conversion to a true value will return the unconverted value. This is useful for e.g. pointers which can be tested through boolean conversion.

In the failure case, this macro will return from the containing function with a failing Result. The failing result will include information about the call site, details from the optional second argument if given, and details from the failing inner expression if it is a Result.

This macro must be invoked only in functions that return a Result.

Example usage:

Result<std::string> CreateTempDir();

Result<std::string> CreatePopulatedTempDir() {
  std::string dir = CF_EXPECT(CreateTempDir(), "Failed to create dir");
  // Do something with dir
  return dir;
}

If CreateTempDir fails, the function will returna Result with an error message that looks like

 Internal error
   at /path/to/otherfile.cpp:50
   in Result<std::string> CreateTempDir()
 Failed to create dir
   at /path/to/file.cpp:81:
   in Result<std::string> CreatePopulatedTempDir()
   for CF_EXPECT(CreateTempDir())

◆ CF_EXPECT1

#define CF_EXPECT1 (   RESULT)    CF_EXPECT2(RESULT, "")

◆ CF_EXPECT2

#define CF_EXPECT2 (   RESULT,
  MSG 
)
Value:
({ \
decltype(RESULT)&& macro_intermediate_result = RESULT; \
if (!TypeIsSuccess(macro_intermediate_result)) { \
auto current_entry = CF_STACK_TRACE_ENTRY(#RESULT); \
current_entry << MSG; \
auto error = ErrorFromType(macro_intermediate_result); \
error.PushEntry(std::move(current_entry)); \
return std::move(error); \
}; \
OutcomeDereference(std::move(macro_intermediate_result)); \
})
bool TypeIsSuccess(Result< T > &&value)
Definition: result.h:340

◆ CF_EXPECT_EQ

#define CF_EXPECT_EQ (   LHS_RESULT,
  RHS_RESULT,
  ... 
)     CF_COMPARE_EXPECT(==, LHS_RESULT, RHS_RESULT, ##__VA_ARGS__)

◆ CF_EXPECT_GE

#define CF_EXPECT_GE (   LHS_RESULT,
  RHS_RESULT,
  ... 
)     CF_COMPARE_EXPECT(>=, LHS_RESULT, RHS_RESULT, ##__VA_ARGS__)

◆ CF_EXPECT_GT

#define CF_EXPECT_GT (   LHS_RESULT,
  RHS_RESULT,
  ... 
)     CF_COMPARE_EXPECT(>, LHS_RESULT, RHS_RESULT, ##__VA_ARGS__)

◆ CF_EXPECT_LE

#define CF_EXPECT_LE (   LHS_RESULT,
  RHS_RESULT,
  ... 
)     CF_COMPARE_EXPECT(<=, LHS_RESULT, RHS_RESULT, ##__VA_ARGS__)

◆ CF_EXPECT_LT

#define CF_EXPECT_LT (   LHS_RESULT,
  RHS_RESULT,
  ... 
)     CF_COMPARE_EXPECT(<, LHS_RESULT, RHS_RESULT, ##__VA_ARGS__)

◆ CF_EXPECT_NE

#define CF_EXPECT_NE (   LHS_RESULT,
  RHS_RESULT,
  ... 
)     CF_COMPARE_EXPECT(!=, LHS_RESULT, RHS_RESULT, ##__VA_ARGS__)

◆ CF_EXPECT_OVERLOAD

#define CF_EXPECT_OVERLOAD (   _1,
  _2,
  NAME,
  ... 
)    NAME

◆ CF_EXPECTF

#define CF_EXPECTF (   RESULT,
  MSG,
  ... 
)     CF_EXPECT(RESULT, fmt::format(FMT_STRING(MSG), __VA_ARGS__))

◆ CF_STACK_TRACE_ENTRY

#define CF_STACK_TRACE_ENTRY (   expression)     StackTraceEntry(__FILE__, __LINE__, __PRETTY_FUNCTION__, __func__, expression)