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
ba74bb57
Commit
ba74bb57
authored
Nov 18, 2019
by
Dominik Charousset
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Fix serialization of chrono types
parent
98c970ea
Changes
11
Hide whitespace changes
Inline
Side-by-side
Showing
11 changed files
with
134 additions
and
219 deletions
+134
-219
libcaf_core/caf/binary_deserializer.hpp
libcaf_core/caf/binary_deserializer.hpp
+11
-4
libcaf_core/caf/binary_serializer.hpp
libcaf_core/caf/binary_serializer.hpp
+4
-4
libcaf_core/caf/detail/inspect.hpp
libcaf_core/caf/detail/inspect.hpp
+76
-0
libcaf_core/caf/detail/stringification_inspector.hpp
libcaf_core/caf/detail/stringification_inspector.hpp
+1
-0
libcaf_core/caf/detail/type_traits.hpp
libcaf_core/caf/detail/type_traits.hpp
+0
-151
libcaf_core/caf/make_message.hpp
libcaf_core/caf/make_message.hpp
+38
-14
libcaf_core/caf/read_inspector.hpp
libcaf_core/caf/read_inspector.hpp
+2
-0
libcaf_core/caf/stateful_actor.hpp
libcaf_core/caf/stateful_actor.hpp
+0
-21
libcaf_core/caf/write_inspector.hpp
libcaf_core/caf/write_inspector.hpp
+2
-1
libcaf_core/src/binary_deserializer.cpp
libcaf_core/src/binary_deserializer.cpp
+0
-16
libcaf_core/src/binary_serializer.cpp
libcaf_core/src/binary_serializer.cpp
+0
-8
No files found.
libcaf_core/caf/binary_deserializer.hpp
View file @
ba74bb57
...
...
@@ -53,6 +53,17 @@ public:
reset
(
as_bytes
(
make_span
(
input
)));
}
binary_deserializer
(
execution_unit
*
ctx
,
const
void
*
buf
,
size_t
size
)
noexcept
:
binary_deserializer
(
ctx
,
span
{
reinterpret_cast
<
const
byte
*>
(
buf
),
size
})
{
// nop
}
binary_deserializer
(
actor_system
&
sys
,
const
void
*
buf
,
size_t
size
)
noexcept
:
binary_deserializer
(
sys
,
span
{
reinterpret_cast
<
const
byte
*>
(
buf
),
size
})
{
// nop
}
// -- properties -------------------------------------------------------------
/// Returns how many bytes are still available to read.
...
...
@@ -123,10 +134,6 @@ public:
result_type
apply
(
long
double
&
);
result_type
apply
(
timespan
&
x
)
noexcept
;
result_type
apply
(
timestamp
&
x
)
noexcept
;
result_type
apply
(
span
<
byte
>
)
noexcept
;
result_type
apply
(
std
::
string
&
);
...
...
libcaf_core/caf/binary_serializer.hpp
View file @
ba74bb57
...
...
@@ -41,6 +41,10 @@ public:
using
result_type
=
error_code
<
sec
>
;
using
container_type
=
byte_buffer
;
using
value_type
=
byte
;
// -- constructors, destructors, and assignment operators --------------------
binary_serializer
(
actor_system
&
sys
,
byte_buffer
&
buf
)
noexcept
;
...
...
@@ -111,10 +115,6 @@ public:
void
apply
(
long
double
x
);
void
apply
(
timespan
x
);
void
apply
(
timestamp
x
);
void
apply
(
string_view
x
);
void
apply
(
const
std
::
u16string
&
x
);
...
...
libcaf_core/caf/detail/inspect.hpp
0 → 100644
View file @
ba74bb57
/******************************************************************************
* ____ _ _____ *
* / ___| / \ | ___| 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 <chrono>
#include "caf/meta/load_callback.hpp"
namespace
caf
{
namespace
detail
{
// -- inject `inspect` overloads for some STL types ----------------------------
template
<
class
Inspector
,
class
Rep
,
class
Period
>
auto
inspect
(
Inspector
&
f
,
std
::
chrono
::
duration
<
Rep
,
Period
>&
x
)
{
if
constexpr
(
Inspector
::
reads_state
)
{
return
f
(
x
.
count
());
}
else
{
auto
tmp
=
Rep
{};
auto
cb
=
[
&
]
{
x
=
std
::
chrono
::
duration
<
Rep
,
Period
>
{
tmp
};
};
return
f
(
tmp
,
meta
::
load_callback
(
cb
));
}
}
template
<
class
Inspector
,
class
Clock
,
class
Duration
>
auto
inspect
(
Inspector
&
f
,
std
::
chrono
::
time_point
<
Clock
,
Duration
>&
x
)
{
if
constexpr
(
Inspector
::
reads_state
)
{
return
f
(
x
.
time_since_epoch
());
}
else
{
auto
tmp
=
Duration
{};
auto
cb
=
[
&
]
{
x
=
std
::
chrono
::
time_point
<
Clock
,
Duration
>
{
tmp
};
};
return
f
(
tmp
,
meta
::
load_callback
(
cb
));
}
}
// -- provide is_inspectable trait for metaprogramming -------------------------
/// Checks whether `T` is inspectable by `Inspector`.
template
<
class
Inspector
,
class
T
>
class
is_inspectable
{
private:
template
<
class
U
>
static
auto
sfinae
(
Inspector
&
x
,
U
&
y
)
->
decltype
(
inspect
(
x
,
y
));
static
std
::
false_type
sfinae
(
Inspector
&
,
...);
using
result_type
=
decltype
(
sfinae
(
std
::
declval
<
Inspector
&>
(),
std
::
declval
<
T
&>
()));
public:
static
constexpr
bool
value
=
!
std
::
is_same
<
result_type
,
std
::
false_type
>::
value
;
};
// pointers are never inspectable
template
<
class
Inspector
,
class
T
>
struct
is_inspectable
<
Inspector
,
T
*>
:
std
::
false_type
{};
}
// namespace detail
}
// namespace caf
libcaf_core/caf/detail/stringification_inspector.hpp
View file @
ba74bb57
...
...
@@ -26,6 +26,7 @@
#include "caf/detail/append_hex.hpp"
#include "caf/detail/apply_args.hpp"
#include "caf/detail/inspect.hpp"
#include "caf/detail/type_traits.hpp"
#include "caf/fwd.hpp"
#include "caf/meta/annotation.hpp"
...
...
libcaf_core/caf/detail/type_traits.hpp
View file @
ba74bb57
...
...
@@ -86,22 +86,6 @@ using enable_if_tt = typename std::enable_if<Trait::value, T>::type;
template
<
class
T
>
using
remove_reference_t
=
typename
std
::
remove_reference
<
T
>::
type
;
/// Checks whether `T` is inspectable by `Inspector`.
template
<
class
Inspector
,
class
T
>
class
is_inspectable
{
private:
template
<
class
U
>
static
auto
sfinae
(
Inspector
&
x
,
U
&
y
)
->
decltype
(
inspect
(
x
,
y
));
static
std
::
false_type
sfinae
(
Inspector
&
,
...);
using
result_type
=
decltype
(
sfinae
(
std
::
declval
<
Inspector
&>
(),
std
::
declval
<
T
&>
()));
public:
static
constexpr
bool
value
=
!
std
::
is_same
<
result_type
,
std
::
false_type
>::
value
;
};
/// Checks whether `T` defines a free function `to_string`.
template
<
class
T
>
class
has_to_string
{
...
...
@@ -117,10 +101,6 @@ public:
static
constexpr
bool
value
=
std
::
is_convertible
<
result
,
std
::
string
>::
value
;
};
// pointers are never inspectable
template
<
class
Inspector
,
class
T
>
struct
is_inspectable
<
Inspector
,
T
*>
:
std
::
false_type
{};
template
<
bool
X
>
using
bool_token
=
std
::
integral_constant
<
bool
,
X
>
;
...
...
@@ -274,137 +254,6 @@ public:
template
<
class
T
>
constexpr
bool
is_iterable
<
T
>::
value
;
/// Checks whether `T` provides either a free function or a member function for
/// serialization. The checks test whether both serialization and
/// deserialization can succeed. The meta function tests the following
/// functions with `Processor` being both `serializer` and `deserializer` and
/// returns an integral constant if and only if the test succeeds for both.
///
/// - `serialize(Processor&, T&, const unsigned int)`
/// - `serialize(Processor&, T&)`
/// - `T::serialize(Processor&, const unsigned int)`.
/// - `T::serialize(Processor&)`.
template
<
class
T
,
bool
Ignore
=
std
::
is_pointer
<
T
>
::
value
||
std
::
is_function
<
T
>::
value
>
struct
has_serialize
{
template
<
class
U
>
static
auto
test_serialize
(
caf
::
serializer
*
sink
,
U
*
x
,
unsigned
int
y
=
0
)
->
decltype
(
serialize
(
*
sink
,
*
x
,
y
));
template
<
class
U
>
static
auto
test_serialize
(
caf
::
serializer
*
sink
,
U
*
x
)
->
decltype
(
serialize
(
*
sink
,
*
x
));
template
<
class
>
static
auto
test_serialize
(...)
->
std
::
false_type
;
template
<
class
U
>
static
auto
test_deserialize
(
caf
::
deserializer
*
source
,
U
*
x
,
unsigned
int
y
=
0
)
->
decltype
(
serialize
(
*
source
,
*
x
,
y
));
template
<
class
U
>
static
auto
test_deserialize
(
caf
::
deserializer
*
source
,
U
*
x
)
->
decltype
(
serialize
(
*
source
,
*
x
));
template
<
class
>
static
auto
test_deserialize
(...)
->
std
::
false_type
;
using
serialize_type
=
decltype
(
test_serialize
<
T
>
(
nullptr
,
nullptr
));
using
deserialize_type
=
decltype
(
test_deserialize
<
T
>
(
nullptr
,
nullptr
));
using
type
=
std
::
integral_constant
<
bool
,
std
::
is_same
<
serialize_type
,
void
>::
value
&&
std
::
is_same
<
deserialize_type
,
void
>::
value
>
;
static
constexpr
bool
value
=
type
::
value
;
};
template
<
class
T
>
struct
has_serialize
<
T
,
true
>
{
static
constexpr
bool
value
=
false
;
};
/// Any inspectable type is considered to be serializable.
template
<
class
T
>
struct
is_serializable
;
template
<
class
T
,
bool
IsIterable
=
is_iterable
<
T
>
::
value
,
bool
Ignore
=
std
::
is_pointer
<
T
>::
value
||
std
::
is_function
<
T
>::
value
>
struct
is_serializable_impl
;
/// Checks whether `T` is builtin or provides a `serialize`
/// (free or member) function.
template
<
class
T
>
struct
is_serializable_impl
<
T
,
false
,
false
>
{
static
constexpr
bool
value
=
has_serialize
<
T
>::
value
||
is_inspectable
<
serializer
,
T
>::
value
||
is_builtin
<
T
>::
value
;
};
template
<
class
F
,
class
S
>
struct
is_serializable_impl
<
std
::
pair
<
F
,
S
>
,
false
,
false
>
{
static
constexpr
bool
value
=
is_serializable
<
F
>::
value
&&
is_serializable
<
S
>::
value
;
};
template
<
class
...
Ts
>
struct
is_serializable_impl
<
std
::
tuple
<
Ts
...
>
,
false
,
false
>
{
static
constexpr
bool
value
=
conjunction
<
is_serializable
<
Ts
>::
value
...
>::
value
;
};
template
<
class
T
>
struct
is_serializable_impl
<
T
,
true
,
false
>
{
using
value_type
=
typename
T
::
value_type
;
static
constexpr
bool
value
=
is_serializable
<
value_type
>::
value
;
};
template
<
class
T
,
size_t
S
>
struct
is_serializable_impl
<
T
[
S
],
false
,
false
>
{
static
constexpr
bool
value
=
is_serializable
<
T
>::
value
;
};
template
<
class
T
,
bool
IsIterable
>
struct
is_serializable_impl
<
T
,
IsIterable
,
true
>
{
static
constexpr
bool
value
=
false
;
};
/// Checks whether `T` is builtin or provides a `serialize`
/// (free or member) function.
template
<
class
T
>
struct
is_serializable
{
static
constexpr
bool
value
=
is_serializable_impl
<
T
>::
value
||
is_inspectable
<
serializer
,
T
>::
value
||
std
::
is_empty
<
T
>::
value
||
std
::
is_enum
<
T
>::
value
;
};
template
<
>
struct
is_serializable
<
bool
>
:
std
::
true_type
{
// nop
};
template
<
class
T
>
struct
is_serializable
<
T
&>
:
is_serializable
<
T
>
{
// nop
};
template
<
class
T
>
struct
is_serializable
<
const
T
>
:
is_serializable
<
T
>
{
// nop
};
template
<
class
T
>
struct
is_serializable
<
const
T
&>
:
is_serializable
<
T
>
{
// nop
};
/// Checks wheter `T` is a non-const reference.
template
<
class
T
>
struct
is_mutable_ref
:
std
::
false_type
{
};
...
...
libcaf_core/caf/make_message.hpp
View file @
ba74bb57
...
...
@@ -18,15 +18,20 @@
#pragma once
#include <string>
#include <tuple>
#include <sstream>
#include <type_traits>
#include "caf/message.hpp"
#include "caf/allowed_unsafe_message_type.hpp"
#include "caf/binary_deserializer.hpp"
#include "caf/binary_serializer.hpp"
#include "caf/byte.hpp"
#include "caf/deserializer.hpp"
#include "caf/detail/inspect.hpp"
#include "caf/detail/tuple_vals.hpp"
#include "caf/detail/type_traits.hpp"
#include "caf/message.hpp"
#include "caf/serializer.hpp"
namespace
caf
{
...
...
@@ -55,10 +60,32 @@ struct unbox_message_element<actor_control_block*, 0> {
///
template
<
class
T
>
struct
is_serializable_or_whitelisted
{
static
constexpr
bool
value
=
detail
::
is_serializable
<
T
>::
value
||
allowed_unsafe_message_type
<
T
>::
value
;
static
constexpr
bool
value
=
std
::
is_arithmetic
<
T
>::
value
//
||
std
::
is_empty
<
T
>::
value
//
||
std
::
is_enum
<
T
>::
value
//
||
detail
::
is_stl_tuple_type
<
T
>::
value
//
||
detail
::
is_map_like
<
T
>::
value
//
||
detail
::
is_list_like
<
T
>::
value
||
(
detail
::
is_inspectable
<
binary_serializer
,
T
>::
value
&&
detail
::
is_inspectable
<
binary_deserializer
,
T
>::
value
&&
detail
::
is_inspectable
<
serializer
,
T
>::
value
&&
detail
::
is_inspectable
<
deserializer
,
T
>::
value
)
||
allowed_unsafe_message_type
<
T
>::
value
;
};
template
<
>
struct
is_serializable_or_whitelisted
<
byte
>
:
std
::
true_type
{};
template
<
>
struct
is_serializable_or_whitelisted
<
std
::
string
>
:
std
::
true_type
{};
template
<
>
struct
is_serializable_or_whitelisted
<
std
::
u16string
>
:
std
::
true_type
{};
template
<
>
struct
is_serializable_or_whitelisted
<
std
::
u32string
>
:
std
::
true_type
{};
/// Returns a new `message` containing the values `(x, xs...)`.
/// @relates message
template
<
class
T
,
class
...
Ts
>
...
...
@@ -72,15 +99,12 @@ message make_message(T&& x, Ts&&... xs) {
typename
unbox_message_element
<
typename
strip_and_convert
<
T
>::
type
>::
type
,
typename
unbox_message_element
<
typename
strip_and_convert
<
Ts
>::
type
>::
type
...
>
;
static_assert
(
tl_forall
<
stored_types
,
is_serializable_or_whitelisted
>::
value
,
"at least one type is neither inspectable via "
"inspect(Inspector&, T&) nor serializable via "
"'serialize(Processor&, T&, const unsigned int)' or "
"`T::serialize(Processor&, const unsigned int)`; "
"you can whitelist individual types by "
"specializing `caf::allowed_unsafe_message_type<T>` "
"or using the macro CAF_ALLOW_UNSAFE_MESSAGE_TYPE"
);
static_assert
(
tl_forall
<
stored_types
,
is_serializable_or_whitelisted
>::
value
,
"at least one type is not inspectable via inspect(Inspector&, T&). If "
"you are not sending this type over the network, you can whitelist "
"individual types by specializing caf::allowed_unsafe_message_type<T> "
"or by using the macro CAF_ALLOW_UNSAFE_MESSAGE_TYPE"
);
using
storage
=
typename
tl_apply
<
stored_types
,
tuple_vals
>::
type
;
auto
ptr
=
make_counted
<
storage
>
(
std
::
forward
<
T
>
(
x
),
std
::
forward
<
Ts
>
(
xs
)...);
...
...
libcaf_core/caf/read_inspector.hpp
View file @
ba74bb57
...
...
@@ -21,6 +21,7 @@
#include <type_traits>
#include "caf/allowed_unsafe_message_type.hpp"
#include "caf/detail/inspect.hpp"
#include "caf/detail/squashed_int.hpp"
#include "caf/detail/type_traits.hpp"
#include "caf/meta/annotation.hpp"
...
...
@@ -98,6 +99,7 @@ public:
CAF_READ_INSPECTOR_TRY
(
dref
.
end_sequence
())
}
else
{
static_assert
(
detail
::
is_inspectable
<
Subtype
,
type
>::
value
);
using
caf
::
detail
::
inspect
;
// We require that the implementation for `inspect` does not modify its
// arguments when passing a reading inspector.
CAF_READ_INSPECTOR_TRY
(
inspect
(
dref
,
const_cast
<
type
&>
(
x
)));
...
...
libcaf_core/caf/stateful_actor.hpp
View file @
ba74bb57
...
...
@@ -42,8 +42,6 @@ public:
explicit
stateful_actor
(
actor_config
&
cfg
,
Ts
&&
...
xs
)
:
Base
(
cfg
,
std
::
forward
<
Ts
>
(
xs
)...),
state
(
state_
)
{
if
(
detail
::
is_serializable
<
State
>::
value
)
this
->
setf
(
Base
::
is_serializable_flag
);
cr_state
(
this
);
}
...
...
@@ -61,14 +59,6 @@ public:
return
get_name
(
state_
);
}
error
save_state
(
serializer
&
sink
,
unsigned
int
version
)
override
{
return
serialize_state
(
&
sink
,
state
,
version
);
}
error
load_state
(
deserializer
&
source
,
unsigned
int
version
)
override
{
return
serialize_state
(
&
source
,
state
,
version
);
}
/// A reference to the actor's state.
State
&
state
;
...
...
@@ -81,17 +71,6 @@ public:
/// @endcond
private:
template
<
class
Inspector
,
class
T
>
auto
serialize_state
(
Inspector
*
f
,
T
&
x
,
unsigned
int
)
->
decltype
(
inspect
(
*
f
,
x
))
{
return
inspect
(
*
f
,
x
);
}
template
<
class
T
>
error
serialize_state
(
void
*
,
T
&
,
unsigned
int
)
{
return
sec
::
invalid_argument
;
}
template
<
class
T
>
typename
std
::
enable_if
<
std
::
is_constructible
<
State
,
T
>::
value
>::
type
cr_state
(
T
arg
)
{
...
...
libcaf_core/caf/write_inspector.hpp
View file @
ba74bb57
...
...
@@ -24,6 +24,7 @@
#include <utility>
#include "caf/allowed_unsafe_message_type.hpp"
#include "caf/detail/inspect.hpp"
#include "caf/detail/squashed_int.hpp"
#include "caf/detail/type_traits.hpp"
#include "caf/meta/annotation.hpp"
...
...
@@ -45,7 +46,6 @@ namespace caf {
/// - all fixed-size integer types from `<cstdint>`
/// - floating point numbers
/// - enum types
/// - `timespan`, `timestamp`, and `atom_value`
/// - `std::string`, `std::u16string`, and `std::u32string`
template
<
class
Subtype
>
class
write_inspector
{
...
...
@@ -102,6 +102,7 @@ public:
static_assert
(
std
::
is_lvalue_reference_v
<
decltype
(
x
)
>
//
&&
!
std
::
is_const_v
<
decltype
(
x
)
>
);
static_assert
(
detail
::
is_inspectable
<
Subtype
,
type
>::
value
);
using
caf
::
detail
::
inspect
;
CAF_WRITE_INSPECTOR_TRY
(
inspect
(
dref
,
x
));
}
return
true
;
...
...
libcaf_core/src/binary_deserializer.cpp
View file @
ba74bb57
...
...
@@ -189,22 +189,6 @@ result_type binary_deserializer::apply(long double& x) {
return
sec
::
invalid_argument
;
}
result_type
binary_deserializer
::
apply
(
timespan
&
x
)
noexcept
{
int64_t
tmp
=
0
;
if
(
auto
err
=
apply
(
tmp
))
return
err
;
x
=
timespan
{
tmp
};
return
none
;
}
result_type
binary_deserializer
::
apply
(
timestamp
&
x
)
noexcept
{
int64_t
tmp
=
0
;
if
(
auto
err
=
apply
(
tmp
))
return
err
;
x
=
timestamp
{
timespan
{
tmp
}};
return
none
;
}
result_type
binary_deserializer
::
apply
(
span
<
byte
>
x
)
noexcept
{
if
(
!
range_check
(
x
.
size
()))
return
sec
::
end_of_stream
;
...
...
libcaf_core/src/binary_serializer.cpp
View file @
ba74bb57
...
...
@@ -143,14 +143,6 @@ void binary_serializer::apply(long double x) {
apply
(
tmp
);
}
void
binary_serializer
::
apply
(
timespan
x
)
{
apply
(
x
.
count
());
}
void
binary_serializer
::
apply
(
timestamp
x
)
{
apply
(
x
.
time_since_epoch
().
count
());
}
void
binary_serializer
::
apply
(
string_view
x
)
{
begin_sequence
(
x
.
size
());
apply
(
as_bytes
(
make_span
(
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