Unverified Commit d8fe071c authored by Joseph Noir's avatar Joseph Noir Committed by GitHub

Merge pull request #987

Resurrect serialized_size function
parents 37c1c9de c05c1e0e
...@@ -74,6 +74,7 @@ set(LIBCAF_CORE_SRCS ...@@ -74,6 +74,7 @@ set(LIBCAF_CORE_SRCS
src/detail/pretty_type_name.cpp src/detail/pretty_type_name.cpp
src/detail/private_thread.cpp src/detail/private_thread.cpp
src/detail/ripemd_160.cpp src/detail/ripemd_160.cpp
src/detail/serialized_size.cpp
src/detail/set_thread_name.cpp src/detail/set_thread_name.cpp
src/detail/shared_spinlock.cpp src/detail/shared_spinlock.cpp
src/detail/simple_actor_clock.cpp src/detail/simple_actor_clock.cpp
......
...@@ -106,15 +106,6 @@ public: ...@@ -106,15 +106,6 @@ public:
/// @copydoc apply /// @copydoc apply
virtual result_type apply(long double&) = 0; virtual result_type apply(long double&) = 0;
/// @copydoc apply
virtual result_type apply(timespan x) = 0;
/// @copydoc apply
virtual result_type apply(timestamp x) = 0;
/// @copydoc apply
virtual result_type apply(atom_value x) = 0;
/// @copydoc apply /// @copydoc apply
virtual result_type apply(std::string&) = 0; virtual result_type apply(std::string&) = 0;
...@@ -133,7 +124,7 @@ public: ...@@ -133,7 +124,7 @@ public:
/// Reads a byte sequence from the input. /// Reads a byte sequence from the input.
/// @param x The byte sequence. /// @param x The byte sequence.
/// @returns A non-zero error code on failure, `sec::success` otherwise. /// @returns A non-zero error code on failure, `sec::success` otherwise.
virtual result_type apply_raw(span<byte> x) = 0; virtual result_type apply(span<byte> x) = 0;
/// Adds each boolean in `xs` to the output. Derived classes can override this /// Adds each boolean in `xs` to the output. Derived classes can override this
/// member function to pack the booleans, for example to avoid using one byte /// member function to pack the booleans, for example to avoid using one byte
......
/******************************************************************************
* ____ _ _____ *
* / ___| / \ | ___| C++ *
* | | / _ \ | |_ Actor *
* | |___ / ___ \| _| Framework *
* \____/_/ \_|_| *
* *
* Copyright 2011-2019 Dominik Charousset *
* *
* Distributed under the terms and conditions of the BSD 3-Clause License or *
* (at your option) under the terms and conditions of the Boost Software *
* License 1.0. See accompanying files LICENSE and LICENSE_ALTERNATIVE. *
* *
* If you did not receive a copy of the license files, see *
* http://opensource.org/licenses/BSD-3-Clause and *
* http://www.boost.org/LICENSE_1_0.txt. *
******************************************************************************/
#pragma once
#include "caf/error.hpp"
#include "caf/serializer.hpp"
namespace caf::detail {
class serialized_size_inspector final : public serializer {
public:
using super = serializer;
using super::super;
size_t result() const noexcept {
return result_;
}
result_type begin_object(uint16_t typenr, string_view type_name) override;
result_type end_object() override;
result_type begin_sequence(size_t num) override;
result_type end_sequence() override;
result_type apply(bool x) override;
result_type apply(int8_t x) override;
result_type apply(uint8_t x) override;
result_type apply(int16_t x) override;
result_type apply(uint16_t x) override;
result_type apply(int32_t x) override;
result_type apply(uint32_t x) override;
result_type apply(int64_t x) override;
result_type apply(uint64_t x) override;
result_type apply(float x) override;
result_type apply(double x) override;
result_type apply(long double x) override;
result_type apply(string_view x) override;
result_type apply(const std::u16string& x) override;
result_type apply(const std::u32string& x) override;
result_type apply(span<const byte> x) override;
result_type apply(const std::vector<bool>& xs) override;
private:
size_t result_ = 0;
};
template <class T>
size_t serialized_size(actor_system& sys, const T& x) {
serialized_size_inspector f{sys};
auto err = f(x);
static_cast<void>(err);
return f.result();
}
} // namespace caf::detail
...@@ -84,12 +84,12 @@ private: ...@@ -84,12 +84,12 @@ private:
if constexpr (std::is_empty<T>::value if constexpr (std::is_empty<T>::value
|| is_allowed_unsafe_message_type_v<T>) { || is_allowed_unsafe_message_type_v<T>) {
// skip element // skip element
} else if constexpr (detail::can_apply_v<Subtype, decltype(x)>) {
CAF_READ_INSPECTOR_TRY(dref.apply(x))
} else if constexpr (std::is_integral<T>::value) { } else if constexpr (std::is_integral<T>::value) {
using squashed_type = detail::squashed_int_t<T>; using squashed_type = detail::squashed_int_t<T>;
auto squashed_x = static_cast<squashed_type>(x); auto squashed_x = static_cast<squashed_type>(x);
CAF_READ_INSPECTOR_TRY(dref.apply(squashed_x)) CAF_READ_INSPECTOR_TRY(dref.apply(squashed_x))
} else if constexpr (detail::can_apply_v<Subtype, decltype(x)>) {
CAF_READ_INSPECTOR_TRY(dref.apply(x))
} else if constexpr (std::is_array<T>::value) { } else if constexpr (std::is_array<T>::value) {
std::make_index_sequence<std::extent<T>::value> seq; std::make_index_sequence<std::extent<T>::value> seq;
CAF_READ_INSPECTOR_TRY(apply_array(dref, x, seq)) CAF_READ_INSPECTOR_TRY(apply_array(dref, x, seq))
......
...@@ -113,15 +113,6 @@ public: ...@@ -113,15 +113,6 @@ public:
/// @copydoc apply /// @copydoc apply
virtual result_type apply(long double x) = 0; virtual result_type apply(long double x) = 0;
/// @copydoc apply
virtual result_type apply(timespan x) = 0;
/// @copydoc apply
virtual result_type apply(timestamp x) = 0;
/// @copydoc apply
virtual result_type apply(atom_value x) = 0;
/// @copydoc apply /// @copydoc apply
virtual result_type apply(string_view x) = 0; virtual result_type apply(string_view x) = 0;
......
...@@ -92,12 +92,12 @@ private: ...@@ -92,12 +92,12 @@ private:
if constexpr (std::is_empty<T>::value if constexpr (std::is_empty<T>::value
|| is_allowed_unsafe_message_type_v<T>) { || is_allowed_unsafe_message_type_v<T>) {
// skip element // skip element
} else if constexpr (detail::can_apply_v<Subtype, decltype(x)>) {
CAF_WRITE_INSPECTOR_TRY(dref.apply(x))
} else if constexpr (std::is_integral<T>::value) { } else if constexpr (std::is_integral<T>::value) {
using squashed_type = detail::squashed_int_t<T>; using squashed_type = detail::squashed_int_t<T>;
auto& squashed_x = reinterpret_cast<squashed_type&>(x); auto& squashed_x = reinterpret_cast<squashed_type&>(x);
CAF_WRITE_INSPECTOR_TRY(dref.apply(squashed_x)) CAF_WRITE_INSPECTOR_TRY(dref.apply(squashed_x))
} else if constexpr (detail::can_apply_v<Subtype, decltype(x)>) {
CAF_WRITE_INSPECTOR_TRY(dref.apply(x))
} else if constexpr (std::is_array<T>::value) { } else if constexpr (std::is_array<T>::value) {
std::make_index_sequence<std::extent<T>::value> seq; std::make_index_sequence<std::extent<T>::value> seq;
CAF_WRITE_INSPECTOR_TRY(apply_array(dref, x, seq)) CAF_WRITE_INSPECTOR_TRY(apply_array(dref, x, seq))
......
/******************************************************************************
* ____ _ _____ *
* / ___| / \ | ___| C++ *
* | | / _ \ | |_ Actor *
* | |___ / ___ \| _| Framework *
* \____/_/ \_|_| *
* *
* Copyright 2011-2019 Dominik Charousset *
* *
* Distributed under the terms and conditions of the BSD 3-Clause License or *
* (at your option) under the terms and conditions of the Boost Software *
* License 1.0. See accompanying files LICENSE and LICENSE_ALTERNATIVE. *
* *
* If you did not receive a copy of the license files, see *
* http://opensource.org/licenses/BSD-3-Clause and *
* http://www.boost.org/LICENSE_1_0.txt. *
******************************************************************************/
#include "caf/detail/serialized_size.hpp"
#include <iomanip>
#include <sstream>
#include "caf/error.hpp"
#include "caf/string_view.hpp"
namespace caf::detail {
error serialized_size_inspector::begin_object(uint16_t nr, string_view name) {
if (nr != 0)
return apply(nr);
apply(nr);
return apply(name);
}
error serialized_size_inspector::end_object() {
return none;
}
error serialized_size_inspector::begin_sequence(size_t list_size) {
// Use varbyte encoding to compress sequence size on the wire.
// For 64-bit values, the encoded representation cannot get larger than 10
// bytes. A scratch space of 16 bytes suffices as upper bound.
uint8_t buf[16];
auto i = buf;
auto x = static_cast<uint32_t>(list_size);
while (x > 0x7f) {
*i++ = (static_cast<uint8_t>(x) & 0x7f) | 0x80;
x >>= 7;
}
*i++ = static_cast<uint8_t>(x) & 0x7f;
result_ += static_cast<size_t>(i - buf);
return none;
}
error serialized_size_inspector::end_sequence() {
return none;
}
error serialized_size_inspector::apply(bool) {
result_ += sizeof(uint8_t);
return none;
}
error serialized_size_inspector::apply(int8_t x) {
result_ += sizeof(x);
return none;
}
error serialized_size_inspector::apply(uint8_t x) {
result_ += sizeof(x);
return none;
}
error serialized_size_inspector::apply(int16_t x) {
result_ += sizeof(x);
return none;
}
error serialized_size_inspector::apply(uint16_t x) {
result_ += sizeof(x);
return none;
}
error serialized_size_inspector::apply(int32_t x) {
result_ += sizeof(x);
return none;
}
error serialized_size_inspector::apply(uint32_t x) {
result_ += sizeof(x);
return none;
}
error serialized_size_inspector::apply(int64_t x) {
result_ += sizeof(x);
return none;
}
error serialized_size_inspector::apply(uint64_t x) {
result_ += sizeof(x);
return none;
}
error serialized_size_inspector::apply(float x) {
result_ += sizeof(x);
return none;
}
error serialized_size_inspector::apply(double x) {
result_ += sizeof(x);
return none;
}
error serialized_size_inspector::apply(long double x) {
// The IEEE-754 conversion does not work for long double
// => fall back to string serialization (event though it sucks).
std::ostringstream oss;
oss << std::setprecision(std::numeric_limits<long double>::digits) << x;
auto tmp = oss.str();
return apply(tmp);
}
error serialized_size_inspector::apply(string_view x) {
begin_sequence(x.size());
result_ += x.size();
return end_sequence();
}
error serialized_size_inspector::apply(const std::u16string& x) {
begin_sequence(x.size());
result_ += x.size() * sizeof(uint16_t);
return end_sequence();
}
error serialized_size_inspector::apply(const std::u32string& x) {
begin_sequence(x.size());
result_ += x.size() * sizeof(uint32_t);
return end_sequence();
}
error serialized_size_inspector::apply(span<const byte> x) {
result_ += x.size();
return none;
}
error serialized_size_inspector::apply(const std::vector<bool>& xs) {
begin_sequence(xs.size());
result_ += (xs.size() + static_cast<size_t>(xs.size() % 8 != 0)) / 8;
return end_sequence();
}
} // namespace caf::detail
/******************************************************************************
* ____ _ _____ *
* / ___| / \ | ___| C++ *
* | | / _ \ | |_ Actor *
* | |___ / ___ \| _| Framework *
* \____/_/ \_|_| *
* *
* Copyright 2011-2019 Dominik Charousset *
* *
* Distributed under the terms and conditions of the BSD 3-Clause License or *
* (at your option) under the terms and conditions of the Boost Software *
* License 1.0. See accompanying files LICENSE and LICENSE_ALTERNATIVE. *
* *
* If you did not receive a copy of the license files, see *
* http://opensource.org/licenses/BSD-3-Clause and *
* http://www.boost.org/LICENSE_1_0.txt. *
******************************************************************************/
#define CAF_SUITE detail.serialized_size
#include "caf/detail/serialized_size.hpp"
#include "caf/test/dsl.hpp"
#include <vector>
#include "caf/binary_serializer.hpp"
#include "caf/byte.hpp"
#include "caf/byte_buffer.hpp"
using namespace caf;
using caf::detail::serialized_size;
namespace {
struct fixture : test_coordinator_fixture<> {
template <class... Ts>
size_t actual_size(const Ts&... xs) {
byte_buffer buf;
binary_serializer sink{sys, buf};
if (auto err = sink(xs...))
CAF_FAIL("failed to serialize data: " << sys.render(err));
return buf.size();
}
};
} // namespace
#define CHECK_SAME_SIZE(...) \
CAF_CHECK_EQUAL(serialized_size(sys, __VA_ARGS__), actual_size(__VA_ARGS__))
CAF_TEST_FIXTURE_SCOPE(serialized_size_tests, fixture)
CAF_TEST(numbers) {
CHECK_SAME_SIZE(int8_t{42});
CHECK_SAME_SIZE(int16_t{42});
CHECK_SAME_SIZE(int32_t{42});
CHECK_SAME_SIZE(int64_t{42});
CHECK_SAME_SIZE(uint8_t{42});
CHECK_SAME_SIZE(uint16_t{42});
CHECK_SAME_SIZE(uint32_t{42});
CHECK_SAME_SIZE(uint64_t{42});
CHECK_SAME_SIZE(4.2f);
CHECK_SAME_SIZE(4.2);
}
CAF_TEST(containers) {
CHECK_SAME_SIZE(std::string{"foobar"});
CHECK_SAME_SIZE(std::vector<char>({'a', 'b', 'c'}));
CHECK_SAME_SIZE(std::vector<std::string>({"hello", "world"}));
}
CAF_TEST(messages) {
CHECK_SAME_SIZE(make_message(42));
CHECK_SAME_SIZE(make_message(1, 2, 3));
CHECK_SAME_SIZE(make_message("hello", "world"));
}
CAF_TEST_FIXTURE_SCOPE_END()
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