LCOV - code coverage report
Current view: top level - src/util - result.h (source / functions) Hit Total Coverage
Test: fuzz_coverage.info Lines: 3 19 15.8 %
Date: 2023-10-05 12:38:51 Functions: 5 116 4.3 %
Branches: 0 20 0.0 %

           Branch data     Line data    Source code
       1                 :            : // Copyright (c) 2022 The Bitcoin Core developers
       2                 :            : // Distributed under the MIT software license, see the accompanying
       3                 :            : // file COPYING or https://www.opensource.org/licenses/mit-license.php.
       4                 :            : 
       5                 :            : #ifndef BITCOIN_UTIL_RESULT_H
       6                 :            : #define BITCOIN_UTIL_RESULT_H
       7                 :            : 
       8                 :            : #include <attributes.h>
       9                 :            : #include <util/translation.h>
      10                 :            : 
      11                 :            : #include <variant>
      12                 :            : 
      13                 :            : namespace util {
      14                 :            : 
      15                 :            : struct Error {
      16                 :            :     bilingual_str message;
      17                 :            : };
      18                 :            : 
      19                 :            : //! The util::Result class provides a standard way for functions to return
      20                 :            : //! either error messages or result values.
      21                 :            : //!
      22                 :            : //! It is intended for high-level functions that need to report error strings to
      23                 :            : //! end users. Lower-level functions that don't need this error-reporting and
      24                 :            : //! only need error-handling should avoid util::Result and instead use standard
      25                 :            : //! classes like std::optional, std::variant, and std::tuple, or custom structs
      26                 :            : //! and enum types to return function results.
      27                 :            : //!
      28                 :            : //! Usage examples can be found in \example ../test/result_tests.cpp, but in
      29                 :            : //! general code returning `util::Result<T>` values is very similar to code
      30                 :            : //! returning `std::optional<T>` values. Existing functions returning
      31                 :            : //! `std::optional<T>` can be updated to return `util::Result<T>` and return
      32                 :            : //! error strings usually just replacing `return std::nullopt;` with `return
      33                 :            : //! util::Error{error_string};`.
      34                 :            : template <class M>
      35                 :            : class Result
      36                 :            : {
      37                 :            : private:
      38                 :            :     using T = std::conditional_t<std::is_same_v<M, void>, std::monostate, M>;
      39                 :            : 
      40                 :            :     std::variant<bilingual_str, T> m_variant;
      41                 :            : 
      42                 :            :     template <typename FT>
      43                 :            :     friend bilingual_str ErrorString(const Result<FT>& result);
      44                 :            : 
      45                 :            : public:
      46                 :          5 :     Result() : m_variant{std::in_place_index_t<1>{}, std::monostate{}} {}  // constructor for void
      47                 :          0 :     Result(T obj) : m_variant{std::in_place_index_t<1>{}, std::move(obj)} {}
      48                 :          0 :     Result(Error error) : m_variant{std::in_place_index_t<0>{}, std::move(error.message)} {}
      49                 :            : 
      50                 :            :     //! std::optional methods, so functions returning optional<T> can change to
      51                 :            :     //! return Result<T> with minimal changes to existing code, and vice versa.
      52                 :          5 :     bool has_value() const noexcept { return m_variant.index() == 1; }
      53                 :          0 :     const T& value() const LIFETIMEBOUND
      54                 :            :     {
      55         [ #  # ]:          0 :         assert(has_value());
      56                 :          0 :         return std::get<1>(m_variant);
      57                 :            :     }
      58                 :          0 :     T& value() LIFETIMEBOUND
      59                 :            :     {
      60   [ #  #  #  #  :          0 :         assert(has_value());
             #  #  #  # ]
      61                 :          0 :         return std::get<1>(m_variant);
      62                 :            :     }
      63                 :            :     template <class U>
      64                 :            :     T value_or(U&& default_value) const&
      65                 :            :     {
      66                 :            :         return has_value() ? value() : std::forward<U>(default_value);
      67                 :            :     }
      68                 :            :     template <class U>
      69                 :          0 :     T value_or(U&& default_value) &&
      70                 :            :     {
      71         [ #  # ]:          0 :         return has_value() ? std::move(value()) : std::forward<U>(default_value);
      72                 :            :     }
      73                 :          5 :     explicit operator bool() const noexcept { return has_value(); }
      74                 :          0 :     const T* operator->() const LIFETIMEBOUND { return &value(); }
      75                 :          0 :     const T& operator*() const LIFETIMEBOUND { return value(); }
      76                 :          0 :     T* operator->() LIFETIMEBOUND { return &value(); }
      77                 :          0 :     T& operator*() LIFETIMEBOUND { return value(); }
      78                 :            : };
      79                 :            : 
      80                 :            : template <typename T>
      81                 :          0 : bilingual_str ErrorString(const Result<T>& result)
      82                 :            : {
      83   [ #  #  #  #  :          0 :     return result ? bilingual_str{} : std::get<0>(result.m_variant);
             #  #  #  # ]
      84                 :            : }
      85                 :            : } // namespace util
      86                 :            : 
      87                 :            : #endif // BITCOIN_UTIL_RESULT_H

Generated by: LCOV version 1.14