Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
A
Actor Framework
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Operations
Operations
Metrics
Environments
Analytics
Analytics
CI / CD
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
cpp-libs
Actor Framework
Commits
324644b6
Commit
324644b6
authored
Aug 06, 2019
by
Jakob Otto
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Add serialization_impl + test scaffold
parent
2d79652b
Changes
2
Show whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
447 additions
and
0 deletions
+447
-0
libcaf_core/caf/serializer_impl.hpp
libcaf_core/caf/serializer_impl.hpp
+228
-0
libcaf_core/test/serializer_impl.cpp
libcaf_core/test/serializer_impl.cpp
+219
-0
No files found.
libcaf_core/caf/serializer_impl.hpp
0 → 100644
View file @
324644b6
/******************************************************************************
* ____ _ _____ *
* / ___| / \ | ___| 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 <iomanip>
#include <sstream>
#include <vector>
#include "caf/detail/ieee_754.hpp"
#include "caf/serializer.hpp"
namespace
caf
{
/// Implements the serializer interface with a binary serialization protocol.
template
<
class
Container
>
class
serializer_impl
final
:
public
serializer
{
public:
// -- member types -----------------------------------------------------------
using
super
=
serializer
;
using
container_type
=
Container
;
// -- constructors, destructors, and assignment operators --------------------
serializer_impl
(
actor_system
&
sys
,
container_type
&
buf
)
:
super
(
sys
),
buf_
(
buf
),
write_pos_
(
buf_
.
size
())
{
// nop
}
serializer_impl
(
execution_unit
*
ctx
,
container_type
&
buf
)
:
super
(
ctx
),
buf_
(
buf
),
write_pos_
(
buf_
.
size
())
{
// nop
}
// -- position management ----------------------------------------------------
/// Sets the write position to given offset.
/// @pre `offset <= buf.size()`
void
seek
(
size_t
offset
)
{
write_pos_
=
offset
;
}
/// Jumps `num_bytes` forward. Resizes the buffer (filling it with zeros)
/// when skipping past the end.
void
skip
(
size_t
num_bytes
)
{
auto
remaining
=
buf_
.
size
()
-
write_pos_
;
if
(
remaining
<
num_bytes
)
buf_
.
insert
(
buf_
.
end
(),
num_bytes
-
remaining
,
0
);
write_pos_
+=
num_bytes
;
}
// -- overridden member functions --------------------------------------------
error
begin_object
(
uint16_t
&
nr
,
std
::
string
&
name
)
override
{
if
(
nr
!=
0
)
return
apply
(
nr
);
if
(
auto
err
=
apply
(
nr
))
return
err
;
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.
// 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
end_sequence
()
override
{
return
none
;
}
error
apply_raw
(
size_t
num_bytes
,
void
*
data
)
override
{
CAF_ASSERT
(
write_pos_
<=
buf_
.
size
());
auto
ptr
=
reinterpret_cast
<
char
*>
(
data
);
auto
buf_size
=
buf_
.
size
();
if
(
write_pos_
==
buf_size
)
{
buf_
.
insert
(
buf_
.
end
(),
ptr
,
ptr
+
num_bytes
);
}
else
if
(
write_pos_
+
num_bytes
<=
buf_size
)
{
memcpy
(
buf_
.
data
()
+
write_pos_
,
ptr
,
num_bytes
);
}
else
{
auto
remaining
=
buf_size
-
write_pos_
;
CAF_ASSERT
(
remaining
<
num_bytes
);
memcpy
(
buf_
.
data
()
+
write_pos_
,
ptr
,
remaining
);
buf_
.
insert
(
buf_
.
end
(),
ptr
+
remaining
,
ptr
+
num_bytes
);
}
write_pos_
+=
num_bytes
;
CAF_ASSERT
(
write_pos_
<=
buf_
.
size
());
return
none
;
}
// -- properties -------------------------------------------------------------
container_type
&
buf
()
{
return
buf_
;
}
const
container_type
&
buf
()
const
{
return
buf_
;
}
size_t
write_pos
()
const
noexcept
{
return
write_pos_
;
}
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
,
static_cast
<
uint16_t
>
(
x
));
}
error
apply_impl
(
uint16_t
&
x
)
override
{
return
apply_int
(
*
this
,
x
);
}
error
apply_impl
(
int32_t
&
x
)
override
{
return
apply_int
(
*
this
,
static_cast
<
uint32_t
>
(
x
));
}
error
apply_impl
(
uint32_t
&
x
)
override
{
return
apply_int
(
*
this
,
x
);
}
error
apply_impl
(
int64_t
&
x
)
override
{
return
apply_int
(
*
this
,
static_cast
<
uint64_t
>
(
x
));
}
error
apply_impl
(
uint64_t
&
x
)
override
{
return
apply_int
(
*
this
,
x
);
}
error
apply_impl
(
float
&
x
)
override
{
return
apply_int
(
*
this
,
detail
::
pack754
(
x
));
}
error
apply_impl
(
double
&
x
)
override
{
return
apply_int
(
*
this
,
detail
::
pack754
(
x
));
}
error
apply_impl
(
long
double
&
x
)
override
{
// 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
apply_impl
(
std
::
string
&
x
)
override
{
auto
str_size
=
x
.
size
();
if
(
str_size
==
0
)
return
error
::
eval
([
&
]
{
return
begin_sequence
(
str_size
);
},
[
&
]
{
return
end_sequence
();
});
auto
data
=
const_cast
<
char
*>
(
x
.
c_str
());
return
error
::
eval
([
&
]
{
return
begin_sequence
(
str_size
);
},
[
&
]
{
return
apply_raw
(
str_size
,
data
);
},
[
&
]
{
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
(
auto
c
:
x
)
{
// The standard does not guarantee that char16_t is exactly 16 bits.
if
(
auto
err
=
apply_int
(
*
this
,
static_cast
<
uint16_t
>
(
c
)))
return
err
;
}
return
none
;
}
error
apply_impl
(
std
::
u32string
&
x
)
override
{
auto
str_size
=
x
.
size
();
if
(
auto
err
=
begin_sequence
(
str_size
))
return
err
;
for
(
auto
c
:
x
)
{
// The standard does not guarantee that char16_t is exactly 16 bits.
if
(
auto
err
=
apply_int
(
*
this
,
static_cast
<
uint32_t
>
(
c
)))
return
err
;
}
return
none
;
}
private:
container_type
&
buf_
;
size_t
write_pos_
;
};
}
// namespace caf
libcaf_core/test/serializer_impl.cpp
0 → 100644
View file @
324644b6
/******************************************************************************
* ____ _ _____ *
* / ___| / \ | ___| 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 serialization
#include "caf/test/unit_test.hpp"
#include <algorithm>
#include <cassert>
#include <cstdint>
#include <cstring>
#include <functional>
#include <iostream>
#include <iterator>
#include <limits>
#include <list>
#include <locale>
#include <memory>
#include <new>
#include <set>
#include <sstream>
#include <stack>
#include <stdexcept>
#include <string>
#include <tuple>
#include <type_traits>
#include <typeinfo>
#include <vector>
#include "caf/actor_system.hpp"
#include "caf/actor_system_config.hpp"
#include "caf/binary_deserializer.hpp"
#include "caf/binary_serializer.hpp"
#include "caf/deserializer.hpp"
#include "caf/event_based_actor.hpp"
#include "caf/make_type_erased_tuple_view.hpp"
#include "caf/make_type_erased_view.hpp"
#include "caf/message.hpp"
#include "caf/message_handler.hpp"
#include "caf/primitive_variant.hpp"
#include "caf/proxy_registry.hpp"
#include "caf/ref_counted.hpp"
#include "caf/serializer.hpp"
#include "caf/stream_deserializer.hpp"
#include "caf/stream_serializer.hpp"
#include "caf/streambuf.hpp"
#include "caf/variant.hpp"
#include "caf/detail/enum_to_string.hpp"
#include "caf/detail/get_mac_addresses.hpp"
#include "caf/detail/ieee_754.hpp"
#include "caf/detail/int_list.hpp"
#include "caf/detail/safe_equal.hpp"
#include "caf/detail/type_traits.hpp"
using namespace std;
using namespace caf;
using caf::detail::type_erased_value_impl;
namespace {
struct test_data {
int32_t i32 = -345;
int64_t i64 = -1234567890123456789ll;
float f32 = 3.45f;
double f64 = 54.3;
duration dur = duration{time_unit::seconds, 123};
timestamp ts = timestamp{timestamp::duration{1478715821 * 1000000000ll}};
test_enum te = test_enum::b;
string str = "Lorem ipsum dolor sit amet.";
raw_struct rs;
test_array ta{
{0, 1, 2, 3},
{{0, 1, 2, 3}, {4, 5, 6, 7}},
};
};
template <class Inspector>
typename Inspector::result_type inspect(Inspector& f, test_data& x) {
return f(x.value, x.value2);
}
template <class Serializer, class Deserializer>
struct fixture {
int32_t i32 = -345;
int64_t i64 = -1234567890123456789ll;
float f32 = 3.45f;
double f64 = 54.3;
duration dur = duration{time_unit::seconds, 123};
timestamp ts = timestamp{timestamp::duration{1478715821 * 1000000000ll}};
test_enum te = test_enum::b;
string str = "Lorem ipsum dolor sit amet.";
raw_struct rs;
test_array ta{
{0, 1, 2, 3},
{{0, 1, 2, 3}, {4, 5, 6, 7}},
};
int ra[3] = {1, 2, 3};
test_data testData{
};
config cfg;
actor_system system;
message msg;
message recursive;
template <class T, class... Ts>
vector<char> serialize(T& x, Ts&... xs) {
vector<char> buf;
binary_serializer sink{system, buf};
if (auto err = sink(x, xs...))
CAF_FAIL("serialization failed: "
<< system.render(err) << ", data: "
<< deep_to_string(std::forward_as_tuple(x, xs...)));
return buf;
}
template <class T, class... Ts>
void deserialize(const vector<char>& buf, T& x, Ts&... xs) {
binary_deserializer source{system, buf};
if (auto err = source(x, xs...))
CAF_FAIL("deserialization failed: " << system.render(err));
}
// serializes `x` and then deserializes and returns the serialized value
template <class T>
T roundtrip(T x) {
T result;
deserialize(serialize(x), result);
return result;
}
// converts `x` to a message, serialize it, then deserializes it, and
// finally returns unboxed value
template <class T>
T msg_roundtrip(const T& x) {
message result;
auto tmp = make_message(x);
deserialize(serialize(tmp), result);
if (!result.match_elements<T>())
CAF_FAIL("expected: " << x << ", got: " << result);
return result.get_as<T>(0);
}
fixture() : system(cfg) {
rs.str.assign(string(str.rbegin(), str.rend()));
msg = make_message(i32, i64, dur, ts, te, str, rs);
config_value::dictionary dict;
put(dict, "scheduler.policy", atom("none"));
put(dict, "scheduler.max-threads", 42);
put(dict, "nodes.preload",
make_config_value_list("sun", "venus", "mercury", "earth", "mars"));
recursive = make_message(config_value{std::move(dict)});
}
};
} // namespace
#define SERIALIZATION_TEST(name) \
template <class Serializer, class Deserializer> \
struct name##_tpl : fixture<Serializer, Deserializer> { \
using super = fixture<Serializer, Deserializer>; \
using super::i32; \
using super::i64; \
using super::f32; \
using super::f64; \
using super::dur; \
using super::ts; \
using super::te; \
using super::str; \
using super::rs; \
using super::ta; \
using super::ra; \
using super::system; \
using super::msg; \
using super::recursive; \
using super::serialize; \
using super::deserialize; \
using super::roundtrip; \
using super::msg_roundtrip; \
void run_test_impl(); \
}; \
namespace { \
using name##_binary = name##_tpl<binary_serializer, binary_deserializer>; \
using name##_stream = name##_tpl<stream_serializer<vectorbuf>, \
stream_deserializer<charbuf>>; \
::caf::test::detail::adder<::caf::test::test_impl<name##_binary>> \
CAF_UNIQUE(a_binary){CAF_XSTR(CAF_SUITE), CAF_XSTR(name##_binary), false}; \
::caf::test::detail::adder<::caf::test::test_impl<name##_stream>> \
CAF_UNIQUE(a_stream){CAF_XSTR(CAF_SUITE), CAF_XSTR(name##_stream), false}; \
} \
template <class Serializer, class Deserializer> \
void name##_tpl<Serializer, Deserializer>::run_test_impl()
SERIALIZATION_TEST(i32_values) {
auto buf = serialize(i32);
int32_t x;
deserialize(buf, x);
CAF_CHECK_EQUAL(i32, x);
}
*/
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment