Commit e48d80e7 authored by Jakob Otto's avatar Jakob Otto

Remove deserializer_impl and move serialization_fixture to serializer_impl test.

parent 31fa45f9
/******************************************************************************
* ____ _ _____ *
* / ___| / \ | ___| C++ *
* | | / _ \ | |_ Actor *
* | |___ / ___ \| _| Framework *
* \____/_/ \_|_| *
* *
* Copyright 2011-2018 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 <cstddef>
#include <cstdint>
#include <cstring>
#include <vector>
#include "caf/deserializer.hpp"
#include "caf/detail/ieee_754.hpp"
#include "caf/detail/network_order.hpp"
namespace caf {
/// Implements the deserializer interface with a binary serialization protocol.
template <class Container>
class deserializer_impl final : public deserializer {
public:
// -- member types -----------------------------------------------------------
using super = deserializer;
using container_type = Container;
using value_type = typename container_type::value_type;
// -- constructors, destructors, and assignment operators --------------------
deserializer_impl(actor_system& sys, const value_type* buf, size_t buf_size)
: super(sys), current_(buf), end_(buf + buf_size) {
// nop
}
deserializer_impl(execution_unit* ctx, const value_type* buf, size_t buf_size)
: super(ctx), current_(buf), end_(buf + buf_size) {
// nop
}
deserializer_impl(actor_system& sys, const container_type& buf)
: deserializer_impl(sys, buf.data(), buf.size()) {
// nop
}
deserializer_impl(execution_unit* ctx, const container_type& buf)
: deserializer_impl(ctx, buf.data(), buf.size()) {
// nop
}
// -- overridden member functions --------------------------------------------
error begin_object(uint16_t& nr, std::string& name) override {
if (auto err = apply(nr))
return err;
if (nr != 0)
return none;
return apply(name);
}
error end_object() override {
return none;
}
error begin_sequence(size_t& list_size) override {
// Use varbyte encoding to compress sequence size on the wire.
uint32_t x = 0;
int n = 0;
uint8_t low7 = 0;
do {
if (auto err = apply_impl(low7))
return err;
x |= static_cast<uint32_t>((low7 & 0x7F)) << (7 * n);
++n;
} while (low7 & 0x80);
list_size = x;
return none;
}
error end_sequence() override {
return none;
}
error apply_raw(size_t num_bytes, void* storage) override {
if (!range_check(num_bytes))
return sec::end_of_stream;
memcpy(storage, current_, num_bytes);
current_ += num_bytes;
return none;
}
// -- properties -------------------------------------------------------------
/// Returns the current read position.
const value_type* current() const {
return current_;
}
/// Returns the past-the-end iterator.
const value_type* end() const {
return end_;
}
/// Returns how many bytes are still available to read.
size_t remaining() const {
return static_cast<size_t>(end_ - current_);
}
/// Jumps `num_bytes` forward.
/// @pre `num_bytes <= remaining()`
void skip(size_t num_bytes) {
current_ += num_bytes;
}
protected:
error apply_impl(int8_t& x) override {
return apply_raw(sizeof(int8_t), &x);
}
error apply_impl(uint8_t& x) override {
return apply_raw(sizeof(uint8_t), &x);
}
error apply_impl(int16_t& x) override {
return apply_int(*this, x);
}
error apply_impl(uint16_t& x) override {
return apply_int(*this, x);
}
error apply_impl(int32_t& x) override {
return apply_int(*this, x);
}
error apply_impl(uint32_t& x) override {
return apply_int(*this, x);
}
error apply_impl(int64_t& x) override {
return apply_int(*this, x);
}
error apply_impl(uint64_t& x) override {
return apply_int(*this, x);
}
error apply_impl(float& x) override {
return apply_float(*this, x);
}
error apply_impl(double& x) override {
return apply_float(*this, x);
}
error apply_impl(long double& x) override {
// The IEEE-754 conversion does not work for long double
// => fall back to string serialization (even though it sucks).
std::string tmp;
if (auto err = apply(tmp))
return err;
std::istringstream iss{std::move(tmp)};
iss >> x;
return none;
}
error apply_impl(std::string& x) override {
size_t str_size;
if (auto err = begin_sequence(str_size))
return err;
if (!range_check(str_size))
return sec::end_of_stream;
x.assign((char*) current_, (char*) current_ + str_size);
current_ += str_size;
return end_sequence();
}
error apply_impl(std::u16string& x) override {
auto str_size = x.size();
if (auto err = begin_sequence(str_size))
return err;
for (size_t i = 0; i < str_size; ++i) {
// The standard does not guarantee that char16_t is exactly 16 bits.
uint16_t tmp;
if (auto err = apply_int(*this, tmp))
return err;
x.push_back(static_cast<char16_t>(tmp));
}
return none;
}
error apply_impl(std::u32string& x) override {
auto str_size = x.size();
if (auto err = begin_sequence(str_size))
return err;
for (size_t i = 0; i < str_size; ++i) {
// The standard does not guarantee that char32_t is exactly 32 bits.
uint32_t tmp;
if (auto err = apply_int(*this, tmp))
return err;
x.push_back(static_cast<char32_t>(tmp));
}
return none;
}
private:
template <class T>
error apply_int(deserializer_impl<Container>& bs, T& x) {
typename std::make_unsigned<T>::type tmp;
if (auto err = bs.apply_raw(sizeof(T), &tmp))
return err;
x = static_cast<T>(detail::from_network_order(tmp));
return none;
}
template <class T>
error apply_float(deserializer_impl<Container>& bs, T& x) {
typename detail::ieee_754_trait<T>::packed_type tmp;
if (auto err = apply_int(bs, tmp))
return err;
x = detail::unpack754(tmp);
return none;
}
bool range_check(size_t read_size) {
return current_ + read_size <= end_;
}
const value_type* current_;
const value_type* end_;
};
} // namespace caf
/******************************************************************************
* ____ _ _____ *
* / ___| / \ | ___| C++ *
* | | / _ \ | |_ Actor *
* | |___ / ___ \| _| Framework *
* \____/_/ \_|_| *
* *
* Copyright 2011-2018 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/config.hpp"
#define CAF_SUITE deserializer_impl
#include "caf/test/unit_test.hpp"
#include <vector>
#include "caf/actor_system.hpp"
#include "caf/actor_system_config.hpp"
#include "caf/byte.hpp"
#include "caf/deserializer_impl.hpp"
#include "caf/serializer_impl.hpp"
#include "serialization_fixture.hpp"
using namespace caf;
CAF_TEST_FIXTURE_SCOPE(deserialization_tests, serialization_fixture)
CAF_TEST("deserialize std::vector<char>") {
using container_type = std::vector<char>;
container_type buffer;
serializer_impl<container_type> serializer{sys, buffer};
if (auto err = serializer(source))
CAF_FAIL("serialisation with serializer_impl<std::vector<char>> failed: "
<< sys.render(err));
deserializer_impl<container_type> deserializer{sys, buffer};
if (auto err = deserializer(sink))
CAF_FAIL("deserialisation with deserializer_impl<std::vector<char>> failed:"
<< sys.render(err));
CAF_CHECK_EQUAL(source, sink);
}
CAF_TEST("deserialize std::vector<byte>") {
using container_type = std::vector<byte>;
container_type buffer;
serializer_impl<container_type> serializer{sys, buffer};
if (auto err = serializer(source))
CAF_FAIL("serialisation with serializer_impl<std::vector<byte>> failed: "
<< sys.render(err));
deserializer_impl<container_type> deserializer{sys, buffer};
if (auto err = deserializer(sink))
CAF_FAIL("deserialisation with deserializer_impl<std::vector<byte>> failed:"
<< sys.render(err));
CAF_CHECK_EQUAL(source, sink);
}
CAF_TEST("deserialize std::vector<uint8_t>") {
using container_type = std::vector<uint8_t>;
container_type buffer;
serializer_impl<container_type> serializer{sys, buffer};
if (auto err = serializer(source))
CAF_FAIL("serialisation with serializer_impl<std::vector<uint8_t>> failed: "
<< sys.render(err));
deserializer_impl<container_type> deserializer{sys, buffer};
if (auto err = deserializer(sink))
CAF_FAIL(
"deserialisation with deserializer_impl<std::vector<uint8_t>> failed:"
<< sys.render(err));
CAF_CHECK_EQUAL(source, sink);
}
CAF_TEST_FIXTURE_SCOPE_END()
/******************************************************************************
* ____ _ _____ *
* / ___| / \ | ___| C++ *
* | | / _ \ | |_ Actor *
* | |___ / ___ \| _| Framework *
* \____/_/ \_|_| *
* *
* Copyright 2011-2018 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/actor_system.hpp"
#include "caf/actor_system_config.hpp"
#include "caf/duration.hpp"
#include "caf/timestamp.hpp"
enum class test_enum {
a,
b,
c,
};
struct test_data {
test_data(int32_t i32, int64_t i64, float f32, double f64, caf::duration dur,
caf::timestamp ts, test_enum te, const std::string& str)
: i32_(i32),
i64_(i64),
f32_(f32),
f64_(f64),
dur_(dur),
ts_(ts),
te_(te),
str_(str) {
}
test_data()
: test_data(-345, -1234567890123456789ll, 3.45, 54.3,
caf::duration(caf::time_unit::seconds, 123),
caf::timestamp{
caf::timestamp::duration{1478715821 * 1000000000ll}},
test_enum::b, "Lorem ipsum dolor sit amet.") {
}
int32_t i32_;
int64_t i64_;
float f32_;
double f64_;
caf::duration dur_;
caf::timestamp ts_;
test_enum te_;
std::string str_;
friend bool operator==(const test_data& data, const test_data& other) {
return (data.f64_ == other.f64_ && data.i32_ == other.i32_
&& data.i64_ == other.i64_ && data.str_ == other.str_
&& data.te_ == other.te_ && data.ts_ == other.ts_);
}
};
template <class Inspector>
typename Inspector::result_type inspect(Inspector& f, test_data& x) {
return f(caf::meta::type_name("test_data"), x.i32_, x.i64_, x.f32_, x.f64_,
x.dur_, x.ts_, x.te_, x.str_);
}
struct serialization_fixture {
caf::actor_system_config cfg;
caf::actor_system sys{cfg};
test_data source;
test_data sink{0,
0,
0,
0,
caf::duration(caf::time_unit::seconds, 0),
caf::timestamp{caf::timestamp::duration{0}},
test_enum::a,
""};
};
...@@ -22,16 +22,85 @@ ...@@ -22,16 +22,85 @@
#include "caf/test/dsl.hpp" #include "caf/test/dsl.hpp"
#include "serialization_fixture.hpp"
#include <cstring> #include <cstring>
#include <vector> #include <vector>
#include "caf/actor_system.hpp"
#include "caf/actor_system_config.hpp"
#include "caf/binary_serializer.hpp" #include "caf/binary_serializer.hpp"
#include "caf/byte.hpp" #include "caf/byte.hpp"
#include "caf/duration.hpp"
#include "caf/timestamp.hpp"
using namespace caf; using namespace caf;
namespace {
enum class test_enum {
a,
b,
c,
};
struct test_data {
test_data(int32_t i32, int64_t i64, float f32, double f64, caf::duration dur,
caf::timestamp ts, test_enum te, const std::string& str)
: i32_(i32),
i64_(i64),
f32_(f32),
f64_(f64),
dur_(dur),
ts_(ts),
te_(te),
str_(str) {
}
test_data()
: test_data(-345, -1234567890123456789ll, 3.45, 54.3,
caf::duration(caf::time_unit::seconds, 123),
caf::timestamp{
caf::timestamp::duration{1478715821 * 1000000000ll}},
test_enum::b, "Lorem ipsum dolor sit amet.") {
}
int32_t i32_;
int64_t i64_;
float f32_;
double f64_;
caf::duration dur_;
caf::timestamp ts_;
test_enum te_;
std::string str_;
friend bool operator==(const test_data& data, const test_data& other) {
return (data.f64_ == other.f64_ && data.i32_ == other.i32_
&& data.i64_ == other.i64_ && data.str_ == other.str_
&& data.te_ == other.te_ && data.ts_ == other.ts_);
}
};
template <class Inspector>
typename Inspector::result_type inspect(Inspector& f, test_data& x) {
return f(caf::meta::type_name("test_data"), x.i32_, x.i64_, x.f32_, x.f64_,
x.dur_, x.ts_, x.te_, x.str_);
}
struct serialization_fixture {
caf::actor_system_config cfg;
caf::actor_system sys{cfg};
test_data source;
test_data sink{0,
0,
0,
0,
caf::duration(caf::time_unit::seconds, 0),
caf::timestamp{caf::timestamp::duration{0}},
test_enum::a,
""};
};
} // namespace
CAF_TEST_FIXTURE_SCOPE(serializer_impl_tests, serialization_fixture) CAF_TEST_FIXTURE_SCOPE(serializer_impl_tests, serialization_fixture)
CAF_TEST(serialize to std::vector<char>) { CAF_TEST(serialize to std::vector<char>) {
......
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