Commit 0d97fcde authored by Dominik Charousset's avatar Dominik Charousset

Restore deep_to_string output for several cases

parent 34237d75
...@@ -20,19 +20,13 @@ ...@@ -20,19 +20,13 @@
#include <cstddef> #include <cstddef>
#include <string> #include <string>
#include <tuple>
#include <type_traits>
#include <utility>
#include <vector> #include <vector>
#include "caf/byte.hpp" #include "caf/byte.hpp"
#include "caf/byte_buffer.hpp" #include "caf/byte_buffer.hpp"
#include "caf/detail/core_export.hpp" #include "caf/detail/core_export.hpp"
#include "caf/detail/squashed_int.hpp"
#include "caf/error_code.hpp"
#include "caf/fwd.hpp" #include "caf/fwd.hpp"
#include "caf/save_inspector.hpp" #include "caf/save_inspector.hpp"
#include "caf/sec.hpp"
#include "caf/span.hpp" #include "caf/span.hpp"
namespace caf { namespace caf {
...@@ -135,6 +129,8 @@ public: ...@@ -135,6 +129,8 @@ public:
bool value(byte x); bool value(byte x);
bool value(bool x);
bool value(int8_t x); bool value(int8_t x);
bool value(uint8_t x); bool value(uint8_t x);
......
...@@ -30,12 +30,20 @@ namespace caf { ...@@ -30,12 +30,20 @@ namespace caf {
/// `to_string` for user-defined types via argument-dependent /// `to_string` for user-defined types via argument-dependent
/// loopkup (ADL). Any user-defined type that does not /// loopkup (ADL). Any user-defined type that does not
/// provide a `to_string` is mapped to `<unprintable>`. /// provide a `to_string` is mapped to `<unprintable>`.
template <class... Ts> template <class T>
std::string deep_to_string(const Ts&... xs) { std::string deep_to_string(const T& x) {
using inspector_type = detail::stringification_inspector;
auto access_token = guess_inspector_access_type<inspector_type, T>();
using access_type = decltype(access_token);
std::string result; std::string result;
detail::stringification_inspector f{result}; detail::stringification_inspector f{result};
auto inspect_result = (inspect_object(f, xs) && ...); if constexpr (std::is_same<access_type,
static_cast<void>(inspect_result); // Always true. inspector_access_type::inspect>::value) {
auto inspect_result = inspect(f, detail::as_mutable_ref(x));
static_cast<void>(inspect_result); // Always true.
} else {
detail::save_value(f, detail::as_mutable_ref(x), access_token);
}
return result; return result;
} }
......
...@@ -71,7 +71,8 @@ bool load(deserializer& source, void* ptr) { ...@@ -71,7 +71,8 @@ bool load(deserializer& source, void* ptr) {
template <class T> template <class T>
void stringify(std::string& buf, const void* ptr) { void stringify(std::string& buf, const void* ptr) {
stringification_inspector f{buf}; stringification_inspector f{buf};
auto unused = inspect_object(f, *static_cast<const T*>(ptr)); auto unused
= inspect_object(f, detail::as_mutable_ref(*static_cast<const T*>(ptr)));
static_cast<void>(unused); static_cast<void>(unused);
} }
......
...@@ -30,9 +30,7 @@ public: ...@@ -30,9 +30,7 @@ public:
using super::super; using super::super;
size_t result() const noexcept { size_t result = 0;
return result_;
}
bool begin_object(string_view) override; bool begin_object(string_view) override;
...@@ -91,25 +89,22 @@ public: ...@@ -91,25 +89,22 @@ public:
bool value(span<const byte> x) override; bool value(span<const byte> x) override;
bool value(const std::vector<bool>& xs) override; bool value(const std::vector<bool>& xs) override;
private:
size_t result_ = 0;
}; };
template <class T> template <class T>
size_t serialized_size(const T& x) { size_t serialized_size(const T& x) {
serialized_size_inspector f; serialized_size_inspector f;
auto inspection_res = inspect_object(f, x); auto inspection_res = inspect_object(f, detail::as_mutable_ref(x));
static_cast<void>(inspection_res); // Always true. static_cast<void>(inspection_res); // Always true.
return f.result(); return f.result;
} }
template <class T> template <class T>
size_t serialized_size(actor_system& sys, const T& x) { size_t serialized_size(actor_system& sys, const T& x) {
serialized_size_inspector f{sys}; serialized_size_inspector f{sys};
auto inspection_res = inspect_object(f, x); auto inspection_res = inspect_object(f, detail::as_mutable_ref(x));
static_cast<void>(inspection_res); // Always true. static_cast<void>(inspection_res); // Always true.
return f.result(); return f.result;
} }
} // namespace caf::detail } // namespace caf::detail
...@@ -21,6 +21,7 @@ ...@@ -21,6 +21,7 @@
#include <chrono> #include <chrono>
#include <string> #include <string>
#include <type_traits> #include <type_traits>
#include <vector>
#include "caf/detail/core_export.hpp" #include "caf/detail/core_export.hpp"
#include "caf/fwd.hpp" #include "caf/fwd.hpp"
...@@ -90,12 +91,18 @@ public: ...@@ -90,12 +91,18 @@ public:
bool value(long double x); bool value(long double x);
bool value(timespan x);
bool value(timestamp x);
bool value(string_view x); bool value(string_view x);
bool value(const std::u16string& x); bool value(const std::u16string& x);
bool value(const std::u32string& x); bool value(const std::u32string& x);
bool value(const std::vector<bool>& xs);
template <class T> template <class T>
std::enable_if_t<has_to_string<T>::value, bool> value(const T& x) { std::enable_if_t<has_to_string<T>::value, bool> value(const T& x) {
auto str = to_string(x); auto str = to_string(x);
...@@ -103,6 +110,18 @@ public: ...@@ -103,6 +110,18 @@ public:
return true; return true;
} }
template <class T>
bool value(const T* x) {
sep();
if (!x) {
result_ += "null";
} else {
result_ += '*';
inspect_value(*this, detail::as_mutable_ref(*x));
}
return true;
}
template <class T> template <class T>
void append(T&& str) { void append(T&& str) {
sep(); sep();
...@@ -110,12 +129,19 @@ public: ...@@ -110,12 +129,19 @@ public:
} }
template <class T> template <class T>
bool opaque_value(const T&) { bool opaque_value(const T& val) {
result_ += "<unprintable>"; sep();
if constexpr (detail::is_iterable<T>::value) {
result_ += '[';
for (auto&& x : val)
inspect_value(*this, detail::as_mutable_ref(x));
result_ += ']';
} else {
result_ += "<unprintable>";
}
return true; return true;
} }
// -- DSL entry point -------------------------------------------------------- // -- DSL entry point --------------------------------------------------------
template <class Object> template <class Object>
......
...@@ -225,15 +225,15 @@ bool save_value(Inspector& f, T (&xs)[N], inspector_access_type::array) { ...@@ -225,15 +225,15 @@ bool save_value(Inspector& f, T (&xs)[N], inspector_access_type::array) {
if (!f.begin_tuple(N)) if (!f.begin_tuple(N))
return false; return false;
for (size_t index = 0; index < N; ++index) for (size_t index = 0; index < N; ++index)
if (!inspect_value(f, xs[index])) if (!inspect_value(f, as_mutable_ref(xs[index])))
return false; return false;
return f.end_tuple(); return f.end_tuple();
} }
template <class Inspector, class T, size_t... Ns> template <class Inspector, class T, size_t... Ns>
bool save_tuple(Inspector& f, T& xs, std::index_sequence<Ns...>) { bool save_tuple(Inspector& f, T& xs, std::index_sequence<Ns...>) {
return f.begin_tuple(sizeof...(Ns)) // return f.begin_tuple(sizeof...(Ns)) //
&& (inspect_value(f, get<Ns>(xs)) && ...) // && (inspect_value(f, detail::as_mutable_ref(get<Ns>(xs))) && ...) //
&& f.end_tuple(); && f.end_tuple();
} }
...@@ -248,9 +248,9 @@ bool save_value(Inspector& f, T& x, inspector_access_type::map) { ...@@ -248,9 +248,9 @@ bool save_value(Inspector& f, T& x, inspector_access_type::map) {
auto size = x.size(); auto size = x.size();
if (!f.begin_sequence(size)) if (!f.begin_sequence(size))
return false; return false;
for (auto& kvp : x) { for (auto&& kvp : x) {
if (!(f.begin_tuple(2) && inspect_value(f, as_mutable_ref(kvp.first)) if (!(f.begin_tuple(2) && inspect_value(f, as_mutable_ref(kvp.first))
&& inspect_value(f, kvp.second) && f.end_tuple())) && inspect_value(f, as_mutable_ref(kvp.second)) && f.end_tuple()))
return false; return false;
} }
return f.end_sequence(); return f.end_sequence();
...@@ -262,7 +262,7 @@ bool save_value(Inspector& f, T& x, inspector_access_type::list) { ...@@ -262,7 +262,7 @@ bool save_value(Inspector& f, T& x, inspector_access_type::list) {
if (!f.begin_sequence(size)) if (!f.begin_sequence(size))
return false; return false;
for (auto&& val : x) for (auto&& val : x)
if (!inspect_value(f, val)) if (!inspect_value(f, detail::as_mutable_ref(val)))
return false; return false;
return f.end_sequence(); return f.end_sequence();
} }
...@@ -295,15 +295,10 @@ constexpr auto inspector_access_tag_v ...@@ -295,15 +295,10 @@ constexpr auto inspector_access_tag_v
/// `inspector_access<T>::apply_value(f, x)` otherwise. /// `inspector_access<T>::apply_value(f, x)` otherwise.
template <class Inspector, class T> template <class Inspector, class T>
bool inspect_value(Inspector& f, T& x) { bool inspect_value(Inspector& f, T& x) {
static_assert(!std::is_const<T>::value);
return inspector_access<T>::apply_value(f, x); return inspector_access<T>::apply_value(f, x);
} }
/// @copydoc inspect_value
template <class Inspector, class T>
bool inspect_value(Inspector& f, const T& x) {
return inspector_access<T>::apply_value(f, const_cast<T&>(x));
}
template <class Inspector, class Get, class Set> template <class Inspector, class Get, class Set>
bool inspect_value(Inspector& f, Get&& get, Set&& set) { bool inspect_value(Inspector& f, Get&& get, Set&& set) {
using value_type = std::decay_t<decltype(get())>; using value_type = std::decay_t<decltype(get())>;
...@@ -334,8 +329,8 @@ struct inspector_access_base { ...@@ -334,8 +329,8 @@ struct inspector_access_base {
IsPresent& is_present, Get& get) { IsPresent& is_present, Get& get) {
if (is_present()) { if (is_present()) {
auto&& x = get(); auto&& x = get();
return f.begin_field(field_name, true) // return f.begin_field(field_name, true) //
&& inspect_value(f, x) // && inspect_value(f, detail::as_mutable_ref(x)) //
&& f.end_field(); && f.end_field();
} }
return f.begin_field(field_name, false) && f.end_field(); return f.begin_field(field_name, false) && f.end_field();
...@@ -450,6 +445,13 @@ template <class Inspector, class T> ...@@ -450,6 +445,13 @@ template <class Inspector, class T>
return inspector_access<T>::apply_object(f, x); return inspector_access<T>::apply_object(f, x);
} }
/// Inspects `x` using the inspector `f`.
template <class Inspector, class T>
[[nodiscard]] bool inspect_object(Inspector& f, const T& x) {
static_assert(!Inspector::is_loading);
return inspect_object(f, detail::as_mutable_ref(x));
}
/// Inspects all `xs` using the inspector `f`. /// Inspects all `xs` using the inspector `f`.
template <class Inspector, class... Ts> template <class Inspector, class... Ts>
[[nodiscard]] bool inspect_objects(Inspector& f, Ts&... xs) { [[nodiscard]] bool inspect_objects(Inspector& f, Ts&... xs) {
...@@ -580,6 +582,10 @@ struct inspector_access<optional<T>> : optional_inspector_access<optional<T>> { ...@@ -580,6 +582,10 @@ struct inspector_access<optional<T>> : optional_inspector_access<optional<T>> {
template <class... Ts> template <class... Ts>
struct inspector_access<variant<Ts...>> { struct inspector_access<variant<Ts...>> {
static_assert(
(has_type_id<Ts> && ...),
"inspectors requires that each type in a variant has a type_id");
using value_type = variant<Ts...>; using value_type = variant<Ts...>;
static constexpr type_id_t allowed_types_arr[] = {type_id_v<Ts>...}; static constexpr type_id_t allowed_types_arr[] = {type_id_v<Ts>...};
...@@ -609,7 +615,9 @@ struct inspector_access<variant<Ts...>> { ...@@ -609,7 +615,9 @@ struct inspector_access<variant<Ts...>> {
auto allowed_types = make_span(allowed_types_arr); auto allowed_types = make_span(allowed_types_arr);
if (is_present()) { if (is_present()) {
auto&& x = get(); auto&& x = get();
auto g = [&f](auto& y) { return inspect_value(f, y); }; auto g = [&f](auto& y) {
return inspect_value(f, detail::as_mutable_ref(y));
};
return f.begin_field(field_name, true, allowed_types, x.index()) // return f.begin_field(field_name, true, allowed_types, x.index()) //
&& visit(g, x) // && visit(g, x) //
&& f.end_field(); && f.end_field();
...@@ -677,18 +685,24 @@ struct inspector_access<variant<Ts...>> { ...@@ -677,18 +685,24 @@ struct inspector_access<variant<Ts...>> {
if (!f.begin_field(field_name, is_present, allowed_types, type_index)) if (!f.begin_field(field_name, is_present, allowed_types, type_index))
return false; return false;
if (is_present) { if (is_present) {
if (type_index >= allowed_types.size()) if (type_index >= allowed_types.size()) {
return f.load_field_failed(field_name, sec::invalid_field_type); f.emplace_error(sec::invalid_field_type, to_string(field_name));
return false;
}
auto runtime_type = allowed_types[type_index]; auto runtime_type = allowed_types[type_index];
detail::type_list<Ts...> types; detail::type_list<Ts...> types;
if (!load_variant_value(f, field_name, x, runtime_type, types)) if (!load_variant_value(f, field_name, x, runtime_type, types))
return false; return false;
if (!is_valid(x)) if (!is_valid(x)) {
return f.load_field_failed(field_name, f.emplace_error(sec::field_invariant_check_failed,
sec::field_invariant_check_failed); to_string(field_name));
if (!sync_value()) return false;
return f.load_field_failed(field_name, }
sec::field_value_synchronization_failed); if (!sync_value()) {
f.emplace_error(sec::field_value_synchronization_failed,
to_string(field_name));
return false;
}
} else { } else {
set_fallback(); set_fallback();
} }
......
...@@ -71,8 +71,11 @@ constexpr auto guess_inspector_access_type() { ...@@ -71,8 +71,11 @@ constexpr auto guess_inspector_access_type() {
using namespace detail; using namespace detail;
if constexpr (is_inspectable<Inspector, T>::value) { if constexpr (is_inspectable<Inspector, T>::value) {
return inspector_access_type::inspect{}; return inspector_access_type::inspect{};
} else if constexpr (std::is_integral<T>::value) { } else if constexpr (std::is_integral<T>::value
&& !std::is_same<T, bool>::value) {
return inspector_access_type::integral{}; return inspector_access_type::integral{};
} else if constexpr (std::is_array<T>::value) {
return inspector_access_type::array{};
} else if constexpr (is_trivially_inspectable<Inspector, T>::value) { } else if constexpr (is_trivially_inspectable<Inspector, T>::value) {
return inspector_access_type::builtin{}; return inspector_access_type::builtin{};
} else if constexpr (std::is_enum<T>::value) { } else if constexpr (std::is_enum<T>::value) {
...@@ -81,8 +84,6 @@ constexpr auto guess_inspector_access_type() { ...@@ -81,8 +84,6 @@ constexpr auto guess_inspector_access_type() {
return inspector_access_type::empty{}; return inspector_access_type::empty{};
} else if constexpr (is_allowed_unsafe_message_type_v<T>) { } else if constexpr (is_allowed_unsafe_message_type_v<T>) {
return inspector_access_type::unsafe{}; return inspector_access_type::unsafe{};
} else if constexpr (std::is_array<T>::value) {
return inspector_access_type::array{};
} else if constexpr (is_stl_tuple_type_v<T>) { } else if constexpr (is_stl_tuple_type_v<T>) {
return inspector_access_type::tuple{}; return inspector_access_type::tuple{};
} else if constexpr (is_map_like_v<T>) { } else if constexpr (is_map_like_v<T>) {
......
...@@ -271,6 +271,23 @@ public: ...@@ -271,6 +271,23 @@ public:
} }
}; };
template <class T, class Reset, class Set>
struct optional_virt_field_t {
string_view field_name;
Reset reset;
Set set;
template <class Inspector>
bool operator()(Inspector& f) {
auto tmp = T{};
auto sync = [this, &tmp] { return set(std::move(tmp)); };
return inspector_access<T>::load_field(f, field_name, tmp,
detail::always_true, sync, reset);
}
};
// -- DSL type for the object ------------------------------------------------
template <class Inspector, class LoadCallback> template <class Inspector, class LoadCallback>
struct object_with_load_callback_t { struct object_with_load_callback_t {
string_view object_name; string_view object_name;
...@@ -339,6 +356,7 @@ public: ...@@ -339,6 +356,7 @@ public:
template <class T> template <class T>
static auto field(string_view name, T& x) { static auto field(string_view name, T& x) {
static_assert(!std::is_const<T>::value);
return field_t<T>{name, &x}; return field_t<T>{name, &x};
} }
...@@ -348,6 +366,13 @@ public: ...@@ -348,6 +366,13 @@ public:
return virt_field_t<field_type, Set>{name, set}; return virt_field_t<field_type, Set>{name, set};
} }
template <class IsPresent, class Get, class Reset, class Set>
static auto
field(string_view name, IsPresent&&, Get&& get, Reset reset, Set set) {
using field_type = std::decay_t<decltype(get())>;
return optional_virt_field_t<field_type, Reset, Set>{name, reset, set};
}
protected: protected:
error err_; error err_;
}; };
......
...@@ -85,8 +85,16 @@ public: ...@@ -85,8 +85,16 @@ public:
class CAF_CORE_EXPORT node_id_data : public ref_counted { class CAF_CORE_EXPORT node_id_data : public ref_counted {
public: public:
// -- member types -----------------------------------------------------------
using variant_type = variant<uri, hashed_node_id>;
// -- constructors, destructors, and assignment operators -------------------- // -- constructors, destructors, and assignment operators --------------------
explicit node_id_data(variant_type value) : content(std::move(value)) {
// nop
}
explicit node_id_data(uri value) : content(std::move(value)) { explicit node_id_data(uri value) : content(std::move(value)) {
// nop // nop
} }
...@@ -110,15 +118,7 @@ public: ...@@ -110,15 +118,7 @@ public:
// -- member variables ------------------------------------------------------- // -- member variables -------------------------------------------------------
variant<uri, hashed_node_id> content; variant_type content;
// -- friend functions -------------------------------------------------------
template <class Inspector>
friend bool inspect(Inspector& f, node_id_data& x) {
return f.object(x).fields(f.field("content", x.content));
}
}; };
/// A node ID is an opaque value for representing CAF instances in the network. /// A node ID is an opaque value for representing CAF instances in the network.
...@@ -167,7 +167,17 @@ public: ...@@ -167,7 +167,17 @@ public:
template <class Inspector> template <class Inspector>
friend bool inspect(Inspector& f, node_id& x) { friend bool inspect(Inspector& f, node_id& x) {
return f.object(x).fields(f.field("data", x.data_)); auto is_present = [&x] { return x.data_ != nullptr; };
auto get = [&] { return x.data_->content; };
auto reset = [&] { x.data_.reset(); };
auto set = [&](node_id_data::variant_type&& val) {
if (!x.data_ || !x.data_->unique())
x.data_.emplace(std::move(val));
else
x.data_->content = std::move(val);
return true;
};
return f.object(x).fields(f.field("data", is_present, get, reset, set));
} }
// -- private API ------------------------------------------------------------ // -- private API ------------------------------------------------------------
...@@ -196,12 +206,6 @@ private: ...@@ -196,12 +206,6 @@ private:
intrusive_ptr<node_id_data> data_; intrusive_ptr<node_id_data> data_;
}; };
template <>
struct inspector_access<intrusive_ptr<node_id_data>>
: optional_inspector_access<intrusive_ptr<node_id_data>> {
// nop
};
/// Returns whether `x` contains an URI. /// Returns whether `x` contains an URI.
/// @relates node_id /// @relates node_id
inline bool wraps_uri(const node_id& x) noexcept { inline bool wraps_uri(const node_id& x) noexcept {
......
...@@ -166,6 +166,20 @@ public: ...@@ -166,6 +166,20 @@ public:
} }
}; };
template <class T, class IsPresent, class Get>
struct optional_virt_field_t {
string_view field_name;
IsPresent is_present;
Get get;
template <class Inspector>
bool operator()(Inspector& f) {
return inspector_access<T>::save_field(f, field_name, is_present, get);
}
};
// -- DSL type for the object ------------------------------------------------
template <class Inspector, class SaveCallback> template <class Inspector, class SaveCallback>
struct object_with_save_callback_t { struct object_with_save_callback_t {
string_view object_name; string_view object_name;
...@@ -234,7 +248,8 @@ public: ...@@ -234,7 +248,8 @@ public:
template <class T> template <class T>
static auto field(string_view name, T& x) { static auto field(string_view name, T& x) {
return field_t<T>{name, &x}; static_assert(!std::is_const<T>::value);
return field_t<T>{name, std::addressof(x)};
} }
template <class Get, class Set> template <class Get, class Set>
...@@ -243,6 +258,16 @@ public: ...@@ -243,6 +258,16 @@ public:
return virt_field_t<field_type, Get>{name, get}; return virt_field_t<field_type, Get>{name, get};
} }
template <class IsPresent, class Get, class... Ts>
static auto field(string_view name, IsPresent is_present, Get get, Ts&&...) {
using field_type = std::decay_t<decltype(get())>;
return optional_virt_field_t<field_type, IsPresent, Get>{
name,
is_present,
get,
};
}
protected: protected:
error err_; error err_;
}; };
......
...@@ -145,6 +145,10 @@ bool binary_serializer::value(byte x) { ...@@ -145,6 +145,10 @@ bool binary_serializer::value(byte x) {
return ok; return ok;
} }
bool binary_serializer::value(bool x) {
return value(static_cast<uint8_t>(x));
}
bool binary_serializer::value(int8_t x) { bool binary_serializer::value(int8_t x) {
return value(static_cast<byte>(x)); return value(static_cast<byte>(x));
} }
......
...@@ -35,7 +35,7 @@ bool serialized_size_inspector::end_object() { ...@@ -35,7 +35,7 @@ bool serialized_size_inspector::end_object() {
} }
bool serialized_size_inspector::begin_field(string_view, bool) { bool serialized_size_inspector::begin_field(string_view, bool) {
result_ += 1; result += 1;
return true; return true;
} }
...@@ -47,20 +47,20 @@ constexpr size_t max_value = static_cast<size_t>(std::numeric_limits<T>::max()); ...@@ -47,20 +47,20 @@ constexpr size_t max_value = static_cast<size_t>(std::numeric_limits<T>::max());
} // namespace } // namespace
bool serialized_size_inspector::begin_field(string_view) { bool serialized_size_inspector::begin_field(string_view) {
return false; return true;
} }
bool serialized_size_inspector::begin_field(string_view, bool serialized_size_inspector::begin_field(string_view,
span<const type_id_t> types, span<const type_id_t> types,
size_t) { size_t) {
if (types.size() < max_value<int8_t>) { if (types.size() < max_value<int8_t>) {
result_ += sizeof(int8_t); result += sizeof(int8_t);
} else if (types.size() < max_value<int16_t>) { } else if (types.size() < max_value<int16_t>) {
result_ += sizeof(int16_t); result += sizeof(int16_t);
} else if (types.size() < max_value<int32_t>) { } else if (types.size() < max_value<int32_t>) {
result_ += sizeof(int32_t); result += sizeof(int32_t);
} else { } else {
result_ += sizeof(int64_t); result += sizeof(int64_t);
} }
return true; return true;
} }
...@@ -95,7 +95,7 @@ bool serialized_size_inspector::begin_sequence(size_t list_size) { ...@@ -95,7 +95,7 @@ bool serialized_size_inspector::begin_sequence(size_t list_size) {
x >>= 7; x >>= 7;
} }
*i++ = static_cast<uint8_t>(x) & 0x7f; *i++ = static_cast<uint8_t>(x) & 0x7f;
result_ += static_cast<size_t>(i - buf); result += static_cast<size_t>(i - buf);
return true; return true;
} }
...@@ -104,57 +104,57 @@ bool serialized_size_inspector::end_sequence() { ...@@ -104,57 +104,57 @@ bool serialized_size_inspector::end_sequence() {
} }
bool serialized_size_inspector::value(bool) { bool serialized_size_inspector::value(bool) {
result_ += sizeof(uint8_t); result += sizeof(uint8_t);
return true; return true;
} }
bool serialized_size_inspector::value(int8_t x) { bool serialized_size_inspector::value(int8_t x) {
result_ += sizeof(x); result += sizeof(x);
return true; return true;
} }
bool serialized_size_inspector::value(uint8_t x) { bool serialized_size_inspector::value(uint8_t x) {
result_ += sizeof(x); result += sizeof(x);
return true; return true;
} }
bool serialized_size_inspector::value(int16_t x) { bool serialized_size_inspector::value(int16_t x) {
result_ += sizeof(x); result += sizeof(x);
return true; return true;
} }
bool serialized_size_inspector::value(uint16_t x) { bool serialized_size_inspector::value(uint16_t x) {
result_ += sizeof(x); result += sizeof(x);
return true; return true;
} }
bool serialized_size_inspector::value(int32_t x) { bool serialized_size_inspector::value(int32_t x) {
result_ += sizeof(x); result += sizeof(x);
return true; return true;
} }
bool serialized_size_inspector::value(uint32_t x) { bool serialized_size_inspector::value(uint32_t x) {
result_ += sizeof(x); result += sizeof(x);
return true; return true;
} }
bool serialized_size_inspector::value(int64_t x) { bool serialized_size_inspector::value(int64_t x) {
result_ += sizeof(x); result += sizeof(x);
return true; return true;
} }
bool serialized_size_inspector::value(uint64_t x) { bool serialized_size_inspector::value(uint64_t x) {
result_ += sizeof(x); result += sizeof(x);
return true; return true;
} }
bool serialized_size_inspector::value(float x) { bool serialized_size_inspector::value(float x) {
result_ += sizeof(x); result += sizeof(x);
return true; return true;
} }
bool serialized_size_inspector::value(double x) { bool serialized_size_inspector::value(double x) {
result_ += sizeof(x); result += sizeof(x);
return true; return true;
} }
...@@ -169,30 +169,30 @@ bool serialized_size_inspector::value(long double x) { ...@@ -169,30 +169,30 @@ bool serialized_size_inspector::value(long double x) {
bool serialized_size_inspector::value(string_view x) { bool serialized_size_inspector::value(string_view x) {
CAF_IGNORE_UNUSED(begin_sequence(x.size())); CAF_IGNORE_UNUSED(begin_sequence(x.size()));
result_ += x.size(); result += x.size();
return end_sequence(); return end_sequence();
} }
bool serialized_size_inspector::value(const std::u16string& x) { bool serialized_size_inspector::value(const std::u16string& x) {
CAF_IGNORE_UNUSED(begin_sequence(x.size())); CAF_IGNORE_UNUSED(begin_sequence(x.size()));
result_ += x.size() * sizeof(uint16_t); result += x.size() * sizeof(uint16_t);
return end_sequence(); return end_sequence();
} }
bool serialized_size_inspector::value(const std::u32string& x) { bool serialized_size_inspector::value(const std::u32string& x) {
CAF_IGNORE_UNUSED(begin_sequence(x.size())); CAF_IGNORE_UNUSED(begin_sequence(x.size()));
result_ += x.size() * sizeof(uint32_t); result += x.size() * sizeof(uint32_t);
return end_sequence(); return end_sequence();
} }
bool serialized_size_inspector::value(span<const byte> x) { bool serialized_size_inspector::value(span<const byte> x) {
result_ += x.size(); result += x.size();
return true; return true;
} }
bool serialized_size_inspector::value(const std::vector<bool>& xs) { bool serialized_size_inspector::value(const std::vector<bool>& xs) {
CAF_IGNORE_UNUSED(begin_sequence(xs.size())); CAF_IGNORE_UNUSED(begin_sequence(xs.size()));
result_ += (xs.size() + static_cast<size_t>(xs.size() % 8 != 0)) / 8; result += (xs.size() + static_cast<size_t>(xs.size() % 8 != 0)) / 8;
return end_sequence(); return end_sequence();
} }
......
...@@ -50,7 +50,7 @@ namespace caf::detail { ...@@ -50,7 +50,7 @@ namespace caf::detail {
bool stringification_inspector::begin_object(string_view name) { bool stringification_inspector::begin_object(string_view name) {
sep(); sep();
result_.insert(result_.end(), name.begin(), name.end()); result_.insert(result_.end(), name.begin(), name.end());
result_ += ')'; result_ += '(';
return ok; return ok;
} }
...@@ -68,6 +68,7 @@ bool stringification_inspector::begin_field(string_view, bool is_present) { ...@@ -68,6 +68,7 @@ bool stringification_inspector::begin_field(string_view, bool is_present) {
sep(); sep();
result_ += "null"; result_ += "null";
} }
result_ += '*';
return ok; return ok;
} }
...@@ -82,6 +83,7 @@ bool stringification_inspector::begin_field(string_view, bool is_present, ...@@ -82,6 +83,7 @@ bool stringification_inspector::begin_field(string_view, bool is_present,
sep(); sep();
result_ += "null"; result_ += "null";
} }
result_ += '*';
return ok; return ok;
} }
...@@ -115,24 +117,64 @@ bool stringification_inspector::value(bool x) { ...@@ -115,24 +117,64 @@ bool stringification_inspector::value(bool x) {
} }
bool stringification_inspector::value(float x) { bool stringification_inspector::value(float x) {
sep();
auto str = std::to_string(x); auto str = std::to_string(x);
result_ += str; result_ += str;
return true; return true;
} }
bool stringification_inspector::value(double x) { bool stringification_inspector::value(double x) {
sep();
auto str = std::to_string(x); auto str = std::to_string(x);
result_ += str; result_ += str;
return true; return true;
} }
bool stringification_inspector::value(long double x) { bool stringification_inspector::value(long double x) {
sep();
auto str = std::to_string(x); auto str = std::to_string(x);
result_ += str; result_ += str;
return true; return true;
} }
namespace {
template <class Duration>
auto dcast(timespan x) {
return std::chrono::duration_cast<Duration>(x);
}
} // namespace
bool stringification_inspector::value(timespan x) {
namespace sc = std::chrono;
sep();
auto try_print = [this](auto converted, const char* suffix) {
if (converted.count() < 1)
return false;
value(converted.count());
result_ += suffix;
return true;
};
if (try_print(dcast<sc::hours>(x), "h")
|| try_print(dcast<sc::minutes>(x), "min")
|| try_print(dcast<sc::seconds>(x), "s")
|| try_print(dcast<sc::milliseconds>(x), "ms")
|| try_print(dcast<sc::microseconds>(x), "us"))
return true;
value(x.count());
result_ += "ns";
return true;
}
bool stringification_inspector::value(timestamp x) {
sep();
append_timestamp_to_string(result_, x);
return true;
}
bool stringification_inspector::value(string_view str) { bool stringification_inspector::value(string_view str) {
sep();
if (str.empty()) { if (str.empty()) {
result_ += R"("")"; result_ += R"("")";
return true; return true;
...@@ -151,18 +193,21 @@ bool stringification_inspector::value(string_view str) { ...@@ -151,18 +193,21 @@ bool stringification_inspector::value(string_view str) {
} }
bool stringification_inspector::value(const std::u16string&) { bool stringification_inspector::value(const std::u16string&) {
sep();
// Convert to UTF-8 and print? // Convert to UTF-8 and print?
result_ += "<unprintable>"; result_ += "<unprintable>";
return true; return true;
} }
bool stringification_inspector::value(const std::u32string&) { bool stringification_inspector::value(const std::u32string&) {
sep();
// Convert to UTF-8 and print? // Convert to UTF-8 and print?
result_ += "<unprintable>"; result_ += "<unprintable>";
return true; return true;
} }
bool stringification_inspector::int_value(int64_t x) { bool stringification_inspector::int_value(int64_t x) {
sep();
if (x >= 0) if (x >= 0)
return int_value(static_cast<uint64_t>(x)); return int_value(static_cast<uint64_t>(x));
result_ += '-'; result_ += '-';
...@@ -178,6 +223,7 @@ bool stringification_inspector::int_value(int64_t x) { ...@@ -178,6 +223,7 @@ bool stringification_inspector::int_value(int64_t x) {
} }
bool stringification_inspector::int_value(uint64_t x) { bool stringification_inspector::int_value(uint64_t x) {
sep();
auto begin = result_.size(); auto begin = result_.size();
result_ += (x % 10) + '0'; result_ += (x % 10) + '0';
x /= 10; x /= 10;
...@@ -189,12 +235,20 @@ bool stringification_inspector::int_value(uint64_t x) { ...@@ -189,12 +235,20 @@ bool stringification_inspector::int_value(uint64_t x) {
return true; return true;
} }
bool stringification_inspector::value(const std::vector<bool>& xs) {
begin_sequence(xs.size());
for (bool x : xs)
value(x);
return end_sequence();
}
void stringification_inspector::sep() { void stringification_inspector::sep() {
if (!result_.empty()) if (!result_.empty())
switch (result_.back()) { switch (result_.back()) {
case '(': case '(':
case '[': case '[':
case '{': case '{':
case '*':
case ' ': // only at back if we've printed ", " before case ' ': // only at back if we've printed ", " before
break; break;
default: default:
......
...@@ -135,14 +135,16 @@ save_data(Serializer& sink, const message::data_ptr& data) { ...@@ -135,14 +135,16 @@ save_data(Serializer& sink, const message::data_ptr& data) {
&& sink.end_field() // && sink.end_field() //
&& sink.end_object(); && sink.end_object();
} }
// Write type information. GUARDED(sink.begin_object("message"));
auto type_ids = data->types(); auto type_ids = data->types();
GUARDED(sink.begin_object("message") // // Write type information.
&& sink.begin_field("types") // if (!sink.has_human_readable_format()) {
&& sink.begin_sequence(type_ids.size())); GUARDED(sink.begin_field("types") //
for (auto id : type_ids) && sink.begin_sequence(type_ids.size()));
GUARDED(sink.value(id)); for (auto id : type_ids)
GUARDED(sink.end_sequence() && sink.end_field()); GUARDED(sink.value(id));
GUARDED(sink.end_sequence() && sink.end_field());
}
// Write elements. // Write elements.
auto gmos = detail::global_meta_objects(); auto gmos = detail::global_meta_objects();
auto storage = data->storage(); auto storage = data->storage();
......
...@@ -51,14 +51,16 @@ CAF_TEST(erase) { ...@@ -51,14 +51,16 @@ CAF_TEST(erase) {
CAF_TEST(serialization roundtrips go through the registry) { CAF_TEST(serialization roundtrips go through the registry) {
auto hdl = sys.spawn(dummy); auto hdl = sys.spawn(dummy);
CAF_MESSAGE("hdl.id: " << hdl->id());
byte_buffer buf; byte_buffer buf;
binary_serializer sink{sys, buf}; binary_serializer sink{sys, buf};
if (!inspect_object(sink,hdl)) if (!inspect_object(sink, hdl))
CAF_FAIL("serialization failed: " << sink.get_error()); CAF_FAIL("serialization failed: " << sink.get_error());
CAF_MESSAGE("buf: " << buf);
actor hdl2; actor hdl2;
binary_deserializer source{sys, buf}; binary_deserializer source{sys, buf};
if (!inspect_object(source, hdl2)) if (!inspect_object(source, hdl2))
CAF_FAIL("serialization failed: " << source.get_error()); CAF_FAIL("deserialization failed: " << source.get_error());
CAF_CHECK_EQUAL(hdl, hdl2); CAF_CHECK_EQUAL(hdl, hdl2);
anon_send_exit(hdl, exit_reason::user_shutdown); anon_send_exit(hdl, exit_reason::user_shutdown);
} }
......
...@@ -43,6 +43,18 @@ byte operator"" _b(char x) { ...@@ -43,6 +43,18 @@ byte operator"" _b(char x) {
return static_cast<byte>(x); return static_cast<byte>(x);
} }
struct arr {
int8_t xs[3];
int8_t operator[](size_t index) const noexcept {
return xs[index];
}
};
template <class Inspector>
bool inspect(Inspector& f, arr& x) {
return f.object(x).fields(f.field("xs", x.xs));
}
struct fixture { struct fixture {
template <class... Ts> template <class... Ts>
void load(const std::vector<byte>& buf, Ts&... xs) { void load(const std::vector<byte>& buf, Ts&... xs) {
...@@ -135,7 +147,7 @@ CAF_TEST(concatenation) { ...@@ -135,7 +147,7 @@ CAF_TEST(concatenation) {
0x80_b, 0x55_b, 7_b); 0x80_b, 0x55_b, 7_b);
} }
SUBTEST("arrays behave like tuples") { SUBTEST("arrays behave like tuples") {
int8_t xs[] = {0, 0, 0}; arr xs{{0, 0, 0}};
load(byte_buffer({1_b, 2_b, 3_b}), xs); load(byte_buffer({1_b, 2_b, 3_b}), xs);
CAF_CHECK_EQUAL(xs[0], 1); CAF_CHECK_EQUAL(xs[0], 1);
CAF_CHECK_EQUAL(xs[1], 2); CAF_CHECK_EQUAL(xs[1], 2);
...@@ -158,7 +170,7 @@ CAF_TEST(binary serializer picks up inspect functions) { ...@@ -158,7 +170,7 @@ CAF_TEST(binary serializer picks up inspect functions) {
SUBTEST("node ID") { SUBTEST("node ID") {
auto nid = make_node_id(123, "000102030405060708090A0B0C0D0E0F10111213"); auto nid = make_node_id(123, "000102030405060708090A0B0C0D0E0F10111213");
CHECK_LOAD(node_id, unbox(nid), CHECK_LOAD(node_id, unbox(nid),
// Implementation ID: node_id::default_data::class_id (1) // content index for hashed_node_id (1)
1_b, 1_b,
// Process ID. // Process ID.
0_b, 0_b, 0_b, 123_b, 0_b, 0_b, 0_b, 123_b,
......
...@@ -43,12 +43,21 @@ byte operator"" _b(char x) { ...@@ -43,12 +43,21 @@ byte operator"" _b(char x) {
return static_cast<byte>(x); return static_cast<byte>(x);
} }
struct arr {
int8_t xs[3];
};
template <class Inspector>
bool inspect(Inspector& f, arr& x) {
return f.object(x).fields(f.field("xs", x.xs));
}
struct fixture { struct fixture {
template <class... Ts> template <class... Ts>
auto save(const Ts&... xs) { auto save(const Ts&... xs) {
byte_buffer result; byte_buffer result;
binary_serializer sink{nullptr, result}; binary_serializer sink{nullptr, result};
if (!inspect_objects(sink, xs...)) if (!inspect_objects(sink, detail::as_mutable_ref(xs)...))
CAF_FAIL("binary_serializer failed to save: " << sink.get_error()); CAF_FAIL("binary_serializer failed to save: " << sink.get_error());
return result; return result;
} }
...@@ -56,7 +65,7 @@ struct fixture { ...@@ -56,7 +65,7 @@ struct fixture {
template <class... Ts> template <class... Ts>
void save_to_buf(byte_buffer& data, const Ts&... xs) { void save_to_buf(byte_buffer& data, const Ts&... xs) {
binary_serializer sink{nullptr, data}; binary_serializer sink{nullptr, data};
if (!inspect_objects(sink, xs...)) if (!inspect_objects(sink, detail::as_mutable_ref(xs)...))
CAF_FAIL("binary_serializer failed to save: " << sink.get_error()); CAF_FAIL("binary_serializer failed to save: " << sink.get_error());
} }
}; };
...@@ -139,7 +148,7 @@ CAF_TEST(concatenation) { ...@@ -139,7 +148,7 @@ CAF_TEST(concatenation) {
0x80_b, 0x55_b, 7_b); 0x80_b, 0x55_b, 7_b);
} }
SUBTEST("arrays behave like tuples") { SUBTEST("arrays behave like tuples") {
int8_t xs[] = {1, 2, 3}; arr xs{{1, 2, 3}};
CAF_CHECK_EQUAL(save(xs), byte_buffer({1_b, 2_b, 3_b})); CAF_CHECK_EQUAL(save(xs), byte_buffer({1_b, 2_b, 3_b}));
} }
} }
...@@ -159,7 +168,7 @@ CAF_TEST(binary serializer picks up inspect functions) { ...@@ -159,7 +168,7 @@ CAF_TEST(binary serializer picks up inspect functions) {
SUBTEST("node ID") { SUBTEST("node ID") {
auto nid = make_node_id(123, "000102030405060708090A0B0C0D0E0F10111213"); auto nid = make_node_id(123, "000102030405060708090A0B0C0D0E0F10111213");
CHECK_SAVE(node_id, unbox(nid), CHECK_SAVE(node_id, unbox(nid),
// Implementation ID: node_id::default_data::class_id (1) // content index for hashed_node_id (1)
1_b, 1_b,
// Process ID. // Process ID.
0_b, 0_b, 0_b, 123_b, 0_b, 0_b, 0_b, 123_b,
......
...@@ -24,14 +24,6 @@ ...@@ -24,14 +24,6 @@
using namespace caf; using namespace caf;
namespace {
void foobar() {
// nop
}
} // namespace
#define CHECK_DEEP_TO_STRING(val, str) CAF_CHECK_EQUAL(deep_to_string(val), str) #define CHECK_DEEP_TO_STRING(val, str) CAF_CHECK_EQUAL(deep_to_string(val), str)
CAF_TEST(timespans) { CAF_TEST(timespans) {
...@@ -65,7 +57,6 @@ CAF_TEST(boolean lists) { ...@@ -65,7 +57,6 @@ CAF_TEST(boolean lists) {
CAF_TEST(pointers) { CAF_TEST(pointers) {
auto i = 42; auto i = 42;
CHECK_DEEP_TO_STRING(&i, "*42"); CHECK_DEEP_TO_STRING(&i, "*42");
CHECK_DEEP_TO_STRING(foobar, "<fun>");
} }
CAF_TEST(buffers) { CAF_TEST(buffers) {
......
...@@ -39,7 +39,7 @@ struct fixture : test_coordinator_fixture<> { ...@@ -39,7 +39,7 @@ struct fixture : test_coordinator_fixture<> {
size_t actual_size(const Ts&... xs) { size_t actual_size(const Ts&... xs) {
byte_buffer buf; byte_buffer buf;
binary_serializer sink{sys, buf}; binary_serializer sink{sys, buf};
if (inspect_objects(sink, xs...)) if (!inspect_objects(sink, detail::as_mutable_ref(xs)...))
CAF_FAIL("failed to serialize data: " << sink.get_error()); CAF_FAIL("failed to serialize data: " << sink.get_error());
return buf.size(); return buf.size();
} }
......
...@@ -205,21 +205,10 @@ struct binary_serialization_policy { ...@@ -205,21 +205,10 @@ struct binary_serialization_policy {
} }
template <class T> template <class T>
detail::enable_if_t<is_integral_or_enum<T>::value, bool> operator()(T& x) { bool operator()(T& x) {
auto buf = to_buf(x); auto buf = to_buf(x);
binary_deserializer source{&context, buf}; binary_deserializer source{&context, buf};
auto y = static_cast<T>(0); auto y = T{};
if (!inspect_objects(source, y))
CAF_FAIL("failed to deserialize from buffer: " << source.get_error());
CAF_CHECK_EQUAL(x, y);
return detail::safe_equal(x, y);
}
template <class T>
detail::enable_if_t<!is_integral_or_enum<T>::value, bool> operator()(T& x) {
auto buf = to_buf(x);
binary_deserializer source{&context, buf};
T y;
if (!inspect_objects(source, y)) if (!inspect_objects(source, y))
CAF_FAIL("failed to deserialize from buffer: " << source.get_error()); CAF_FAIL("failed to deserialize from buffer: " << source.get_error());
CAF_CHECK_EQUAL(x, y); CAF_CHECK_EQUAL(x, y);
......
...@@ -197,6 +197,11 @@ struct testee : load_inspector { ...@@ -197,6 +197,11 @@ struct testee : load_inspector {
return object_t<testee>{T::tname, this}; return object_t<testee>{T::tname, this};
} }
template <class T>
auto object(optional<T>&) {
return object_t<testee>{"optional", this};
}
bool begin_object(string_view object_name) { bool begin_object(string_view object_name) {
new_line(); new_line();
indent += 2; indent += 2;
...@@ -373,6 +378,16 @@ begin object line ...@@ -373,6 +378,16 @@ begin object line
end object)_"); end object)_");
} }
CAF_TEST(load inspectors support optional) {
optional<int32_t> x;
CAF_CHECK_EQUAL(inspect_object(f, x), true);
CAF_CHECK_EQUAL(f.log, R"_(
begin object optional
begin optional field value
end field
end object)_");
}
CAF_TEST(load inspectors support fields with fallbacks and invariants) { CAF_TEST(load inspectors support fields with fallbacks and invariants) {
duration d{"minutes", 42}; duration d{"minutes", 42};
CAF_CHECK_EQUAL(inspect(f, d), true); CAF_CHECK_EQUAL(inspect(f, d), true);
......
...@@ -294,6 +294,17 @@ struct fixture { ...@@ -294,6 +294,17 @@ struct fixture {
CAF_TEST_FIXTURE_SCOPE(load_inspector_tests, fixture) CAF_TEST_FIXTURE_SCOPE(load_inspector_tests, fixture)
CAF_TEST(save inspectors can visit C arrays) {
int32_t xs[] = {1, 2, 3};
CAF_CHECK_EQUAL(inspect_value(f, xs), true);
CAF_CHECK_EQUAL(f.log, R"_(
begin tuple of size 3
int32_t value
int32_t value
int32_t value
end tuple)_");
}
CAF_TEST(save inspectors can visit simple POD types) { CAF_TEST(save inspectors can visit simple POD types) {
point_3d p{1, 1, 1}; point_3d p{1, 1, 1};
CAF_CHECK_EQUAL(inspect(f, p), true); CAF_CHECK_EQUAL(inspect(f, p), true);
...@@ -389,6 +400,16 @@ end object)_"); ...@@ -389,6 +400,16 @@ end object)_");
} }
} }
CAF_TEST(save inspectors support optional) {
optional<int32_t> x;
CAF_CHECK_EQUAL(inspect_object(f, x), true);
CAF_CHECK_EQUAL(f.log, R"_(
begin object optional
begin optional field value
end field
end object)_");
}
CAF_TEST(save inspectors support fields with optional values) { CAF_TEST(save inspectors support fields with optional values) {
person p1{"Eduard Example", none}; person p1{"Eduard Example", none};
CAF_CHECK_EQUAL(inspect(f, p1), true); CAF_CHECK_EQUAL(inspect(f, p1), true);
...@@ -435,6 +456,7 @@ end object)_"); ...@@ -435,6 +456,7 @@ end object)_");
CAF_TEST(save inspectors support nasty data structures) { CAF_TEST(save inspectors support nasty data structures) {
nasty x; nasty x;
CAF_CHECK(inspect(f, x)); CAF_CHECK(inspect(f, x));
CAF_CHECK_EQUAL(f.get_error(), error{});
CAF_CHECK_EQUAL(f.log, R"_( CAF_CHECK_EQUAL(f.log, R"_(
begin object nasty begin object nasty
begin field field_01 begin field field_01
......
...@@ -139,7 +139,10 @@ struct fixture : test_coordinator_fixture<> { ...@@ -139,7 +139,10 @@ struct fixture : test_coordinator_fixture<> {
T msg_roundtrip(const T& x) { T msg_roundtrip(const T& x) {
message result; message result;
auto tmp = make_message(x); auto tmp = make_message(x);
deserialize(serialize(tmp), result); auto buf = serialize(tmp);
CAF_MESSAGE("serialized " << to_string(msg) << " into " << buf.size()
<< " bytes");
deserialize(buf, result);
if (!result.match_elements<T>()) if (!result.match_elements<T>())
CAF_FAIL("expected: " << x << ", got: " << result); CAF_FAIL("expected: " << x << ", got: " << result);
return result.get_as<T>(0); return result.get_as<T>(0);
......
...@@ -26,8 +26,6 @@ ...@@ -26,8 +26,6 @@
#include "caf/actor_system.hpp" #include "caf/actor_system.hpp"
#include "caf/actor_system_config.hpp" #include "caf/actor_system_config.hpp"
#include "caf/binary_deserializer.hpp"
#include "caf/binary_serializer.hpp"
#include "caf/byte_buffer.hpp" #include "caf/byte_buffer.hpp"
#include "caf/deep_to_string.hpp" #include "caf/deep_to_string.hpp"
#include "caf/none.hpp" #include "caf/none.hpp"
...@@ -79,31 +77,22 @@ macro_repeat20(i_n) ...@@ -79,31 +77,22 @@ macro_repeat20(i_n)
using v20 = variant<i01, i02, i03, i04, i05, i06, i07, i08, i09, i10, using v20 = variant<i01, i02, i03, i04, i05, i06, i07, i08, i09, i10,
i11, i12, i13, i14, i15, i16, i17, i18, i19, i20>; i11, i12, i13, i14, i15, i16, i17, i18, i19, i20>;
#define VARIANT_EQ(x, y) \
do { \
using type = std::decay_t<decltype(y)>; \
CAF_CHECK(holds_alternative<type>(x) && get<type>(x) == y); \
} while (false)
#define v20_test(n) \ #define v20_test(n) \
x3 = i##n{0x##n}; \ x3 = i##n{0x##n}; \
CAF_CHECK_EQUAL(deep_to_string(x3), \ VARIANT_EQ(v20{x3}, i##n{0x##n}); \
CAF_STR(i##n) + "("s + std::to_string(0x##n) + ")"); \
CAF_CHECK_EQUAL(v20{x3}, i##n{0x##n}); \
x4 = x3; \ x4 = x3; \
CAF_CHECK_EQUAL(x4, i##n{0x##n}); \ VARIANT_EQ(x4, i##n{0x##n}); \
CAF_CHECK_EQUAL(v20{std::move(x3)}, i##n{0x##n}); \ VARIANT_EQ(v20{std::move(x3)}, i##n{0x##n}); \
CAF_CHECK_EQUAL(x3, i##n{0}); \ VARIANT_EQ(x3, i##n{0}); \
x3 = std::move(x4); \ x3 = std::move(x4); \
CAF_CHECK_EQUAL(x4, i##n{0}); \ VARIANT_EQ(x4, i##n{0}); \
CAF_CHECK_EQUAL(x3, i##n{0x##n}); VARIANT_EQ(x3, i##n{0x##n});
// { \
// byte_buffer buf; \
// binary_serializer sink{sys.dummy_execution_unit(), buf}; \
// if (!inspect_object(sink, x3)) \
// CAF_FAIL("failed to serialize data: " << sink.get_error()); \
// CAF_CHECK_EQUAL(x3, i##n{0x##n}); \
// v20 tmp; \
// binary_deserializer source{sys.dummy_execution_unit(), buf}; \
// if (!inspect_object(source, tmp)) \
// CAF_FAIL("failed to deserialize data: " << source.get_error()); \
// CAF_CHECK_EQUAL(tmp, i##n{0x##n}); \
// CAF_CHECK_EQUAL(tmp, x3); \
// }
// copy construction, copy assign, move construction, move assign // copy construction, copy assign, move construction, move assign
// and finally serialization round-trip // and finally serialization round-trip
...@@ -114,9 +103,9 @@ CAF_TEST(copying_moving_roundtrips) { ...@@ -114,9 +103,9 @@ CAF_TEST(copying_moving_roundtrips) {
variant<none_t> x1; variant<none_t> x1;
CAF_CHECK_EQUAL(x1, none); CAF_CHECK_EQUAL(x1, none);
variant<int, none_t> x2; variant<int, none_t> x2;
CAF_CHECK_EQUAL(x2, 0); VARIANT_EQ(x2, 0);
v20 x3; v20 x3;
CAF_CHECK_EQUAL(x3, i01{0}); VARIANT_EQ(x3, i01{0});
v20 x4; v20 x4;
macro_repeat20(v20_test); macro_repeat20(v20_test);
} }
......
...@@ -81,7 +81,8 @@ constexpr uint64_t spawn_serv_id = basp::header::spawn_server_id; ...@@ -81,7 +81,8 @@ constexpr uint64_t spawn_serv_id = basp::header::spawn_server_id;
constexpr uint64_t config_serv_id = basp::header::config_server_id; constexpr uint64_t config_serv_id = basp::header::config_server_id;
std::string hexstr(const byte_buffer& buf) { std::string hexstr(const byte_buffer& buf) {
return deep_to_string(meta::hex_formatted(), buf); // TODO: re-implement hex-formatted option
return deep_to_string(buf);
} }
struct node { struct node {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment