LCOV - code coverage report
Current view: top level - src/util - result.h (source / functions) Coverage Total Hit
Test: fuzz_coverage.info Lines: 95.5 % 22 21
Test Date: 2024-12-04 04:00:22 Functions: 57.7 % 26 15
Branches: 47.8 % 186 89

             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   [ #  #  #  # ]:      388571 : 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                 :             :     //! Disallow copy constructor, require Result to be moved for efficiency.
      43                 :             :     Result(const Result&) = delete;
      44                 :             : 
      45                 :             :     //! Disallow operator= to avoid confusion in the future when the Result
      46                 :             :     //! class gains support for richer error reporting, and callers should have
      47                 :             :     //! ability to set a new result value without clearing existing error
      48                 :             :     //! messages.
      49                 :             :     Result& operator=(const Result&) = delete;
      50                 :             :     Result& operator=(Result&&) = delete;
      51                 :             : 
      52                 :             :     template <typename FT>
      53                 :             :     friend bilingual_str ErrorString(const Result<FT>& result);
      54                 :             : 
      55                 :             : public:
      56         [ +  - ]:       48549 :     Result() : m_variant{std::in_place_index_t<1>{}, std::monostate{}} {}  // constructor for void
      57         [ -  + ]:     1824961 :     Result(T obj) : m_variant{std::in_place_index_t<1>{}, std::move(obj)} {}
      58                 :      194663 :     Result(Error error) : m_variant{std::in_place_index_t<0>{}, std::move(error.message)} {}
      59                 :     1097408 :     Result(Result&&) = default;
      60   [ -  -  -  -  :     3155393 :     ~Result() = default;
          -  -  +  -  +  
           - ][ +  -  #  
          #  #  #  #  #  
           #  # ][ +  -  
             +  +  +  + ]
      61                 :             : 
      62                 :             :     //! std::optional methods, so functions returning optional<T> can change to
      63                 :             :     //! return Result<T> with minimal changes to existing code, and vice versa.
      64   [ +  -  -  + ]:     1593420 :     bool has_value() const noexcept { return m_variant.index() == 1; }
                 [ +  + ]
      65         [ -  + ]:        4286 :     const T& value() const LIFETIMEBOUND
      66                 :             :     {
      67         [ -  + ]:        4286 :         assert(has_value());
      68                 :        4286 :         return std::get<1>(m_variant);
      69                 :             :     }
      70         [ -  + ]:     3199812 :     T& value() LIFETIMEBOUND
      71                 :             :     {
      72         [ -  + ]:     3199812 :         assert(has_value());
      73                 :     3199812 :         return std::get<1>(m_variant);
      74                 :             :     }
      75                 :             :     template <class U>
      76                 :             :     T value_or(U&& default_value) const&
      77                 :             :     {
      78                 :             :         return has_value() ? value() : std::forward<U>(default_value);
      79                 :             :     }
      80                 :             :     template <class U>
      81         [ +  - ]:      313762 :     T value_or(U&& default_value) &&
      82                 :             :     {
      83         [ +  - ]:      313762 :         return has_value() ? std::move(value()) : std::forward<U>(default_value);
      84                 :             :     }
      85 [ +  + ][ +  +  :     3450200 :     explicit operator bool() const noexcept { return has_value(); }
          +  +  +  +  -  
          +  +  +  +  +  
          -  +  -  +  -  
             +  +  +  +  
           + ][ -  -  -  
          -  -  -  -  +  
          -  +  +  +  +  
           +  -  + ][ -  
          +  -  +  -  +  
          +  +  #  #  #  
             #  #  #  #  
           # ][ -  -  +  
          +  +  +  +  +  
             +  +  -  - ]
           [ +  +  +  +  
          +  +  -  +  -  
          +  +  +  -  +  
          +  +  -  +  +  
          +  +  +  +  +  
             +  +  +  + ]
           [ #  #  #  # ]
           [ #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
             #  #  #  # ]
      86                 :             :     const T* operator->() const LIFETIMEBOUND { return &value(); }
      87                 :           0 :     const T& operator*() const LIFETIMEBOUND { return value(); }
      88                 :      471052 :     T* operator->() LIFETIMEBOUND { return &value(); }
      89                 :     2412997 :     T& operator*() LIFETIMEBOUND { return value(); }
      90                 :             : };
      91                 :             : 
      92                 :             : template <typename T>
      93         [ +  + ]:      155450 : bilingual_str ErrorString(const Result<T>& result)
      94                 :             : {
      95   [ +  +  -  + ]:      155450 :     return result ? bilingual_str{} : std::get<0>(result.m_variant);
      96                 :       44085 : }
      97                 :             : } // namespace util
      98                 :             : 
      99                 :             : #endif // BITCOIN_UTIL_RESULT_H
        

Generated by: LCOV version 2.0-1