Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow easy printing ranges of objects #4488

Merged
merged 1 commit into from
Mar 13, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
34 changes: 33 additions & 1 deletion nano/core_test/object_stream.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -556,4 +556,36 @@ TEST (object_stream, to_json)
)");

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);
}
3 changes: 1 addition & 2 deletions nano/lib/object_stream.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -281,7 +281,7 @@ class array_stream : private object_stream_base

array_stream (array_stream const &) = delete; // Disallow copying

private:
public:
template <class Value>
void write_single (Value const & value)
{
Expand All @@ -290,7 +290,6 @@ class array_stream : private object_stream_base
ctx.end_array_element ();
}

public:
// Handle `.write (container)`
template <class Container>
void write (Container const & container)
Expand Down
49 changes: 36 additions & 13 deletions nano/lib/object_stream_adapters.hpp
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
#pragma once

#include <nano/lib/object_stream.hpp>
#include <nano/lib/utility.hpp>

#include <ostream>
#include <sstream>
Expand All @@ -9,42 +10,64 @@

namespace nano
{
template <class Streamable>
template <class Streamable, class Writer>
struct object_stream_formatter
{
nano::object_stream_config const & config;
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 },
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 };
obs.write (self.value);
self.writer (self.value, obs);
return os;
}

// 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>
auto streamed (Streamable const & value)
enum class streamed_format
{
basic,
json
};

inline nano::object_stream_config const & to_object_stream_config (streamed_format format)
{
return object_stream_formatter{ value, nano::object_stream_config::default_config () };
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>
auto streamed_as_json (Streamable const & value)
auto streamed (Streamable const & value, streamed_format format = streamed_format::basic)
{
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, nano::object_stream_config::json_config () };
return object_stream_formatter{ value, [] (auto const & value, nano::root_object_stream & obs) { obs.write_range (value); }, to_object_stream_config (format) };
}

/**
Expand Down Expand Up @@ -109,7 +132,7 @@ template <nano::object_or_array_streamable Value>
std::string to_json (Value const & value)
{
std::stringstream ss;
ss << nano::streamed_as_json (value);
ss << nano::streamed (value, nano::streamed_format::json);
return ss.str ();
}
}
Expand Down
Loading