parcel 0.2.2
Wrappable, wire-transferable C++23 value system with JSON serialization
Loading...
Searching...
No Matches
format.h
Go to the documentation of this file.
1#pragma once
2
20#include <parcel/cell.h>
21
22#include <ostream>
23#include <utility>
24
25namespace parcel {
26
27inline std::ostream& operator<<(std::ostream& os, ICell const& v) {
28 return os << v.to_string();
29}
30
31inline std::ostream& operator<<(std::ostream& os, cell_t const& v) {
32 return os << (v ? v->to_string() : std::string{"<null>"});
33}
34
35} // namespace parcel
36
37#if defined(__cpp_lib_format) && __cpp_lib_format >= 201907L
38
39#include <concepts>
40#include <format>
41
42template <>
43struct std::formatter<parcel::ICell, char> {
44 enum class Mode { Compact, Formatted, JsonCompact, JsonPretty, KindOnly };
45 Mode mode = Mode::Compact;
46
47 constexpr auto parse(const std::format_parse_context& ctx) {
48 // std::format_parse_context::iterator is implementation-defined
49 // NOLINTNEXTLINE(readability-qualified-auto)
50 auto it = ctx.begin();
51 // std::format_parse_context::iterator is implementation-defined
52 // NOLINTNEXTLINE(readability-qualified-auto)
53 const auto end = ctx.end();
54 if (it != end && *it == '#') {
55 mode = Mode::Formatted;
56 ++it;
57 } else if (it != end && *it == 'j') {
58 ++it;
59 if (it != end && *it == '2') {
60 mode = Mode::JsonPretty;
61 ++it;
62 } else {
63 mode = Mode::JsonCompact;
64 }
65 } else if (it != end && *it == 'k') {
66 mode = Mode::KindOnly;
67 ++it;
68 }
69 if (it != end && *it != '}') {
70 throw std::format_error(
71 "parcel::ICell formatter: expected one of '{}', '{:#}', '{:j}', '{:j2}', '{:k}'");
72 }
73 return it;
74 }
75
76 auto format(parcel::ICell const& v, std::format_context& ctx) const {
77 switch (mode) {
78 case Mode::Formatted:
79 return std::format_to(ctx.out(), "{}", v.to_formatted_string());
80 case Mode::JsonCompact:
81 return std::format_to(ctx.out(), "{}", v.to_json().dump());
82 case Mode::JsonPretty:
83 return std::format_to(ctx.out(), "{}", v.to_json().dump(2));
84 case Mode::KindOnly:
85 return std::format_to(ctx.out(), "{}", v.kind());
86 case Mode::Compact:
87 default:
88 return std::format_to(ctx.out(), "{}", v.to_string());
89 }
90 }
91};
92
93template <typename T>
94 requires std::derived_from<T, parcel::ICell> && (!std::same_as<T, parcel::ICell>)
95struct std::formatter<T, char> : std::formatter<parcel::ICell, char> {
96 auto format(T const& v, std::format_context& ctx) const {
97 return std::formatter<parcel::ICell, char>::format(static_cast<parcel::ICell const&>(v),
98 ctx);
99 }
100};
101
102template <>
103struct std::formatter<parcel::cell_t, char> : std::formatter<parcel::ICell, char> {
104 auto format(parcel::cell_t const& v, std::format_context& ctx) const {
105 if (!v) {
106 return std::format_to(ctx.out(), "<null>");
107 }
108 return std::formatter<parcel::ICell, char>::format(*v, ctx);
109 }
110};
111
112#endif // __cpp_lib_format
113
114#if defined(__cpp_lib_print) && __cpp_lib_print >= 202207L
115#include <print>
116
117namespace parcel {
118
123template <class... Args>
124void print(std::format_string<Args...> fmt, Args&&... args) {
125 std::print(fmt, std::forward<Args>(args)...);
126}
127
129template <class... Args>
130void println(std::format_string<Args...> fmt, Args&&... args) {
131 std::println(fmt, std::forward<Args>(args)...);
132}
133
134} // namespace parcel
135#endif
Core ICell interface, cell_t handle, BaseCell CRTP base, and CellLike concept.
std::shared_ptr< ICell > cell_t
Shared handle to any ICell-derived value — the canonical cell pointer.
Definition cell.h:68
Polymorphic root of every parcel cell.
Definition cell.h:84
virtual std::string to_formatted_string() const
Render the cell as a multi-line, indented string.
Definition cell.h:122
virtual std::string to_string() const =0
Render the cell's value as a compact human-readable string.
virtual json_t to_json() const =0
Serialize this cell to its canonical JSON representation.
virtual std::string_view kind() const =0
Wire-stable kind identifier for this cell.