Commit db299ded authored by Dominik Charousset's avatar Dominik Charousset

Add function to estimate serialized message size

parent c63020f6
......@@ -105,6 +105,7 @@ set(LIBCAF_CORE_SRCS
src/scoped_execution_unit.cpp
src/sec.cpp
src/sequencer.cpp
src/serialized_size.cpp
src/serializer.cpp
src/set_thread_name.cpp
src/settings.cpp
......
/******************************************************************************
* ____ _ _____ *
* / ___| / \ | ___| 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/serializer.hpp"
namespace caf {
namespace detail {
class serialized_size_inspector final : public serializer {
public:
using super = serializer;
using super::super;
size_t result() const noexcept {
return result_;
}
error begin_object(uint16_t& nr, std::string& name) override;
error end_object() override;
error begin_sequence(size_t& list_size) override;
error end_sequence() override;
error apply_raw(size_t num_bytes, void* data) override;
protected:
error apply_impl(int8_t& x) override;
error apply_impl(uint8_t& x) override;
error apply_impl(int16_t& x) override;
error apply_impl(uint16_t& x) override;
error apply_impl(int32_t& x) override;
error apply_impl(uint32_t& x) override;
error apply_impl(int64_t& x) override;
error apply_impl(uint64_t& x) override;
error apply_impl(float& x) override;
error apply_impl(double& x) override;
error apply_impl(long double& x) override;
error apply_impl(std::string& x) override;
error apply_impl(std::u16string& x) override;
error apply_impl(std::u32string& x) override;
private:
size_t result_ = 0;
};
template <class T>
size_t serialized_size(actor_system& sys, const T& x) {
serialized_size_inspector f{sys};
f(const_cast<T&>(x));
return f.result();
}
} // namespace detail
} // namespace caf
/******************************************************************************
* ____ _ _____ *
* / ___| / \ | ___| 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>
namespace caf {
namespace detail {
error serialized_size_inspector::begin_object(uint16_t& nr, std::string& name) {
if (nr != 0)
return apply(nr);
if (auto err = apply(nr))
return err;
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;
apply_raw(static_cast<size_t>(i - buf), buf);
return none;
}
error serialized_size_inspector::end_sequence() {
return none;
}
error serialized_size_inspector::apply_raw(size_t num_bytes, void*) {
result_ += num_bytes;
return none;
}
error serialized_size_inspector::apply_impl(int8_t& x) {
result_ += sizeof(x);
return none;
}
error serialized_size_inspector::apply_impl(uint8_t& x) {
result_ += sizeof(x);
return none;
}
error serialized_size_inspector::apply_impl(int16_t& x) {
result_ += sizeof(x);
return none;
}
error serialized_size_inspector::apply_impl(uint16_t& x) {
result_ += sizeof(x);
return none;
}
error serialized_size_inspector::apply_impl(int32_t& x) {
result_ += sizeof(x);
return none;
}
error serialized_size_inspector::apply_impl(uint32_t& x) {
result_ += sizeof(x);
return none;
}
error serialized_size_inspector::apply_impl(int64_t& x) {
result_ += sizeof(x);
return none;
}
error serialized_size_inspector::apply_impl(uint64_t& x) {
result_ += sizeof(x);
return none;
}
error serialized_size_inspector::apply_impl(float& x) {
result_ += sizeof(x);
return none;
}
error serialized_size_inspector::apply_impl(double& x) {
result_ += sizeof(x);
return none;
}
error serialized_size_inspector::apply_impl(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_impl(tmp);
}
error serialized_size_inspector::apply_impl(std::string& x) {
size_t str_size = x.size();
begin_sequence(str_size);
result_ += x.size();
end_sequence();
return none;
}
error serialized_size_inspector::apply_impl(std::u16string& x) {
size_t str_size = x.size();
begin_sequence(str_size);
result_ += x.size() * sizeof(uint16_t);
end_sequence();
return none;
}
error serialized_size_inspector::apply_impl(std::u32string& x) {
size_t str_size = x.size();
begin_sequence(str_size);
result_ += x.size() * sizeof(uint32_t);
end_sequence();
return none;
}
} // namespace detail
} // namespace caf
/******************************************************************************
* ____ _ _____ *
* / ___| / \ | ___| 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 serialized_size
#include "caf/detail/serialized_size.hpp"
#include "caf/test/dsl.hpp"
#include <vector>
#include "caf/byte.hpp"
#include "caf/serializer_impl.hpp"
using namespace caf;
using caf::detail::serialized_size;
namespace {
struct fixture : test_coordinator_fixture<> {
using buffer_type = std::vector<byte>;
template <class... Ts>
size_t actual_size(const Ts&... xs) {
buffer_type buf;
serializer_impl<buffer_type> 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