mirror of
https://github.com/bitcoin/bitcoin.git
synced 2026-06-05 02:33:07 +02:00
Add SpanWriter class for zero-allocation stream writing
Co-authored-by: stickies-v <stickies-v@protonmail.com>
This commit is contained in:
@@ -121,6 +121,38 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
/** Minimal stream for writing to an existing span of bytes.
|
||||
*/
|
||||
class SpanWriter
|
||||
{
|
||||
private:
|
||||
std::span<std::byte> m_dest;
|
||||
|
||||
public:
|
||||
explicit SpanWriter(std::span<std::byte> dest) : m_dest{dest} {}
|
||||
template <typename... Args>
|
||||
SpanWriter(std::span<std::byte> dest, Args&&... args) : SpanWriter{dest}
|
||||
{
|
||||
::SerializeMany(*this, std::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
void write(std::span<const std::byte> src)
|
||||
{
|
||||
if (src.size() > m_dest.size()) {
|
||||
throw std::ios_base::failure("SpanWriter::write(): exceeded buffer size");
|
||||
}
|
||||
memcpy(m_dest.data(), src.data(), src.size());
|
||||
m_dest = m_dest.subspan(src.size());
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
SpanWriter& operator<<(const T& obj)
|
||||
{
|
||||
::Serialize(*this, obj);
|
||||
return *this;
|
||||
}
|
||||
};
|
||||
|
||||
/** Double ended buffer combining vector and stream-like interfaces.
|
||||
*
|
||||
* >> and << read and write unformatted data using the above serialization templates.
|
||||
|
||||
@@ -207,6 +207,28 @@ BOOST_AUTO_TEST_CASE(streams_vector_writer)
|
||||
vch.clear();
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(streams_span_writer)
|
||||
{
|
||||
unsigned char a(1);
|
||||
unsigned char b(2);
|
||||
unsigned char bytes[] = {3, 4, 5, 6};
|
||||
std::array<std::byte, 8> arr{};
|
||||
|
||||
// Test operator<<
|
||||
SpanWriter writer{arr};
|
||||
writer << a << b;
|
||||
BOOST_CHECK_EQUAL(HexStr(arr), "0102000000000000");
|
||||
|
||||
// Use variadic constructor and write to subspan.
|
||||
SpanWriter{std::span{arr}.subspan(2), a, bytes, b};
|
||||
BOOST_CHECK_EQUAL(HexStr(arr), "0102010304050602");
|
||||
|
||||
// Writing past the end throws
|
||||
std::array<std::byte, 1> small{};
|
||||
BOOST_CHECK_THROW(SpanWriter(std::span{small}, a, b), std::ios_base::failure);
|
||||
BOOST_CHECK_THROW(SpanWriter(std::span{small}) << a << b, std::ios_base::failure);
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(streams_vector_reader)
|
||||
{
|
||||
std::vector<unsigned char> vch = {1, 255, 3, 4, 5, 6};
|
||||
|
||||
Reference in New Issue
Block a user