Bitcoin Core Fuzz Coverage Report

Coverage Report

Created: 2026-03-24 13:57

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