Bitcoin Core Fuzz Coverage Report

Coverage Report

Created: 2026-05-28 15:05

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/Users/brunogarcia/projects/bitcoin-core-dev/src/util/expected.h
Line
Count
Source
1
// Copyright (c) The Bitcoin Core developers
2
// Distributed under the MIT software license, see the accompanying
3
// file COPYING or https://opensource.org/license/mit.
4
5
#ifndef BITCOIN_UTIL_EXPECTED_H
6
#define BITCOIN_UTIL_EXPECTED_H
7
8
#include <attributes.h>
9
#include <util/check.h>
10
11
#include <exception>
12
#include <utility>
13
#include <variant>
14
15
namespace util {
16
17
/// The util::Unexpected class represents an unexpected value stored in
18
/// util::Expected.
19
template <class E>
20
class Unexpected
21
{
22
public:
23
0
    constexpr explicit Unexpected(E e) : m_error(std::move(e)) {}
Unexecuted instantiation: util::Unexpected<ThreadPool::SubmitError>::Unexpected(ThreadPool::SubmitError)
Unexecuted instantiation: util::Unexpected<char const*>::Unexpected(char const*)
Unexecuted instantiation: util::Unexpected<node::ReadRawError>::Unexpected(node::ReadRawError)
24
25
    constexpr const E& error() const& noexcept LIFETIMEBOUND { return m_error; }
26
    constexpr E& error() & noexcept LIFETIMEBOUND { return m_error; }
27
0
    constexpr E&& error() && noexcept LIFETIMEBOUND { return std::move(m_error); }
Unexecuted instantiation: util::Unexpected<ThreadPool::SubmitError>::error() &&
Unexecuted instantiation: util::Unexpected<char const*>::error() &&
Unexecuted instantiation: util::Unexpected<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char>>>::error() &&
Unexecuted instantiation: util::Unexpected<node::ReadRawError>::error() &&
28
29
private:
30
    E m_error;
31
};
32
33
struct BadExpectedAccess : std::exception {
34
0
    const char* what() const noexcept override { return "Bad util::Expected access"; }
35
};
36
37
/// The util::Expected class provides a standard way for low-level functions to
38
/// return either error values or result values.
39
///
40
/// It provides a smaller version of std::expected from C++23. Missing features
41
/// can be added, if needed.
42
template <class T, class E>
43
class Expected
44
{
45
private:
46
    std::variant<T, E> m_data;
47
48
public:
49
    constexpr Expected() : m_data{std::in_place_index<0>, T{}} {}
50
0
    constexpr Expected(T v) : m_data{std::in_place_index<0>, std::move(v)} {}
Unexecuted instantiation: util::Expected<std::__1::future<void>, ThreadPool::SubmitError>::Expected(std::__1::future<void>)
Unexecuted instantiation: util::Expected<TxoSpender, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char>>>::Expected(TxoSpender)
Unexecuted instantiation: util::Expected<std::__1::optional<TxoSpender>, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char>>>::Expected(std::__1::optional<TxoSpender>)
Unexecuted instantiation: util::Expected<std::__1::vector<std::byte, std::__1::allocator<std::byte>>, node::ReadRawError>::Expected(std::__1::vector<std::byte, std::__1::allocator<std::byte>>)
51
    template <class Err>
52
0
    constexpr Expected(Unexpected<Err> u) : m_data{std::in_place_index<1>, std::move(u).error()}
53
0
    {
54
0
    }
Unexecuted instantiation: util::Expected<std::__1::future<void>, ThreadPool::SubmitError>::Expected<ThreadPool::SubmitError>(util::Unexpected<ThreadPool::SubmitError>)
Unexecuted instantiation: util::Expected<TxoSpender, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char>>>::Expected<char const*>(util::Unexpected<char const*>)
Unexecuted instantiation: util::Expected<std::__1::optional<TxoSpender>, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char>>>::Expected<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char>>>(util::Unexpected<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char>>>)
Unexecuted instantiation: util::Expected<std::__1::vector<std::byte, std::__1::allocator<std::byte>>, node::ReadRawError>::Expected<node::ReadRawError>(util::Unexpected<node::ReadRawError>)
55
56
0
    constexpr bool has_value() const noexcept { return m_data.index() == 0; }
Unexecuted instantiation: util::Expected<std::__1::future<void>, ThreadPool::SubmitError>::has_value() const
Unexecuted instantiation: util::Expected<TxoSpender, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char>>>::has_value() const
Unexecuted instantiation: util::Expected<std::__1::vector<std::byte, std::__1::allocator<std::byte>>, node::ReadRawError>::has_value() const
Unexecuted instantiation: util::Expected<std::__1::optional<TxoSpender>, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char>>>::has_value() const
57
0
    constexpr explicit operator bool() const noexcept { return has_value(); }
Unexecuted instantiation: util::Expected<std::__1::future<void>, ThreadPool::SubmitError>::operator bool() const
Unexecuted instantiation: util::Expected<TxoSpender, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char>>>::operator bool() const
Unexecuted instantiation: util::Expected<std::__1::vector<std::byte, std::__1::allocator<std::byte>>, node::ReadRawError>::operator bool() const
Unexecuted instantiation: util::Expected<std::__1::optional<TxoSpender>, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char>>>::operator bool() const
58
59
    constexpr const T& value() const& LIFETIMEBOUND
60
0
    {
61
0
        if (!has_value()) {
62
0
            throw BadExpectedAccess{};
63
0
        }
64
0
        return std::get<0>(m_data);
65
0
    }
Unexecuted instantiation: util::Expected<TxoSpender, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char>>>::value() const &
Unexecuted instantiation: util::Expected<std::__1::vector<std::byte, std::__1::allocator<std::byte>>, node::ReadRawError>::value() const &
Unexecuted instantiation: util::Expected<std::__1::optional<TxoSpender>, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char>>>::value() const &
66
    constexpr T& value() & LIFETIMEBOUND
67
0
    {
68
0
        if (!has_value()) {
69
0
            throw BadExpectedAccess{};
70
0
        }
71
0
        return std::get<0>(m_data);
72
0
    }
Unexecuted instantiation: util::Expected<std::__1::future<void>, ThreadPool::SubmitError>::value() &
Unexecuted instantiation: util::Expected<std::__1::vector<std::byte, std::__1::allocator<std::byte>>, node::ReadRawError>::value() &
73
    constexpr T&& value() && LIFETIMEBOUND { return std::move(value()); }
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
    T value_or(U&& default_value) &&
82
    {
83
        return has_value() ? std::move(value()) : std::forward<U>(default_value);
84
    }
85
86
0
    constexpr const E& error() const& noexcept LIFETIMEBOUND { return *Assert(std::get_if<1>(&m_data)); }
Line
Count
Source
116
0
#define Assert(val) inline_assertion_check<true>(val, std::source_location::current(), #val)
    constexpr const E& error() const& noexcept LIFETIMEBOUND { return *Assert(std::get_if<1>(&m_data)); }
Line
Count
Source
116
0
#define Assert(val) inline_assertion_check<true>(val, std::source_location::current(), #val)
    constexpr const E& error() const& noexcept LIFETIMEBOUND { return *Assert(std::get_if<1>(&m_data)); }
Line
Count
Source
116
0
#define Assert(val) inline_assertion_check<true>(val, std::source_location::current(), #val)
Unexecuted instantiation: util::Expected<TxoSpender, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char>>>::error() const &
Unexecuted instantiation: util::Expected<std::__1::vector<std::byte, std::__1::allocator<std::byte>>, node::ReadRawError>::error() const &
Unexecuted instantiation: util::Expected<std::__1::optional<TxoSpender>, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char>>>::error() const &
87
0
    constexpr E& error() & noexcept LIFETIMEBOUND { return *Assert(std::get_if<1>(&m_data)); }
Line
Count
Source
116
0
#define Assert(val) inline_assertion_check<true>(val, std::source_location::current(), #val)
88
    constexpr E&& error() && noexcept LIFETIMEBOUND { return std::move(error()); }
89
90
    constexpr void swap(Expected& other) noexcept { m_data.swap(other.m_data); }
91
92
0
    constexpr T& operator*() & noexcept LIFETIMEBOUND { return value(); }
93
0
    constexpr const T& operator*() const& noexcept LIFETIMEBOUND { return value(); }
Unexecuted instantiation: util::Expected<TxoSpender, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char>>>::operator*() const &
Unexecuted instantiation: util::Expected<std::__1::vector<std::byte, std::__1::allocator<std::byte>>, node::ReadRawError>::operator*() const &
94
0
    constexpr T&& operator*() && noexcept LIFETIMEBOUND { return std::move(value()); }
95
96
    constexpr T* operator->() noexcept LIFETIMEBOUND { return &value(); }
97
0
    constexpr const T* operator->() const noexcept LIFETIMEBOUND { return &value(); }
98
};
99
100
template <class E>
101
class Expected<void, E>
102
{
103
private:
104
    std::variant<std::monostate, E> m_data;
105
106
public:
107
0
    constexpr Expected() : m_data{std::in_place_index<0>, std::monostate{}} {}
108
    template <class Err>
109
0
    constexpr Expected(Unexpected<Err> u) : m_data{std::in_place_index<1>, std::move(u).error()}
110
0
    {
111
0
    }
112
113
0
    constexpr bool has_value() const noexcept { return m_data.index() == 0; }
114
0
    constexpr explicit operator bool() const noexcept { return has_value(); }
115
116
    constexpr void operator*() const noexcept { return value(); }
117
    constexpr void value() const
118
    {
119
        if (!has_value()) {
120
            throw BadExpectedAccess{};
121
        }
122
    }
123
124
0
    constexpr const E& error() const& noexcept LIFETIMEBOUND { return *Assert(std::get_if<1>(&m_data)); }
Line
Count
Source
116
0
#define Assert(val) inline_assertion_check<true>(val, std::source_location::current(), #val)
125
    constexpr E& error() & noexcept LIFETIMEBOUND { return *Assert(std::get_if<1>(&m_data)); }
126
    constexpr E&& error() && noexcept LIFETIMEBOUND { return std::move(error()); }
127
};
128
129
} // namespace util
130
131
#endif // BITCOIN_UTIL_EXPECTED_H