Allow easy printing ranges of objects (#4488)

This commit is contained in:
Piotr Wójcik 2024-03-13 09:56:35 +01:00 committed by GitHub
commit 97cc02ce29
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 70 additions and 16 deletions

View file

@ -557,3 +557,35 @@ TEST (object_stream, to_json)
ASSERT_EQ (str, expected); ASSERT_EQ (str, expected);
} }
TEST (object_stream, print_range)
{
std::deque<streamable_object> objects;
objects.push_back ({ 1 });
objects.push_back ({ 2 });
objects.push_back ({ 3 });
std::stringstream ss1, ss2;
ss1 << nano::streamed_range (objects);
ss2 << fmt::format ("{}", nano::streamed_range (objects));
auto expected = trim (R"(
[
{
uint256_union_field: "0000000000000000000000000000000000000000000000000000000000000001",
block_hash: "0000000000000000000000000000000000000000000000000000000000000000"
},
{
uint256_union_field: "0000000000000000000000000000000000000000000000000000000000000002",
block_hash: "0000000000000000000000000000000000000000000000000000000000000000"
},
{
uint256_union_field: "0000000000000000000000000000000000000000000000000000000000000003",
block_hash: "0000000000000000000000000000000000000000000000000000000000000000"
}
]
)");
ASSERT_EQ (ss1.str (), expected);
ASSERT_EQ (ss2.str (), expected);
}

View file

@ -281,7 +281,7 @@ public:
array_stream (array_stream const &) = delete; // Disallow copying array_stream (array_stream const &) = delete; // Disallow copying
private: public:
template <class Value> template <class Value>
void write_single (Value const & value) void write_single (Value const & value)
{ {
@ -290,7 +290,6 @@ private:
ctx.end_array_element (); ctx.end_array_element ();
} }
public:
// Handle `.write (container)` // Handle `.write (container)`
template <class Container> template <class Container>
void write (Container const & container) void write (Container const & container)

View file

@ -1,6 +1,7 @@
#pragma once #pragma once
#include <nano/lib/object_stream.hpp> #include <nano/lib/object_stream.hpp>
#include <nano/lib/utility.hpp>
#include <ostream> #include <ostream>
#include <sstream> #include <sstream>
@ -9,42 +10,64 @@
namespace nano namespace nano
{ {
template <class Streamable> template <class Streamable, class Writer>
struct object_stream_formatter struct object_stream_formatter
{ {
nano::object_stream_config const & config; nano::object_stream_config const & config;
Streamable const & value; Streamable const & value;
Writer writer;
explicit object_stream_formatter (Streamable const & value, nano::object_stream_config const & config) : explicit object_stream_formatter (Streamable const & value, Writer writer, nano::object_stream_config const & config) :
config{ config }, config{ config },
value{ value } value{ value },
writer{ writer }
{ {
} }
friend std::ostream & operator<< (std::ostream & os, object_stream_formatter<Streamable> const & self) friend std::ostream & operator<< (std::ostream & os, object_stream_formatter<Streamable, Writer> const & self)
{ {
nano::root_object_stream obs{ os, self.config }; nano::root_object_stream obs{ os, self.config };
obs.write (self.value); self.writer (self.value, obs);
return os; return os;
} }
// Needed for fmt formatting, uses the ostream operator under the hood // Needed for fmt formatting, uses the ostream operator under the hood
friend auto format_as (object_stream_formatter<Streamable> const & val) friend auto format_as (object_stream_formatter<Streamable, Writer> const & self)
{ {
return fmt::streamed (val); return fmt::streamed (self);
} }
}; };
template <class Streamable> enum class streamed_format
auto streamed (Streamable const & value)
{ {
return object_stream_formatter{ value, nano::object_stream_config::default_config () }; basic,
json
};
inline nano::object_stream_config const & to_object_stream_config (streamed_format format)
{
switch (format)
{
case streamed_format::basic:
return nano::object_stream_config::default_config ();
case streamed_format::json:
return nano::object_stream_config::json_config ();
default:
debug_assert (false);
return nano::object_stream_config::default_config ();
}
} }
template <class Streamable> template <class Streamable>
auto streamed_as_json (Streamable const & value) auto streamed (Streamable const & value, streamed_format format = streamed_format::basic)
{ {
return object_stream_formatter{ value, nano::object_stream_config::json_config () }; return object_stream_formatter{ value, [] (auto const & value, nano::root_object_stream & obs) { obs.write (value); }, to_object_stream_config (format) };
}
template <class StreamableRange>
auto streamed_range (StreamableRange const & value, streamed_format format = streamed_format::basic)
{
return object_stream_formatter{ value, [] (auto const & value, nano::root_object_stream & obs) { obs.write_range (value); }, to_object_stream_config (format) };
} }
/** /**
@ -109,7 +132,7 @@ template <nano::object_or_array_streamable Value>
std::string to_json (Value const & value) std::string to_json (Value const & value)
{ {
std::stringstream ss; std::stringstream ss;
ss << nano::streamed_as_json (value); ss << nano::streamed (value, nano::streamed_format::json);
return ss.str (); return ss.str ();
} }
} }