LCOV - code coverage report
Current view: top level - src/util - result.h (source / functions) Coverage Total Hit
Test: test_bitcoin_coverage.info Lines: 100.0 % 23 23
Test Date: 2024-11-04 04:45:35 Functions: 70.3 % 37 26
Branches: 43.2 % 354 153

             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   [ -  -  -  - ]:        1586 : 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         [ +  - ]:        3150 :     Result() : m_variant{std::in_place_index_t<1>{}, std::monostate{}} {}  // constructor for void
      57         [ -  + ]:       65148 :     Result(T obj) : m_variant{std::in_place_index_t<1>{}, std::move(obj)} {}
      58                 :         804 :     Result(Error error) : m_variant{std::in_place_index_t<0>{}, std::move(error.message)} {}
      59                 :        6484 :     Result(Result&&) = default;
      60   [ +  -  +  - ]:       75007 :     ~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 [ +  + ][ +  -  :        3446 :     bool has_value() const noexcept { return m_variant.index() == 1; }
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  +  -  +  
           - ][ +  -  +  
                -  +  - ]
      65         [ -  + ]:         178 :     const T& value() const LIFETIMEBOUND
      66                 :             :     {
      67         [ -  + ]:         178 :         assert(has_value());
      68                 :         178 :         return std::get<1>(m_variant);
      69                 :             :     }
      70         [ -  + ]:       71185 :     T& value() LIFETIMEBOUND
      71                 :             :     {
      72         [ -  + ]:       71185 :         assert(has_value());
      73                 :       71185 :         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 [ +  - ][ +  +  :       53167 :     T value_or(U&& default_value) &&
          +  -  -  +  +  
                -  -  + ]
      82                 :             :     {
      83 [ +  - ][ +  +  :       53167 :         return has_value() ? std::move(value()) : std::forward<U>(default_value);
          +  -  -  +  +  
                -  -  + ]
      84                 :             :     }
      85 [ +  + ][ +  +  :       75488 :     explicit operator bool() const noexcept { return has_value(); }
          +  +  +  +  +  
             +  +  -  +  
           - ][ -  +  -  
          -  #  #  #  #  
          #  #  #  #  #  
           #  #  # ][ -  
          -  -  -  -  -  
          -  +  -  +  -  
             +  +  +  -  
           + ][ -  -  +  
          +  +  -  -  +  
          -  +  +  +  -  
          +  +  +  +  +  
          +  +  +  +  -  
             -  +  +  +  
           - ][ +  -  +  
          -  +  -  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
             #  #  #  #  
           # ][ -  -  +  
             -  +  -  +  
           - ][ -  -  +  
          -  +  -  +  -  
          +  -  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
           #  #  # ][ -  
          +  -  +  +  -  
          +  -  +  -  +  
          +  +  -  +  -  
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  +  -  +  
             -  +  +  +  
                      + ]
      86                 :         129 :     const T* operator->() const LIFETIMEBOUND { return &value(); }
      87                 :          33 :     const T& operator*() const LIFETIMEBOUND { return value(); }
      88                 :          27 :     T* operator->() LIFETIMEBOUND { return &value(); }
      89                 :       17994 :     T& operator*() LIFETIMEBOUND { return value(); }
      90                 :             : };
      91                 :             : 
      92                 :             : template <typename T>
      93         [ +  + ]:         204 : bilingual_str ErrorString(const Result<T>& result)
      94                 :             : {
      95   [ +  +  -  + ]:         204 :     return result ? bilingual_str{} : std::get<0>(result.m_variant);
      96                 :         134 : }
      97                 :             : } // namespace util
      98                 :             : 
      99                 :             : #endif // BITCOIN_UTIL_RESULT_H
        

Generated by: LCOV version 2.0-1