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
dc04d789
Unverified
Commit
dc04d789
authored
Dec 16, 2020
by
Noir
Committed by
GitHub
Dec 16, 2020
Browse files
Options
Browse Files
Download
Plain Diff
Merge pull request #1186
Simplify and streamline the type inspection API
parents
8de7ba03
7dd7ced5
Changes
80
Hide whitespace changes
Inline
Side-by-side
Showing
80 changed files
with
1876 additions
and
907 deletions
+1876
-907
CHANGELOG.md
CHANGELOG.md
+5
-0
cmake/caf-generate-enum-strings.cpp
cmake/caf-generate-enum-strings.cpp
+55
-24
examples/custom_type/custom_types_1.cpp
examples/custom_type/custom_types_1.cpp
+2
-2
libcaf_core/caf/binary_deserializer.hpp
libcaf_core/caf/binary_deserializer.hpp
+25
-8
libcaf_core/caf/binary_serializer.hpp
libcaf_core/caf/binary_serializer.hpp
+18
-9
libcaf_core/caf/config_value.hpp
libcaf_core/caf/config_value.hpp
+2
-2
libcaf_core/caf/config_value_reader.hpp
libcaf_core/caf/config_value_reader.hpp
+2
-0
libcaf_core/caf/config_value_writer.hpp
libcaf_core/caf/config_value_writer.hpp
+2
-0
libcaf_core/caf/cow_tuple.hpp
libcaf_core/caf/cow_tuple.hpp
+3
-11
libcaf_core/caf/deep_to_string.hpp
libcaf_core/caf/deep_to_string.hpp
+1
-1
libcaf_core/caf/default_enum_inspect.hpp
libcaf_core/caf/default_enum_inspect.hpp
+54
-0
libcaf_core/caf/deserializer.hpp
libcaf_core/caf/deserializer.hpp
+25
-4
libcaf_core/caf/detail/make_meta_object.hpp
libcaf_core/caf/detail/make_meta_object.hpp
+5
-5
libcaf_core/caf/detail/serialized_size.hpp
libcaf_core/caf/detail/serialized_size.hpp
+7
-3
libcaf_core/caf/detail/size_based_credit_controller.hpp
libcaf_core/caf/detail/size_based_credit_controller.hpp
+1
-1
libcaf_core/caf/detail/stringification_inspector.hpp
libcaf_core/caf/detail/stringification_inspector.hpp
+15
-9
libcaf_core/caf/detail/type_traits.hpp
libcaf_core/caf/detail/type_traits.hpp
+42
-17
libcaf_core/caf/exit_reason.hpp
libcaf_core/caf/exit_reason.hpp
+15
-0
libcaf_core/caf/fwd.hpp
libcaf_core/caf/fwd.hpp
+1
-1
libcaf_core/caf/hash/fnv.hpp
libcaf_core/caf/hash/fnv.hpp
+3
-1
libcaf_core/caf/hash/sha1.hpp
libcaf_core/caf/hash/sha1.hpp
+4
-1
libcaf_core/caf/inspector_access.hpp
libcaf_core/caf/inspector_access.hpp
+157
-300
libcaf_core/caf/inspector_access_base.hpp
libcaf_core/caf/inspector_access_base.hpp
+4
-4
libcaf_core/caf/inspector_access_type.hpp
libcaf_core/caf/inspector_access_type.hpp
+10
-100
libcaf_core/caf/load_inspector.hpp
libcaf_core/caf/load_inspector.hpp
+1
-8
libcaf_core/caf/load_inspector_base.hpp
libcaf_core/caf/load_inspector_base.hpp
+118
-18
libcaf_core/caf/message_id.hpp
libcaf_core/caf/message_id.hpp
+9
-22
libcaf_core/caf/pec.hpp
libcaf_core/caf/pec.hpp
+15
-0
libcaf_core/caf/save_inspector.hpp
libcaf_core/caf/save_inspector.hpp
+1
-8
libcaf_core/caf/save_inspector_base.hpp
libcaf_core/caf/save_inspector_base.hpp
+79
-16
libcaf_core/caf/sec.hpp
libcaf_core/caf/sec.hpp
+14
-0
libcaf_core/caf/serializer.hpp
libcaf_core/caf/serializer.hpp
+21
-4
libcaf_core/caf/stream_priority.hpp
libcaf_core/caf/stream_priority.hpp
+19
-4
libcaf_core/caf/uri.hpp
libcaf_core/caf/uri.hpp
+3
-24
libcaf_core/src/binary_serializer.cpp
libcaf_core/src/binary_serializer.cpp
+2
-2
libcaf_core/src/config_value_reader.cpp
libcaf_core/src/config_value_reader.cpp
+11
-0
libcaf_core/src/config_value_writer.cpp
libcaf_core/src/config_value_writer.cpp
+4
-0
libcaf_core/src/deserializer.cpp
libcaf_core/src/deserializer.cpp
+1
-1
libcaf_core/src/detail/serialized_size.cpp
libcaf_core/src/detail/serialized_size.cpp
+6
-1
libcaf_core/src/detail/stringification_inspector.cpp
libcaf_core/src/detail/stringification_inspector.cpp
+20
-10
libcaf_core/src/exit_reason_strings.cpp
libcaf_core/src/exit_reason_strings.cpp
+50
-0
libcaf_core/src/intrusive/inbox_result_strings.cpp
libcaf_core/src/intrusive/inbox_result_strings.cpp
+30
-0
libcaf_core/src/intrusive/task_result_strings.cpp
libcaf_core/src/intrusive/task_result_strings.cpp
+34
-0
libcaf_core/src/invoke_message_result_strings.cpp
libcaf_core/src/invoke_message_result_strings.cpp
+30
-0
libcaf_core/src/logger.cpp
libcaf_core/src/logger.cpp
+1
-1
libcaf_core/src/message_priority_strings.cpp
libcaf_core/src/message_priority_strings.cpp
+26
-0
libcaf_core/src/pec_strings.cpp
libcaf_core/src/pec_strings.cpp
+110
-0
libcaf_core/src/sec_strings.cpp
libcaf_core/src/sec_strings.cpp
+270
-0
libcaf_core/src/serializer.cpp
libcaf_core/src/serializer.cpp
+1
-1
libcaf_core/src/stream_priority_strings.cpp
libcaf_core/src/stream_priority_strings.cpp
+38
-0
libcaf_core/test/actor_profiler.cpp
libcaf_core/test/actor_profiler.cpp
+6
-6
libcaf_core/test/actor_registry.cpp
libcaf_core/test/actor_registry.cpp
+2
-2
libcaf_core/test/binary_deserializer.cpp
libcaf_core/test/binary_deserializer.cpp
+1
-1
libcaf_core/test/binary_serializer.cpp
libcaf_core/test/binary_serializer.cpp
+2
-2
libcaf_core/test/config_value_reader.cpp
libcaf_core/test/config_value_reader.cpp
+13
-7
libcaf_core/test/config_value_writer.cpp
libcaf_core/test/config_value_writer.cpp
+13
-9
libcaf_core/test/core-test.hpp
libcaf_core/test/core-test.hpp
+58
-0
libcaf_core/test/detail/serialized_size.cpp
libcaf_core/test/detail/serialized_size.cpp
+1
-1
libcaf_core/test/ipv4_endpoint.cpp
libcaf_core/test/ipv4_endpoint.cpp
+2
-2
libcaf_core/test/ipv6_endpoint.cpp
libcaf_core/test/ipv6_endpoint.cpp
+2
-2
libcaf_core/test/load_inspector.cpp
libcaf_core/test/load_inspector.cpp
+27
-20
libcaf_core/test/message.cpp
libcaf_core/test/message.cpp
+7
-10
libcaf_core/test/message_builder.cpp
libcaf_core/test/message_builder.cpp
+3
-5
libcaf_core/test/nasty.hpp
libcaf_core/test/nasty.hpp
+11
-15
libcaf_core/test/node_id.cpp
libcaf_core/test/node_id.cpp
+2
-2
libcaf_core/test/save_inspector.cpp
libcaf_core/test/save_inspector.cpp
+46
-64
libcaf_core/test/serialization.cpp
libcaf_core/test/serialization.cpp
+52
-2
libcaf_core/test/tracing_data.cpp
libcaf_core/test/tracing_data.cpp
+5
-5
libcaf_core/test/uri.cpp
libcaf_core/test/uri.cpp
+2
-2
libcaf_io/caf/io/basp/message_type.hpp
libcaf_io/caf/io/basp/message_type.hpp
+12
-0
libcaf_io/caf/io/basp/remote_message_handler.hpp
libcaf_io/caf/io/basp/remote_message_handler.hpp
+4
-4
libcaf_io/caf/io/network/protocol.hpp
libcaf_io/caf/io/network/protocol.hpp
+22
-0
libcaf_io/src/io/basp/instance.cpp
libcaf_io/src/io/basp/instance.cpp
+26
-15
libcaf_io/src/io/basp/message_type_strings.cpp
libcaf_io/src/io/basp/message_type_strings.cpp
+46
-0
libcaf_io/src/io/network/operation_strings.cpp
libcaf_io/src/io/network/operation_strings.cpp
+30
-0
libcaf_io/test/io/basp_broker.cpp
libcaf_io/test/io/basp_broker.cpp
+12
-9
libcaf_io/test/io/network/ip_endpoint.cpp
libcaf_io/test/io/network/ip_endpoint.cpp
+6
-6
libcaf_io/test/io/worker.cpp
libcaf_io/test/io/worker.cpp
+1
-1
libcaf_test/caf/test/dsl.hpp
libcaf_test/caf/test/dsl.hpp
+2
-2
manual/TypeInspection.rst
manual/TypeInspection.rst
+88
-90
No files found.
CHANGELOG.md
View file @
dc04d789
...
...
@@ -21,6 +21,11 @@ is based on [Keep a Changelog](https://keepachangelog.com).
-
When using
`CAF_MAIN`
, CAF now looks for the correct default config file name,
i.e.,
`caf-application.conf`
.
-
Simplify the type inspection API by removing the distinction between
`apply_object`
and
`apply_value`
. Instead, inspectors only offer
`apply`
and
users may now also call
`map`
,
`list`
,
`tuple`
and
`value`
for unboxing simple
wrapper types. Furthermore, CAF no longer automatically serializes enumeration
types using their underlying value because this is fundamentally unsafe.
### Fixed
...
...
cmake/caf-generate-enum-strings.cpp
View file @
dc04d789
...
...
@@ -94,6 +94,27 @@ int main(int argc, char** argv) {
cerr
<<
"empty enum name found
\n
"
;
return
EXIT_FAILURE
;
}
std
::
string
case_label_prefix
;
if
(
is_enum_class
)
case_label_prefix
=
enum_name
+
"::"
;
// Read until hitting the closing '}'.
std
::
vector
<
std
::
string
>
enum_values
;
for
(;;)
{
if
(
!
getline
(
in
,
line
))
{
cerr
<<
"unable to read enum values
\n
"
;
return
EXIT_FAILURE
;
}
trim
(
line
);
if
(
line
.
empty
())
continue
;
if
(
line
[
0
]
==
'}'
)
break
;
if
(
line
[
0
]
!=
'/'
)
{
keep_alnum
(
line
);
enum_values
.
emplace_back
(
line
);
}
}
// Generate output file.
std
::
ofstream
out
{
argv
[
2
]};
if
(
!
out
)
{
cerr
<<
"unable to open output file: "
<<
argv
[
2
]
<<
'\n'
;
...
...
@@ -104,7 +125,8 @@ int main(int argc, char** argv) {
<<
"// DO NOT EDIT: "
"this file is auto-generated by caf-generate-enum-strings.
\n
"
"// Run the target update-enum-strings if this file is out of sync.
\n
"
"#include
\"
caf/config.hpp
\"\n\n
"
"#include
\"
caf/config.hpp
\"\n
"
"#include
\"
caf/string_view.hpp
\"\n\n
"
"CAF_PUSH_DEPRECATED_WARNING
\n\n
"
<<
"#include
\"
"
<<
namespaces
[
0
];
for
(
size_t
i
=
1
;
i
<
namespaces
.
size
();
++
i
)
...
...
@@ -114,35 +136,44 @@ int main(int argc, char** argv) {
<<
"namespace "
<<
namespaces
[
0
]
<<
" {
\n
"
;
for
(
size_t
i
=
1
;
i
<
namespaces
.
size
();
++
i
)
out
<<
"namespace "
<<
namespaces
[
i
]
<<
" {
\n
"
;
out
<<
"
\n
std::string to_string("
<<
enum_name
<<
" x) {
\n
"
out
<<
'\n'
;
// Generate to_string implementation.
out
<<
"std::string to_string("
<<
enum_name
<<
" x) {
\n
"
<<
" switch(x) {
\n
"
<<
" default:
\n
"
<<
" return
\"
???
\"
;
\n
"
;
// Read until hitting the closing '}'.
std
::
string
case_label_prefix
;
if
(
is_enum_class
)
case_label_prefix
=
enum_name
+
"::"
;
for
(;;)
{
if
(
!
getline
(
in
,
line
))
{
cerr
<<
"unable to read enum values
\n
"
;
return
EXIT_FAILURE
;
}
trim
(
line
);
if
(
line
.
empty
())
continue
;
if
(
line
[
0
]
==
'}'
)
break
;
if
(
line
[
0
]
!=
'/'
)
{
keep_alnum
(
line
);
out
<<
" case "
<<
case_label_prefix
<<
line
<<
":
\n
"
<<
" return
\"
"
<<
line
<<
"
\"
;
\n
"
;
}
}
// Done. Print file footer and exit.
for
(
auto
&
val
:
enum_values
)
out
<<
" case "
<<
case_label_prefix
<<
val
<<
":
\n
"
<<
" return
\"
"
<<
val
<<
"
\"
;
\n
"
;
out
<<
" };
\n
"
<<
"}
\n\n
"
;
// Generate from_string implementation.
out
<<
"bool from_string(string_view in, "
<<
enum_name
<<
"& out) {
\n
"
;
for
(
auto
&
val
:
enum_values
)
out
<<
"if (in ==
\"
"
<<
val
<<
"
\"
) {
\n
"
<<
" out = "
<<
case_label_prefix
<<
val
<<
";
\n
"
<<
" return true;
\n
"
<<
" } else "
;
out
<<
"{
\n
"
<<
" return false;
\n
"
<<
" }
\n
"
<<
"}
\n\n
"
;
// Generate from_integer implementation.
out
<<
"bool from_integer(std::underlying_type_t<"
<<
enum_name
<<
"> in,
\n
"
<<
" "
<<
enum_name
<<
"& out) {
\n
"
<<
" auto result = static_cast<"
<<
enum_name
<<
">(in);
\n
"
<<
" switch(result) {
\n
"
<<
" default:
\n
"
<<
" return false;
\n
"
;
for
(
auto
&
val
:
enum_values
)
out
<<
" case "
<<
case_label_prefix
<<
val
<<
":
\n
"
;
out
<<
" out = result;
\n
"
<<
" return true;
\n
"
<<
" };
\n
"
<<
"}
\n\n
"
;
// Done. Print file footer and exit.
for
(
auto
i
=
namespaces
.
rbegin
();
i
!=
namespaces
.
rend
();
++
i
)
out
<<
"} // namespace "
<<
*
i
<<
'\n'
;
out
<<
"
\n
CAF_POP_WARNINGS
\n
"
;
return
EXIT_SUCCESS
;
}
examples/custom_type/custom_types_1.cpp
View file @
dc04d789
...
...
@@ -94,14 +94,14 @@ void caf_main(actor_system& sys) {
binary_serializer
::
container_type
buf
;
// write f1 to buffer
binary_serializer
sink
{
sys
,
buf
};
if
(
!
sink
.
apply
_object
(
f1
))
{
if
(
!
sink
.
apply
(
f1
))
{
std
::
cerr
<<
"*** failed to serialize foo2: "
<<
to_string
(
sink
.
get_error
())
<<
'\n'
;
return
;
}
// read f2 back from buffer
binary_deserializer
source
{
sys
,
buf
};
if
(
!
source
.
apply
_object
(
f2
))
{
if
(
!
source
.
apply
(
f2
))
{
std
::
cerr
<<
"*** failed to deserialize foo2: "
<<
to_string
(
source
.
get_error
())
<<
'\n'
;
return
;
...
...
libcaf_core/caf/binary_deserializer.hpp
View file @
dc04d789
...
...
@@ -21,9 +21,11 @@
#include <cstddef>
#include <string>
#include <tuple>
#include <type_traits>
#include <utility>
#include "caf/detail/core_export.hpp"
#include "caf/detail/squashed_int.hpp"
#include "caf/error_code.hpp"
#include "caf/fwd.hpp"
#include "caf/load_inspector_base.hpp"
...
...
@@ -37,6 +39,10 @@ namespace caf {
class
CAF_CORE_EXPORT
binary_deserializer
:
public
load_inspector_base
<
binary_deserializer
>
{
public:
// -- member types -----------------------------------------------------------
using
super
=
load_inspector_base
<
binary_deserializer
>
;
// -- constructors, destructors, and assignment operators --------------------
template
<
class
Container
>
...
...
@@ -107,11 +113,11 @@ public:
bool
fetch_next_object_type
(
type_id_t
&
type
)
noexcept
;
constexpr
bool
begin_object
(
string_view
)
noexcept
{
return
ok
;
return
true
;
}
constexpr
bool
end_object
()
noexcept
{
return
ok
;
return
true
;
}
constexpr
bool
begin_field
(
string_view
)
noexcept
{
...
...
@@ -127,29 +133,29 @@ public:
span
<
const
type_id_t
>
types
,
size_t
&
index
)
noexcept
;
constexpr
bool
end_field
()
{
return
ok
;
return
true
;
}
constexpr
bool
begin_tuple
(
size_t
)
noexcept
{
return
ok
;
return
true
;
}
constexpr
bool
end_tuple
()
noexcept
{
return
ok
;
return
true
;
}
constexpr
bool
begin_key_value_pair
()
noexcept
{
return
ok
;
return
true
;
}
constexpr
bool
end_key_value_pair
()
noexcept
{
return
ok
;
return
true
;
}
bool
begin_sequence
(
size_t
&
list_size
)
noexcept
;
constexpr
bool
end_sequence
()
noexcept
{
return
ok
;
return
true
;
}
bool
begin_associative_array
(
size_t
&
size
)
noexcept
{
...
...
@@ -180,6 +186,17 @@ public:
bool
value
(
uint64_t
&
x
)
noexcept
;
template
<
class
T
>
std
::
enable_if_t
<
std
::
is_integral
<
T
>::
value
,
bool
>
value
(
T
&
x
)
noexcept
{
auto
tmp
=
detail
::
squashed_int_t
<
T
>
{
0
};
if
(
value
(
tmp
))
{
x
=
static_cast
<
T
>
(
tmp
);
return
true
;
}
else
{
return
false
;
}
}
bool
value
(
float
&
x
)
noexcept
;
bool
value
(
double
&
x
)
noexcept
;
...
...
libcaf_core/caf/binary_serializer.hpp
View file @
dc04d789
...
...
@@ -20,11 +20,13 @@
#include <cstddef>
#include <string>
#include <type_traits>
#include <vector>
#include "caf/byte.hpp"
#include "caf/byte_buffer.hpp"
#include "caf/detail/core_export.hpp"
#include "caf/detail/squashed_int.hpp"
#include "caf/fwd.hpp"
#include "caf/save_inspector_base.hpp"
#include "caf/span.hpp"
...
...
@@ -37,6 +39,8 @@ class CAF_CORE_EXPORT binary_serializer
public:
// -- member types -----------------------------------------------------------
using
super
=
save_inspector_base
<
binary_serializer
>
;
using
container_type
=
byte_buffer
;
using
value_type
=
byte
;
...
...
@@ -94,15 +98,15 @@ public:
bool
inject_next_object_type
(
type_id_t
type
);
constexpr
bool
begin_object
(
string_view
)
{
return
ok
;
return
true
;
}
constexpr
bool
end_object
()
{
return
ok
;
return
true
;
}
constexpr
bool
begin_field
(
string_view
)
noexcept
{
return
ok
;
return
true
;
}
bool
begin_field
(
string_view
,
bool
is_present
);
...
...
@@ -113,29 +117,29 @@ public:
size_t
index
);
constexpr
bool
end_field
()
{
return
ok
;
return
true
;
}
constexpr
bool
begin_tuple
(
size_t
)
{
return
ok
;
return
true
;
}
constexpr
bool
end_tuple
()
{
return
ok
;
return
true
;
}
constexpr
bool
begin_key_value_pair
()
{
return
ok
;
return
true
;
}
constexpr
bool
end_key_value_pair
()
{
return
ok
;
return
true
;
}
bool
begin_sequence
(
size_t
list_size
);
constexpr
bool
end_sequence
()
{
return
ok
;
return
true
;
}
bool
begin_associative_array
(
size_t
size
)
{
...
...
@@ -166,6 +170,11 @@ public:
bool
value
(
uint64_t
x
);
template
<
class
T
>
std
::
enable_if_t
<
std
::
is_integral
<
T
>::
value
,
bool
>
value
(
T
x
)
{
return
value
(
static_cast
<
detail
::
squashed_int_t
<
T
>>
(
x
));
}
bool
value
(
float
x
);
bool
value
(
double
x
);
...
...
libcaf_core/caf/config_value.hpp
View file @
dc04d789
...
...
@@ -942,7 +942,7 @@ struct inspect_config_value_access {
static
optional
<
T
>
get_if
(
const
config_value
*
x
)
{
config_value_reader
reader
{
x
};
auto
tmp
=
T
{};
if
(
detail
::
load
_value
(
reader
,
tmp
))
if
(
detail
::
load
(
reader
,
tmp
))
return
optional
<
T
>
{
std
::
move
(
tmp
)};
return
none
;
}
...
...
@@ -985,7 +985,7 @@ struct inspect_config_value_access {
static
config_value
convert
(
const
T
&
x
)
{
config_value
result
;
config_value_writer
writer
{
&
result
};
if
(
!
detail
::
save
_value
(
writer
,
x
))
if
(
!
detail
::
save
(
writer
,
x
))
CAF_RAISE_ERROR
(
"unable to convert type to a config_value"
);
return
result
;
}
...
...
libcaf_core/caf/config_value_reader.hpp
View file @
dc04d789
...
...
@@ -131,6 +131,8 @@ public:
bool
end_associative_array
()
override
;
bool
value
(
byte
&
x
)
override
;
bool
value
(
bool
&
x
)
override
;
bool
value
(
int8_t
&
x
)
override
;
...
...
libcaf_core/caf/config_value_writer.hpp
View file @
dc04d789
...
...
@@ -102,6 +102,8 @@ public:
bool
end_associative_array
()
override
;
bool
value
(
byte
x
)
override
;
bool
value
(
bool
x
)
override
;
bool
value
(
int8_t
x
)
override
;
...
...
libcaf_core/caf/cow_tuple.hpp
View file @
dc04d789
...
...
@@ -136,19 +136,11 @@ struct inspector_access<cow_tuple<Ts...>> {
using
value_type
=
cow_tuple
<
Ts
...
>
;
template
<
class
Inspector
>
static
bool
apply
_object
(
Inspector
&
f
,
value_type
&
x
)
{
static
bool
apply
(
Inspector
&
f
,
value_type
&
x
)
{
if
constexpr
(
Inspector
::
is_loading
)
return
detail
::
load_object
(
f
,
x
.
unshared
());
return
f
.
tuple
(
x
.
unshared
());
else
return
detail
::
save_object
(
f
,
detail
::
as_mutable_ref
(
x
.
data
()));
}
template
<
class
Inspector
>
static
bool
apply_value
(
Inspector
&
f
,
value_type
&
x
)
{
if
constexpr
(
Inspector
::
is_loading
)
return
detail
::
load_value
(
f
,
x
.
unshared
());
else
return
detail
::
save_value
(
f
,
detail
::
as_mutable_ref
(
x
.
data
()));
return
f
.
tuple
(
x
.
data
());
}
template
<
class
Inspector
>
...
...
libcaf_core/caf/deep_to_string.hpp
View file @
dc04d789
...
...
@@ -35,7 +35,7 @@ std::string deep_to_string(const T& x) {
using
inspector_type
=
detail
::
stringification_inspector
;
std
::
string
result
;
inspector_type
f
{
result
};
detail
::
save
_value
(
f
,
detail
::
as_mutable_ref
(
x
));
detail
::
save
(
f
,
detail
::
as_mutable_ref
(
x
));
return
result
;
}
...
...
libcaf_core/caf/default_enum_inspect.hpp
0 → 100644
View file @
dc04d789
/******************************************************************************
* ____ _ _____ *
* / ___| / \ | ___| C++ *
* | | / _ \ | |_ Actor *
* | |___ / ___ \| _| Framework *
* \____/_/ \_|_| *
* *
* Copyright 2011-2020 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 <string>
#include <type_traits>
#include "caf/string_view.hpp"
namespace
caf
{
/// Convenience function for providing a default inspection scaffold for custom
/// enumeration types.
///
/// The enumeration type must provide the following interface based on free
/// functions:
///
/// ~~~(cpp)
/// enum class Enumeration : ... { ... };
/// std::string to_string(Enumeration);
/// bool from_string(string_view, Enumeration&);
/// bool from_integer(std::underlying_type_t<Enumeration>, Enumeration&);
/// ~~~
template
<
class
Inspector
,
class
Enumeration
>
bool
default_enum_inspect
(
Inspector
&
f
,
Enumeration
&
x
)
{
using
integer_type
=
std
::
underlying_type_t
<
Enumeration
>
;
if
(
f
.
has_human_readable_format
())
{
auto
get
=
[
&
x
]
{
return
to_string
(
x
);
};
auto
set
=
[
&
x
](
string_view
str
)
{
return
from_string
(
str
,
x
);
};
return
f
.
apply
(
get
,
set
);
}
else
{
auto
get
=
[
&
x
]
{
return
static_cast
<
integer_type
>
(
x
);
};
auto
set
=
[
&
x
](
integer_type
val
)
{
return
from_integer
(
val
,
x
);
};
return
f
.
apply
(
get
,
set
);
}
}
}
// namespace caf
libcaf_core/caf/deserializer.hpp
View file @
dc04d789
...
...
@@ -26,6 +26,7 @@
#include "caf/byte.hpp"
#include "caf/detail/core_export.hpp"
#include "caf/detail/squashed_int.hpp"
#include "caf/fwd.hpp"
#include "caf/load_inspector_base.hpp"
#include "caf/span.hpp"
...
...
@@ -37,6 +38,10 @@ namespace caf {
/// Technology-independent deserialization interface.
class
CAF_CORE_EXPORT
deserializer
:
public
load_inspector_base
<
deserializer
>
{
public:
// -- member types -----------------------------------------------------------
using
super
=
load_inspector_base
<
deserializer
>
;
// -- constructors, destructors, and assignment operators --------------------
explicit
deserializer
(
actor_system
&
sys
)
noexcept
;
...
...
@@ -111,9 +116,12 @@ public:
/// @note the default implementation calls `end_sequence()`.
virtual
bool
end_associative_array
();
/// Reads primitive value from the input.
/// @param x The primitive value.
/// @returns A non-zero error code on failure, `sec::success` otherwise.
/// Reads `x` from the input.
/// @param x A reference to a builtin type.
/// @returns `true` on success, `false` otherwise.
virtual
bool
value
(
byte
&
x
)
=
0
;
/// @copydoc value
virtual
bool
value
(
bool
&
x
)
=
0
;
/// @copydoc value
...
...
@@ -140,6 +148,17 @@ public:
/// @copydoc value
virtual
bool
value
(
uint64_t
&
)
=
0
;
/// @copydoc value
template
<
class
T
>
std
::
enable_if_t
<
std
::
is_integral
<
T
>::
value
,
bool
>
value
(
T
&
x
)
noexcept
{
auto
tmp
=
detail
::
squashed_int_t
<
T
>
{
0
};
if
(
value
(
tmp
))
{
x
=
static_cast
<
T
>
(
tmp
);
return
true
;
}
else
{
return
false
;
}
}
/// @copydoc value
virtual
bool
value
(
float
&
)
=
0
;
...
...
@@ -163,10 +182,12 @@ public:
/// @returns A non-zero error code on failure, `sec::success` otherwise.
virtual
bool
value
(
span
<
byte
>
x
)
=
0
;
using
super
::
list
;
/// 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
/// for each value in a binary output format.
virtual
bool
value
(
std
::
vector
<
bool
>&
xs
);
virtual
bool
list
(
std
::
vector
<
bool
>&
xs
);
protected:
/// Provides access to the ::proxy_registry and to the ::actor_system.
...
...
libcaf_core/caf/detail/make_meta_object.hpp
View file @
dc04d789
...
...
@@ -50,28 +50,28 @@ void copy_construct(void* ptr, const void* src) {
template
<
class
T
>
bool
save_binary
(
binary_serializer
&
sink
,
const
void
*
ptr
)
{
return
sink
.
apply
_object
(
*
static_cast
<
const
T
*>
(
ptr
));
return
sink
.
apply
(
*
static_cast
<
const
T
*>
(
ptr
));
}
template
<
class
T
>
bool
load_binary
(
binary_deserializer
&
source
,
void
*
ptr
)
{
return
source
.
apply
_object
(
*
static_cast
<
T
*>
(
ptr
));
return
source
.
apply
(
*
static_cast
<
T
*>
(
ptr
));
}
template
<
class
T
>
bool
save
(
serializer
&
sink
,
const
void
*
ptr
)
{
return
sink
.
apply
_object
(
*
static_cast
<
const
T
*>
(
ptr
));
return
sink
.
apply
(
*
static_cast
<
const
T
*>
(
ptr
));
}
template
<
class
T
>
bool
load
(
deserializer
&
source
,
void
*
ptr
)
{
return
source
.
apply
_object
(
*
static_cast
<
T
*>
(
ptr
));
return
source
.
apply
(
*
static_cast
<
T
*>
(
ptr
));
}
template
<
class
T
>
void
stringify
(
std
::
string
&
buf
,
const
void
*
ptr
)
{
stringification_inspector
f
{
buf
};
auto
unused
=
f
.
apply
_object
(
*
static_cast
<
const
T
*>
(
ptr
));
auto
unused
=
f
.
apply
(
*
static_cast
<
const
T
*>
(
ptr
));
static_cast
<
void
>
(
unused
);
}
...
...
libcaf_core/caf/detail/serialized_size.hpp
View file @
dc04d789
...
...
@@ -58,6 +58,8 @@ public:
bool
end_sequence
()
override
;
bool
value
(
byte
x
)
override
;
bool
value
(
bool
x
)
override
;
bool
value
(
int8_t
x
)
override
;
...
...
@@ -90,13 +92,15 @@ public:
bool
value
(
span
<
const
byte
>
x
)
override
;
bool
value
(
const
std
::
vector
<
bool
>&
xs
)
override
;
using
super
::
list
;
bool
list
(
const
std
::
vector
<
bool
>&
xs
)
override
;
};
template
<
class
T
>
size_t
serialized_size
(
const
T
&
x
)
{
serialized_size_inspector
f
;
auto
unused
=
f
.
apply
_object
(
x
);
auto
unused
=
f
.
apply
(
x
);
static_cast
<
void
>
(
unused
);
// Always true.
return
f
.
result
;
}
...
...
@@ -104,7 +108,7 @@ size_t serialized_size(const T& x) {
template
<
class
T
>
size_t
serialized_size
(
actor_system
&
sys
,
const
T
&
x
)
{
serialized_size_inspector
f
{
sys
};
auto
unused
=
f
.
apply
_object
(
x
);
auto
unused
=
f
.
apply
(
x
);
static_cast
<
void
>
(
unused
);
// Always true.
return
f
.
result
;
}
...
...
libcaf_core/caf/detail/size_based_credit_controller.hpp
View file @
dc04d789
...
...
@@ -66,7 +66,7 @@ public:
this
->
inspector_
.
result
=
0
;
this
->
sampled_elements_
+=
x
.
xs_size
;
for
(
auto
&
element
:
x
.
xs
.
get_as
<
std
::
vector
<
T
>>
(
0
))
detail
::
save
_value
(
this
->
inspector_
,
element
);
detail
::
save
(
this
->
inspector_
,
element
);
this
->
sampled_total_size_
+=
static_cast
<
int64_t
>
(
this
->
inspector_
.
result
);
}
...
...
libcaf_core/caf/detail/stringification_inspector.hpp
View file @
dc04d789
...
...
@@ -40,7 +40,7 @@ class CAF_CORE_EXPORT stringification_inspector
public:
// -- member types -----------------------------------------------------------
using
super
=
save_inspector
;
using
super
=
save_inspector
_base
<
stringification_inspector
>
;
// -- constructors, destructors, and assignment operators --------------------
...
...
@@ -100,6 +100,8 @@ public:
return
end_sequence
();
}
bool
value
(
byte
x
);
bool
value
(
bool
x
);
template
<
class
Integral
>
...
...
@@ -126,7 +128,11 @@ public:
bool
value
(
const
std
::
u32string
&
x
);
bool
value
(
const
std
::
vector
<
bool
>&
xs
);
bool
value
(
span
<
const
byte
>
x
);
using
super
::
list
;
bool
list
(
const
std
::
vector
<
bool
>&
xs
);
// -- builtin inspection to pick up to_string or provide nicer formatting ----
...
...
@@ -146,14 +152,14 @@ public:
return
true
;
}
result_
+=
'{'
;
save
_value
(
*
this
,
i
->
first
);
save
(
*
this
,
i
->
first
);
result_
+=
" = "
;
save
_value
(
*
this
,
i
->
second
);
save
(
*
this
,
i
->
second
);
while
(
++
i
!=
last
)
{
sep
();
save
_value
(
*
this
,
i
->
first
);
save
(
*
this
,
i
->
first
);
result_
+=
" = "
;
save
_value
(
*
this
,
i
->
second
);
save
(
*
this
,
i
->
second
);
}
result_
+=
'}'
;
return
true
;
...
...
@@ -186,7 +192,7 @@ public:
}
else
{
sep
();
result_
+=
'*'
;
save
_value
(
*
this
,
detail
::
as_mutable_ref
(
*
x
));
save
(
*
this
,
detail
::
as_mutable_ref
(
*
x
));
return
true
;
}
}
...
...
@@ -198,7 +204,7 @@ public:
result_
+=
"null"
;
}
else
{
result_
+=
'*'
;
save
_value
(
*
this
,
detail
::
as_mutable_ref
(
*
x
));
save
(
*
this
,
detail
::
as_mutable_ref
(
*
x
));
}
return
true
;
}
...
...
@@ -228,7 +234,7 @@ private:
sep
();
result_
+=
'['
;
while
(
first
!=
sentinel
)
save
_value
(
*
this
,
*
first
++
);
save
(
*
this
,
*
first
++
);
result_
+=
']'
;
}
...
...
libcaf_core/caf/detail/type_traits.hpp
View file @
dc04d789
...
...
@@ -878,23 +878,6 @@ public:
static
constexpr
bool
value
=
result_type
::
value
;
};
/// Checks whether `T` provides an `inspect_value` overload for `Inspector`.
template
<
class
Inspector
,
class
T
>
class
has_inspect_value_overload
{
private:
template
<
class
U
>
static
auto
sfinae
(
Inspector
&
x
,
U
&
y
)
->
decltype
(
inspect_value
(
x
,
y
),
std
::
true_type
{});
static
std
::
false_type
sfinae
(
Inspector
&
,
...);
using
result_type
=
decltype
(
sfinae
(
std
::
declval
<
Inspector
&>
(),
std
::
declval
<
T
&>
()));
public:
static
constexpr
bool
value
=
result_type
::
value
;
};
/// Checks whether the inspector has a `builtin_inspect` overload for `T`.
template
<
class
Inspector
,
class
T
>
class
has_builtin_inspect
{
...
...
@@ -980,6 +963,48 @@ public:
static
constexpr
bool
value
=
sfinae_result
::
value
;
};
/// Checks whether `T` is primitive, i.e., either an arithmetic type or
/// convertible to one of STL's string types.
template
<
class
T
,
bool
IsLoading
>
struct
is_builtin_inspector_type
{
static
constexpr
bool
value
=
std
::
is_arithmetic
<
T
>::
value
;
};
template
<
bool
IsLoading
>
struct
is_builtin_inspector_type
<
byte
,
IsLoading
>
{
static
constexpr
bool
value
=
true
;
};
template
<
bool
IsLoading
>
struct
is_builtin_inspector_type
<
span
<
byte
>
,
IsLoading
>
{
static
constexpr
bool
value
=
true
;
};
template
<
bool
IsLoading
>
struct
is_builtin_inspector_type
<
std
::
string
,
IsLoading
>
{
static
constexpr
bool
value
=
true
;
};
template
<
bool
IsLoading
>
struct
is_builtin_inspector_type
<
std
::
u16string
,
IsLoading
>
{
static
constexpr
bool
value
=
true
;
};
template
<
bool
IsLoading
>
struct
is_builtin_inspector_type
<
std
::
u32string
,
IsLoading
>
{
static
constexpr
bool
value
=
true
;
};
template
<
>
struct
is_builtin_inspector_type
<
string_view
,
false
>
{
static
constexpr
bool
value
=
true
;
};
template
<
>
struct
is_builtin_inspector_type
<
span
<
const
byte
>
,
false
>
{
static
constexpr
bool
value
=
true
;
};
}
// namespace caf::detail
#undef CAF_HAS_MEMBER_TRAIT
...
...
libcaf_core/caf/exit_reason.hpp
View file @
dc04d789
...
...
@@ -24,8 +24,11 @@
#include <cstdint>
#include <string>
#include <type_traits>
#include "caf/default_enum_inspect.hpp"
#include "caf/detail/core_export.hpp"
#include "caf/fwd.hpp"
#include "caf/is_error_code_enum.hpp"
namespace
caf
{
...
...
@@ -55,6 +58,18 @@ enum class exit_reason : uint8_t {
/// @relates exit_reason
CAF_CORE_EXPORT
std
::
string
to_string
(
exit_reason
);
/// @relates exit_reason
CAF_CORE_EXPORT
bool
from_string
(
string_view
,
exit_reason
&
);
/// @relates exit_reason
CAF_CORE_EXPORT
bool
from_integer
(
std
::
underlying_type_t
<
exit_reason
>
,
exit_reason
&
);
template
<
class
Inspector
>
bool
inspect
(
Inspector
&
f
,
exit_reason
&
x
)
{
return
default_enum_inspect
(
f
,
x
);
}
}
// namespace caf
CAF_ERROR_CODE_ENUM
(
exit_reason
)
libcaf_core/caf/fwd.hpp
View file @
dc04d789
...
...
@@ -196,7 +196,7 @@ enum class exit_reason : uint8_t;
enum
class
invoke_message_result
;
enum
class
pec
:
uint8_t
;
enum
class
sec
:
uint8_t
;
enum
class
stream_priority
;
enum
class
stream_priority
:
uint8_t
;
// -- aliases ------------------------------------------------------------------
...
...
libcaf_core/caf/hash/fnv.hpp
View file @
dc04d789
...
...
@@ -43,6 +43,8 @@ class fnv : public save_inspector_base<fnv<T>> {
public:
static_assert
(
sizeof
(
T
)
==
4
||
sizeof
(
T
)
==
8
);
using
super
=
save_inspector_base
<
fnv
<
T
>>
;
constexpr
fnv
()
noexcept
:
result
(
init
())
{
// nop
}
...
...
@@ -154,7 +156,7 @@ public:
static
T
compute
(
Ts
&&
...
xs
)
noexcept
{
using
detail
::
as_mutable_ref
;
fnv
f
;
auto
unused
=
f
.
apply_objects
(
xs
...);
auto
unused
=
(
f
.
apply
(
xs
)
&&
...);
static_cast
<
void
>
(
unused
);
// Always true.
return
f
.
result
;
}
...
...
libcaf_core/caf/hash/sha1.hpp
View file @
dc04d789
...
...
@@ -37,6 +37,9 @@ public:
/// Hash size in bytes.
static
constexpr
size_t
hash_size
=
20
;
/// Alias to the super types.
using
super
=
save_inspector_base
<
sha1
>
;
/// Array type for storing a 160-bit hash.
using
result_type
=
std
::
array
<
byte
,
hash_size
>
;
...
...
@@ -152,7 +155,7 @@ public:
static
result_type
compute
(
Ts
&&
...
xs
)
noexcept
{
using
detail
::
as_mutable_ref
;
sha1
f
;
auto
unused
=
f
.
apply
_objects
(
xs
...);
auto
unused
=
f
.
apply
(
xs
...);
static_cast
<
void
>
(
unused
);
// Always true.
return
f
.
result
();
}
...
...
libcaf_core/caf/inspector_access.hpp
View file @
dc04d789
...
...
@@ -70,140 +70,97 @@ constexpr auto always_true = always_true_t{};
template
<
class
>
constexpr
bool
assertion_failed_v
=
false
;
// -- loading ------------------------------------------------------------------
// TODO: remove with CAF 0.19
template
<
class
T
,
class
Inspector
,
class
Obj
>
class
has_static_apply
{
private:
template
<
class
U
>
static
auto
sfinae
(
Inspector
*
f
,
Obj
*
x
)
->
decltype
(
U
::
apply
(
*
f
,
*
x
),
std
::
true_type
());
template
<
class
Inspector
,
class
T
>
bool
load_value
(
Inspector
&
f
,
T
&
x
)
;
template
<
class
U
>
static
auto
sfinae
(...)
->
std
::
false_type
;
template
<
class
Inspector
,
class
T
>
bool
load_value
(
Inspector
&
f
,
T
&
x
,
inspector_access_type
::
specialization
)
{
return
inspector_access
<
T
>::
apply_value
(
f
,
x
);
}
using
sfinae_type
=
decltype
(
sfinae
<
T
>
(
nullptr
,
nullptr
));
template
<
class
Inspector
,
class
T
>
bool
load_value
(
Inspector
&
f
,
T
&
x
,
inspector_access_type
::
inspect_value
)
{
return
inspect_value
(
f
,
x
);
}
public:
static
constexpr
bool
value
=
sfinae_type
::
value
;
};
template
<
class
T
,
class
Inspector
,
class
Obj
>
constexpr
bool
has_static_apply_v
=
has_static_apply
<
T
,
Inspector
,
Obj
>::
value
;
// -- loading ------------------------------------------------------------------
// TODO: remove with CAF 0.19
template
<
class
Inspector
,
class
T
>
bool
load_value
(
Inspector
&
f
,
T
&
x
,
inspector_access_type
::
inspect
)
{
return
inspect
(
f
,
x
);
[[
deprecated
(
"please provide apply instead of apply_object/apply_value"
)]]
//
std
::
enable_if_t
<!
has_static_apply_v
<
inspector_access
<
T
>
,
Inspector
,
T
>
,
bool
>
load
(
Inspector
&
f
,
T
&
x
,
inspector_access_type
::
specialization
)
{
return
inspector_access
<
T
>::
apply_value
(
f
,
x
);
}
template
<
class
Inspector
,
class
T
>
bool
load_value
(
Inspector
&
f
,
T
&
x
,
inspector_access_type
::
integral
)
{
auto
tmp
=
detail
::
squashed_int_t
<
T
>
{
0
};
if
(
f
.
value
(
tmp
))
{
x
=
static_cast
<
T
>
(
tmp
);
return
true
;
}
return
false
;
std
::
enable_if_t
<
has_static_apply_v
<
inspector_access
<
T
>
,
Inspector
,
T
>
,
bool
>
load
(
Inspector
&
f
,
T
&
x
,
inspector_access_type
::
specialization
)
{
return
inspector_access
<
T
>::
apply
(
f
,
x
);
}
template
<
class
Inspector
,
class
T
>
bool
load
_value
(
Inspector
&
f
,
T
&
x
,
inspector_access_type
::
builtin
)
{
return
f
.
builtin_inspect
(
x
);
bool
load
(
Inspector
&
f
,
T
&
x
,
inspector_access_type
::
inspect
)
{
return
inspect
(
f
,
x
);
}
template
<
class
Inspector
,
class
T
>
bool
load
_value
(
Inspector
&
f
,
T
&
x
,
inspector_access_type
::
trivial
)
{
bool
load
(
Inspector
&
f
,
T
&
x
,
inspector_access_type
::
builtin
)
{
return
f
.
value
(
x
);
}
template
<
class
Inspector
,
class
T
>
bool
load_value
(
Inspector
&
f
,
T
&
x
,
inspector_access_type
::
enumeration
)
{
auto
tmp
=
detail
::
squashed_int_t
<
std
::
underlying_type_t
<
T
>>
{
0
};
if
(
f
.
value
(
tmp
))
{
x
=
static_cast
<
T
>
(
tmp
);
return
true
;
}
return
false
;
bool
load
(
Inspector
&
f
,
T
&
x
,
inspector_access_type
::
builtin_inspect
)
{
return
f
.
builtin_inspect
(
x
);
}
template
<
class
Inspector
,
class
T
>
bool
load
_value
(
Inspector
&
f
,
T
&
x
,
inspector_access_type
::
empty
)
{
bool
load
(
Inspector
&
f
,
T
&
x
,
inspector_access_type
::
empty
)
{
return
f
.
object
(
x
).
fields
();
}
template
<
class
Inspector
,
class
T
>
bool
load
_value
(
Inspector
&
f
,
T
&
,
inspector_access_type
::
unsafe
)
{
bool
load
(
Inspector
&
f
,
T
&
,
inspector_access_type
::
unsafe
)
{
f
.
emplace_error
(
sec
::
unsafe_type
);
return
false
;
}
template
<
class
Inspector
,
class
T
,
size_t
N
>
bool
load_value
(
Inspector
&
f
,
T
(
&
xs
)[
N
],
inspector_access_type
::
array
)
{
if
(
!
f
.
begin_tuple
(
N
))
return
false
;
for
(
size_t
index
=
0
;
index
<
N
;
++
index
)
if
(
!
load_value
(
f
,
xs
[
index
]))
return
false
;
return
f
.
end_tuple
();
}
template
<
class
Inspector
,
class
T
,
size_t
...
Ns
>
bool
load_tuple
(
Inspector
&
f
,
T
&
xs
,
std
::
index_sequence
<
Ns
...
>
)
{
return
f
.
begin_tuple
(
sizeof
...(
Ns
))
//
&&
(
load_value
(
f
,
get
<
Ns
>
(
xs
))
&&
...)
//
&&
f
.
end_tuple
();
bool
load
(
Inspector
&
f
,
T
(
&
xs
)[
N
],
inspector_access_type
::
tuple
)
{
return
f
.
tuple
(
xs
);
}
template
<
class
Inspector
,
class
T
>
bool
load_value
(
Inspector
&
f
,
T
&
x
,
inspector_access_type
::
tuple
)
{
return
load_tuple
(
f
,
x
,
std
::
make_index_sequence
<
std
::
tuple_size
<
T
>::
value
>
{});
bool
load
(
Inspector
&
f
,
T
&
xs
,
inspector_access_type
::
tuple
)
{
return
f
.
tuple
(
xs
);
}
template
<
class
Inspector
,
class
T
>
bool
load_value
(
Inspector
&
f
,
T
&
x
,
inspector_access_type
::
map
)
{
x
.
clear
();
size_t
size
=
0
;
if
(
!
f
.
begin_associative_array
(
size
))
return
false
;
for
(
size_t
i
=
0
;
i
<
size
;
++
i
)
{
auto
key
=
typename
T
::
key_type
{};
auto
val
=
typename
T
::
mapped_type
{};
if
(
!
(
f
.
begin_key_value_pair
()
//
&&
load_value
(
f
,
key
)
//
&&
load_value
(
f
,
val
)
//
&&
f
.
end_key_value_pair
()))
return
false
;
// A multimap returns an iterator, a regular map returns a pair.
auto
emplace_result
=
x
.
emplace
(
std
::
move
(
key
),
std
::
move
(
val
));
if
constexpr
(
is_pair
<
decltype
(
emplace_result
)
>::
value
)
{
if
(
!
emplace_result
.
second
)
{
f
.
emplace_error
(
sec
::
runtime_error
,
"multiple key definitions"
);
return
false
;
}
}
}
return
f
.
end_associative_array
();
bool
load
(
Inspector
&
f
,
T
&
x
,
inspector_access_type
::
map
)
{
return
f
.
map
(
x
);
}
template
<
class
Inspector
,
class
T
>
bool
load_value
(
Inspector
&
f
,
T
&
x
,
inspector_access_type
::
list
)
{
x
.
clear
();
size_t
size
=
0
;
if
(
!
f
.
begin_sequence
(
size
))
return
false
;
for
(
size_t
i
=
0
;
i
<
size
;
++
i
)
{
auto
val
=
typename
T
::
value_type
{};
if
(
!
detail
::
load_value
(
f
,
val
))
return
false
;
x
.
insert
(
x
.
end
(),
std
::
move
(
val
));
}
return
f
.
end_sequence
();
bool
load
(
Inspector
&
f
,
T
&
x
,
inspector_access_type
::
list
)
{
return
f
.
list
(
x
);
}
template
<
class
Inspector
,
class
T
>
std
::
enable_if_t
<
accepts_opaque_value
<
Inspector
,
T
>::
value
,
bool
>
load
_value
(
Inspector
&
f
,
T
&
x
,
inspector_access_type
::
none
)
{
load
(
Inspector
&
f
,
T
&
x
,
inspector_access_type
::
none
)
{
return
f
.
opaque_value
(
x
);
}
template
<
class
Inspector
,
class
T
>
std
::
enable_if_t
<!
accepts_opaque_value
<
Inspector
,
T
>::
value
,
bool
>
load
_value
(
Inspector
&
,
T
&
,
inspector_access_type
::
none
)
{
load
(
Inspector
&
,
T
&
,
inspector_access_type
::
none
)
{
static_assert
(
detail
::
assertion_failed_v
<
T
>
,
"please provide an inspect overload for T or specialize inspector_access"
);
...
...
@@ -211,28 +168,8 @@ load_value(Inspector&, T&, inspector_access_type::none) {
}
template
<
class
Inspector
,
class
T
>
bool
load_value
(
Inspector
&
f
,
T
&
x
)
{
return
load_value
(
f
,
x
,
inspect_value_access_type
<
Inspector
,
T
>
());
}
template
<
class
Inspector
,
class
T
>
bool
load_object
(
Inspector
&
f
,
T
&
x
,
inspector_access_type
::
specialization
)
{
return
inspector_access
<
T
>::
apply_object
(
f
,
x
);
}
template
<
class
Inspector
,
class
T
>
bool
load_object
(
Inspector
&
f
,
T
&
x
,
inspector_access_type
::
inspect
)
{
return
inspect
(
f
,
x
);
}
template
<
class
Inspector
,
class
T
,
class
Token
>
bool
load_object
(
Inspector
&
f
,
T
&
x
,
Token
)
{
return
f
.
object
(
x
).
fields
(
f
.
field
(
"value"
,
x
));
}
template
<
class
Inspector
,
class
T
>
bool
load_object
(
Inspector
&
f
,
T
&
x
)
{
return
load_object
(
f
,
x
,
inspect_object_access_type
<
Inspector
,
T
>
());
bool
load
(
Inspector
&
f
,
T
&
x
)
{
return
load
(
f
,
x
,
inspect_access_type
<
Inspector
,
T
>
());
}
template
<
class
Inspector
,
class
T
,
class
IsValid
,
class
SyncValue
>
...
...
@@ -256,117 +193,75 @@ bool load_field(Inspector& f, string_view field_name, T& x, IsValid& is_valid,
// -- saving -------------------------------------------------------------------
// TODO: remove with CAF 0.19
template
<
class
Inspector
,
class
T
>
bool
save_value
(
Inspector
&
f
,
T
&
x
);
template
<
class
Inspector
,
class
T
>
bool
save_value
(
Inspector
&
f
,
const
T
&
x
);
template
<
class
Inspector
,
class
T
>
bool
save_value
(
Inspector
&
f
,
T
&
x
,
inspector_access_type
::
specialization
)
{
[[
deprecated
(
"please provide apply instead of apply_object/apply_value"
)]]
//
std
::
enable_if_t
<!
has_static_apply_v
<
inspector_access
<
T
>
,
Inspector
,
T
>
,
bool
>
save
(
Inspector
&
f
,
T
&
x
,
inspector_access_type
::
specialization
)
{
return
inspector_access
<
T
>::
apply_value
(
f
,
x
);
}
template
<
class
Inspector
,
class
T
>
bool
save_value
(
Inspector
&
f
,
T
&
x
,
inspector_access_type
::
inspect_value
)
{
return
inspect_value
(
f
,
x
);
std
::
enable_if_t
<
has_static_apply_v
<
inspector_access
<
T
>
,
Inspector
,
T
>
,
bool
>
save
(
Inspector
&
f
,
T
&
x
,
inspector_access_type
::
specialization
)
{
return
inspector_access
<
T
>::
apply
(
f
,
x
);
}
template
<
class
Inspector
,
class
T
>
bool
save
_value
(
Inspector
&
f
,
T
&
x
,
inspector_access_type
::
inspect
)
{
bool
save
(
Inspector
&
f
,
T
&
x
,
inspector_access_type
::
inspect
)
{
return
inspect
(
f
,
x
);
}
template
<
class
Inspector
,
class
T
>
bool
save_value
(
Inspector
&
f
,
T
&
x
,
inspector_access_type
::
integral
)
{
auto
tmp
=
static_cast
<
detail
::
squashed_int_t
<
T
>>
(
x
);
return
f
.
value
(
tmp
);
}
template
<
class
Inspector
,
class
T
>
bool
save_value
(
Inspector
&
f
,
T
&
x
,
inspector_access_type
::
builtin
)
{
return
f
.
builtin_inspect
(
x
);
}
template
<
class
Inspector
,
class
T
>
bool
save_value
(
Inspector
&
f
,
T
&
x
,
inspector_access_type
::
trivial
)
{
bool
save
(
Inspector
&
f
,
T
&
x
,
inspector_access_type
::
builtin
)
{
return
f
.
value
(
x
);
}
template
<
class
Inspector
,
class
T
>
bool
save_value
(
Inspector
&
f
,
T
&
x
,
inspector_access_type
::
enumeration
)
{
auto
tmp
=
static_cast
<
detail
::
squashed_int_t
<
std
::
underlying_type_t
<
T
>>>
(
x
);
return
f
.
value
(
tmp
);
bool
save
(
Inspector
&
f
,
T
&
x
,
inspector_access_type
::
builtin_inspect
)
{
return
f
.
builtin_inspect
(
x
);
}
template
<
class
Inspector
,
class
T
>
bool
save
_value
(
Inspector
&
f
,
T
&
x
,
inspector_access_type
::
empty
)
{
bool
save
(
Inspector
&
f
,
T
&
x
,
inspector_access_type
::
empty
)
{
return
f
.
object
(
x
).
fields
();
}
template
<
class
Inspector
,
class
T
>
bool
save
_value
(
Inspector
&
f
,
T
&
,
inspector_access_type
::
unsafe
)
{
bool
save
(
Inspector
&
f
,
T
&
,
inspector_access_type
::
unsafe
)
{
f
.
emplace_error
(
sec
::
unsafe_type
);
return
false
;
}
template
<
class
Inspector
,
class
T
,
size_t
N
>
bool
save_value
(
Inspector
&
f
,
T
(
&
xs
)[
N
],
inspector_access_type
::
array
)
{
if
(
!
f
.
begin_tuple
(
N
))
return
false
;
for
(
size_t
index
=
0
;
index
<
N
;
++
index
)
if
(
!
save_value
(
f
,
xs
[
index
]))
return
false
;
return
f
.
end_tuple
();
}
template
<
class
Inspector
,
class
T
,
size_t
...
Ns
>
bool
save_tuple
(
Inspector
&
f
,
T
&
xs
,
std
::
index_sequence
<
Ns
...
>
)
{
return
f
.
begin_tuple
(
sizeof
...(
Ns
))
//
&&
(
save_value
(
f
,
get
<
Ns
>
(
xs
))
&&
...)
//
&&
f
.
end_tuple
();
bool
save
(
Inspector
&
f
,
T
(
&
xs
)[
N
],
inspector_access_type
::
tuple
)
{
return
f
.
tuple
(
xs
);
}
template
<
class
Inspector
,
class
T
>
bool
save_value
(
Inspector
&
f
,
T
&
x
,
inspector_access_type
::
tuple
)
{
return
save_tuple
(
f
,
x
,
std
::
make_index_sequence
<
std
::
tuple_size
<
T
>::
value
>
{});
bool
save
(
Inspector
&
f
,
const
T
&
xs
,
inspector_access_type
::
tuple
)
{
return
f
.
tuple
(
xs
);
}
template
<
class
Inspector
,
class
T
>
bool
save_value
(
Inspector
&
f
,
T
&
x
,
inspector_access_type
::
map
)
{
if
(
!
f
.
begin_associative_array
(
x
.
size
()))
return
false
;
for
(
auto
&&
kvp
:
x
)
{
if
(
!
(
f
.
begin_key_value_pair
()
//
&&
save_value
(
f
,
kvp
.
first
)
//
&&
save_value
(
f
,
kvp
.
second
)
//
&&
f
.
end_key_value_pair
()))
return
false
;
}
return
f
.
end_associative_array
();
bool
save
(
Inspector
&
f
,
T
&
x
,
inspector_access_type
::
map
)
{
return
f
.
map
(
x
);
}
template
<
class
Inspector
,
class
T
>
bool
save_value
(
Inspector
&
f
,
T
&
x
,
inspector_access_type
::
list
)
{
auto
size
=
x
.
size
();
if
(
!
f
.
begin_sequence
(
size
))
return
false
;
for
(
auto
&&
val
:
x
)
if
(
!
save_value
(
f
,
val
))
return
false
;
return
f
.
end_sequence
();
bool
save
(
Inspector
&
f
,
T
&
x
,
inspector_access_type
::
list
)
{
return
f
.
list
(
x
);
}
template
<
class
Inspector
,
class
T
>
std
::
enable_if_t
<
accepts_opaque_value
<
Inspector
,
T
>::
value
,
bool
>
save
_value
(
Inspector
&
f
,
T
&
x
,
inspector_access_type
::
none
)
{
save
(
Inspector
&
f
,
T
&
x
,
inspector_access_type
::
none
)
{
return
f
.
opaque_value
(
x
);
}
template
<
class
Inspector
,
class
T
>
std
::
enable_if_t
<!
accepts_opaque_value
<
Inspector
,
T
>::
value
,
bool
>
save
_value
(
Inspector
&
,
T
&
,
inspector_access_type
::
none
)
{
save
(
Inspector
&
,
T
&
,
inspector_access_type
::
none
)
{
static_assert
(
detail
::
assertion_failed_v
<
T
>
,
"please provide an inspect overload for T or specialize inspector_access"
);
...
...
@@ -374,34 +269,13 @@ save_value(Inspector&, T&, inspector_access_type::none) {
}
template
<
class
Inspector
,
class
T
>
bool
save_value
(
Inspector
&
f
,
T
&
x
)
{
return
save_value
(
f
,
x
,
inspect_value_access_type
<
Inspector
,
T
>
());
}
template
<
class
Inspector
,
class
T
>
bool
save_value
(
Inspector
&
f
,
const
T
&
x
)
{
return
save_value
(
f
,
as_mutable_ref
(
x
),
inspect_value_access_type
<
Inspector
,
T
>
());
}
template
<
class
Inspector
,
class
T
>
bool
save_object
(
Inspector
&
f
,
T
&
x
,
inspector_access_type
::
specialization
)
{
return
inspector_access
<
T
>::
apply_object
(
f
,
x
);
}
template
<
class
Inspector
,
class
T
>
bool
save_object
(
Inspector
&
f
,
T
&
x
,
inspector_access_type
::
inspect
)
{
return
inspect
(
f
,
x
);
}
template
<
class
Inspector
,
class
T
,
class
Token
>
bool
save_object
(
Inspector
&
f
,
T
&
x
,
Token
)
{
return
f
.
object
(
x
).
fields
(
f
.
field
(
"value"
,
x
));
bool
save
(
Inspector
&
f
,
T
&
x
)
{
return
save
(
f
,
x
,
inspect_access_type
<
Inspector
,
T
>
());
}
template
<
class
Inspector
,
class
T
>
bool
save
_object
(
Inspector
&
f
,
T
&
x
)
{
return
save
_object
(
f
,
x
,
inspect_obj
ect_access_type
<
Inspector
,
T
>
());
bool
save
(
Inspector
&
f
,
const
T
&
x
)
{
return
save
(
f
,
as_mutable_ref
(
x
),
insp
ect_access_type
<
Inspector
,
T
>
());
}
template
<
class
Inspector
,
class
T
>
...
...
@@ -422,77 +296,13 @@ bool save_field(Inspector& f, string_view field_name, IsPresent& is_present,
return
impl
::
save_field
(
f
,
field_name
,
is_present
,
get
);
}
// -- dispatching to save or load using getter/setter API ----------------------
template
<
class
Inspector
,
class
T
>
bool
split_save_load
(
Inspector
&
f
,
T
&
x
)
{
if
constexpr
(
Inspector
::
is_loading
)
return
load_value
(
f
,
x
);
else
return
save_value
(
f
,
x
);
}
template
<
class
Inspector
,
class
Get
,
class
Set
>
bool
split_save_load
(
Inspector
&
f
,
Get
&&
get
,
Set
&&
set
)
{
using
value_type
=
std
::
decay_t
<
decltype
(
get
())
>
;
if
constexpr
(
Inspector
::
is_loading
)
{
auto
tmp
=
value_type
{};
if
(
load_value
(
f
,
tmp
))
return
set
(
std
::
move
(
tmp
));
return
false
;
}
else
{
auto
&&
x
=
get
();
return
save_value
(
f
,
x
);
}
}
}
// namespace caf::detail
namespace
caf
{
/// Default implementation for @ref inspector_access.
template
<
class
T
>
struct
default_inspector_access
:
inspector_access_base
<
T
>
{
// -- interface functions ----------------------------------------------------
// -- customization points -----------------------------------------------------
/// Applies `x` as an object to `f`.
template
<
class
Inspector
>
[[
nodiscard
]]
static
bool
apply_object
(
Inspector
&
f
,
T
&
x
)
{
// Dispatch to user-provided `inspect` overload or assume a trivial type.
if
constexpr
(
std
::
is_empty
<
T
>::
value
)
{
return
f
.
object
(
x
).
fields
();
}
else
{
return
f
.
object
(
x
).
fields
(
f
.
field
(
"value"
,
x
));
}
}
/// Applies `x` as a single value to `f`.
template
<
class
Inspector
>
[[
nodiscard
]]
static
bool
apply_value
(
Inspector
&
f
,
T
&
x
)
{
constexpr
auto
token
=
nested_inspect_value_access_type
<
Inspector
,
T
>
();
if
constexpr
(
Inspector
::
is_loading
)
return
detail
::
load_value
(
f
,
x
,
token
);
else
return
detail
::
save_value
(
f
,
x
,
token
);
}
// -- deprecated API ---------------------------------------------------------
template
<
class
Inspector
>
[[
deprecated
(
"inspect() overloads should return bool"
)]]
//
[[
nodiscard
]]
static
bool
apply_deprecated
(
Inspector
&
f
,
T
&
x
)
{
if
(
auto
err
=
inspect
(
f
,
x
))
{
f
.
emplace_error
(
std
::
move
(
err
));
return
false
;
}
return
true
;
}
};
/// Customization point for adding support for a custom type. The default
/// implementation requires an `inspect` overload for `T` that is available via
/// ADL.
/// Customization point for adding support for a custom type.
template
<
class
T
>
struct
inspector_access
;
...
...
@@ -559,13 +369,20 @@ struct optional_inspector_access {
using
value_type
=
typename
traits
::
value_type
;
template
<
class
Inspector
>
[[
nodiscard
]]
static
bool
apply
_object
(
Inspector
&
f
,
container_type
&
x
)
{
[[
nodiscard
]]
static
bool
apply
(
Inspector
&
f
,
container_type
&
x
)
{
return
f
.
object
(
x
).
fields
(
f
.
field
(
"value"
,
x
));
}
template
<
class
Inspector
>
[[
nodiscard
]]
static
bool
apply_value
(
Inspector
&
f
,
container_type
&
x
)
{
return
apply_object
(
f
,
x
);
[[
deprecated
(
"use apply instead"
)]]
static
bool
apply_object
(
Inspector
&
f
,
container_type
&
x
)
{
return
apply
(
f
,
x
);
}
template
<
class
Inspector
>
[[
deprecated
(
"use apply instead"
)]]
static
bool
apply_value
(
Inspector
&
f
,
container_type
&
x
)
{
return
apply
(
f
,
x
);
}
template
<
class
Inspector
>
...
...
@@ -696,18 +513,25 @@ struct variant_inspector_access {
using
traits
=
variant_inspector_traits
<
T
>
;
template
<
class
Inspector
>
[[
nodiscard
]]
static
bool
apply
_object
(
Inspector
&
f
,
value_type
&
x
)
{
[[
nodiscard
]]
static
bool
apply
(
Inspector
&
f
,
value_type
&
x
)
{
return
f
.
object
(
x
).
fields
(
f
.
field
(
"value"
,
x
));
}
template
<
class
Inspector
>
[[
nodiscard
]]
static
bool
apply_value
(
Inspector
&
f
,
value_type
&
x
)
{
return
apply_object
(
f
,
x
);
[[
deprecated
(
"use apply instead"
)]]
static
bool
apply_object
(
Inspector
&
f
,
T
&
x
)
{
return
apply
(
f
,
x
);
}
template
<
class
Inspector
>
[[
deprecated
(
"use apply instead"
)]]
static
bool
apply_value
(
Inspector
&
f
,
T
&
x
)
{
return
apply
(
f
,
x
);
}
template
<
class
Inspector
>
static
bool
save_field
(
Inspector
&
f
,
string_view
field_name
,
value_type
&
x
)
{
auto
g
=
[
&
f
](
auto
&
y
)
{
return
detail
::
save
_value
(
f
,
y
);
};
auto
g
=
[
&
f
](
auto
&
y
)
{
return
detail
::
save
(
f
,
y
);
};
return
f
.
begin_field
(
field_name
,
make_span
(
traits
::
allowed_types
),
traits
::
type_index
(
x
))
//
&&
traits
::
visit
(
g
,
x
)
//
...
...
@@ -720,7 +544,7 @@ struct variant_inspector_access {
auto
allowed_types
=
make_span
(
traits
::
allowed_types
);
if
(
is_present
())
{
auto
&&
x
=
get
();
auto
g
=
[
&
f
](
auto
&
y
)
{
return
detail
::
save
_value
(
f
,
y
);
};
auto
g
=
[
&
f
](
auto
&
y
)
{
return
detail
::
save
(
f
,
y
);
};
return
f
.
begin_field
(
field_name
,
true
,
allowed_types
,
traits
::
type_index
(
x
))
//
&&
traits
::
visit
(
g
,
x
)
//
...
...
@@ -735,7 +559,7 @@ struct variant_inspector_access {
value_type
&
x
,
type_id_t
runtime_type
)
{
auto
res
=
false
;
auto
type_found
=
traits
::
load
(
runtime_type
,
[
&
](
auto
&
tmp
)
{
if
(
!
detail
::
load
_value
(
f
,
tmp
))
if
(
!
detail
::
load
(
f
,
tmp
))
return
;
traits
::
assign
(
x
,
std
::
move
(
tmp
));
res
=
true
;
...
...
@@ -876,12 +700,7 @@ struct inspector_access<std::chrono::duration<Rep, Period>>
using
value_type
=
std
::
chrono
::
duration
<
Rep
,
Period
>
;
template
<
class
Inspector
>
static
bool
apply_object
(
Inspector
&
f
,
value_type
&
x
)
{
return
f
.
object
(
x
).
fields
(
f
.
field
(
"value"
,
x
));
}
template
<
class
Inspector
>
static
bool
apply_value
(
Inspector
&
f
,
value_type
&
x
)
{
static
bool
apply
(
Inspector
&
f
,
value_type
&
x
)
{
if
(
f
.
has_human_readable_format
())
{
auto
get
=
[
&
x
]
{
std
::
string
str
;
...
...
@@ -892,14 +711,27 @@ struct inspector_access<std::chrono::duration<Rep, Period>>
auto
err
=
detail
::
parse
(
str
,
x
);
return
!
err
;
};
return
detail
::
split_save_load
(
f
,
get
,
set
);
return
f
.
apply
(
get
,
set
);
}
else
{
auto
get
=
[
&
x
]
{
return
x
.
count
();
};
auto
set
=
[
&
x
](
Rep
value
)
{
x
=
std
::
chrono
::
duration
<
Rep
,
Period
>
{
value
};
return
true
;
};
return
f
.
apply
(
get
,
set
);
}
auto
get
=
[
&
x
]
{
return
x
.
count
();
};
auto
set
=
[
&
x
](
Rep
value
)
{
x
=
std
::
chrono
::
duration
<
Rep
,
Period
>
{
value
};
return
true
;
};
return
detail
::
split_save_load
(
f
,
get
,
set
);
}
template
<
class
Inspector
>
[[
deprecated
(
"use apply instead"
)]]
static
bool
apply_object
(
Inspector
&
f
,
value_type
&
x
)
{
return
apply
(
f
,
x
);
}
template
<
class
Inspector
>
[[
deprecated
(
"use apply instead"
)]]
static
bool
apply_value
(
Inspector
&
f
,
value_type
&
x
)
{
return
apply
(
f
,
x
);
}
};
...
...
@@ -912,12 +744,7 @@ struct inspector_access<
=
std
::
chrono
::
time_point
<
std
::
chrono
::
system_clock
,
Duration
>
;
template
<
class
Inspector
>
static
bool
apply_object
(
Inspector
&
f
,
value_type
&
x
)
{
return
f
.
object
(
x
).
fields
(
f
.
field
(
"value"
,
x
));
}
template
<
class
Inspector
>
static
bool
apply_value
(
Inspector
&
f
,
value_type
&
x
)
{
static
bool
apply
(
Inspector
&
f
,
value_type
&
x
)
{
if
(
f
.
has_human_readable_format
())
{
auto
get
=
[
&
x
]
{
std
::
string
str
;
...
...
@@ -928,15 +755,45 @@ struct inspector_access<
auto
err
=
detail
::
parse
(
str
,
x
);
return
!
err
;
};
return
detail
::
split_save_load
(
f
,
get
,
set
);
return
f
.
apply
(
get
,
set
);
}
else
{
using
rep_type
=
typename
Duration
::
rep
;
auto
get
=
[
&
x
]
{
return
x
.
time_since_epoch
().
count
();
};
auto
set
=
[
&
x
](
rep_type
value
)
{
x
=
value_type
{
Duration
{
value
}};
return
true
;
};
return
f
.
apply
(
get
,
set
);
}
using
rep_type
=
typename
Duration
::
rep
;
auto
get
=
[
&
x
]
{
return
x
.
time_since_epoch
().
count
();
};
auto
set
=
[
&
x
](
rep_type
value
)
{
x
=
value_type
{
Duration
{
value
}};
return
true
;
};
return
detail
::
split_save_load
(
f
,
get
,
set
);
}
template
<
class
Inspector
>
[[
deprecated
(
"use apply instead"
)]]
static
bool
apply_object
(
Inspector
&
f
,
value_type
&
x
)
{
return
apply
(
f
,
x
);
}
template
<
class
Inspector
>
[[
deprecated
(
"use apply instead"
)]]
static
bool
apply_value
(
Inspector
&
f
,
value_type
&
x
)
{
return
apply
(
f
,
x
);
}
};
// -- deprecated API -----------------------------------------------------------
template
<
class
T
>
struct
default_inspector_access
:
inspector_access_base
<
T
>
{
template
<
class
Inspector
>
[[
deprecated
(
"call f.apply(x) instead"
)]]
static
bool
apply_object
(
Inspector
&
f
,
T
&
x
)
{
return
f
.
apply
(
x
);
}
template
<
class
Inspector
>
[[
deprecated
(
"call f.apply(x) instead"
)]]
static
bool
apply_value
(
Inspector
&
f
,
T
&
x
)
{
return
f
.
apply
(
x
);
}
};
...
...
libcaf_core/caf/inspector_access_base.hpp
View file @
dc04d789
...
...
@@ -32,7 +32,7 @@ struct inspector_access_base {
template
<
class
Inspector
,
class
IsValid
,
class
SyncValue
>
static
bool
load_field
(
Inspector
&
f
,
string_view
field_name
,
T
&
x
,
IsValid
&
is_valid
,
SyncValue
&
sync_value
)
{
if
(
f
.
begin_field
(
field_name
)
&&
f
.
apply
_value
(
x
))
{
if
(
f
.
begin_field
(
field_name
)
&&
f
.
apply
(
x
))
{
if
(
!
is_valid
(
x
))
{
f
.
emplace_error
(
sec
::
field_invariant_check_failed
,
to_string
(
field_name
));
...
...
@@ -58,7 +58,7 @@ struct inspector_access_base {
if
(
!
f
.
begin_field
(
field_name
,
is_present
))
return
false
;
if
(
is_present
)
{
if
(
!
f
.
apply
_value
(
x
))
if
(
!
f
.
apply
(
x
))
return
false
;
if
(
!
is_valid
(
x
))
{
f
.
emplace_error
(
sec
::
field_invariant_check_failed
,
...
...
@@ -80,7 +80,7 @@ struct inspector_access_base {
template
<
class
Inspector
>
static
bool
save_field
(
Inspector
&
f
,
string_view
field_name
,
T
&
x
)
{
return
f
.
begin_field
(
field_name
)
//
&&
f
.
apply
_value
(
x
)
//
&&
f
.
apply
(
x
)
//
&&
f
.
end_field
();
}
...
...
@@ -91,7 +91,7 @@ struct inspector_access_base {
if
(
is_present
())
{
auto
&&
x
=
get
();
return
f
.
begin_field
(
field_name
,
true
)
//
&&
f
.
apply
_value
(
x
)
//
&&
f
.
apply
(
x
)
//
&&
f
.
end_field
();
}
return
f
.
begin_field
(
field_name
,
false
)
&&
f
.
end_field
();
...
...
libcaf_core/caf/inspector_access_type.hpp
View file @
dc04d789
...
...
@@ -35,23 +35,14 @@ struct inspector_access_type {
/// Flags types that provide an `inspector_access` specialization.
struct
specialization
{};
/// Flags types that provide an `inspect_value()` overload.
struct
inspect_value
{};
/// Flags types that provide an `inspect()` overload.
struct
inspect
{};
/// Flags builtin integral types.
struct
integral
{};
/// Flags types with builtin support via `Inspector::builtin_inspect`.
/// Flags types with builtin support of the inspection API.
struct
builtin
{};
/// Flags types with builtin support via `Inspector::value`.
struct
trivial
{};
/// Flags `enum` types.
struct
enumeration
{};
/// Flags types with builtin support via `Inspector::builtin_inspect`.
struct
builtin_inspect
{};
/// Flags stateless message types.
struct
empty
{};
...
...
@@ -59,15 +50,9 @@ struct inspector_access_type {
/// Flags allowed unsafe message types.
struct
unsafe
{};
/// Flags native C array types.
struct
array
{};
/// Flags types with `std::tuple`-like API.
struct
tuple
{};
/// Flags type that specialize `inspector_access_boxed_value_traits`.
struct
boxed_value
{};
/// Flags types with `std::map`-like API.
struct
map
{};
...
...
@@ -80,98 +65,23 @@ struct inspector_access_type {
/// @relates inspector_access_type
template
<
class
Inspector
,
class
T
>
constexpr
auto
inspect_
object_
access_type
()
{
constexpr
auto
inspect_access_type
()
{
using
namespace
detail
;
// Order: unsafe (error) > C Array > builtin
_inspect > inspector_access >
// inspect > trivial > defaults.
// Order: unsafe (error) > C Array > builtin
> builtin_inspect
//
> inspector_access >
inspect > trivial > defaults.
if
constexpr
(
is_allowed_unsafe_message_type_v
<
T
>
)
return
inspector_access_type
::
unsafe
{};
else
if
constexpr
(
std
::
is_array
<
T
>::
value
)
return
inspector_access_type
::
array
{};
else
if
constexpr
(
has_builtin_inspect
<
Inspector
,
T
>::
value
)
return
inspector_access_type
::
builtin
{};
else
if
constexpr
(
detail
::
is_complete
<
inspector_access
<
T
>>
)
return
inspector_access_type
::
specialization
{};
else
if
constexpr
(
has_inspect_overload
<
Inspector
,
T
>::
value
)
return
inspector_access_type
::
inspect
{};
else
if
constexpr
(
is_trivial_inspector_value_v
<
Inspector
::
is_loading
,
T
>
)
return
inspector_access_type
::
trivial
{};
else
if
constexpr
(
std
::
is_integral
<
T
>::
value
)
return
inspector_access_type
::
integral
{};
else
if
constexpr
(
std
::
is_enum
<
T
>::
value
)
return
inspector_access_type
::
enumeration
{};
else
if
constexpr
(
std
::
is_empty
<
T
>::
value
)
return
inspector_access_type
::
empty
{};
else
if
constexpr
(
is_stl_tuple_type_v
<
T
>
)
return
inspector_access_type
::
tuple
{};
else
if
constexpr
(
is_map_like_v
<
T
>
)
return
inspector_access_type
::
map
{};
else
if
constexpr
(
is_list_like_v
<
T
>
)
return
inspector_access_type
::
list
{};
else
return
inspector_access_type
::
none
{};
}
/// @relates inspector_access_type
template
<
class
Inspector
,
class
T
>
constexpr
auto
inspect_value_access_type
()
{
// Order: unsafe (error) > C Array > builtin_inspect > inspector_access >
// inspect_value > inspect > defaults.
// This is the same as in inspect_object_access_type, except that we pick up
// inspect_value overloads.
using
namespace
detail
;
if
constexpr
(
is_allowed_unsafe_message_type_v
<
T
>
)
return
inspector_access_type
::
unsafe
{};
else
if
constexpr
(
std
::
is_array
<
T
>::
value
)
return
inspector_access_type
::
array
{};
else
if
constexpr
(
has_builtin_inspect
<
Inspector
,
T
>::
value
)
else
if
constexpr
(
detail
::
is_builtin_inspector_type
<
T
,
Inspector
::
is_loading
>::
value
)
return
inspector_access_type
::
builtin
{};
else
if
constexpr
(
has_builtin_inspect
<
Inspector
,
T
>::
value
)
return
inspector_access_type
::
builtin_inspect
{};
else
if
constexpr
(
detail
::
is_complete
<
inspector_access
<
T
>>
)
return
inspector_access_type
::
specialization
{};
else
if
constexpr
(
has_inspect_value_overload
<
Inspector
,
T
>::
value
)
return
inspector_access_type
::
inspect_value
{};
else
if
constexpr
(
has_inspect_overload
<
Inspector
,
T
>::
value
)
return
inspector_access_type
::
inspect
{};
else
if
constexpr
(
is_trivial_inspector_value_v
<
Inspector
::
is_loading
,
T
>
)
return
inspector_access_type
::
trivial
{};
else
if
constexpr
(
std
::
is_integral
<
T
>::
value
)
return
inspector_access_type
::
integral
{};
else
if
constexpr
(
std
::
is_enum
<
T
>::
value
)
return
inspector_access_type
::
enumeration
{};
else
if
constexpr
(
std
::
is_empty
<
T
>::
value
)
return
inspector_access_type
::
empty
{};
else
if
constexpr
(
is_stl_tuple_type_v
<
T
>
)
return
inspector_access_type
::
tuple
{};
else
if
constexpr
(
is_map_like_v
<
T
>
)
return
inspector_access_type
::
map
{};
else
if
constexpr
(
is_list_like_v
<
T
>
)
return
inspector_access_type
::
list
{};
else
return
inspector_access_type
::
none
{};
}
/// Same as `inspect_value_access_type`, but ignores specialization of
/// `inspector_access` as well as `inspect` and `inspect_value` overloads.
/// @relates inspector_access_type
template
<
class
Inspector
,
class
T
>
constexpr
auto
nested_inspect_value_access_type
()
{
// Order: unsafe (error) > C Array > builtin_inspect > inspector_access >
// inspect_value > inspect > defaults.
// This is the same as in inspect_object_access_type, except that we pick up
// inspect_value overloads.
using
namespace
detail
;
if
constexpr
(
is_allowed_unsafe_message_type_v
<
T
>
)
return
inspector_access_type
::
unsafe
{};
else
if
constexpr
(
std
::
is_array
<
T
>::
value
)
return
inspector_access_type
::
array
{};
else
if
constexpr
(
has_builtin_inspect
<
Inspector
,
T
>::
value
)
return
inspector_access_type
::
builtin
{};
else
if
constexpr
(
is_trivial_inspector_value_v
<
Inspector
::
is_loading
,
T
>
)
return
inspector_access_type
::
trivial
{};
else
if
constexpr
(
std
::
is_integral
<
T
>::
value
)
return
inspector_access_type
::
integral
{};
else
if
constexpr
(
std
::
is_enum
<
T
>::
value
)
return
inspector_access_type
::
enumeration
{};
else
if
constexpr
(
std
::
is_empty
<
T
>::
value
)
return
inspector_access_type
::
empty
{};
else
if
constexpr
(
is_stl_tuple_type_v
<
T
>
)
...
...
libcaf_core/caf/load_inspector.hpp
View file @
dc04d789
...
...
@@ -37,17 +37,10 @@ class CAF_CORE_EXPORT load_inspector {
public:
// -- member types -----------------------------------------------------------
using
result_type
=
bool
;
using
result_type
[[
deprecated
(
"inspectors always return bool"
)]]
=
bool
;
// -- constants --------------------------------------------------------------
/// Convenience constant to indicate success of a processing step.
static
constexpr
bool
ok
=
true
;
/// Convenience constant to indicate that a processing step failed and no
/// further processing steps should take place.
static
constexpr
bool
stop
=
false
;
/// Enables dispatching on the inspector type.
static
constexpr
bool
is_loading
=
true
;
...
...
libcaf_core/caf/load_inspector_base.hpp
View file @
dc04d789
...
...
@@ -18,6 +18,10 @@
#pragma once
#include <array>
#include <tuple>
#include <utility>
#include "caf/inspector_access.hpp"
#include "caf/load_inspector.hpp"
...
...
@@ -37,35 +41,131 @@ public:
return
super
::
object_t
<
Subtype
>
{
type_name_or_anonymous
<
T
>
(),
dptr
()};
}
// -- dispatching to load/load functions -------------------------------------
template
<
class
T
>
bool
list
(
T
&
xs
)
{
xs
.
clear
();
auto
size
=
size_t
{
0
};
if
(
!
dref
().
begin_sequence
(
size
))
return
false
;
for
(
size_t
i
=
0
;
i
<
size
;
++
i
)
{
auto
val
=
typename
T
::
value_type
{};
if
(
!
detail
::
load
(
dref
(),
val
))
return
false
;
xs
.
insert
(
xs
.
end
(),
std
::
move
(
val
));
}
return
dref
().
end_sequence
();
}
template
<
class
T
>
[[
nodiscard
]]
bool
apply_object
(
T
&
x
)
{
static_assert
(
!
std
::
is_const
<
T
>::
value
);
constexpr
auto
token
=
inspect_object_access_type
<
Subtype
,
T
>
();
return
detail
::
load_object
(
dref
(),
x
,
token
);
bool
map
(
T
&
xs
)
{
xs
.
clear
();
auto
size
=
size_t
{
0
};
if
(
!
dref
().
begin_associative_array
(
size
))
return
false
;
for
(
size_t
i
=
0
;
i
<
size
;
++
i
)
{
auto
key
=
typename
T
::
key_type
{};
auto
val
=
typename
T
::
mapped_type
{};
if
(
!
(
dref
().
begin_key_value_pair
()
//
&&
detail
::
load
(
dref
(),
key
)
//
&&
detail
::
load
(
dref
(),
val
)
//
&&
dref
().
end_key_value_pair
()))
return
false
;
// A multimap returns an iterator, a regular map returns a pair.
auto
emplace_result
=
xs
.
emplace
(
std
::
move
(
key
),
std
::
move
(
val
));
if
constexpr
(
detail
::
is_pair
<
decltype
(
emplace_result
)
>::
value
)
{
if
(
!
emplace_result
.
second
)
{
dref
().
emplace_error
(
sec
::
runtime_error
,
"multiple key definitions"
);
return
false
;
}
}
}
return
dref
().
end_associative_array
();
}
template
<
class
...
Ts
>
[[
nodiscard
]]
bool
apply_objects
(
Ts
&
...
xs
)
{
return
(
apply_object
(
xs
)
&&
...);
template
<
class
T
,
size_t
...
Is
>
bool
tuple
(
T
&
xs
,
std
::
index_sequence
<
Is
...
>
)
{
return
dref
().
begin_tuple
(
sizeof
...(
Is
))
&&
(
detail
::
load
(
dref
(),
get
<
Is
>
(
xs
))
&&
...)
//
&&
dref
().
end_tuple
();
}
template
<
class
T
>
bool
apply_value
(
T
&
x
)
{
return
detail
::
load_value
(
dref
(),
x
);
bool
tuple
(
T
&
xs
)
{
return
tuple
(
xs
,
std
::
make_index_sequence
<
std
::
tuple_size
<
T
>::
value
>
{});
}
template
<
class
T
,
size_t
N
>
bool
tuple
(
T
(
&
xs
)[
N
])
{
if
(
!
dref
().
begin_tuple
(
N
))
return
false
;
for
(
size_t
index
=
0
;
index
<
N
;
++
index
)
if
(
!
detail
::
load
(
dref
(),
xs
[
index
]))
return
false
;
return
dref
().
end_tuple
();
}
// -- dispatching to load/load functions -------------------------------------
template
<
class
T
>
[[
nodiscard
]]
bool
apply
(
T
&
x
)
{
static_assert
(
!
std
::
is_const
<
T
>::
value
);
return
detail
::
load
(
dref
(),
x
);
}
/// Deserializes a primitive value with getter / setter access.
template
<
class
Get
,
class
Set
>
bool
apply_value
(
Get
&&
get
,
Set
&&
set
)
{
using
field_type
=
std
::
decay_t
<
decltype
(
get
())
>
;
auto
tmp
=
field_type
{};
if
(
apply_value
(
tmp
))
{
if
(
set
(
std
::
move
(
tmp
)))
return
true
;
this
->
set_error
(
sec
::
load_callback_failed
);
[[
nodiscard
]]
bool
apply
(
Get
&&
get
,
Set
&&
set
)
{
using
value_type
=
std
::
decay_t
<
decltype
(
get
())
>
;
auto
tmp
=
value_type
{};
using
setter_result
=
decltype
(
set
(
std
::
move
(
tmp
)));
if
constexpr
(
std
::
is_same
<
setter_result
,
bool
>::
value
)
{
if
(
dref
().
value
(
tmp
))
return
set
(
std
::
move
(
tmp
));
else
return
false
;
}
else
{
static_assert
(
std
::
is_convertible
<
setter_result
,
error
>::
value
);
if
(
dref
().
value
(
tmp
))
{
if
(
auto
err
=
set
(
std
::
move
(
tmp
));
!
err
)
{
return
true
;
}
else
{
this
->
emplace_error
(
std
::
move
(
err
));
return
false
;
}
}
else
{
return
false
;
}
}
}
// -- deprecated API: remove with CAF 0.19 -----------------------------------
template
<
class
T
>
[[
deprecated
(
"auto-conversion to underlying type is unsafe, add inspect"
)]]
//
std
::
enable_if_t
<
std
::
is_enum
<
T
>::
value
,
bool
>
opaque_value
(
T
&
val
)
{
auto
tmp
=
std
::
underlying_type_t
<
T
>
{
0
};
if
(
dref
().
value
(
tmp
))
{
val
=
static_cast
<
T
>
(
tmp
);
return
true
;
}
else
{
return
false
;
}
return
false
;
}
template
<
class
T
>
[[
deprecated
(
"use apply instead"
)]]
bool
apply_object
(
T
&
x
)
{
return
detail
::
save
(
dref
(),
x
);
}
template
<
class
...
Ts
>
[[
deprecated
(
"use apply instead"
)]]
bool
apply_objects
(
Ts
&
...
xs
)
{
return
(
apply
(
xs
)
&&
...);
}
template
<
class
T
>
[[
deprecated
(
"use apply instead"
)]]
bool
apply_value
(
T
&
x
)
{
return
detail
::
save
(
dref
(),
x
);
}
private:
...
...
libcaf_core/caf/message_id.hpp
View file @
dc04d789
...
...
@@ -229,28 +229,15 @@ constexpr message_id make_message_id(message_priority p) {
// -- inspection support -------------------------------------------------------
template
<
>
struct
inspector_access
<
message_id
>
:
inspector_access_base
<
message_id
>
{
template
<
class
Inspector
>
static
bool
apply_object
(
Inspector
&
f
,
message_id
&
x
)
{
auto
get
=
[
&
x
]
{
return
x
.
integer_value
();
};
auto
set
=
[
&
x
](
uint64_t
val
)
{
x
=
message_id
{
val
};
return
true
;
};
return
f
.
object
(
x
).
fields
(
f
.
field
(
"value"
,
get
,
set
));
}
template
<
class
Inspector
>
static
bool
apply_value
(
Inspector
&
f
,
message_id
&
x
)
{
auto
get
=
[
&
x
]
{
return
x
.
integer_value
();
};
auto
set
=
[
&
x
](
uint64_t
val
)
{
x
=
message_id
{
val
};
return
true
;
};
return
detail
::
split_save_load
(
f
,
get
,
set
);
}
};
template
<
class
Inspector
>
bool
inspect
(
Inspector
&
f
,
message_id
&
x
)
{
auto
get
=
[
&
x
]
{
return
x
.
integer_value
();
};
auto
set
=
[
&
x
](
uint64_t
val
)
{
x
=
message_id
{
val
};
return
true
;
};
return
f
.
apply
(
get
,
set
);
}
}
// namespace caf
...
...
libcaf_core/caf/pec.hpp
View file @
dc04d789
...
...
@@ -20,7 +20,9 @@
#include <cstdint>
#include <string>
#include <type_traits>
#include "caf/default_enum_inspect.hpp"
#include "caf/detail/core_export.hpp"
#include "caf/fwd.hpp"
#include "caf/is_error_code_enum.hpp"
...
...
@@ -80,8 +82,21 @@ enum class pec : uint8_t {
invalid_state
,
};
/// @relates pec
CAF_CORE_EXPORT
std
::
string
to_string
(
pec
);
/// @relates pec
CAF_CORE_EXPORT
bool
from_string
(
string_view
,
pec
&
);
/// @relates pec
CAF_CORE_EXPORT
bool
from_integer
(
std
::
underlying_type_t
<
pec
>
,
pec
&
);
/// @relates pec
template
<
class
Inspector
>
bool
inspect
(
Inspector
&
f
,
pec
&
x
)
{
return
default_enum_inspect
(
f
,
x
);
}
}
// namespace caf
CAF_ERROR_CODE_ENUM
(
pec
)
libcaf_core/caf/save_inspector.hpp
View file @
dc04d789
...
...
@@ -37,17 +37,10 @@ class CAF_CORE_EXPORT save_inspector {
public:
// -- member types -----------------------------------------------------------
using
result_type
=
bool
;
using
result_type
[[
deprecated
(
"inspectors always return bool"
)]]
=
bool
;
// -- constants --------------------------------------------------------------
/// Convenience constant to indicate success of a processing step.
static
constexpr
bool
ok
=
true
;
/// Convenience constant to indicate that a processing step failed and no
/// further processing steps should take place.
static
constexpr
bool
stop
=
false
;
/// Enables dispatching on the inspector type.
static
constexpr
bool
is_loading
=
false
;
...
...
libcaf_core/caf/save_inspector_base.hpp
View file @
dc04d789
...
...
@@ -30,41 +30,104 @@ public:
using
super
=
save_inspector
;
// -- DSL entry point
-
-------------------------------------------------------
// -- DSL entry point
s
-------------------------------------------------------
template
<
class
T
>
constexpr
auto
object
(
T
&
)
noexcept
{
return
super
::
object_t
<
Subtype
>
{
type_name_or_anonymous
<
T
>
(),
dptr
()};
}
// -- dispatching to load/save functions -------------------------------------
template
<
class
T
>
bool
list
(
const
T
&
xs
)
{
using
value_type
=
typename
T
::
value_type
;
auto
size
=
xs
.
size
();
if
(
!
dref
().
begin_sequence
(
size
))
return
false
;
for
(
auto
&&
val
:
xs
)
{
using
found_type
=
std
::
decay_t
<
decltype
(
val
)
>
;
if
constexpr
(
std
::
is_same
<
found_type
,
value_type
>::
value
)
{
if
(
!
detail
::
save
(
dref
(),
val
))
return
false
;
}
else
{
// Deals with atrocities like std::vector<bool>.
auto
tmp
=
static_cast
<
value_type
>
(
val
);
if
(
!
detail
::
save
(
dref
(),
tmp
))
return
false
;
}
}
return
dref
().
end_sequence
();
}
template
<
class
T
>
[[
nodiscard
]]
bool
apply_object
(
T
&
x
)
{
constexpr
auto
token
=
inspect_object_access_type
<
Subtype
,
T
>
();
return
detail
::
save_object
(
dref
(),
x
,
token
);
bool
map
(
const
T
&
xs
)
{
if
(
!
dref
().
begin_associative_array
(
xs
.
size
()))
return
false
;
for
(
auto
&&
kvp
:
xs
)
{
if
(
!
(
dref
().
begin_key_value_pair
()
//
&&
detail
::
save
(
dref
(),
kvp
.
first
)
//
&&
detail
::
save
(
dref
(),
kvp
.
second
)
//
&&
dref
().
end_key_value_pair
()))
return
false
;
}
return
dref
().
end_associative_array
();
}
template
<
class
T
,
size_t
...
Is
>
bool
tuple
(
const
T
&
xs
,
std
::
index_sequence
<
Is
...
>
)
{
return
dref
().
begin_tuple
(
sizeof
...(
Is
))
//
&&
(
detail
::
save
(
dref
(),
get
<
Is
>
(
xs
))
&&
...)
//
&&
dref
().
end_tuple
();
}
template
<
class
T
>
[[
nodiscard
]]
bool
apply_object
(
const
T
&
x
)
{
constexpr
auto
token
=
inspect_object_access_type
<
Subtype
,
T
>
();
return
detail
::
save_object
(
dref
(),
detail
::
as_mutable_ref
(
x
),
token
);
bool
tuple
(
const
T
&
xs
)
{
return
tuple
(
xs
,
std
::
make_index_sequence
<
std
::
tuple_size
<
T
>::
value
>
{});
}
template
<
class
...
Ts
>
[[
nodiscard
]]
bool
apply_objects
(
Ts
&&
...
xs
)
{
return
(
apply_object
(
xs
)
&&
...);
template
<
class
T
,
size_t
N
>
bool
tuple
(
T
(
&
xs
)[
N
])
{
if
(
!
dref
().
begin_tuple
(
N
))
return
false
;
for
(
size_t
index
=
0
;
index
<
N
;
++
index
)
if
(
!
detail
::
save
(
dref
(),
xs
[
index
]))
return
false
;
return
dref
().
end_tuple
();
}
// -- dispatching to load/save functions -------------------------------------
template
<
class
T
>
[[
nodiscard
]]
bool
apply
_value
(
T
&
x
)
{
return
detail
::
save
_value
(
dref
(),
x
);
[[
nodiscard
]]
bool
apply
(
const
T
&
x
)
{
return
detail
::
save
(
dref
(),
x
);
}
template
<
class
Get
,
class
Set
>
[[
nodiscard
]]
bool
apply_value
(
Get
&&
get
,
Set
&&
)
{
auto
&&
x
=
get
();
return
detail
::
save_value
(
dref
(),
x
);
[[
nodiscard
]]
bool
apply
(
Get
&&
get
,
Set
&&
)
{
return
detail
::
save
(
dref
(),
get
());
}
// -- deprecated API: remove with CAF 0.19 -----------------------------------
template
<
class
T
>
[[
deprecated
(
"auto-conversion to underlying type is unsafe, add inspect"
)]]
//
std
::
enable_if_t
<
std
::
is_enum
<
T
>::
value
,
bool
>
opaque_value
(
T
val
)
{
return
dref
().
value
(
static_cast
<
std
::
underlying_type_t
<
T
>>
(
val
));
}
template
<
class
T
>
[[
deprecated
(
"use apply instead"
)]]
bool
apply_object
(
const
T
&
x
)
{
return
apply
(
x
);
}
template
<
class
...
Ts
>
[[
deprecated
(
"use apply instead"
)]]
bool
apply_objects
(
const
Ts
&
...
xs
)
{
return
(
apply
(
xs
)
&&
...);
}
template
<
class
T
>
[[
deprecated
(
"use apply instead"
)]]
bool
apply_value
(
const
T
&
x
)
{
return
apply
(
x
);
}
private:
...
...
libcaf_core/caf/sec.hpp
View file @
dc04d789
...
...
@@ -24,7 +24,9 @@
#include <cstdint>
#include <string>
#include <type_traits>
#include "caf/default_enum_inspect.hpp"
#include "caf/detail/core_export.hpp"
#include "caf/fwd.hpp"
#include "caf/is_error_code_enum.hpp"
...
...
@@ -167,6 +169,18 @@ enum class sec : uint8_t {
/// @relates sec
CAF_CORE_EXPORT
std
::
string
to_string
(
sec
);
/// @relates sec
CAF_CORE_EXPORT
bool
from_string
(
string_view
,
sec
&
);
/// @relates sec
CAF_CORE_EXPORT
bool
from_integer
(
std
::
underlying_type_t
<
sec
>
,
sec
&
);
/// @relates sec
template
<
class
Inssector
>
bool
inspect
(
Inssector
&
f
,
sec
&
x
)
{
return
default_enum_inspect
(
f
,
x
);
}
}
// namespace caf
CAF_ERROR_CODE_ENUM
(
sec
)
libcaf_core/caf/serializer.hpp
View file @
dc04d789
...
...
@@ -22,10 +22,12 @@
#include <cstdint>
#include <string>
#include <tuple>
#include <type_traits>
#include <utility>
#include "caf/byte.hpp"
#include "caf/detail/core_export.hpp"
#include "caf/detail/squashed_int.hpp"
#include "caf/fwd.hpp"
#include "caf/meta/annotation.hpp"
#include "caf/meta/save_callback.hpp"
...
...
@@ -40,6 +42,10 @@ namespace caf {
/// Technology-independent serialization interface.
class
CAF_CORE_EXPORT
serializer
:
public
save_inspector_base
<
serializer
>
{
public:
// -- member types -----------------------------------------------------------
using
super
=
save_inspector_base
<
serializer
>
;
// -- constructors, destructors, and assignment operators --------------------
explicit
serializer
(
actor_system
&
sys
)
noexcept
;
...
...
@@ -116,9 +122,12 @@ public:
/// @note the default implementation calls `end_sequence()`.
virtual
bool
end_associative_array
();
/// Adds the primitive type `x` to the output.
/// @param x The primitive value.
/// @returns A non-zero error code on failure, `sec::success` otherwise.
/// Adds `x` to the output.
/// @param x A value for a builtin type.
/// @returns `true` on success, `false` otherwise.
virtual
bool
value
(
byte
x
)
=
0
;
/// @copydoc value
virtual
bool
value
(
bool
x
)
=
0
;
/// @copydoc value
...
...
@@ -145,6 +154,12 @@ public:
/// @copydoc value
virtual
bool
value
(
uint64_t
x
)
=
0
;
/// @copydoc value
template
<
class
T
>
std
::
enable_if_t
<
std
::
is_integral
<
T
>::
value
,
bool
>
value
(
T
x
)
{
return
value
(
static_cast
<
detail
::
squashed_int_t
<
T
>>
(
x
));
}
/// @copydoc value
virtual
bool
value
(
float
x
)
=
0
;
...
...
@@ -168,10 +183,12 @@ public:
/// @returns A non-zero error code on failure, `sec::success` otherwise.
virtual
bool
value
(
span
<
const
byte
>
x
)
=
0
;
using
super
::
list
;
/// 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
/// for each value in a binary output format.
virtual
bool
value
(
const
std
::
vector
<
bool
>&
xs
);
virtual
bool
list
(
const
std
::
vector
<
bool
>&
xs
);
protected:
/// Provides access to the ::proxy_registry and to the ::actor_system.
...
...
libcaf_core/caf/stream_priority.hpp
View file @
dc04d789
...
...
@@ -18,14 +18,18 @@
#pragma once
#include <cstdint>
#include <string>
#include <type_traits>
#include "caf/default_enum_inspect.hpp"
#include "caf/detail/core_export.hpp"
#include "caf/fwd.hpp"
namespace
caf
{
/// Categorizes individual streams.
enum
class
stream_priority
{
enum
class
stream_priority
:
uint8_t
{
/// Denotes soft-realtime traffic.
very_high
,
/// Denotes time-sensitive traffic.
...
...
@@ -38,9 +42,20 @@ enum class stream_priority {
very_low
};
/// Stores the number of `stream_priority` classes.
static
constexpr
size_t
stream_priorities
=
5
;
/// @relates stream_priority
CAF_CORE_EXPORT
std
::
string
to_string
(
stream_priority
x
);
/// @relates stream_priority
CAF_CORE_EXPORT
bool
from_string
(
string_view
,
stream_priority
&
);
/// @relates stream_priority
CAF_CORE_EXPORT
bool
from_integer
(
std
::
underlying_type_t
<
stream_priority
>
,
stream_priority
&
);
/// @relates stream_priority
template
<
class
Inspector
>
bool
inspect
(
Inspector
&
f
,
stream_priority
&
x
)
{
return
default_enum_inspect
(
f
,
x
);
}
}
// namespace caf
libcaf_core/caf/uri.hpp
View file @
dc04d789
...
...
@@ -260,35 +260,14 @@ CAF_CORE_EXPORT expected<uri> make_uri(string_view str);
template
<
>
struct
inspector_access
<
uri
>
:
inspector_access_base
<
uri
>
{
template
<
class
Inspector
>
static
bool
apply
_object
(
Inspector
&
f
,
uri
&
x
)
{
static
bool
apply
(
Inspector
&
f
,
uri
&
x
)
{
if
(
f
.
has_human_readable_format
())
{
// TODO: extend the inspector DSL to promote string_view to std::string
// automatically to avoid unnecessary to_string conversions.
auto
get
=
[
&
x
]
{
return
to_string
(
x
);
};
// TODO: setters should be able to return the error directly to avoid loss
// of information.
auto
set
=
[
&
x
](
std
::
string
str
)
{
auto
err
=
parse
(
str
,
x
);
return
err
.
empty
()
;
return
!
err
;
};
return
f
.
object
(
x
).
fields
(
f
.
field
(
"value"
,
get
,
set
));
}
else
{
if
constexpr
(
Inspector
::
is_loading
)
if
(
!
x
.
impl_
->
unique
())
x
.
impl_
.
reset
(
new
uri
::
impl_type
,
false
);
return
inspect
(
f
,
*
x
.
impl_
);
}
}
template
<
class
Inspector
>
static
bool
apply_value
(
Inspector
&
f
,
uri
&
x
)
{
if
(
f
.
has_human_readable_format
())
{
auto
get
=
[
&
x
]
{
return
to_string
(
x
);
};
auto
set
=
[
&
x
](
std
::
string
str
)
{
auto
err
=
parse
(
str
,
x
);
return
err
.
empty
();
};
return
detail
::
split_save_load
(
f
,
get
,
set
);
return
f
.
apply
(
get
,
set
);
}
else
{
if
constexpr
(
Inspector
::
is_loading
)
if
(
!
x
.
impl_
->
unique
())
...
...
libcaf_core/src/binary_serializer.cpp
View file @
dc04d789
...
...
@@ -139,7 +139,7 @@ bool binary_serializer::value(span<const byte> x) {
}
write_pos_
+=
x
.
size
();
CAF_ASSERT
(
write_pos_
<=
buf_
.
size
());
return
ok
;
return
true
;
}
bool
binary_serializer
::
value
(
byte
x
)
{
...
...
@@ -148,7 +148,7 @@ bool binary_serializer::value(byte x) {
else
buf_
[
write_pos_
]
=
x
;
++
write_pos_
;
return
ok
;
return
true
;
}
bool
binary_serializer
::
value
(
bool
x
)
{
...
...
libcaf_core/src/config_value_reader.cpp
View file @
dc04d789
...
...
@@ -448,6 +448,17 @@ bool pull(config_value_reader& reader, T& x) {
}
// namespace
bool
config_value_reader
::
value
(
byte
&
x
)
{
CHECK_NOT_EMPTY
();
auto
tmp
=
uint8_t
{
0
};
if
(
pull
(
*
this
,
tmp
))
{
x
=
static_cast
<
byte
>
(
tmp
);
return
true
;
}
else
{
return
false
;
}
}
bool
config_value_reader
::
value
(
bool
&
x
)
{
CHECK_NOT_EMPTY
();
return
pull
(
*
this
,
x
);
...
...
libcaf_core/src/config_value_writer.cpp
View file @
dc04d789
...
...
@@ -339,6 +339,10 @@ bool config_value_writer::end_associative_array() {
return
true
;
}
bool
config_value_writer
::
value
(
byte
x
)
{
return
push
(
config_value
{
static_cast
<
config_value
::
integer
>
(
x
)});
}
bool
config_value_writer
::
value
(
bool
x
)
{
return
push
(
config_value
{
x
});
}
...
...
libcaf_core/src/deserializer.cpp
View file @
dc04d789
...
...
@@ -51,7 +51,7 @@ bool deserializer::end_associative_array() {
return
end_sequence
();
}
bool
deserializer
::
value
(
std
::
vector
<
bool
>&
x
)
{
bool
deserializer
::
list
(
std
::
vector
<
bool
>&
x
)
{
x
.
clear
();
size_t
size
=
0
;
if
(
!
begin_sequence
(
size
))
...
...
libcaf_core/src/detail/serialized_size.cpp
View file @
dc04d789
...
...
@@ -107,6 +107,11 @@ bool serialized_size_inspector::end_sequence() {
return
true
;
}
bool
serialized_size_inspector
::
value
(
byte
x
)
{
result
+=
sizeof
(
x
);
return
true
;
}
bool
serialized_size_inspector
::
value
(
bool
)
{
result
+=
sizeof
(
uint8_t
);
return
true
;
...
...
@@ -194,7 +199,7 @@ bool serialized_size_inspector::value(span<const byte> x) {
return
true
;
}
bool
serialized_size_inspector
::
value
(
const
std
::
vector
<
bool
>&
xs
)
{
bool
serialized_size_inspector
::
list
(
const
std
::
vector
<
bool
>&
xs
)
{
CAF_IGNORE_UNUSED
(
begin_sequence
(
xs
.
size
()));
result
+=
(
xs
.
size
()
+
static_cast
<
size_t
>
(
xs
.
size
()
%
8
!=
0
))
/
8
;
return
end_sequence
();
...
...
libcaf_core/src/detail/stringification_inspector.cpp
View file @
dc04d789
...
...
@@ -57,7 +57,7 @@ bool stringification_inspector::begin_object(string_view name) {
}
else
{
in_string_object_
=
true
;
}
return
ok
;
return
true
;
}
bool
stringification_inspector
::
end_object
()
{
...
...
@@ -65,11 +65,11 @@ bool stringification_inspector::end_object() {
result_
+=
')'
;
else
in_string_object_
=
false
;
return
ok
;
return
true
;
}
bool
stringification_inspector
::
begin_field
(
string_view
)
{
return
ok
;
return
true
;
}
bool
stringification_inspector
::
begin_field
(
string_view
,
bool
is_present
)
{
...
...
@@ -78,12 +78,12 @@ bool stringification_inspector::begin_field(string_view, bool is_present) {
result_
+=
"null"
;
else
result_
+=
'*'
;
return
ok
;
return
true
;
}
bool
stringification_inspector
::
begin_field
(
string_view
,
span
<
const
type_id_t
>
,
size_t
)
{
return
ok
;
return
true
;
}
bool
stringification_inspector
::
begin_field
(
string_view
,
bool
is_present
,
...
...
@@ -93,22 +93,26 @@ bool stringification_inspector::begin_field(string_view, bool is_present,
result_
+=
"null"
;
else
result_
+=
'*'
;
return
ok
;
return
true
;
}
bool
stringification_inspector
::
end_field
()
{
return
ok
;
return
true
;
}
bool
stringification_inspector
::
begin_sequence
(
size_t
)
{
sep
();
result_
+=
'['
;
return
ok
;
return
true
;
}
bool
stringification_inspector
::
end_sequence
()
{
result_
+=
']'
;
return
ok
;
return
true
;
}
bool
stringification_inspector
::
value
(
byte
x
)
{
return
value
(
span
<
const
byte
>
(
&
x
,
1
));
}
bool
stringification_inspector
::
value
(
bool
x
)
{
...
...
@@ -228,7 +232,13 @@ bool stringification_inspector::int_value(uint64_t x) {
return
true
;
}
bool
stringification_inspector
::
value
(
const
std
::
vector
<
bool
>&
xs
)
{
bool
stringification_inspector
::
value
(
span
<
const
byte
>
x
)
{
sep
();
detail
::
append_hex
(
result_
,
x
.
data
(),
x
.
size
());
return
true
;
}
bool
stringification_inspector
::
list
(
const
std
::
vector
<
bool
>&
xs
)
{
begin_sequence
(
xs
.
size
());
for
(
bool
x
:
xs
)
value
(
x
);
...
...
libcaf_core/src/exit_reason_strings.cpp
View file @
dc04d789
...
...
@@ -2,6 +2,7 @@
// DO NOT EDIT: this file is auto-generated by caf-generate-enum-strings.
// Run the target update-enum-strings if this file is out of sync.
#include "caf/config.hpp"
#include "caf/string_view.hpp"
CAF_PUSH_DEPRECATED_WARNING
...
...
@@ -34,6 +35,55 @@ std::string to_string(exit_reason x) {
};
}
bool
from_string
(
string_view
in
,
exit_reason
&
out
)
{
if
(
in
==
"normal"
)
{
out
=
exit_reason
::
normal
;
return
true
;
}
else
if
(
in
==
"unhandled_exception"
)
{
out
=
exit_reason
::
unhandled_exception
;
return
true
;
}
else
if
(
in
==
"unknown"
)
{
out
=
exit_reason
::
unknown
;
return
true
;
}
else
if
(
in
==
"out_of_workers"
)
{
out
=
exit_reason
::
out_of_workers
;
return
true
;
}
else
if
(
in
==
"user_shutdown"
)
{
out
=
exit_reason
::
user_shutdown
;
return
true
;
}
else
if
(
in
==
"kill"
)
{
out
=
exit_reason
::
kill
;
return
true
;
}
else
if
(
in
==
"remote_link_unreachable"
)
{
out
=
exit_reason
::
remote_link_unreachable
;
return
true
;
}
else
if
(
in
==
"unreachable"
)
{
out
=
exit_reason
::
unreachable
;
return
true
;
}
else
{
return
false
;
}
}
bool
from_integer
(
std
::
underlying_type_t
<
exit_reason
>
in
,
exit_reason
&
out
)
{
auto
result
=
static_cast
<
exit_reason
>
(
in
);
switch
(
result
)
{
default:
return
false
;
case
exit_reason
:
:
normal
:
case
exit_reason
:
:
unhandled_exception
:
case
exit_reason
:
:
unknown
:
case
exit_reason
:
:
out_of_workers
:
case
exit_reason
:
:
user_shutdown
:
case
exit_reason
:
:
kill
:
case
exit_reason
:
:
remote_link_unreachable
:
case
exit_reason
:
:
unreachable
:
out
=
result
;
return
true
;
};
}
}
// namespace caf
CAF_POP_WARNINGS
libcaf_core/src/intrusive/inbox_result_strings.cpp
View file @
dc04d789
...
...
@@ -2,6 +2,7 @@
// DO NOT EDIT: this file is auto-generated by caf-generate-enum-strings.
// Run the target update-enum-strings if this file is out of sync.
#include "caf/config.hpp"
#include "caf/string_view.hpp"
CAF_PUSH_DEPRECATED_WARNING
...
...
@@ -25,6 +26,35 @@ std::string to_string(inbox_result x) {
};
}
bool
from_string
(
string_view
in
,
inbox_result
&
out
)
{
if
(
in
==
"success"
)
{
out
=
inbox_result
::
success
;
return
true
;
}
else
if
(
in
==
"unblocked_reader"
)
{
out
=
inbox_result
::
unblocked_reader
;
return
true
;
}
else
if
(
in
==
"queue_closed"
)
{
out
=
inbox_result
::
queue_closed
;
return
true
;
}
else
{
return
false
;
}
}
bool
from_integer
(
std
::
underlying_type_t
<
inbox_result
>
in
,
inbox_result
&
out
)
{
auto
result
=
static_cast
<
inbox_result
>
(
in
);
switch
(
result
)
{
default:
return
false
;
case
inbox_result
:
:
success
:
case
inbox_result
:
:
unblocked_reader
:
case
inbox_result
:
:
queue_closed
:
out
=
result
;
return
true
;
};
}
}
// namespace intrusive
}
// namespace caf
...
...
libcaf_core/src/intrusive/task_result_strings.cpp
View file @
dc04d789
...
...
@@ -2,6 +2,7 @@
// DO NOT EDIT: this file is auto-generated by caf-generate-enum-strings.
// Run the target update-enum-strings if this file is out of sync.
#include "caf/config.hpp"
#include "caf/string_view.hpp"
CAF_PUSH_DEPRECATED_WARNING
...
...
@@ -27,6 +28,39 @@ std::string to_string(task_result x) {
};
}
bool
from_string
(
string_view
in
,
task_result
&
out
)
{
if
(
in
==
"resume"
)
{
out
=
task_result
::
resume
;
return
true
;
}
else
if
(
in
==
"skip"
)
{
out
=
task_result
::
skip
;
return
true
;
}
else
if
(
in
==
"stop"
)
{
out
=
task_result
::
stop
;
return
true
;
}
else
if
(
in
==
"stop_all"
)
{
out
=
task_result
::
stop_all
;
return
true
;
}
else
{
return
false
;
}
}
bool
from_integer
(
std
::
underlying_type_t
<
task_result
>
in
,
task_result
&
out
)
{
auto
result
=
static_cast
<
task_result
>
(
in
);
switch
(
result
)
{
default:
return
false
;
case
task_result
:
:
resume
:
case
task_result
:
:
skip
:
case
task_result
:
:
stop
:
case
task_result
:
:
stop_all
:
out
=
result
;
return
true
;
};
}
}
// namespace intrusive
}
// namespace caf
...
...
libcaf_core/src/invoke_message_result_strings.cpp
View file @
dc04d789
...
...
@@ -2,6 +2,7 @@
// DO NOT EDIT: this file is auto-generated by caf-generate-enum-strings.
// Run the target update-enum-strings if this file is out of sync.
#include "caf/config.hpp"
#include "caf/string_view.hpp"
CAF_PUSH_DEPRECATED_WARNING
...
...
@@ -24,6 +25,35 @@ std::string to_string(invoke_message_result x) {
};
}
bool
from_string
(
string_view
in
,
invoke_message_result
&
out
)
{
if
(
in
==
"consumed"
)
{
out
=
invoke_message_result
::
consumed
;
return
true
;
}
else
if
(
in
==
"skipped"
)
{
out
=
invoke_message_result
::
skipped
;
return
true
;
}
else
if
(
in
==
"dropped"
)
{
out
=
invoke_message_result
::
dropped
;
return
true
;
}
else
{
return
false
;
}
}
bool
from_integer
(
std
::
underlying_type_t
<
invoke_message_result
>
in
,
invoke_message_result
&
out
)
{
auto
result
=
static_cast
<
invoke_message_result
>
(
in
);
switch
(
result
)
{
default:
return
false
;
case
invoke_message_result
:
:
consumed
:
case
invoke_message_result
:
:
skipped
:
case
invoke_message_result
:
:
dropped
:
out
=
result
;
return
true
;
};
}
}
// namespace caf
CAF_POP_WARNINGS
libcaf_core/src/logger.cpp
View file @
dc04d789
...
...
@@ -602,7 +602,7 @@ void logger::log_first_line() {
msg
+=
to_string
(
system_
.
node
());
msg
+=
", excluded-components = "
;
detail
::
stringification_inspector
f
{
msg
};
detail
::
save
_value
(
f
,
filter
);
detail
::
save
(
f
,
filter
);
return
msg
;
};
namespace
lg
=
defaults
::
logger
;
...
...
libcaf_core/src/message_priority_strings.cpp
View file @
dc04d789
...
...
@@ -2,6 +2,7 @@
// DO NOT EDIT: this file is auto-generated by caf-generate-enum-strings.
// Run the target update-enum-strings if this file is out of sync.
#include "caf/config.hpp"
#include "caf/string_view.hpp"
CAF_PUSH_DEPRECATED_WARNING
...
...
@@ -22,6 +23,31 @@ std::string to_string(message_priority x) {
};
}
bool
from_string
(
string_view
in
,
message_priority
&
out
)
{
if
(
in
==
"high"
)
{
out
=
message_priority
::
high
;
return
true
;
}
else
if
(
in
==
"normal"
)
{
out
=
message_priority
::
normal
;
return
true
;
}
else
{
return
false
;
}
}
bool
from_integer
(
std
::
underlying_type_t
<
message_priority
>
in
,
message_priority
&
out
)
{
auto
result
=
static_cast
<
message_priority
>
(
in
);
switch
(
result
)
{
default:
return
false
;
case
message_priority
:
:
high
:
case
message_priority
:
:
normal
:
out
=
result
;
return
true
;
};
}
}
// namespace caf
CAF_POP_WARNINGS
libcaf_core/src/pec_strings.cpp
View file @
dc04d789
...
...
@@ -2,6 +2,7 @@
// DO NOT EDIT: this file is auto-generated by caf-generate-enum-strings.
// Run the target update-enum-strings if this file is out of sync.
#include "caf/config.hpp"
#include "caf/string_view.hpp"
CAF_PUSH_DEPRECATED_WARNING
...
...
@@ -64,6 +65,115 @@ std::string to_string(pec x) {
};
}
bool
from_string
(
string_view
in
,
pec
&
out
)
{
if
(
in
==
"success"
)
{
out
=
pec
::
success
;
return
true
;
}
else
if
(
in
==
"trailing_character"
)
{
out
=
pec
::
trailing_character
;
return
true
;
}
else
if
(
in
==
"unexpected_eof"
)
{
out
=
pec
::
unexpected_eof
;
return
true
;
}
else
if
(
in
==
"unexpected_character"
)
{
out
=
pec
::
unexpected_character
;
return
true
;
}
else
if
(
in
==
"timespan_overflow"
)
{
out
=
pec
::
timespan_overflow
;
return
true
;
}
else
if
(
in
==
"fractional_timespan"
)
{
out
=
pec
::
fractional_timespan
;
return
true
;
}
else
if
(
in
==
"too_many_characters"
)
{
out
=
pec
::
too_many_characters
;
return
true
;
}
else
if
(
in
==
"invalid_escape_sequence"
)
{
out
=
pec
::
invalid_escape_sequence
;
return
true
;
}
else
if
(
in
==
"unexpected_newline"
)
{
out
=
pec
::
unexpected_newline
;
return
true
;
}
else
if
(
in
==
"integer_overflow"
)
{
out
=
pec
::
integer_overflow
;
return
true
;
}
else
if
(
in
==
"integer_underflow"
)
{
out
=
pec
::
integer_underflow
;
return
true
;
}
else
if
(
in
==
"exponent_underflow"
)
{
out
=
pec
::
exponent_underflow
;
return
true
;
}
else
if
(
in
==
"exponent_overflow"
)
{
out
=
pec
::
exponent_overflow
;
return
true
;
}
else
if
(
in
==
"type_mismatch"
)
{
out
=
pec
::
type_mismatch
;
return
true
;
}
else
if
(
in
==
"not_an_option"
)
{
out
=
pec
::
not_an_option
;
return
true
;
}
else
if
(
in
==
"invalid_argument"
)
{
out
=
pec
::
invalid_argument
;
return
true
;
}
else
if
(
in
==
"missing_argument"
)
{
out
=
pec
::
missing_argument
;
return
true
;
}
else
if
(
in
==
"invalid_category"
)
{
out
=
pec
::
invalid_category
;
return
true
;
}
else
if
(
in
==
"invalid_field_name"
)
{
out
=
pec
::
invalid_field_name
;
return
true
;
}
else
if
(
in
==
"repeated_field_name"
)
{
out
=
pec
::
repeated_field_name
;
return
true
;
}
else
if
(
in
==
"missing_field"
)
{
out
=
pec
::
missing_field
;
return
true
;
}
else
if
(
in
==
"invalid_range_expression"
)
{
out
=
pec
::
invalid_range_expression
;
return
true
;
}
else
if
(
in
==
"invalid_state"
)
{
out
=
pec
::
invalid_state
;
return
true
;
}
else
{
return
false
;
}
}
bool
from_integer
(
std
::
underlying_type_t
<
pec
>
in
,
pec
&
out
)
{
auto
result
=
static_cast
<
pec
>
(
in
);
switch
(
result
)
{
default:
return
false
;
case
pec
:
:
success
:
case
pec
:
:
trailing_character
:
case
pec
:
:
unexpected_eof
:
case
pec
:
:
unexpected_character
:
case
pec
:
:
timespan_overflow
:
case
pec
:
:
fractional_timespan
:
case
pec
:
:
too_many_characters
:
case
pec
:
:
invalid_escape_sequence
:
case
pec
:
:
unexpected_newline
:
case
pec
:
:
integer_overflow
:
case
pec
:
:
integer_underflow
:
case
pec
:
:
exponent_underflow
:
case
pec
:
:
exponent_overflow
:
case
pec
:
:
type_mismatch
:
case
pec
:
:
not_an_option
:
case
pec
:
:
invalid_argument
:
case
pec
:
:
missing_argument
:
case
pec
:
:
invalid_category
:
case
pec
:
:
invalid_field_name
:
case
pec
:
:
repeated_field_name
:
case
pec
:
:
missing_field
:
case
pec
:
:
invalid_range_expression
:
case
pec
:
:
invalid_state
:
out
=
result
;
return
true
;
};
}
}
// namespace caf
CAF_POP_WARNINGS
libcaf_core/src/sec_strings.cpp
View file @
dc04d789
...
...
@@ -2,6 +2,7 @@
// DO NOT EDIT: this file is auto-generated by caf-generate-enum-strings.
// Run the target update-enum-strings if this file is out of sync.
#include "caf/config.hpp"
#include "caf/string_view.hpp"
CAF_PUSH_DEPRECATED_WARNING
...
...
@@ -144,6 +145,275 @@ std::string to_string(sec x) {
};
}
bool
from_string
(
string_view
in
,
sec
&
out
)
{
if
(
in
==
"none"
)
{
out
=
sec
::
none
;
return
true
;
}
else
if
(
in
==
"unexpected_message"
)
{
out
=
sec
::
unexpected_message
;
return
true
;
}
else
if
(
in
==
"unexpected_response"
)
{
out
=
sec
::
unexpected_response
;
return
true
;
}
else
if
(
in
==
"request_receiver_down"
)
{
out
=
sec
::
request_receiver_down
;
return
true
;
}
else
if
(
in
==
"request_timeout"
)
{
out
=
sec
::
request_timeout
;
return
true
;
}
else
if
(
in
==
"no_such_group_module"
)
{
out
=
sec
::
no_such_group_module
;
return
true
;
}
else
if
(
in
==
"no_actor_published_at_port"
)
{
out
=
sec
::
no_actor_published_at_port
;
return
true
;
}
else
if
(
in
==
"unexpected_actor_messaging_interface"
)
{
out
=
sec
::
unexpected_actor_messaging_interface
;
return
true
;
}
else
if
(
in
==
"state_not_serializable"
)
{
out
=
sec
::
state_not_serializable
;
return
true
;
}
else
if
(
in
==
"unsupported_sys_key"
)
{
out
=
sec
::
unsupported_sys_key
;
return
true
;
}
else
if
(
in
==
"unsupported_sys_message"
)
{
out
=
sec
::
unsupported_sys_message
;
return
true
;
}
else
if
(
in
==
"disconnect_during_handshake"
)
{
out
=
sec
::
disconnect_during_handshake
;
return
true
;
}
else
if
(
in
==
"cannot_forward_to_invalid_actor"
)
{
out
=
sec
::
cannot_forward_to_invalid_actor
;
return
true
;
}
else
if
(
in
==
"no_route_to_receiving_node"
)
{
out
=
sec
::
no_route_to_receiving_node
;
return
true
;
}
else
if
(
in
==
"failed_to_assign_scribe_from_handle"
)
{
out
=
sec
::
failed_to_assign_scribe_from_handle
;
return
true
;
}
else
if
(
in
==
"failed_to_assign_doorman_from_handle"
)
{
out
=
sec
::
failed_to_assign_doorman_from_handle
;
return
true
;
}
else
if
(
in
==
"cannot_close_invalid_port"
)
{
out
=
sec
::
cannot_close_invalid_port
;
return
true
;
}
else
if
(
in
==
"cannot_connect_to_node"
)
{
out
=
sec
::
cannot_connect_to_node
;
return
true
;
}
else
if
(
in
==
"cannot_open_port"
)
{
out
=
sec
::
cannot_open_port
;
return
true
;
}
else
if
(
in
==
"network_syscall_failed"
)
{
out
=
sec
::
network_syscall_failed
;
return
true
;
}
else
if
(
in
==
"invalid_argument"
)
{
out
=
sec
::
invalid_argument
;
return
true
;
}
else
if
(
in
==
"invalid_protocol_family"
)
{
out
=
sec
::
invalid_protocol_family
;
return
true
;
}
else
if
(
in
==
"cannot_publish_invalid_actor"
)
{
out
=
sec
::
cannot_publish_invalid_actor
;
return
true
;
}
else
if
(
in
==
"cannot_spawn_actor_from_arguments"
)
{
out
=
sec
::
cannot_spawn_actor_from_arguments
;
return
true
;
}
else
if
(
in
==
"end_of_stream"
)
{
out
=
sec
::
end_of_stream
;
return
true
;
}
else
if
(
in
==
"no_context"
)
{
out
=
sec
::
no_context
;
return
true
;
}
else
if
(
in
==
"unknown_type"
)
{
out
=
sec
::
unknown_type
;
return
true
;
}
else
if
(
in
==
"no_proxy_registry"
)
{
out
=
sec
::
no_proxy_registry
;
return
true
;
}
else
if
(
in
==
"runtime_error"
)
{
out
=
sec
::
runtime_error
;
return
true
;
}
else
if
(
in
==
"remote_linking_failed"
)
{
out
=
sec
::
remote_linking_failed
;
return
true
;
}
else
if
(
in
==
"cannot_add_upstream"
)
{
out
=
sec
::
cannot_add_upstream
;
return
true
;
}
else
if
(
in
==
"upstream_already_exists"
)
{
out
=
sec
::
upstream_already_exists
;
return
true
;
}
else
if
(
in
==
"invalid_upstream"
)
{
out
=
sec
::
invalid_upstream
;
return
true
;
}
else
if
(
in
==
"cannot_add_downstream"
)
{
out
=
sec
::
cannot_add_downstream
;
return
true
;
}
else
if
(
in
==
"downstream_already_exists"
)
{
out
=
sec
::
downstream_already_exists
;
return
true
;
}
else
if
(
in
==
"invalid_downstream"
)
{
out
=
sec
::
invalid_downstream
;
return
true
;
}
else
if
(
in
==
"no_downstream_stages_defined"
)
{
out
=
sec
::
no_downstream_stages_defined
;
return
true
;
}
else
if
(
in
==
"stream_init_failed"
)
{
out
=
sec
::
stream_init_failed
;
return
true
;
}
else
if
(
in
==
"invalid_stream_state"
)
{
out
=
sec
::
invalid_stream_state
;
return
true
;
}
else
if
(
in
==
"unhandled_stream_error"
)
{
out
=
sec
::
unhandled_stream_error
;
return
true
;
}
else
if
(
in
==
"bad_function_call"
)
{
out
=
sec
::
bad_function_call
;
return
true
;
}
else
if
(
in
==
"feature_disabled"
)
{
out
=
sec
::
feature_disabled
;
return
true
;
}
else
if
(
in
==
"cannot_open_file"
)
{
out
=
sec
::
cannot_open_file
;
return
true
;
}
else
if
(
in
==
"socket_invalid"
)
{
out
=
sec
::
socket_invalid
;
return
true
;
}
else
if
(
in
==
"socket_disconnected"
)
{
out
=
sec
::
socket_disconnected
;
return
true
;
}
else
if
(
in
==
"socket_operation_failed"
)
{
out
=
sec
::
socket_operation_failed
;
return
true
;
}
else
if
(
in
==
"unavailable_or_would_block"
)
{
out
=
sec
::
unavailable_or_would_block
;
return
true
;
}
else
if
(
in
==
"incompatible_versions"
)
{
out
=
sec
::
incompatible_versions
;
return
true
;
}
else
if
(
in
==
"incompatible_application_ids"
)
{
out
=
sec
::
incompatible_application_ids
;
return
true
;
}
else
if
(
in
==
"malformed_basp_message"
)
{
out
=
sec
::
malformed_basp_message
;
return
true
;
}
else
if
(
in
==
"serializing_basp_payload_failed"
)
{
out
=
sec
::
serializing_basp_payload_failed
;
return
true
;
}
else
if
(
in
==
"redundant_connection"
)
{
out
=
sec
::
redundant_connection
;
return
true
;
}
else
if
(
in
==
"remote_lookup_failed"
)
{
out
=
sec
::
remote_lookup_failed
;
return
true
;
}
else
if
(
in
==
"no_tracing_context"
)
{
out
=
sec
::
no_tracing_context
;
return
true
;
}
else
if
(
in
==
"all_requests_failed"
)
{
out
=
sec
::
all_requests_failed
;
return
true
;
}
else
if
(
in
==
"field_invariant_check_failed"
)
{
out
=
sec
::
field_invariant_check_failed
;
return
true
;
}
else
if
(
in
==
"field_value_synchronization_failed"
)
{
out
=
sec
::
field_value_synchronization_failed
;
return
true
;
}
else
if
(
in
==
"invalid_field_type"
)
{
out
=
sec
::
invalid_field_type
;
return
true
;
}
else
if
(
in
==
"unsafe_type"
)
{
out
=
sec
::
unsafe_type
;
return
true
;
}
else
if
(
in
==
"save_callback_failed"
)
{
out
=
sec
::
save_callback_failed
;
return
true
;
}
else
if
(
in
==
"load_callback_failed"
)
{
out
=
sec
::
load_callback_failed
;
return
true
;
}
else
if
(
in
==
"conversion_failed"
)
{
out
=
sec
::
conversion_failed
;
return
true
;
}
else
if
(
in
==
"connection_closed"
)
{
out
=
sec
::
connection_closed
;
return
true
;
}
else
{
return
false
;
}
}
bool
from_integer
(
std
::
underlying_type_t
<
sec
>
in
,
sec
&
out
)
{
auto
result
=
static_cast
<
sec
>
(
in
);
switch
(
result
)
{
default:
return
false
;
case
sec
:
:
none
:
case
sec
:
:
unexpected_message
:
case
sec
:
:
unexpected_response
:
case
sec
:
:
request_receiver_down
:
case
sec
:
:
request_timeout
:
case
sec
:
:
no_such_group_module
:
case
sec
:
:
no_actor_published_at_port
:
case
sec
:
:
unexpected_actor_messaging_interface
:
case
sec
:
:
state_not_serializable
:
case
sec
:
:
unsupported_sys_key
:
case
sec
:
:
unsupported_sys_message
:
case
sec
:
:
disconnect_during_handshake
:
case
sec
:
:
cannot_forward_to_invalid_actor
:
case
sec
:
:
no_route_to_receiving_node
:
case
sec
:
:
failed_to_assign_scribe_from_handle
:
case
sec
:
:
failed_to_assign_doorman_from_handle
:
case
sec
:
:
cannot_close_invalid_port
:
case
sec
:
:
cannot_connect_to_node
:
case
sec
:
:
cannot_open_port
:
case
sec
:
:
network_syscall_failed
:
case
sec
:
:
invalid_argument
:
case
sec
:
:
invalid_protocol_family
:
case
sec
:
:
cannot_publish_invalid_actor
:
case
sec
:
:
cannot_spawn_actor_from_arguments
:
case
sec
:
:
end_of_stream
:
case
sec
:
:
no_context
:
case
sec
:
:
unknown_type
:
case
sec
:
:
no_proxy_registry
:
case
sec
:
:
runtime_error
:
case
sec
:
:
remote_linking_failed
:
case
sec
:
:
cannot_add_upstream
:
case
sec
:
:
upstream_already_exists
:
case
sec
:
:
invalid_upstream
:
case
sec
:
:
cannot_add_downstream
:
case
sec
:
:
downstream_already_exists
:
case
sec
:
:
invalid_downstream
:
case
sec
:
:
no_downstream_stages_defined
:
case
sec
:
:
stream_init_failed
:
case
sec
:
:
invalid_stream_state
:
case
sec
:
:
unhandled_stream_error
:
case
sec
:
:
bad_function_call
:
case
sec
:
:
feature_disabled
:
case
sec
:
:
cannot_open_file
:
case
sec
:
:
socket_invalid
:
case
sec
:
:
socket_disconnected
:
case
sec
:
:
socket_operation_failed
:
case
sec
:
:
unavailable_or_would_block
:
case
sec
:
:
incompatible_versions
:
case
sec
:
:
incompatible_application_ids
:
case
sec
:
:
malformed_basp_message
:
case
sec
:
:
serializing_basp_payload_failed
:
case
sec
:
:
redundant_connection
:
case
sec
:
:
remote_lookup_failed
:
case
sec
:
:
no_tracing_context
:
case
sec
:
:
all_requests_failed
:
case
sec
:
:
field_invariant_check_failed
:
case
sec
:
:
field_value_synchronization_failed
:
case
sec
:
:
invalid_field_type
:
case
sec
:
:
unsafe_type
:
case
sec
:
:
save_callback_failed
:
case
sec
:
:
load_callback_failed
:
case
sec
:
:
conversion_failed
:
case
sec
:
:
connection_closed
:
out
=
result
;
return
true
;
};
}
}
// namespace caf
CAF_POP_WARNINGS
libcaf_core/src/serializer.cpp
View file @
dc04d789
...
...
@@ -51,7 +51,7 @@ bool serializer::end_associative_array() {
return
end_sequence
();
}
bool
serializer
::
value
(
const
std
::
vector
<
bool
>&
xs
)
{
bool
serializer
::
list
(
const
std
::
vector
<
bool
>&
xs
)
{
if
(
!
begin_sequence
(
xs
.
size
()))
return
false
;
for
(
bool
x
:
xs
)
...
...
libcaf_core/src/stream_priority_strings.cpp
View file @
dc04d789
...
...
@@ -2,6 +2,7 @@
// DO NOT EDIT: this file is auto-generated by caf-generate-enum-strings.
// Run the target update-enum-strings if this file is out of sync.
#include "caf/config.hpp"
#include "caf/string_view.hpp"
CAF_PUSH_DEPRECATED_WARNING
...
...
@@ -28,6 +29,43 @@ std::string to_string(stream_priority x) {
};
}
bool
from_string
(
string_view
in
,
stream_priority
&
out
)
{
if
(
in
==
"very_high"
)
{
out
=
stream_priority
::
very_high
;
return
true
;
}
else
if
(
in
==
"high"
)
{
out
=
stream_priority
::
high
;
return
true
;
}
else
if
(
in
==
"normal"
)
{
out
=
stream_priority
::
normal
;
return
true
;
}
else
if
(
in
==
"low"
)
{
out
=
stream_priority
::
low
;
return
true
;
}
else
if
(
in
==
"very_low"
)
{
out
=
stream_priority
::
very_low
;
return
true
;
}
else
{
return
false
;
}
}
bool
from_integer
(
std
::
underlying_type_t
<
stream_priority
>
in
,
stream_priority
&
out
)
{
auto
result
=
static_cast
<
stream_priority
>
(
in
);
switch
(
result
)
{
default:
return
false
;
case
stream_priority
:
:
very_high
:
case
stream_priority
:
:
high
:
case
stream_priority
:
:
normal
:
case
stream_priority
:
:
low
:
case
stream_priority
:
:
very_low
:
out
=
result
;
return
true
;
};
}
}
// namespace caf
CAF_POP_WARNINGS
libcaf_core/test/actor_profiler.cpp
View file @
dc04d789
...
...
@@ -210,15 +210,15 @@ CAF_TEST(profilers record request / response messaging) {
"new: worker"
,
"new: server"
,
"new: client"
,
"client sends: message(
int32_t(19), int32_t(23)
)"
,
"server got: message(
int32_t(19), int32_t(23)
)"
,
"server sends: message(
int32_t(19), int32_t(23)
)"
,
"client sends: message(
19, 23
)"
,
"server got: message(
19, 23
)"
,
"server sends: message(
19, 23
)"
,
"server consumed the message"
,
"delete: server"
,
"worker got: message(
int32_t(19), int32_t(23)
)"
,
"worker sends: message(
int32_t(42)
)"
,
"worker got: message(
19, 23
)"
,
"worker sends: message(
42
)"
,
"worker consumed the message"
,
"client got: message(
int32_t(42)
)"
,
"client got: message(
42
)"
,
"client consumed the message"
,
"delete: worker"
,
"delete: client"
,
...
...
libcaf_core/test/actor_registry.cpp
View file @
dc04d789
...
...
@@ -54,12 +54,12 @@ CAF_TEST(serialization roundtrips go through the registry) {
CAF_MESSAGE
(
"hdl.id: "
<<
hdl
->
id
());
byte_buffer
buf
;
binary_serializer
sink
{
sys
,
buf
};
if
(
!
sink
.
apply
_object
(
hdl
))
if
(
!
sink
.
apply
(
hdl
))
CAF_FAIL
(
"serialization failed: "
<<
sink
.
get_error
());
CAF_MESSAGE
(
"buf: "
<<
buf
);
actor
hdl2
;
binary_deserializer
source
{
sys
,
buf
};
if
(
!
source
.
apply
_object
(
hdl2
))
if
(
!
source
.
apply
(
hdl2
))
CAF_FAIL
(
"deserialization failed: "
<<
source
.
get_error
());
CAF_CHECK_EQUAL
(
hdl
,
hdl2
);
anon_send_exit
(
hdl
,
exit_reason
::
user_shutdown
);
...
...
libcaf_core/test/binary_deserializer.cpp
View file @
dc04d789
...
...
@@ -60,7 +60,7 @@ struct fixture {
template
<
class
...
Ts
>
void
load
(
const
std
::
vector
<
byte
>&
buf
,
Ts
&
...
xs
)
{
binary_deserializer
source
{
nullptr
,
buf
};
if
(
!
source
.
apply_objects
(
xs
...))
if
(
!
(
source
.
apply
(
xs
)
&&
...))
CAF_FAIL
(
"binary_deserializer failed to load: "
<<
source
.
get_error
());
}
...
...
libcaf_core/test/binary_serializer.cpp
View file @
dc04d789
...
...
@@ -58,7 +58,7 @@ struct fixture {
auto
save
(
const
Ts
&
...
xs
)
{
byte_buffer
result
;
binary_serializer
sink
{
nullptr
,
result
};
if
(
!
sink
.
apply_objects
(
xs
...))
if
(
!
(
sink
.
apply
(
xs
)
&&
...))
CAF_FAIL
(
"binary_serializer failed to save: "
<<
sink
.
get_error
());
return
result
;
}
...
...
@@ -66,7 +66,7 @@ struct fixture {
template
<
class
...
Ts
>
void
save_to_buf
(
byte_buffer
&
data
,
const
Ts
&
...
xs
)
{
binary_serializer
sink
{
nullptr
,
data
};
if
(
!
sink
.
apply_objects
(
xs
...))
if
(
!
(
sink
.
apply
(
xs
)
&&
...))
CAF_FAIL
(
"binary_serializer failed to save: "
<<
sink
.
get_error
());
}
};
...
...
libcaf_core/test/config_value_reader.cpp
View file @
dc04d789
...
...
@@ -43,13 +43,13 @@ constexpr i64 operator""_i64(unsigned long long int x) {
using
i64_list
=
std
::
vector
<
i64
>
;
struct
fixture
{
settings
xs
;
config_value
x
;
template
<
class
T
>
void
deserialize
(
const
config_value
&
src
,
T
&
value
)
{
config_value_reader
reader
{
&
src
};
if
(
!
detail
::
load
_value
(
reader
,
value
))
CAF_FAIL
(
"
failed to deserialize from settings
: "
<<
reader
.
get_error
());
if
(
!
detail
::
load
(
reader
,
value
))
CAF_FAIL
(
"
deserialization failed
: "
<<
reader
.
get_error
());
}
template
<
class
T
>
...
...
@@ -59,7 +59,7 @@ struct fixture {
template
<
class
T
>
void
deserialize
(
T
&
value
)
{
return
deserialize
(
x
s
,
value
);
return
deserialize
(
x
,
value
);
}
template
<
class
T
>
...
...
@@ -71,7 +71,10 @@ struct fixture {
template
<
class
T
>
optional
<
T
>
get
(
string_view
key
)
{
return
get
<
T
>
(
xs
,
key
);
if
(
auto
*
xs
=
get_if
<
settings
>
(
&
x
))
return
get
<
T
>
(
*
xs
,
key
);
else
CAF_FAIL
(
"fixture does not contain a dictionary"
);
}
};
...
...
@@ -81,12 +84,14 @@ CAF_TEST_FIXTURE_SCOPE(config_value_reader_tests, fixture)
CAF_TEST
(
readers
deserialize
builtin
types
from
config
values
)
{
std
::
string
value
;
auto
&
xs
=
x
.
as_dictionary
();
put
(
xs
,
"foo"
,
"bar"
);
deserialize
(
xs
[
"foo"
],
value
);
CAF_CHECK_EQUAL
(
value
,
"bar"
);
}
CAF_TEST
(
readers
deserialize
simple
objects
from
configs
)
{
auto
&
xs
=
x
.
as_dictionary
();
put
(
xs
,
"foo"
,
"hello"
);
put
(
xs
,
"bar"
,
"world"
);
foobar
fb
;
...
...
@@ -97,6 +102,7 @@ CAF_TEST(readers deserialize simple objects from configs) {
CAF_TEST
(
readers
deserialize
complex
objects
from
configs
)
{
CAF_MESSAGE
(
"fill a dictionary with data for a 'basics' object"
);
auto
&
xs
=
x
.
as_dictionary
();
put
(
xs
,
"v1"
,
settings
{});
put
(
xs
,
"v2"
,
42
_i64
);
put
(
xs
,
"v3"
,
i64_list
({
1
,
2
,
3
,
4
}));
...
...
@@ -140,11 +146,11 @@ CAF_TEST(readers deserialize objects from the output of writers) {
line
l
{{
10
,
20
,
30
},
{
70
,
60
,
50
}};
config_value
tmp
;
config_value_writer
writer
{
&
tmp
};
if
(
!
detail
::
save
_value
(
writer
,
l
))
if
(
!
detail
::
save
(
writer
,
l
))
CAF_FAIL
(
"failed two write to settings: "
<<
writer
.
get_error
());
if
(
!
holds_alternative
<
settings
>
(
tmp
))
CAF_FAIL
(
"writer failed to produce a dictionary"
);
x
s
=
std
::
move
(
caf
::
get
<
settings
>
(
tmp
));
x
.
as_dictionary
()
=
std
::
move
(
caf
::
get
<
settings
>
(
tmp
));
}
CAF_MESSAGE
(
"serialize and verify the 'line' object"
);
{
...
...
libcaf_core/test/config_value_writer.cpp
View file @
dc04d789
...
...
@@ -41,17 +41,13 @@ constexpr i64 operator""_i64(unsigned long long int x) {
using
i64_list
=
std
::
vector
<
i64
>
;
struct
fixture
{
settings
xs
;
config_value
x
;
template
<
class
T
>
void
set
(
const
T
&
value
)
{
config_value
val
;
config_value_writer
writer
{
&
val
};
if
(
!
detail
::
save_value
(
writer
,
value
))
config_value_writer
writer
{
&
x
};
if
(
!
detail
::
save
(
writer
,
value
))
CAF_FAIL
(
"failed two write to settings: "
<<
writer
.
get_error
());
if
(
!
holds_alternative
<
settings
>
(
val
))
CAF_FAIL
(
"serializing T did not result in a dictionary"
);
xs
=
std
::
move
(
caf
::
get
<
settings
>
(
val
));
}
template
<
class
T
>
...
...
@@ -63,7 +59,10 @@ struct fixture {
template
<
class
T
>
optional
<
T
>
get
(
string_view
key
)
{
return
get
<
T
>
(
xs
,
key
);
if
(
auto
*
xs
=
get_if
<
settings
>
(
&
x
))
return
get
<
T
>
(
*
xs
,
key
);
else
CAF_FAIL
(
"fixture does not contain a dictionary"
);
}
};
...
...
@@ -101,7 +100,6 @@ CAF_TEST(empty types and maps become dictionaries) {
tst
.
v7
[
"two"
]
=
2
;
tst
.
v7
[
"three"
]
=
3
;
set
(
tst
);
CAF_MESSAGE
(
xs
);
CAF_CHECK_EQUAL
(
get
<
settings
>
(
"v1"
),
settings
{});
CAF_CHECK_EQUAL
(
get
<
i64
>
(
"v2"
),
42
_i64
);
CAF_CHECK_EQUAL
(
get
<
i64_list
>
(
"v3"
),
i64_list
({
-
1
,
-
2
,
-
3
,
-
4
}));
...
...
@@ -128,4 +126,10 @@ CAF_TEST(empty types and maps become dictionaries) {
CAF_CHECK_EQUAL
(
get
<
config_value
::
list
>
(
"v8"
),
config_value
::
list
());
}
CAF_TEST
(
custom
inspect
overloads
may
produce
single
values
)
{
auto
tue
=
weekday
::
tuesday
;
set
(
tue
);
CAF_CHECK_EQUAL
(
x
,
"tuesday"
s
);
}
CAF_TEST_FIXTURE_SCOPE_END
()
libcaf_core/test/core-test.hpp
View file @
dc04d789
...
...
@@ -200,6 +200,20 @@ enum class test_enum : int32_t {
// Implemented in serialization.cpp
std
::
string
to_string
(
test_enum
x
);
template
<
class
Inspector
>
bool
inspect
(
Inspector
&
f
,
test_enum
&
x
)
{
auto
get
=
[
&
x
]
{
return
static_cast
<
int32_t
>
(
x
);
};
auto
set
=
[
&
x
](
int32_t
val
)
{
if
(
val
>=
0
&&
val
<=
2
)
{
x
=
static_cast
<
test_enum
>
(
val
);
return
true
;
}
else
{
return
false
;
}
};
return
f
.
apply
(
get
,
set
);
}
// Used in serializer.cpp and deserializer.cpp
struct
test_data
{
int32_t
i32
;
...
...
@@ -231,10 +245,54 @@ enum class dummy_enum_class : short { foo, bar };
return
x
==
dummy_enum_class
::
foo
?
"foo"
:
"bar"
;
}
template
<
class
Inspector
>
bool
inspect
(
Inspector
&
f
,
dummy_enum_class
&
x
)
{
auto
get
=
[
&
x
]
{
return
static_cast
<
short
>
(
x
);
};
auto
set
=
[
&
x
](
short
val
)
{
if
(
val
>=
0
&&
val
<=
1
)
{
x
=
static_cast
<
dummy_enum_class
>
(
val
);
return
true
;
}
else
{
return
false
;
}
};
return
f
.
apply
(
get
,
set
);
}
enum
class
level
{
all
,
trace
,
debug
,
warning
,
error
};
template
<
class
Inspector
>
bool
inspect
(
Inspector
&
f
,
level
&
x
)
{
using
integer_type
=
std
::
underlying_type_t
<
level
>
;
auto
get
=
[
&
x
]
{
return
static_cast
<
integer_type
>
(
x
);
};
auto
set
=
[
&
x
](
integer_type
val
)
{
if
(
val
>=
0
&&
val
<=
4
)
{
x
=
static_cast
<
level
>
(
val
);
return
true
;
}
else
{
return
false
;
}
};
return
f
.
apply
(
get
,
set
);
}
enum
dummy_enum
{
de_foo
,
de_bar
};
template
<
class
Inspector
>
bool
inspect
(
Inspector
&
f
,
dummy_enum
&
x
)
{
using
integer_type
=
std
::
underlying_type_t
<
dummy_enum
>
;
auto
get
=
[
&
x
]
{
return
static_cast
<
integer_type
>
(
x
);
};
auto
set
=
[
&
x
](
integer_type
val
)
{
if
(
val
>=
0
&&
val
<=
1
)
{
x
=
static_cast
<
dummy_enum
>
(
val
);
return
true
;
}
else
{
return
false
;
}
};
return
f
.
apply
(
get
,
set
);
}
// -- type IDs for for all unit test suites ------------------------------------
#define ADD_TYPE_ID(type) CAF_ADD_TYPE_ID(core_test, type)
...
...
libcaf_core/test/detail/serialized_size.cpp
View file @
dc04d789
...
...
@@ -39,7 +39,7 @@ struct fixture : test_coordinator_fixture<> {
size_t
actual_size
(
const
Ts
&
...
xs
)
{
byte_buffer
buf
;
binary_serializer
sink
{
sys
,
buf
};
if
(
!
sink
.
apply_objects
(
xs
...))
if
(
!
(
sink
.
apply
(
xs
)
&&
...))
CAF_FAIL
(
"failed to serialize data: "
<<
sink
.
get_error
());
return
buf
.
size
();
}
...
...
libcaf_core/test/ipv4_endpoint.cpp
View file @
dc04d789
...
...
@@ -54,11 +54,11 @@ struct fixture {
T
roundtrip
(
T
x
)
{
byte_buffer
buf
;
binary_serializer
sink
(
sys
,
buf
);
if
(
!
sink
.
apply
_object
(
x
))
if
(
!
sink
.
apply
(
x
))
CAF_FAIL
(
"serialization failed: "
<<
sink
.
get_error
());
binary_deserializer
source
(
sys
,
make_span
(
buf
));
T
y
;
if
(
!
source
.
apply
_object
(
y
))
if
(
!
source
.
apply
(
y
))
CAF_FAIL
(
"deserialization failed: "
<<
source
.
get_error
());
return
y
;
}
...
...
libcaf_core/test/ipv6_endpoint.cpp
View file @
dc04d789
...
...
@@ -54,11 +54,11 @@ struct fixture {
T
roundtrip
(
T
x
)
{
byte_buffer
buf
;
binary_serializer
sink
(
sys
,
buf
);
if
(
!
sink
.
apply
_object
(
x
))
if
(
!
sink
.
apply
(
x
))
CAF_FAIL
(
"serialization failed: "
<<
sink
.
get_error
());
binary_deserializer
source
(
sys
,
make_span
(
buf
));
T
y
;
if
(
!
source
.
apply
_object
(
y
))
if
(
!
source
.
apply
(
y
))
CAF_FAIL
(
"serialization failed: "
<<
source
.
get_error
());
return
y
;
}
...
...
libcaf_core/test/load_inspector.cpp
View file @
dc04d789
...
...
@@ -44,7 +44,7 @@ struct testee : deserializer {
bool
load_field_failed
(
string_view
,
sec
code
)
{
set_error
(
make_error
(
code
));
return
stop
;
return
false
;
}
size_t
indent
=
0
;
...
...
@@ -63,14 +63,14 @@ struct testee : deserializer {
indent
+=
2
;
log
+=
"begin object "
;
log
.
insert
(
log
.
end
(),
object_name
.
begin
(),
object_name
.
end
());
return
ok
;
return
true
;
}
bool
end_object
()
override
{
indent
-=
2
;
new_line
();
log
+=
"end object"
;
return
ok
;
return
true
;
}
bool
begin_field
(
string_view
name
)
override
{
...
...
@@ -78,7 +78,7 @@ struct testee : deserializer {
indent
+=
2
;
log
+=
"begin field "
;
log
.
insert
(
log
.
end
(),
name
.
begin
(),
name
.
end
());
return
ok
;
return
true
;
}
bool
begin_field
(
string_view
name
,
bool
&
is_present
)
override
{
...
...
@@ -87,7 +87,7 @@ struct testee : deserializer {
log
+=
"begin optional field "
;
log
.
insert
(
log
.
end
(),
name
.
begin
(),
name
.
end
());
is_present
=
false
;
return
ok
;
return
true
;
}
bool
begin_field
(
string_view
name
,
span
<
const
type_id_t
>
,
...
...
@@ -97,7 +97,7 @@ struct testee : deserializer {
log
+=
"begin variant field "
;
log
.
insert
(
log
.
end
(),
name
.
begin
(),
name
.
end
());
type_index
=
0
;
return
ok
;
return
true
;
}
bool
begin_field
(
string_view
name
,
bool
&
is_present
,
span
<
const
type_id_t
>
,
...
...
@@ -107,14 +107,14 @@ struct testee : deserializer {
log
+=
"begin optional variant field "
;
log
.
insert
(
log
.
end
(),
name
.
begin
(),
name
.
end
());
is_present
=
false
;
return
ok
;
return
true
;
}
bool
end_field
()
override
{
indent
-=
2
;
new_line
();
log
+=
"end field"
;
return
ok
;
return
true
;
}
bool
begin_tuple
(
size_t
size
)
override
{
...
...
@@ -122,28 +122,28 @@ struct testee : deserializer {
indent
+=
2
;
log
+=
"begin tuple of size "
;
log
+=
std
::
to_string
(
size
);
return
ok
;
return
true
;
}
bool
end_tuple
()
override
{
indent
-=
2
;
new_line
();
log
+=
"end tuple"
;
return
ok
;
return
true
;
}
bool
begin_key_value_pair
()
override
{
new_line
();
indent
+=
2
;
log
+=
"begin key-value pair"
;
return
ok
;
return
true
;
}
bool
end_key_value_pair
()
override
{
indent
-=
2
;
new_line
();
log
+=
"end key-value pair"
;
return
ok
;
return
true
;
}
bool
begin_sequence
(
size_t
&
size
)
override
{
...
...
@@ -152,14 +152,14 @@ struct testee : deserializer {
indent
+=
2
;
log
+=
"begin sequence of size "
;
log
+=
std
::
to_string
(
size
);
return
ok
;
return
true
;
}
bool
end_sequence
()
override
{
indent
-=
2
;
new_line
();
log
+=
"end sequence"
;
return
ok
;
return
true
;
}
bool
begin_associative_array
(
size_t
&
size
)
override
{
...
...
@@ -168,21 +168,21 @@ struct testee : deserializer {
indent
+=
2
;
log
+=
"begin associative array of size "
;
log
+=
std
::
to_string
(
size
);
return
ok
;
return
true
;
}
bool
end_associative_array
()
override
{
indent
-=
2
;
new_line
();
log
+=
"end associative array"
;
return
ok
;
return
true
;
}
bool
value
(
bool
&
x
)
override
{
new_line
();
log
+=
"bool value"
;
x
=
false
;
return
ok
;
return
true
;
}
template
<
class
T
>
...
...
@@ -192,7 +192,14 @@ struct testee : deserializer {
log
.
insert
(
log
.
end
(),
tn
.
begin
(),
tn
.
end
());
log
+=
" value"
;
x
=
T
{};
return
ok
;
return
true
;
}
bool
value
(
byte
&
x
)
override
{
new_line
();
log
+=
"byte value"
;
x
=
byte
{};
return
true
;
}
bool
value
(
int8_t
&
x
)
override
{
...
...
@@ -256,7 +263,7 @@ struct testee : deserializer {
log
+=
"caf::span<caf::byte> value"
;
for
(
auto
&
x
:
xs
)
x
=
byte
{
0
};
return
ok
;
return
true
;
}
};
...
...
@@ -330,7 +337,7 @@ end object)_");
CAF_TEST
(
load
inspectors
support
optional
)
{
optional
<
int32_t
>
x
;
CAF_CHECK_EQUAL
(
f
.
apply
_object
(
x
),
true
);
CAF_CHECK_EQUAL
(
f
.
apply
(
x
),
true
);
CAF_CHECK_EQUAL
(
f
.
log
,
R"_(
begin object anonymous
begin optional field value
...
...
libcaf_core/test/message.cpp
View file @
dc04d789
...
...
@@ -110,19 +110,16 @@ CAF_TEST(to_string converts messages to strings) {
CAF_CHECK_EQUAL
(
msg_as_string
(),
"message()"
);
CAF_CHECK_EQUAL
(
msg_as_string
(
"hello"
,
"world"
),
R"__(message("hello", "world"))__"
);
CAF_CHECK_EQUAL
(
msg_as_string
(
svec
{
"one"
,
"two"
,
"three"
}),
R"__(message(std::vector<std::string>(["one", "two", "three"])))__"
);
CAF_CHECK_EQUAL
(
msg_as_string
(
svec
{
"one"
,
"two"
},
"three"
,
"four"
,
svec
{
"five"
,
"six"
,
"seven"
}),
R"__(message(std::vector<std::string>(["one", "two"]), "three", "four", )__"
R"__(std::vector<std::string>(["five", "six", "seven"])))__"
);
CAF_CHECK_EQUAL
(
msg_as_string
(
svec
{
"one"
,
"two"
,
"three"
}),
R"__(message(["one", "two", "three"]))__"
);
CAF_CHECK_EQUAL
(
msg_as_string
(
svec
{
"one"
,
"two"
},
"three"
,
"four"
,
svec
{
"five"
,
"six"
,
"seven"
}),
R"__(message(["one", "two"], "three", "four", )__"
R"__(["five", "six", "seven"]))__"
);
auto
teststr
=
R"__(message("this is a \"test\""))__"
;
// fails inline on MSVC
CAF_CHECK_EQUAL
(
msg_as_string
(
R"__(this is a "test")__"
),
teststr
);
CAF_CHECK_EQUAL
(
msg_as_string
(
make_tuple
(
1
,
2
,
3
),
4
,
5
),
"message(std::tuple<int32_t, int32_t, int32_t>([1, 2, 3]), "
"int32_t(4), int32_t(5))"
);
"message([1, 2, 3], 4, 5)"
);
CAF_CHECK_EQUAL
(
msg_as_string
(
s1
{}),
"message(s1([10, 20, 30]))"
);
s2
tmp
;
tmp
.
value
[
0
][
1
]
=
100
;
...
...
libcaf_core/test/message_builder.cpp
View file @
dc04d789
...
...
@@ -47,7 +47,7 @@ CAF_TEST(message builder can build messages incrermenetally) {
CAF_CHECK_EQUAL
(
builder
.
size
(),
1u
);
CAF_CHECK_EQUAL
(
msg
.
types
(),
make_type_id_list
<
int32_t
>
());
CAF_CHECK_EQUAL
(
to_string
(
msg
.
types
()),
"[int32_t]"
);
CAF_CHECK_EQUAL
(
to_string
(
msg
),
"message(
int32_t(1)
)"
);
CAF_CHECK_EQUAL
(
to_string
(
msg
),
"message(
1
)"
);
}
STEP
(
"after adding [2, 3], the message is (1, 2, 3)"
)
{
std
::
vector
<
int32_t
>
xs
{
2
,
3
};
...
...
@@ -57,15 +57,13 @@ CAF_TEST(message builder can build messages incrermenetally) {
CAF_CHECK_EQUAL
(
msg
.
types
(),
(
make_type_id_list
<
int32_t
,
int32_t
,
int32_t
>
()));
CAF_CHECK_EQUAL
(
to_string
(
msg
.
types
()),
"[int32_t, int32_t, int32_t]"
);
CAF_CHECK_EQUAL
(
to_string
(
msg
),
"message(int32_t(1), int32_t(2), int32_t(3))"
);
CAF_CHECK_EQUAL
(
to_string
(
msg
),
"message(1, 2, 3)"
);
}
STEP
(
"moving the content to a message produces the same message again"
)
{
auto
msg
=
builder
.
move_to_message
();
CAF_CHECK_EQUAL
(
msg
.
types
(),
(
make_type_id_list
<
int32_t
,
int32_t
,
int32_t
>
()));
CAF_CHECK_EQUAL
(
to_string
(
msg
.
types
()),
"[int32_t, int32_t, int32_t]"
);
CAF_CHECK_EQUAL
(
to_string
(
msg
),
"message(int32_t(1), int32_t(2), int32_t(3))"
);
CAF_CHECK_EQUAL
(
to_string
(
msg
),
"message(1, 2, 3)"
);
}
}
libcaf_core/test/nasty.hpp
View file @
dc04d789
...
...
@@ -28,22 +28,18 @@ bool inspect(Inspector& f, weekday& x) {
if
(
f
.
has_human_readable_format
())
{
auto
get
=
[
&
x
]
{
return
to_string
(
x
);
};
auto
set
=
[
&
x
](
std
::
string
str
)
{
return
parse
(
str
,
x
);
};
return
f
.
object
(
x
).
fields
(
f
.
field
(
"value"
,
get
,
set
)
);
return
f
.
apply
(
get
,
set
);
}
else
{
using
default_impl
=
caf
::
default_inspector_access
<
weekday
>
;
return
default_impl
::
apply_object
(
f
,
x
);
}
}
template
<
class
Inspector
>
bool
inspect_value
(
Inspector
&
f
,
weekday
&
x
)
{
if
(
f
.
has_human_readable_format
())
{
auto
get
=
[
&
x
]
{
return
to_string
(
x
);
};
auto
set
=
[
&
x
](
std
::
string
str
)
{
return
parse
(
str
,
x
);
};
return
f
.
apply_value
(
get
,
set
);
}
else
{
using
default_impl
=
caf
::
default_inspector_access
<
weekday
>
;
return
default_impl
::
apply_value
(
f
,
x
);
auto
get
=
[
&
x
]
{
return
static_cast
<
uint8_t
>
(
x
);
};
auto
set
=
[
&
x
](
uint8_t
val
)
{
if
(
val
<
7
)
{
x
=
static_cast
<
weekday
>
(
val
);
return
true
;
}
else
{
return
false
;
}
};
return
f
.
apply
(
get
,
set
);
}
}
...
...
libcaf_core/test/node_id.cpp
View file @
dc04d789
...
...
@@ -33,7 +33,7 @@ node_id roundtrip(node_id nid) {
byte_buffer
buf
;
{
binary_serializer
sink
{
nullptr
,
buf
};
if
(
!
sink
.
apply
_object
(
nid
))
if
(
!
sink
.
apply
(
nid
))
CAF_FAIL
(
"serialization failed: "
<<
sink
.
get_error
());
}
if
(
buf
.
empty
())
...
...
@@ -41,7 +41,7 @@ node_id roundtrip(node_id nid) {
node_id
result
;
{
binary_deserializer
source
{
nullptr
,
buf
};
if
(
!
source
.
apply
_object
(
result
))
if
(
!
source
.
apply
(
result
))
CAF_FAIL
(
"deserialization failed: "
<<
source
.
get_error
());
if
(
source
.
remaining
()
>
0
)
CAF_FAIL
(
"binary_serializer ignored part of its input"
);
...
...
libcaf_core/test/save_inspector.cpp
View file @
dc04d789
...
...
@@ -54,7 +54,7 @@ struct testee : serializer {
log
+=
"next object type: "
;
auto
tn
=
detail
::
global_meta_object
(
type
)
->
type_name
;
log
.
insert
(
log
.
end
(),
tn
.
begin
(),
tn
.
end
());
return
ok
;
return
true
;
}
bool
begin_object
(
string_view
object_name
)
override
{
...
...
@@ -62,7 +62,7 @@ struct testee : serializer {
indent
+=
2
;
log
+=
"begin object "
;
log
.
insert
(
log
.
end
(),
object_name
.
begin
(),
object_name
.
end
());
return
ok
;
return
true
;
}
bool
end_object
()
override
{
...
...
@@ -71,7 +71,7 @@ struct testee : serializer {
indent
-=
2
;
new_line
();
log
+=
"end object"
;
return
ok
;
return
true
;
}
bool
begin_field
(
string_view
name
)
override
{
...
...
@@ -79,7 +79,7 @@ struct testee : serializer {
indent
+=
2
;
log
+=
"begin field "
;
log
.
insert
(
log
.
end
(),
name
.
begin
(),
name
.
end
());
return
ok
;
return
true
;
}
bool
begin_field
(
string_view
name
,
bool
)
override
{
...
...
@@ -87,7 +87,7 @@ struct testee : serializer {
indent
+=
2
;
log
+=
"begin optional field "
;
log
.
insert
(
log
.
end
(),
name
.
begin
(),
name
.
end
());
return
ok
;
return
true
;
}
bool
begin_field
(
string_view
name
,
span
<
const
type_id_t
>
,
size_t
)
override
{
...
...
@@ -95,7 +95,7 @@ struct testee : serializer {
indent
+=
2
;
log
+=
"begin variant field "
;
log
.
insert
(
log
.
end
(),
name
.
begin
(),
name
.
end
());
return
ok
;
return
true
;
}
bool
begin_field
(
string_view
name
,
bool
,
span
<
const
type_id_t
>
,
...
...
@@ -104,7 +104,7 @@ struct testee : serializer {
indent
+=
2
;
log
+=
"begin optional variant field "
;
log
.
insert
(
log
.
end
(),
name
.
begin
(),
name
.
end
());
return
ok
;
return
true
;
}
bool
end_field
()
override
{
...
...
@@ -113,7 +113,7 @@ struct testee : serializer {
indent
-=
2
;
new_line
();
log
+=
"end field"
;
return
ok
;
return
true
;
}
bool
begin_tuple
(
size_t
size
)
override
{
...
...
@@ -121,7 +121,7 @@ struct testee : serializer {
indent
+=
2
;
log
+=
"begin tuple of size "
;
log
+=
std
::
to_string
(
size
);
return
ok
;
return
true
;
}
bool
end_tuple
()
override
{
...
...
@@ -130,14 +130,14 @@ struct testee : serializer {
indent
-=
2
;
new_line
();
log
+=
"end tuple"
;
return
ok
;
return
true
;
}
bool
begin_key_value_pair
()
override
{
new_line
();
indent
+=
2
;
log
+=
"begin key-value pair"
;
return
ok
;
return
true
;
}
bool
end_key_value_pair
()
override
{
...
...
@@ -146,7 +146,7 @@ struct testee : serializer {
indent
-=
2
;
new_line
();
log
+=
"end key-value pair"
;
return
ok
;
return
true
;
}
bool
begin_sequence
(
size_t
size
)
override
{
...
...
@@ -154,7 +154,7 @@ struct testee : serializer {
indent
+=
2
;
log
+=
"begin sequence of size "
;
log
+=
std
::
to_string
(
size
);
return
ok
;
return
true
;
}
bool
end_sequence
()
override
{
...
...
@@ -163,7 +163,7 @@ struct testee : serializer {
indent
-=
2
;
new_line
();
log
+=
"end sequence"
;
return
ok
;
return
true
;
}
bool
begin_associative_array
(
size_t
size
)
override
{
...
...
@@ -171,7 +171,7 @@ struct testee : serializer {
indent
+=
2
;
log
+=
"begin associative array of size "
;
log
+=
std
::
to_string
(
size
);
return
ok
;
return
true
;
}
bool
end_associative_array
()
override
{
...
...
@@ -180,103 +180,109 @@ struct testee : serializer {
indent
-=
2
;
new_line
();
log
+=
"end associative array"
;
return
ok
;
return
true
;
}
bool
value
(
byte
)
override
{
new_line
();
log
+=
"byte value"
;
return
true
;
}
bool
value
(
bool
)
override
{
new_line
();
log
+=
"bool value"
;
return
ok
;
return
true
;
}
bool
value
(
int8_t
)
override
{
new_line
();
log
+=
"int8_t value"
;
return
ok
;
return
true
;
}
bool
value
(
uint8_t
)
override
{
new_line
();
log
+=
"uint8_t value"
;
return
ok
;
return
true
;
}
bool
value
(
int16_t
)
override
{
new_line
();
log
+=
"int16_t value"
;
return
ok
;
return
true
;
}
bool
value
(
uint16_t
)
override
{
new_line
();
log
+=
"uint16_t value"
;
return
ok
;
return
true
;
}
bool
value
(
int32_t
)
override
{
new_line
();
log
+=
"int32_t value"
;
return
ok
;
return
true
;
}
bool
value
(
uint32_t
)
override
{
new_line
();
log
+=
"uint32_t value"
;
return
ok
;
return
true
;
}
bool
value
(
int64_t
)
override
{
new_line
();
log
+=
"int64_t value"
;
return
ok
;
return
true
;
}
bool
value
(
uint64_t
)
override
{
new_line
();
log
+=
"uint64_t value"
;
return
ok
;
return
true
;
}
bool
value
(
float
)
override
{
new_line
();
log
+=
"float value"
;
return
ok
;
return
true
;
}
bool
value
(
double
)
override
{
new_line
();
log
+=
"double value"
;
return
ok
;
return
true
;
}
bool
value
(
long
double
)
override
{
new_line
();
log
+=
"long double value"
;
return
ok
;
return
true
;
}
bool
value
(
string_view
)
override
{
new_line
();
log
+=
"std::string value"
;
return
ok
;
return
true
;
}
bool
value
(
const
std
::
u16string
&
)
override
{
new_line
();
log
+=
"std::u16string value"
;
return
ok
;
return
true
;
}
bool
value
(
const
std
::
u32string
&
)
override
{
new_line
();
log
+=
"std::u32string value"
;
return
ok
;
return
true
;
}
bool
value
(
span
<
const
byte
>
)
override
{
new_line
();
log
+=
"byte_span value"
;
return
ok
;
return
true
;
}
};
...
...
@@ -290,7 +296,7 @@ CAF_TEST_FIXTURE_SCOPE(load_inspector_tests, fixture)
CAF_TEST
(
save
inspectors
can
visit
C
arrays
)
{
int32_t
xs
[]
=
{
1
,
2
,
3
};
CAF_CHECK_EQUAL
(
detail
::
save
_value
(
f
,
xs
),
true
);
CAF_CHECK_EQUAL
(
detail
::
save
(
f
,
xs
),
true
);
CAF_CHECK_EQUAL
(
f
.
log
,
R"_(
begin tuple of size 3
int32_t value
...
...
@@ -436,7 +442,7 @@ end object)_");
CAF_TEST
(
save
inspectors
support
optional
)
{
optional
<
int32_t
>
x
;
CAF_CHECK_EQUAL
(
f
.
apply
_object
(
x
),
true
);
CAF_CHECK_EQUAL
(
f
.
apply
(
x
),
true
);
CAF_CHECK_EQUAL
(
f
.
log
,
R"_(
begin object anonymous
begin optional field value
...
...
@@ -717,21 +723,9 @@ begin object message
end field
begin field values
begin tuple of size 3
begin object int32_t
begin field value
int32_t value
end field
end object
begin object std::string
begin field value
std::string value
end field
end object
begin object double
begin field value
double value
end field
end object
int32_t value
std::string value
double value
end tuple
end field
end object)_"
);
...
...
@@ -744,23 +738,11 @@ begin object message
begin field values
begin sequence of size 3
next object type: int32_t
begin object int32_t
begin field value
int32_t value
end field
end object
int32_t value
next object type: std::string
begin object std::string
begin field value
std::string value
end field
end object
std::string value
next object type: double
begin object double
begin field value
double value
end field
end object
double value
end sequence
end field
end object)_"
);
...
...
libcaf_core/test/serialization.cpp
View file @
dc04d789
...
...
@@ -30,6 +30,7 @@
#include <limits>
#include <list>
#include <locale>
#include <map>
#include <memory>
#include <new>
#include <set>
...
...
@@ -52,17 +53,66 @@
#include "caf/detail/ieee_754.hpp"
#include "caf/detail/int_list.hpp"
#include "caf/detail/safe_equal.hpp"
#include "caf/detail/stringification_inspector.hpp"
#include "caf/detail/type_traits.hpp"
#include "caf/event_based_actor.hpp"
#include "caf/message.hpp"
#include "caf/message_handler.hpp"
#include "caf/proxy_registry.hpp"
#include "caf/ref_counted.hpp"
#include "caf/sec.hpp"
#include "caf/serializer.hpp"
#include "caf/variant.hpp"
struct
opaque
{
int
secret
;
};
CAF_ALLOW_UNSAFE_MESSAGE_TYPE
(
opaque
)
struct
the_great_unknown
{
int
secret
;
};
using
namespace
caf
;
using
bs
=
binary_serializer
;
using
si
=
detail
::
stringification_inspector
;
using
iat
=
inspector_access_type
;
template
<
class
Inspector
,
class
T
>
struct
access_of
{
template
<
class
What
>
static
constexpr
bool
is
=
std
::
is_same
<
decltype
(
inspect_access_type
<
Inspector
,
T
>
()),
What
>::
value
;
};
static_assert
(
access_of
<
bs
,
variant
<
int
,
double
>>::
is
<
iat
::
specialization
>
);
static_assert
(
access_of
<
bs
,
sec
>::
is
<
iat
::
inspect
>
);
static_assert
(
access_of
<
bs
,
int
>::
is
<
iat
::
builtin
>
);
static_assert
(
access_of
<
bs
,
dummy_tag_type
>::
is
<
iat
::
empty
>
);
static_assert
(
access_of
<
bs
,
opaque
>::
is
<
iat
::
unsafe
>
);
static_assert
(
access_of
<
bs
,
std
::
tuple
<
int
,
double
>>::
is
<
iat
::
tuple
>
);
static_assert
(
access_of
<
bs
,
std
::
map
<
int
,
int
>>::
is
<
iat
::
map
>
);
static_assert
(
access_of
<
bs
,
std
::
vector
<
bool
>>::
is
<
iat
::
list
>
);
static_assert
(
access_of
<
bs
,
the_great_unknown
>::
is
<
iat
::
none
>
);
// The stringification inspector picks up to_string via builtin_inspect.
static_assert
(
access_of
<
si
,
sec
>::
is
<
iat
::
builtin_inspect
>
);
static_assert
(
access_of
<
si
,
timespan
>::
is
<
iat
::
builtin_inspect
>
);
const
char
*
test_enum_strings
[]
=
{
"a"
,
"b"
,
...
...
@@ -111,7 +161,7 @@ struct fixture : test_coordinator_fixture<> {
byte_buffer
serialize
(
const
Ts
&
...
xs
)
{
byte_buffer
buf
;
binary_serializer
sink
{
sys
,
buf
};
if
(
!
sink
.
apply_objects
(
xs
...))
if
(
!
(
sink
.
apply
(
xs
)
&&
...))
CAF_FAIL
(
"serialization failed: "
<<
sink
.
get_error
()
<<
", data: "
<<
deep_to_string
(
std
::
forward_as_tuple
(
xs
...)));
...
...
@@ -121,7 +171,7 @@ struct fixture : test_coordinator_fixture<> {
template
<
class
...
Ts
>
void
deserialize
(
const
byte_buffer
&
buf
,
Ts
&
...
xs
)
{
binary_deserializer
source
{
sys
,
buf
};
if
(
!
source
.
apply_objects
(
xs
...))
if
(
!
(
source
.
apply
(
xs
)
&&
...))
CAF_FAIL
(
"deserialization failed: "
<<
source
.
get_error
());
}
...
...
libcaf_core/test/tracing_data.cpp
View file @
dc04d789
...
...
@@ -47,11 +47,11 @@ public:
}
bool
serialize
(
serializer
&
sink
)
const
override
{
return
sink
.
apply
_object
(
value
);
return
sink
.
apply
(
value
);
}
bool
serialize
(
binary_serializer
&
sink
)
const
override
{
return
sink
.
apply
_object
(
value
);
return
sink
.
apply
(
value
);
}
};
...
...
@@ -72,7 +72,7 @@ private:
bool
deserialize_impl
(
Deserializer
&
source
,
std
::
unique_ptr
<
tracing_data
>&
dst
)
const
{
string
value
;
if
(
!
source
.
apply
_object
(
value
))
if
(
!
source
.
apply
(
value
))
return
false
;
dst
.
reset
(
new
dummy_tracing_data
(
std
::
move
(
value
)));
return
true
;
...
...
@@ -193,10 +193,10 @@ CAF_TEST(tracing data is serializable) {
byte_buffer
buf
;
binary_serializer
sink
{
sys
,
buf
};
tracing_data_ptr
data
{
new
dummy_tracing_data
(
"iTrace"
)};
CAF_CHECK
(
sink
.
apply
_object
(
data
));
CAF_CHECK
(
sink
.
apply
(
data
));
binary_deserializer
source
{
sys
,
buf
};
tracing_data_ptr
copy
;
CAF_CHECK
(
source
.
apply
_object
(
copy
));
CAF_CHECK
(
source
.
apply
(
copy
));
CAF_REQUIRE_NOT_EQUAL
(
copy
.
get
(),
nullptr
);
CAF_CHECK_EQUAL
(
dynamic_cast
<
dummy_tracing_data
&>
(
*
copy
).
value
,
"iTrace"
);
}
...
...
libcaf_core/test/uri.cpp
View file @
dc04d789
...
...
@@ -133,7 +133,7 @@ struct fixture {
byte_buffer
serialize
(
uri
x
)
{
byte_buffer
buf
;
binary_serializer
sink
{
nullptr
,
buf
};
if
(
!
sink
.
apply
_objects
(
x
))
if
(
!
sink
.
apply
(
x
))
CAF_FAIL
(
"unable to serialize "
<<
x
<<
": "
<<
sink
.
get_error
());
return
buf
;
}
...
...
@@ -141,7 +141,7 @@ struct fixture {
uri
deserialize
(
byte_buffer
buf
)
{
uri
result
;
binary_deserializer
source
{
nullptr
,
buf
};
if
(
!
source
.
apply
_objects
(
result
))
if
(
!
source
.
apply
(
result
))
CAF_FAIL
(
"unable to deserialize from buffer: "
<<
source
.
get_error
());
return
result
;
}
...
...
libcaf_io/caf/io/basp/message_type.hpp
View file @
dc04d789
...
...
@@ -20,7 +20,9 @@
#include <cstdint>
#include <string>
#include <type_traits>
#include "caf/default_enum_inspect.hpp"
#include "caf/detail/io_export.hpp"
namespace
caf
::
io
::
basp
{
...
...
@@ -76,6 +78,16 @@ enum class message_type : uint8_t {
CAF_IO_EXPORT
std
::
string
to_string
(
message_type
);
CAF_IO_EXPORT
bool
from_string
(
string_view
,
message_type
&
);
CAF_IO_EXPORT
bool
from_integer
(
std
::
underlying_type_t
<
message_type
>
,
message_type
&
);
template
<
class
Inssector
>
bool
inspect
(
Inssector
&
f
,
message_type
&
x
)
{
return
default_enum_inspect
(
f
,
x
);
}
/// @}
}
// namespace caf::io::basp
libcaf_io/caf/io/basp/remote_message_handler.hpp
View file @
dc04d789
...
...
@@ -79,12 +79,12 @@ public:
if
(
dref
.
hdr_
.
operation
==
basp
::
message_type
::
routed_message
)
{
node_id
src_node
;
node_id
dst_node
;
if
(
!
source
.
apply
_object
(
src_node
))
{
if
(
!
source
.
apply
(
src_node
))
{
CAF_LOG_ERROR
(
"failed to read source of routed message:"
<<
source
.
get_error
());
return
;
}
if
(
!
source
.
apply
_object
(
dst_node
))
{
if
(
!
source
.
apply
(
dst_node
))
{
CAF_LOG_ERROR
(
"failed to read destination of routed message:"
<<
source
.
get_error
());
return
;
...
...
@@ -108,13 +108,13 @@ public:
return
;
}
// Get the remainder of the message.
if
(
!
source
.
apply
_object
(
stages
))
{
if
(
!
source
.
apply
(
stages
))
{
CAF_LOG_ERROR
(
"failed to read stages:"
<<
source
.
get_error
());
return
;
}
auto
&
mm_metrics
=
ctx
->
system
().
middleman
().
metric_singletons
;
auto
t0
=
telemetry
::
timer
::
clock_type
::
now
();
if
(
!
source
.
apply
_objects
(
msg
))
{
if
(
!
source
.
apply
(
msg
))
{
CAF_LOG_ERROR
(
"failed to read message content:"
<<
source
.
get_error
());
return
;
}
...
...
libcaf_io/caf/io/network/protocol.hpp
View file @
dc04d789
...
...
@@ -40,10 +40,32 @@ inline std::string to_string(protocol::transport x) {
return
x
==
protocol
::
tcp
?
"TCP"
:
"UDP"
;
}
template
<
class
Inspector
>
bool
inspect
(
Inspector
&
f
,
protocol
::
transport
&
x
)
{
using
integer_type
=
std
::
underlying_type_t
<
protocol
::
transport
>
;
auto
get
=
[
&
x
]
{
return
static_cast
<
integer_type
>
(
x
);
};
auto
set
=
[
&
x
](
integer_type
val
)
{
x
=
static_cast
<
protocol
::
transport
>
(
val
);
return
true
;
};
return
f
.
apply
(
get
,
set
);
}
inline
std
::
string
to_string
(
protocol
::
network
x
)
{
return
x
==
protocol
::
ipv4
?
"IPv4"
:
"IPv6"
;
}
template
<
class
Inspector
>
bool
inspect
(
Inspector
&
f
,
protocol
::
network
&
x
)
{
using
integer_type
=
std
::
underlying_type_t
<
protocol
::
network
>
;
auto
get
=
[
&
x
]
{
return
static_cast
<
integer_type
>
(
x
);
};
auto
set
=
[
&
x
](
integer_type
val
)
{
x
=
static_cast
<
protocol
::
network
>
(
val
);
return
true
;
};
return
f
.
apply
(
get
,
set
);
}
template
<
class
Inspector
>
bool
inspect
(
Inspector
&
f
,
protocol
&
x
)
{
return
f
.
object
(
x
).
fields
(
f
.
field
(
"trans"
,
x
.
trans
),
f
.
field
(
"net"
,
x
.
net
));
...
...
libcaf_io/src/io/basp/instance.cpp
View file @
dc04d789
...
...
@@ -73,7 +73,7 @@ connection_state instance::handle(execution_unit* ctx, new_data_msg& dm,
}
}
else
{
binary_deserializer
source
{
ctx
,
dm
.
buf
};
if
(
!
source
.
apply
_object
(
hdr
))
{
if
(
!
source
.
apply
(
hdr
))
{
CAF_LOG_WARNING
(
"failed to receive header:"
<<
source
.
get_error
());
return
err
(
malformed_basp_message
);
}
...
...
@@ -185,7 +185,7 @@ bool instance::dispatch(execution_unit* ctx, const strong_actor_ptr& sender,
sender
?
sender
->
id
()
:
invalid_actor_id
,
dest_actor
};
auto
writer
=
make_callback
([
&
](
binary_serializer
&
sink
)
{
//
return
sink
.
apply
_objects
(
forwarding_stack
,
msg
);
return
sink
.
apply
(
forwarding_stack
)
&&
sink
.
apply
(
msg
);
});
write
(
ctx
,
callee_
.
get_buffer
(
path
->
hdl
),
hdr
,
&
writer
);
}
else
{
...
...
@@ -199,7 +199,10 @@ bool instance::dispatch(execution_unit* ctx, const strong_actor_ptr& sender,
CAF_LOG_DEBUG
(
"send routed message: "
<<
CAF_ARG
(
source_node
)
<<
CAF_ARG
(
dest_node
)
<<
CAF_ARG
(
forwarding_stack
)
<<
CAF_ARG
(
msg
));
return
sink
.
apply_objects
(
source_node
,
dest_node
,
forwarding_stack
,
msg
);
return
sink
.
apply
(
source_node
)
//
&&
sink
.
apply
(
dest_node
)
//
&&
sink
.
apply
(
forwarding_stack
)
//
&&
sink
.
apply
(
msg
);
});
write
(
ctx
,
callee_
.
get_buffer
(
path
->
hdl
),
hdr
,
&
writer
);
}
...
...
@@ -229,7 +232,7 @@ void instance::write(execution_unit* ctx, byte_buffer& buf, header& hdr,
mm_metrics
.
outbound_messages_size
->
observe
(
signed_payload_len
);
hdr
.
payload_len
=
static_cast
<
uint32_t
>
(
payload_len
);
}
if
(
!
sink
.
apply
_objects
(
hdr
))
if
(
!
sink
.
apply
(
hdr
))
CAF_LOG_ERROR
(
sink
.
get_error
());
}
...
...
@@ -258,7 +261,10 @@ void instance::write_server_handshake(execution_unit* ctx, byte_buffer& out_buf,
aid
=
pa
->
first
->
id
();
iface
=
pa
->
second
;
}
return
sink
.
apply_objects
(
this_node_
,
app_ids
,
aid
,
iface
);
return
sink
.
apply
(
this_node_
)
//
&&
sink
.
apply
(
app_ids
)
//
&&
sink
.
apply
(
aid
)
//
&&
sink
.
apply
(
iface
);
});
header
hdr
{
message_type
::
server_handshake
,
0
,
...
...
@@ -271,7 +277,7 @@ void instance::write_server_handshake(execution_unit* ctx, byte_buffer& out_buf,
void
instance
::
write_client_handshake
(
execution_unit
*
ctx
,
byte_buffer
&
buf
)
{
auto
writer
=
make_callback
([
&
](
binary_serializer
&
sink
)
{
//
return
sink
.
apply
_objects
(
this_node_
);
return
sink
.
apply
(
this_node_
);
});
header
hdr
{
message_type
::
client_handshake
,
0
,
...
...
@@ -286,7 +292,7 @@ void instance::write_monitor_message(execution_unit* ctx, byte_buffer& buf,
const
node_id
&
dest_node
,
actor_id
aid
)
{
CAF_LOG_TRACE
(
CAF_ARG
(
dest_node
)
<<
CAF_ARG
(
aid
));
auto
writer
=
make_callback
([
&
](
binary_serializer
&
sink
)
{
//
return
sink
.
apply
_objects
(
this_node_
,
dest_node
);
return
sink
.
apply
(
this_node_
)
&&
sink
.
apply
(
dest_node
);
});
header
hdr
{
message_type
::
monitor_message
,
0
,
0
,
0
,
invalid_actor_id
,
aid
};
write
(
ctx
,
buf
,
hdr
,
&
writer
);
...
...
@@ -296,8 +302,8 @@ void instance::write_down_message(execution_unit* ctx, byte_buffer& buf,
const
node_id
&
dest_node
,
actor_id
aid
,
const
error
&
rsn
)
{
CAF_LOG_TRACE
(
CAF_ARG
(
dest_node
)
<<
CAF_ARG
(
aid
)
<<
CAF_ARG
(
rsn
));
auto
writer
=
make_callback
([
&
](
binary_serializer
&
sink
)
{
//
return
sink
.
apply
_objects
(
this_node_
,
dest_node
,
rsn
);
auto
writer
=
make_callback
([
&
](
binary_serializer
&
sink
)
{
return
sink
.
apply
(
this_node_
)
&&
sink
.
apply
(
dest_node
)
&&
sink
.
apply
(
rsn
);
});
header
hdr
{
message_type
::
down_message
,
0
,
0
,
0
,
aid
,
invalid_actor_id
};
write
(
ctx
,
buf
,
hdr
,
&
writer
);
...
...
@@ -333,7 +339,10 @@ connection_state instance::handle(execution_unit* ctx, connection_handle hdl,
string_list
app_ids
;
actor_id
aid
=
invalid_actor_id
;
std
::
set
<
std
::
string
>
sigs
;
if
(
!
source
.
apply_objects
(
source_node
,
app_ids
,
aid
,
sigs
))
{
if
(
!
source
.
apply
(
source_node
)
//
||
!
source
.
apply
(
app_ids
)
//
||
!
source
.
apply
(
aid
)
//
||
!
source
.
apply
(
sigs
))
{
CAF_LOG_WARNING
(
"unable to deserialize payload of server handshake:"
<<
source
.
get_error
());
return
serializing_basp_payload_failed
;
...
...
@@ -383,7 +392,7 @@ connection_state instance::handle(execution_unit* ctx, connection_handle hdl,
// Deserialize payload.
binary_deserializer
source
{
ctx
,
*
payload
};
node_id
source_node
;
if
(
!
source
.
apply
_objects
(
source_node
))
{
if
(
!
source
.
apply
(
source_node
))
{
CAF_LOG_WARNING
(
"unable to deserialize payload of client handshake:"
<<
source
.
get_error
());
return
serializing_basp_payload_failed
;
...
...
@@ -406,7 +415,7 @@ connection_state instance::handle(execution_unit* ctx, connection_handle hdl,
binary_deserializer
source
{
ctx
,
*
payload
};
node_id
source_node
;
node_id
dest_node
;
if
(
!
source
.
apply
_objects
(
source_node
,
dest_node
))
{
if
(
!
source
.
apply
(
source_node
)
||
!
source
.
apply
(
dest_node
))
{
CAF_LOG_WARNING
(
"unable to deserialize source and destination for routed message:"
<<
source
.
get_error
());
...
...
@@ -465,7 +474,7 @@ connection_state instance::handle(execution_unit* ctx, connection_handle hdl,
binary_deserializer
source
{
ctx
,
*
payload
};
node_id
source_node
;
node_id
dest_node
;
if
(
!
source
.
apply
_objects
(
source_node
,
dest_node
))
{
if
(
!
source
.
apply
(
source_node
)
||
!
source
.
apply
(
dest_node
))
{
CAF_LOG_WARNING
(
"unable to deserialize payload of monitor message:"
<<
source
.
get_error
());
return
serializing_basp_payload_failed
;
...
...
@@ -482,7 +491,9 @@ connection_state instance::handle(execution_unit* ctx, connection_handle hdl,
node_id
source_node
;
node_id
dest_node
;
error
fail_state
;
if
(
!
source
.
apply_objects
(
source_node
,
dest_node
,
fail_state
))
{
if
(
!
source
.
apply
(
source_node
)
//
||
!
source
.
apply
(
dest_node
)
//
||
!
source
.
apply
(
fail_state
))
{
CAF_LOG_WARNING
(
"unable to deserialize payload of down message:"
<<
source
.
get_error
());
return
serializing_basp_payload_failed
;
...
...
@@ -520,7 +531,7 @@ void instance::forward(execution_unit* ctx, const node_id& dest_node,
auto
path
=
lookup
(
dest_node
);
if
(
path
)
{
binary_serializer
sink
{
ctx
,
callee_
.
get_buffer
(
path
->
hdl
)};
if
(
!
sink
.
apply
_object
(
hdr
))
{
if
(
!
sink
.
apply
(
hdr
))
{
CAF_LOG_ERROR
(
"unable to serialize BASP header:"
<<
sink
.
get_error
());
return
;
}
...
...
libcaf_io/src/io/basp/message_type_strings.cpp
View file @
dc04d789
...
...
@@ -2,6 +2,7 @@
// DO NOT EDIT: this file is auto-generated by caf-generate-enum-strings.
// Run the target update-enum-strings if this file is out of sync.
#include "caf/config.hpp"
#include "caf/string_view.hpp"
CAF_PUSH_DEPRECATED_WARNING
...
...
@@ -34,6 +35,51 @@ std::string to_string(message_type x) {
};
}
bool
from_string
(
string_view
in
,
message_type
&
out
)
{
if
(
in
==
"server_handshake"
)
{
out
=
message_type
::
server_handshake
;
return
true
;
}
else
if
(
in
==
"client_handshake"
)
{
out
=
message_type
::
client_handshake
;
return
true
;
}
else
if
(
in
==
"direct_message"
)
{
out
=
message_type
::
direct_message
;
return
true
;
}
else
if
(
in
==
"routed_message"
)
{
out
=
message_type
::
routed_message
;
return
true
;
}
else
if
(
in
==
"monitor_message"
)
{
out
=
message_type
::
monitor_message
;
return
true
;
}
else
if
(
in
==
"down_message"
)
{
out
=
message_type
::
down_message
;
return
true
;
}
else
if
(
in
==
"heartbeat"
)
{
out
=
message_type
::
heartbeat
;
return
true
;
}
else
{
return
false
;
}
}
bool
from_integer
(
std
::
underlying_type_t
<
message_type
>
in
,
message_type
&
out
)
{
auto
result
=
static_cast
<
message_type
>
(
in
);
switch
(
result
)
{
default:
return
false
;
case
message_type
:
:
server_handshake
:
case
message_type
:
:
client_handshake
:
case
message_type
:
:
direct_message
:
case
message_type
:
:
routed_message
:
case
message_type
:
:
monitor_message
:
case
message_type
:
:
down_message
:
case
message_type
:
:
heartbeat
:
out
=
result
;
return
true
;
};
}
}
// namespace basp
}
// namespace io
}
// namespace caf
...
...
libcaf_io/src/io/network/operation_strings.cpp
View file @
dc04d789
...
...
@@ -2,6 +2,7 @@
// DO NOT EDIT: this file is auto-generated by caf-generate-enum-strings.
// Run the target update-enum-strings if this file is out of sync.
#include "caf/config.hpp"
#include "caf/string_view.hpp"
CAF_PUSH_DEPRECATED_WARNING
...
...
@@ -26,6 +27,35 @@ std::string to_string(operation x) {
};
}
bool
from_string
(
string_view
in
,
operation
&
out
)
{
if
(
in
==
"read"
)
{
out
=
operation
::
read
;
return
true
;
}
else
if
(
in
==
"write"
)
{
out
=
operation
::
write
;
return
true
;
}
else
if
(
in
==
"propagate_error"
)
{
out
=
operation
::
propagate_error
;
return
true
;
}
else
{
return
false
;
}
}
bool
from_integer
(
std
::
underlying_type_t
<
operation
>
in
,
operation
&
out
)
{
auto
result
=
static_cast
<
operation
>
(
in
);
switch
(
result
)
{
default:
return
false
;
case
operation
:
:
read
:
case
operation
:
:
write
:
case
operation
:
:
propagate_error
:
out
=
result
;
return
true
;
};
}
}
// namespace network
}
// namespace io
}
// namespace caf
...
...
libcaf_io/test/io/basp_broker.cpp
View file @
dc04d789
...
...
@@ -163,7 +163,7 @@ public:
uint32_t
serialized_size
(
const
message
&
msg
)
{
byte_buffer
buf
;
binary_serializer
sink
{
mpx_
,
buf
};
if
(
!
sink
.
apply
_object
(
msg
))
if
(
!
sink
.
apply
(
msg
))
CAF_FAIL
(
"failed to serialize message: "
<<
sink
.
get_error
());
return
static_cast
<
uint32_t
>
(
buf
.
size
());
}
...
...
@@ -221,7 +221,7 @@ public:
template
<
class
...
Ts
>
void
to_payload
(
byte_buffer
&
buf
,
const
Ts
&
...
xs
)
{
binary_serializer
sink
{
mpx_
,
buf
};
if
(
!
sink
.
apply_objects
(
xs
...))
if
(
!
(
sink
.
apply
(
xs
)
&&
...))
CAF_FAIL
(
"failed to serialize payload: "
<<
sink
.
get_error
());
}
...
...
@@ -229,13 +229,13 @@ public:
instance
().
write
(
mpx_
,
buf
,
hdr
,
writer
);
}
template
<
class
T
,
class
...
Ts
>
template
<
class
...
Ts
>
void
to_buf
(
byte_buffer
&
buf
,
basp
::
header
&
hdr
,
payload_writer
*
writer
,
const
T
&
x
,
const
T
s
&
...
xs
)
{
const
Ts
&
...
xs
)
{
auto
pw
=
make_callback
([
&
](
binary_serializer
&
sink
)
{
if
(
writer
!=
nullptr
&&
!
(
*
writer
)(
sink
))
return
false
;
return
sink
.
apply_objects
(
x
,
xs
...);
return
(
sink
.
apply
(
xs
)
&&
...);
});
to_buf
(
buf
,
hdr
,
&
pw
);
}
...
...
@@ -243,7 +243,7 @@ public:
std
::
pair
<
basp
::
header
,
byte_buffer
>
from_buf
(
const
byte_buffer
&
buf
)
{
basp
::
header
hdr
;
binary_deserializer
source
{
mpx_
,
buf
};
if
(
!
source
.
apply
_object
(
hdr
))
if
(
!
source
.
apply
(
hdr
))
CAF_FAIL
(
"failed to deserialize header: "
<<
source
.
get_error
());
byte_buffer
payload
;
if
(
hdr
.
payload_len
>
0
)
{
...
...
@@ -307,7 +307,7 @@ public:
binary_deserializer
source
{
mpx_
,
buf
};
std
::
vector
<
strong_actor_ptr
>
stages
;
message
msg
;
if
(
!
source
.
apply
_objects
(
stages
,
msg
))
if
(
!
source
.
apply
(
stages
)
||
!
source
.
apply
(
msg
))
CAF_FAIL
(
"deserialization failed: "
<<
source
.
get_error
());
auto
src
=
actor_cast
<
strong_actor_ptr
>
(
registry_
->
get
(
hdr
.
source_actor
));
auto
dest
=
registry_
->
get
(
hdr
.
dest_actor
);
...
...
@@ -348,7 +348,7 @@ public:
basp
::
header
hdr
;
{
// lifetime scope of source
binary_deserializer
source
{
this_
->
mpx
(),
ob
};
if
(
!
source
.
apply
_objects
(
hdr
))
if
(
!
source
.
apply
(
hdr
))
CAF_FAIL
(
"failed to deserialize header: "
<<
source
.
get_error
());
}
byte_buffer
payload
;
...
...
@@ -486,7 +486,10 @@ CAF_TEST(non_empty_server_handshake) {
std
::
set
<
std
::
string
>
ifs
{
"caf::replies_to<@u16>::with<@u16>"
};
binary_serializer
sink
{
nullptr
,
expected_payload
};
auto
id
=
self
()
->
id
();
if
(
!
sink
.
apply_objects
(
instance
().
this_node
(),
app_ids
,
id
,
ifs
))
if
(
!
sink
.
apply
(
instance
().
this_node
())
//
||
!
sink
.
apply
(
app_ids
)
//
||
!
sink
.
apply
(
id
)
//
||
!
sink
.
apply
(
ifs
))
CAF_FAIL
(
"serializing handshake failed: "
<<
sink
.
get_error
());
CAF_CHECK_EQUAL
(
hexstr
(
payload
),
hexstr
(
expected_payload
));
}
...
...
libcaf_io/test/io/network/ip_endpoint.cpp
View file @
dc04d789
...
...
@@ -45,19 +45,19 @@ public:
};
struct
fixture
:
test_coordinator_fixture
<>
{
template
<
class
T
,
class
...
Ts
>
auto
serialize
(
T
&
x
,
T
s
&
...
xs
)
{
template
<
class
...
Ts
>
auto
serialize
(
Ts
&
...
xs
)
{
byte_buffer
buf
;
binary_serializer
sink
{
sys
,
buf
};
if
(
!
sink
.
apply_objects
(
x
,
xs
...))
if
(
!
(
sink
.
apply
(
xs
)
&&
...))
CAF_FAIL
(
"serialization failed: "
<<
sink
.
get_error
());
return
buf
;
}
template
<
class
Buffer
,
class
T
,
class
...
Ts
>
void
deserialize
(
const
Buffer
&
buf
,
T
&
x
,
T
s
&
...
xs
)
{
template
<
class
Buffer
,
class
...
Ts
>
void
deserialize
(
const
Buffer
&
buf
,
Ts
&
...
xs
)
{
binary_deserializer
source
{
sys
,
buf
};
if
(
!
source
.
apply_objects
(
x
,
xs
...))
if
(
!
(
source
.
apply
(
xs
)
&&
...))
CAF_FAIL
(
"serialization failed: "
<<
source
.
get_error
());
}
};
...
...
libcaf_io/test/io/worker.cpp
View file @
dc04d789
...
...
@@ -120,7 +120,7 @@ CAF_TEST(deliver serialized message) {
std
::
vector
<
strong_actor_ptr
>
stages
;
binary_serializer
sink
{
sys
,
payload
};
auto
msg
=
make_message
(
ok_atom_v
);
if
(
!
sink
.
apply
_objects
(
stages
,
msg
))
if
(
!
sink
.
apply
(
stages
)
||
!
sink
.
apply
(
msg
))
CAF_FAIL
(
"unable to serialize message: "
<<
sink
.
get_error
());
io
::
basp
::
header
hdr
{
io
::
basp
::
message_type
::
direct_message
,
0
,
...
...
libcaf_test/caf/test/dsl.hpp
View file @
dc04d789
...
...
@@ -843,7 +843,7 @@ public:
caf
::
byte_buffer
serialize
(
const
Ts
&
...
xs
)
{
caf
::
byte_buffer
buf
;
caf
::
binary_serializer
sink
{
sys
,
buf
};
if
(
!
sink
.
apply_objects
(
xs
...))
if
(
!
(
sink
.
apply
(
xs
)
&&
...))
CAF_FAIL
(
"serialization failed: "
<<
sink
.
get_error
());
return
buf
;
}
...
...
@@ -851,7 +851,7 @@ public:
template
<
class
...
Ts
>
void
deserialize
(
const
caf
::
byte_buffer
&
buf
,
Ts
&
...
xs
)
{
caf
::
binary_deserializer
source
{
sys
,
buf
};
if
(
!
source
.
apply_objects
(
xs
...))
if
(
!
(
source
.
apply
(
xs
)
&&
...))
CAF_FAIL
(
"deserialization failed: "
<<
source
.
get_error
());
}
...
...
manual/TypeInspection.rst
View file @
dc04d789
...
...
@@ -6,20 +6,36 @@ Type Inspection
We designed CAF with distributed systems in mind. Hence, all message types must
be serializable. Using a message type that is not serializable causes a compiler
error unless explicitly listed as unsafe message type by the user (see
:ref:`unsafe-message-type`).
:ref:`unsafe-message-type`). Any unsafe message type may be used only for
messages that remain local, i.e., never cross the wire.
.. _type-inspection-data-model:
Data Model
----------
Type inspection in CAF uses a hierarchical, object-oriented data model. The main
abstraction is the *object*. An object has one or more *fields*. Fields have a
*name* and may be *optional*. Further, fields can take on several different (but
fixed) *types*.
Type inspection in CAF uses a hierarchical data model with the following
building blocks:
Depending on its type, a field contains: a single *value*, a variable-length
*sequence*, or a fixed-size *tuple*.
built-in types
- Signed and unsigned integer types for 8, 16, 32 and 64 bit
- The floating point types ``float``, ``double`` and ``long double``
- Bytes, booleans, and strings
lists
Dynamically-sized container types such as ``std::vector``.
tuples
Fixed-sized container types such as ``std::tuple`` or ``std::array`` as well
as built-in C array types.
maps
Dynamically-sized container types with key/value pairs such as ``std::map``.
objects
User-defined types. An object has one or more *fields*. Fields have a *name*
and may be *optional*. Further, fields may take on a fixed number of different
types.
To see how this maps to C++ types, consider the following type definition:
...
...
@@ -32,25 +48,25 @@ To see how this maps to C++ types, consider the following type definition:
};
Here, field ``x1`` is either a ``string`` or a ``double`` at runtime. The field
``x2`` is optional and may contain a fixed-size tuple with two elements. Lastly,
field ``x3`` contains any number of string values at runtime.
Numbers and strings are primitive types in the inspector API.
``x2`` is optional and may contain a fixed-size tuple with two elements
(built-in types). Lastly, field ``x3`` contains any number of string values at
runtime.
Inspecting Objects
------------------
The inspection API allows CAF to deconstruct C++ objects
into fields and values.
Users can either provide free functions named ``inspect`` that CAF picks up via
`ADL <https://en.wikipedia.org/wiki/Argument-dependent_name_lookup>`_ or
specialize
``caf::inspector_access``.
The inspection API allows CAF to deconstruct C++ objects
. Users can either
provide free functions named ``inspect`` that CAF picks up via `ADL
<https://en.wikipedia.org/wiki/Argument-dependent_name_lookup>`_ or specialize
``caf::inspector_access``.
In both cases, users call members and member functions on an ``Inspector`` that
provides a domain-specific language (DSL) for describing the structure of a C++
object.
After listing a custom type ``T`` in a type ID block and either providing a free
``inspect`` overload or specializing ``inspector_access``, CAF is able to:
``inspect`` function overload or specializing ``inspector_access``, CAF is able
to:
- Serialize and deserialize objects of type ``T`` to/from Byte sequences.
- Render objects of type ``T`` as a human-readable string via
...
...
@@ -65,11 +81,18 @@ the inspection API.
.. code-block:: C++
struct point_3d {
int x;
int y;
int z;
int
32_t
x;
int
32_t
y;
int
32_t
z;
};
.. note::
We strongly recommend using the fixed-width integer types in all user-defined
messaging types. Consistently using these types over ``short``, ``int``,
``long``, etc. avoids bugs in heterogeneous environemnts that are hard to
debug.
.. _writing-inspect-overloads:
Writing ``inspect`` Overloads
...
...
@@ -92,15 +115,13 @@ the inspector:
f.field("z", x.z));
}
Writing ``inspect_value`` Overloads
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
The free function ``inspect`` models the object-level type inspection. As
mentioned in the section on the :ref:`data model <type-inspection-data-model>`,
objects are containers for fields that in turn contain a value. When providing
an ``inspect`` overload, CAF recursively visits a value as an object.
As mentioned in the section on the :ref:`data model
<type-inspection-data-model>`, objects are containers for fields that in turn
contain values. When providing an ``inspect`` overload, CAF recursively
traverses all fields.
For example, consider the following ID type that simply wraps a string:
Not every type needs to expose itself as ``object``, though. For example,
consider the following ID type that simply wraps a string:
.. code-block:: C++
...
...
@@ -111,14 +132,16 @@ For example, consider the following ID type that simply wraps a string:
return f.object(x).fields(f.field("value", x.value));
}
The type ``id`` is basically a *strong typedef* to improve type safety
. To a
type inspector, ID objects look as follows:
The type ``id`` is basically a *strong typedef* to improve type safety
when
writing code. To a
type inspector, ID objects look as follows:
.. code-block:: none
object(type: "id") {
field(name: "value") {
value(type: "string")
value(type: "string") {
...
}
}
}
...
...
@@ -138,7 +161,7 @@ By providing the ``inspect`` overload for ID, inspectors can recursively visit
an ``id`` as an object. Hence, the above implementations work as expected. When
using ``person`` in human-readable data formats such as CAF configurations,
however, allowing CAF to look "inside" a strong typedef can simplify working
with types.
with
such
types.
With the current implementation, we could read the key ``manager.ceo`` from a
configuration file with this content:
...
...
@@ -154,20 +177,23 @@ configuration file with this content:
}
}
This clearly is more verbose than it needs to be. By also providing an overload
for ``inspect_value``, we can teach CAF how to inspect an ID directly as a
*value* without having to recursively visit it as an object:
This clearly appears more verbose than it needs to be. Users generally need not
care about such internal types like ``id`` that only exist as a safeguard during
programming.
Hence, we generally recommend making such types transparent to CAF inspectors.
For our ``id`` type, the ``inspect`` overload may instead look as follows:
.. code-block:: C++
template <class Inspector>
bool inspect
_value
(Inspector& f, id& x) {
return f.apply
_value
(x.value);
bool inspect(Inspector& f, id& x) {
return f.apply(x.value);
}
With this overload in place, inspectors can now remove one level of indirection
and read or write strings whenever they encounter an ``id`` as value. This
allows us to simply our config file from before
:
In contrast to the previous implementation, inspectors now simply read or write
the strings as values whenever they encounter an ``id``. This simplifies our
config file from before and thus gives a much cleaner interface to users
:
.. code-block:: none
...
...
@@ -184,7 +210,7 @@ Specializing ``inspector_access``
Working with 3rd party libraries usually rules out adding free functions for
existing classes, because the namespace belongs to a another project. Hence, CAF
also allows specializing ``inspector_access`` instead. This requires writing
more boilerplate code
and
allows customizing every step of the inspection
more boilerplate code
but
allows customizing every step of the inspection
process.
The full interface of ``inspector_access`` looks as follows:
...
...
@@ -194,10 +220,7 @@ The full interface of ``inspector_access`` looks as follows:
template <class T>
struct inspector_access {
template <class Inspector>
static bool apply_object(Inspector& f, T& x);
template <class Inspector>
static bool apply_value(Inspector& f, T& x);
static bool apply(Inspector& f, T& x);
template <class Inspector>
static bool save_field(Inspector& f, string_view field_name, T& x);
...
...
@@ -216,11 +239,8 @@ The full interface of ``inspector_access`` looks as follows:
SetFallback& set_fallback);
};
The static member function ``apply_object`` has the same role as the free
``inspect`` function. Likewise, ``apply_value`` corresponds to the free
``inspect_value`` function.
For most types, we can implement only ``apply_object`` and use default
The static member function ``apply`` has the same role as the free ``inspect``
function. For most types, we can implement only ``apply`` and use a default
implementation for the other member functions. For example, specializing
``inspector_access`` for our ``point_3d`` would look as follows:
...
...
@@ -231,16 +251,11 @@ implementation for the other member functions. For example, specializing
template <>
struct inspector_access<point_3d> : inspector_access_base<point_3d> {
template <class Inspector>
static bool apply
_object
(Inspector& f, point_3d& x) {
static bool apply(Inspector& f, point_3d& x) {
return f.object(x).fields(f.field("x", x.x),
f.field("y", x.y),
f.field("z", x.z));
}
template <class Inspector>
static bool apply_value(Inspector& f, point_3d& x) {
return apply_object(f, x);
}
};
} // namespace caf
...
...
@@ -255,13 +270,6 @@ becomes necessary when integration custom types that have semantics similar to
Please refer to the Doxygen documentation for more details on ``save_field``
and ``load_field``.
In :ref:`our previous example <writing-inspect-overloads>`, we provided an
``inspect`` overload that was similar to our implementation of ``apply_object``.
Most of the time, we only need to implement ``apply_object`` and can call it
from ``apply_value``. The latter customizes how CAF inspects a value inside a
field. By calling ``apply_object``, we simply recursively visit ``x`` as an
object again.
Types with Getter and Setter Access
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
...
...
@@ -433,13 +441,13 @@ machine-to-machine communication, using the underlying integer representation
gives the best performance. However, using the constant names results in a much
better user experience in all other cases.
The following code illustrates how to
use a string representation for inspectors
that operate on human-readable data representation and the underlying type for
an
``enum class`` otherwise.
The following code illustrates how to
provide a string representation for
inspectors that operate on human-readable data representations while operating
directly on the underlying type of the
``enum class`` otherwise.
.. code-block:: C++
enum class weekday {
enum class weekday
: uint8_t
{
monday,
tuesday,
wednesday,
...
...
@@ -458,34 +466,24 @@ an ``enum class`` otherwise.
if (f.has_human_readable_format()) {
auto get = [&x] { return to_string(x); };
auto set = [&x](std::string str) { return parse(str, x); };
return f.object(x).fields(f.field("value", get, set));
} else {
using default_impl = caf::default_inspector_access<weekday>;
return default_impl::apply_object(f, x);
}
}
template <class Inspector>
bool inspect_value(Inspector& f, weekday& x) {
if (f.has_human_readable_format()) {
auto get = [&x] { return to_string(x); };
auto set = [&x](std::string str) { return parse(str, x); };
return f.apply_value(get, set);
return f.apply(get, set);
} else {
using default_impl = caf::default_inspector_access<weekday>;
return default_impl::apply_value(f, x);
auto get = [&x] { return static_cast<uint8_t>(x); };
auto set = [&x](uint8_t val) {
if (val < 7) {
x = static_cast<weekday>(val);
return true;
} else {
return false;
}
};
return f.apply(get, set);
}
}
When inspecting an object of type ``weekday``, we treat it as if we were
inspecting an object with a single field named ``value``. However, usually we
are going to inspect other objects that contain values of type ``weekday``. In
both cases, we provide getter and setter functions that convert between strings
and enumeration values.
For inspectors that operate on machine-to-machine data formats, we simply fall
back to the default implementation that is going to use the underlying integer
values.
When inspecting an object of type ``weekday``, we treat is as if it were a
string for inspectors with human-readable data formats. Otherwise, we treat the
weekday as if it were an integer between 0 and 6.
.. _unsafe-message-type:
...
...
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