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
e2981877
Commit
e2981877
authored
Sep 06, 2020
by
Dominik Charousset
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Add apply functions to inspectors, add docs
parent
5e8bd93a
Changes
35
Hide whitespace changes
Inline
Side-by-side
Showing
35 changed files
with
265 additions
and
206 deletions
+265
-206
CHANGELOG.md
CHANGELOG.md
+7
-1
examples/custom_type/custom_types_1.cpp
examples/custom_type/custom_types_1.cpp
+2
-2
libcaf_core/caf/detail/make_meta_object.hpp
libcaf_core/caf/detail/make_meta_object.hpp
+5
-6
libcaf_core/caf/detail/parse.hpp
libcaf_core/caf/detail/parse.hpp
+1
-0
libcaf_core/caf/detail/print.hpp
libcaf_core/caf/detail/print.hpp
+1
-0
libcaf_core/caf/detail/serialized_size.hpp
libcaf_core/caf/detail/serialized_size.hpp
+4
-4
libcaf_core/caf/detail/stringification_inspector.hpp
libcaf_core/caf/detail/stringification_inspector.hpp
+7
-1
libcaf_core/caf/hash/fnv.hpp
libcaf_core/caf/hash/fnv.hpp
+2
-3
libcaf_core/caf/inspector_access.hpp
libcaf_core/caf/inspector_access.hpp
+1
-25
libcaf_core/caf/load_inspector.hpp
libcaf_core/caf/load_inspector.hpp
+4
-8
libcaf_core/caf/load_inspector_base.hpp
libcaf_core/caf/load_inspector_base.hpp
+12
-0
libcaf_core/caf/save_inspector.hpp
libcaf_core/caf/save_inspector.hpp
+4
-8
libcaf_core/caf/save_inspector_base.hpp
libcaf_core/caf/save_inspector_base.hpp
+19
-2
libcaf_core/caf/type_id.hpp
libcaf_core/caf/type_id.hpp
+2
-2
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/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
+2
-14
libcaf_core/test/nasty.hpp
libcaf_core/test/nasty.hpp
+20
-27
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
+2
-14
libcaf_core/test/serialization.cpp
libcaf_core/test/serialization.cpp
+2
-2
libcaf_core/test/settings_writer.cpp
libcaf_core/test/settings_writer.cpp
+1
-1
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/remote_message_handler.hpp
libcaf_io/caf/io/basp/remote_message_handler.hpp
+4
-4
libcaf_io/src/io/basp/instance.cpp
libcaf_io/src/io/basp/instance.cpp
+17
-18
libcaf_io/test/io/basp_broker.cpp
libcaf_io/test/io/basp_broker.cpp
+7
-7
libcaf_io/test/io/network/ip_endpoint.cpp
libcaf_io/test/io/network/ip_endpoint.cpp
+2
-2
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
+115
-33
No files found.
CHANGELOG.md
View file @
e2981877
...
...
@@ -127,6 +127,12 @@ is based on [Keep a Changelog](https://keepachangelog.com).
*types*
, but did not enforce it because the name was only used for logging.
Since the new metrics use this name for filtering now, we enforce static names
in order to help avoid hard-to-find issues with the filtering mechanism.
-
The type inspection API received a complete overhaul. The new DSL for writing
`inspect`
functions exposes the entire structure of an object to CAF. This
enables inspectors to read and write a wider range of data formats. In
particular human-readable, structured data such as configuration files, JSON,
XML, etc. The inspection API received too many changes to list them here.
Please refer to the manual section on type inspection instead.
### Removed
...
...
@@ -183,7 +189,7 @@ is based on [Keep a Changelog](https://keepachangelog.com).
-
Datagram servants of UDP socket managers were not added as children to their
parent broker on creation, which prevented proper system shutdown in some
cases. Adding all servants consistently to the broker should make sure UDP
brokers terminate correctly (#1133).
brokers terminate correctly (#1133).
## [0.17.6] - 2020-07-24
...
...
examples/custom_type/custom_types_1.cpp
View file @
e2981877
...
...
@@ -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
(
!
inspect_object
(
sink
,
f1
))
{
if
(
!
sink
.
apply_object
(
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
(
!
inspect_object
(
source
,
f2
))
{
if
(
!
source
.
apply_object
(
f2
))
{
std
::
cerr
<<
"*** failed to deserialize foo2: "
<<
to_string
(
source
.
get_error
())
<<
'\n'
;
return
;
...
...
libcaf_core/caf/detail/make_meta_object.hpp
View file @
e2981877
...
...
@@ -50,29 +50,28 @@ void copy_construct(void* ptr, const void* src) {
template
<
class
T
>
bool
save_binary
(
binary_serializer
&
sink
,
const
void
*
ptr
)
{
return
inspect_object
(
sink
,
as_mutable_ref
(
*
static_cast
<
const
T
*>
(
ptr
)
));
return
sink
.
apply_object
(
*
static_cast
<
const
T
*>
(
ptr
));
}
template
<
class
T
>
bool
load_binary
(
binary_deserializer
&
source
,
void
*
ptr
)
{
return
inspect_object
(
source
,
*
static_cast
<
T
*>
(
ptr
));
return
source
.
apply_object
(
*
static_cast
<
T
*>
(
ptr
));
}
template
<
class
T
>
bool
save
(
serializer
&
sink
,
const
void
*
ptr
)
{
return
inspect_object
(
sink
,
as_mutable_ref
(
*
static_cast
<
const
T
*>
(
ptr
)
));
return
sink
.
apply_object
(
*
static_cast
<
const
T
*>
(
ptr
));
}
template
<
class
T
>
bool
load
(
deserializer
&
source
,
void
*
ptr
)
{
return
inspect_object
(
source
,
*
static_cast
<
T
*>
(
ptr
));
return
source
.
apply_object
(
*
static_cast
<
T
*>
(
ptr
));
}
template
<
class
T
>
void
stringify
(
std
::
string
&
buf
,
const
void
*
ptr
)
{
stringification_inspector
f
{
buf
};
auto
unused
=
inspect_object
(
f
,
detail
::
as_mutable_ref
(
*
static_cast
<
const
T
*>
(
ptr
)));
auto
unused
=
f
.
apply_object
(
*
static_cast
<
const
T
*>
(
ptr
));
static_cast
<
void
>
(
unused
);
}
...
...
libcaf_core/caf/detail/parse.hpp
View file @
e2981877
...
...
@@ -292,6 +292,7 @@ void parse_element(string_parser_state& ps, std::pair<First, Second>& kvp,
// -- convenience functions ----------------------------------------------------
CAF_CORE_EXPORT
error
parse_result
(
const
string_parser_state
&
ps
,
string_view
input
);
template
<
class
T
>
...
...
libcaf_core/caf/detail/print.hpp
View file @
e2981877
...
...
@@ -28,6 +28,7 @@
namespace
caf
::
detail
{
CAF_CORE_EXPORT
size_t
print_timestamp
(
char
*
buf
,
size_t
buf_size
,
time_t
ts
,
size_t
ms
);
template
<
class
Buffer
>
...
...
libcaf_core/caf/detail/serialized_size.hpp
View file @
e2981877
...
...
@@ -96,16 +96,16 @@ public:
template
<
class
T
>
size_t
serialized_size
(
const
T
&
x
)
{
serialized_size_inspector
f
;
auto
inspection_res
=
inspect_object
(
f
,
detail
::
as_mutable_ref
(
x
)
);
static_cast
<
void
>
(
inspection_res
);
// Always true.
auto
unused
=
f
.
apply_object
(
x
);
static_cast
<
void
>
(
unused
);
// Always true.
return
f
.
result
;
}
template
<
class
T
>
size_t
serialized_size
(
actor_system
&
sys
,
const
T
&
x
)
{
serialized_size_inspector
f
{
sys
};
auto
inspection_res
=
inspect_object
(
f
,
detail
::
as_mutable_ref
(
x
)
);
static_cast
<
void
>
(
inspection_res
);
// Always true.
auto
unused
=
f
.
apply_object
(
x
);
static_cast
<
void
>
(
unused
);
// Always true.
return
f
.
result
;
}
...
...
libcaf_core/caf/detail/stringification_inspector.hpp
View file @
e2981877
...
...
@@ -161,7 +161,13 @@ public:
bool
>
value
(
const
T
&
x
)
{
auto
str
=
to_string
(
x
);
append
(
str
);
if
constexpr
(
std
::
is_convertible
<
decltype
(
str
),
const
char
*>::
value
)
{
const
char
*
cstr
=
str
;
sep
();
result_
+=
cstr
;
}
else
{
append
(
str
);
}
return
true
;
}
...
...
libcaf_core/caf/hash/fnv.hpp
View file @
e2981877
...
...
@@ -156,9 +156,8 @@ public:
static
T
compute
(
Ts
&&
...
xs
)
noexcept
{
using
detail
::
as_mutable_ref
;
fnv
f
;
auto
inspect_result
=
(
inspect_object
(
f
,
as_mutable_ref
(
xs
))
&&
...);
// Discard inspection result: always true.
static_cast
<
void
>
(
inspect_result
);
auto
unused
=
f
.
apply_objects
(
xs
...);
static_cast
<
void
>
(
unused
);
// Always true.
return
f
.
result
;
}
...
...
libcaf_core/caf/inspector_access.hpp
View file @
e2981877
...
...
@@ -70,7 +70,7 @@ bool load_value(Inspector& f, T& x, inspector_access_type::specialization) {
}
template
<
class
Inspector
,
class
T
>
bool
load_
object
(
Inspector
&
f
,
T
&
x
,
inspector_access_type
::
inspect_value
)
{
bool
load_
value
(
Inspector
&
f
,
T
&
x
,
inspector_access_type
::
inspect_value
)
{
return
inspect_value
(
f
,
x
);
}
...
...
@@ -477,30 +477,6 @@ struct default_inspector_access : inspector_access_base<T> {
template
<
class
T
>
struct
inspector_access
;
/// Inspects `x` using the inspector `f`.
template
<
class
Inspector
,
class
T
>
[[
nodiscard
]]
bool
inspect_object
(
Inspector
&
f
,
T
&
x
)
{
constexpr
auto
token
=
inspect_object_access_type
<
Inspector
,
T
>
();
if
constexpr
(
Inspector
::
is_loading
)
return
detail
::
load_object
(
f
,
x
,
token
);
else
return
detail
::
save_object
(
f
,
x
,
token
);
}
/// Inspects `x` using the inspector `f`.
template
<
class
Inspector
,
class
T
>
[[
nodiscard
]]
bool
inspect_object
(
Inspector
&
f
,
const
T
&
x
)
{
static_assert
(
!
Inspector
::
is_loading
);
constexpr
auto
token
=
inspect_object_access_type
<
Inspector
,
T
>
();
return
detail
::
save_object
(
f
,
detail
::
as_mutable_ref
(
x
),
token
);
}
/// Inspects all `xs` using the inspector `f`.
template
<
class
Inspector
,
class
...
Ts
>
[[
nodiscard
]]
bool
inspect_objects
(
Inspector
&
f
,
Ts
&
...
xs
)
{
return
(
inspect_object
(
f
,
xs
)
&&
...);
}
// -- inspection support for optional values -----------------------------------
template
<
class
T
>
...
...
libcaf_core/caf/load_inspector.hpp
View file @
e2981877
...
...
@@ -35,6 +35,10 @@ namespace caf {
/// for the DSL.
class
CAF_CORE_EXPORT
load_inspector
{
public:
// -- member types -----------------------------------------------------------
using
result_type
=
bool
;
// -- constants --------------------------------------------------------------
/// Convenience constant to indicate success of a processing step.
...
...
@@ -47,14 +51,6 @@ public:
/// Enables dispatching on the inspector type.
static
constexpr
bool
is_loading
=
true
;
// -- legacy API -------------------------------------------------------------
static
constexpr
bool
reads_state
=
false
;
static
constexpr
bool
writes_state
=
true
;
using
result_type
=
bool
;
// -- constructors, destructors, and assignment operators --------------------
virtual
~
load_inspector
();
...
...
libcaf_core/caf/load_inspector_base.hpp
View file @
e2981877
...
...
@@ -39,6 +39,18 @@ public:
// -- dispatching to load/load functions -------------------------------------
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
);
}
template
<
class
...
Ts
>
[[
nodiscard
]]
bool
apply_objects
(
Ts
&
...
xs
)
{
return
(
apply_object
(
xs
)
&&
...);
}
template
<
class
T
>
bool
apply_value
(
T
&
x
)
{
return
detail
::
load_value
(
dref
(),
x
);
...
...
libcaf_core/caf/save_inspector.hpp
View file @
e2981877
...
...
@@ -35,6 +35,10 @@ namespace caf {
/// for the DSL.
class
CAF_CORE_EXPORT
save_inspector
{
public:
// -- member types -----------------------------------------------------------
using
result_type
=
bool
;
// -- constants --------------------------------------------------------------
/// Convenience constant to indicate success of a processing step.
...
...
@@ -47,14 +51,6 @@ public:
/// Enables dispatching on the inspector type.
static
constexpr
bool
is_loading
=
false
;
// -- legacy API -------------------------------------------------------------
static
constexpr
bool
reads_state
=
true
;
static
constexpr
bool
writes_state
=
false
;
using
result_type
=
bool
;
// -- constructors, destructors, and assignment operators --------------------
virtual
~
save_inspector
();
...
...
libcaf_core/caf/save_inspector_base.hpp
View file @
e2981877
...
...
@@ -40,12 +40,29 @@ public:
// -- dispatching to load/save functions -------------------------------------
template
<
class
T
>
bool
apply_value
(
T
&
x
)
{
[[
nodiscard
]]
bool
apply_object
(
T
&
x
)
{
constexpr
auto
token
=
inspect_object_access_type
<
Subtype
,
T
>
();
return
detail
::
save_object
(
dref
(),
x
,
token
);
}
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
);
}
template
<
class
...
Ts
>
[[
nodiscard
]]
bool
apply_objects
(
Ts
&
...
xs
)
{
return
(
apply_object
(
xs
)
&&
...);
}
template
<
class
T
>
[[
nodiscard
]]
bool
apply_value
(
T
&
x
)
{
return
detail
::
save_value
(
dref
(),
x
);
}
template
<
class
Get
,
class
Set
>
bool
apply_value
(
Get
&&
get
,
Set
&&
)
{
[[
nodiscard
]]
bool
apply_value
(
Get
&&
get
,
Set
&&
)
{
auto
&&
x
=
get
();
return
detail
::
save_value
(
dref
(),
x
);
}
...
...
libcaf_core/caf/type_id.hpp
View file @
e2981877
...
...
@@ -231,8 +231,8 @@ CAF_CORE_EXPORT type_id_t query_type_id(string_view name);
return atom_text; \
} \
template <class Inspector> \
auto inspect(Inspector& f, atom_name&
) {
\
return f
(caf::meta::type_name(#atom_namespace "::" #atom_name));
\
auto inspect(Inspector& f, atom_name&
x) {
\
return f
.object(x).fields();
\
} \
} \
CAF_ADD_TYPE_ID(project_name, (atom_namespace::atom_name))
...
...
libcaf_core/test/actor_registry.cpp
View file @
e2981877
...
...
@@ -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
(
!
inspect_object
(
sink
,
hdl
))
if
(
!
sink
.
apply_object
(
hdl
))
CAF_FAIL
(
"serialization failed: "
<<
sink
.
get_error
());
CAF_MESSAGE
(
"buf: "
<<
buf
);
actor
hdl2
;
binary_deserializer
source
{
sys
,
buf
};
if
(
!
inspect_object
(
source
,
hdl2
))
if
(
!
source
.
apply_object
(
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 @
e2981877
...
...
@@ -59,7 +59,7 @@ struct fixture {
template
<
class
...
Ts
>
void
load
(
const
std
::
vector
<
byte
>&
buf
,
Ts
&
...
xs
)
{
binary_deserializer
source
{
nullptr
,
buf
};
if
(
!
inspect_objects
(
source
,
xs
...))
if
(
!
source
.
apply_objects
(
xs
...))
CAF_FAIL
(
"binary_deserializer failed to load: "
<<
source
.
get_error
());
}
...
...
libcaf_core/test/binary_serializer.cpp
View file @
e2981877
...
...
@@ -57,7 +57,7 @@ struct fixture {
auto
save
(
const
Ts
&
...
xs
)
{
byte_buffer
result
;
binary_serializer
sink
{
nullptr
,
result
};
if
(
!
inspect_objects
(
sink
,
detail
::
as_mutable_ref
(
xs
)
...))
if
(
!
sink
.
apply_objects
(
xs
...))
CAF_FAIL
(
"binary_serializer failed to save: "
<<
sink
.
get_error
());
return
result
;
}
...
...
@@ -65,7 +65,7 @@ struct fixture {
template
<
class
...
Ts
>
void
save_to_buf
(
byte_buffer
&
data
,
const
Ts
&
...
xs
)
{
binary_serializer
sink
{
nullptr
,
data
};
if
(
!
inspect_objects
(
sink
,
detail
::
as_mutable_ref
(
xs
)
...))
if
(
!
sink
.
apply_objects
(
xs
...))
CAF_FAIL
(
"binary_serializer failed to save: "
<<
sink
.
get_error
());
}
};
...
...
libcaf_core/test/detail/serialized_size.cpp
View file @
e2981877
...
...
@@ -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
(
!
inspect_objects
(
sink
,
detail
::
as_mutable_ref
(
xs
)
...))
if
(
!
sink
.
apply_objects
(
xs
...))
CAF_FAIL
(
"failed to serialize data: "
<<
sink
.
get_error
());
return
buf
.
size
();
}
...
...
libcaf_core/test/ipv4_endpoint.cpp
View file @
e2981877
...
...
@@ -54,11 +54,11 @@ struct fixture {
T
roundtrip
(
T
x
)
{
byte_buffer
buf
;
binary_serializer
sink
(
sys
,
buf
);
if
(
!
inspect_object
(
sink
,
x
))
if
(
!
sink
.
apply_object
(
x
))
CAF_FAIL
(
"serialization failed: "
<<
sink
.
get_error
());
binary_deserializer
source
(
sys
,
make_span
(
buf
));
T
y
;
if
(
!
inspect_object
(
source
,
y
))
if
(
!
source
.
apply_object
(
y
))
CAF_FAIL
(
"deserialization failed: "
<<
source
.
get_error
());
return
y
;
}
...
...
libcaf_core/test/ipv6_endpoint.cpp
View file @
e2981877
...
...
@@ -54,11 +54,11 @@ struct fixture {
T
roundtrip
(
T
x
)
{
byte_buffer
buf
;
binary_serializer
sink
(
sys
,
buf
);
if
(
!
inspect_object
(
sink
,
x
))
if
(
!
sink
.
apply_object
(
x
))
CAF_FAIL
(
"serialization failed: "
<<
sink
.
get_error
());
binary_deserializer
source
(
sys
,
make_span
(
buf
));
T
y
;
if
(
!
inspect_object
(
source
,
y
))
if
(
!
source
.
apply_object
(
y
))
CAF_FAIL
(
"serialization failed: "
<<
source
.
get_error
());
return
y
;
}
...
...
libcaf_core/test/load_inspector.cpp
View file @
e2981877
...
...
@@ -54,22 +54,10 @@ struct testee : deserializer {
log
.
insert
(
log
.
end
(),
indent
,
' '
);
}
using
deserializer
::
object
;
bool
fetch_next_object_type
(
type_id_t
&
)
override
{
return
false
;
}
template
<
class
T
>
auto
object
(
optional
<
T
>&
)
{
return
object_t
<
testee
>
{
"optional"
,
this
};
}
template
<
class
...
Ts
>
auto
object
(
variant
<
Ts
...
>&
)
{
return
object_t
<
testee
>
{
"variant"
,
this
};
}
bool
begin_object
(
string_view
object_name
)
override
{
new_line
();
indent
+=
2
;
...
...
@@ -342,9 +330,9 @@ end object)_");
CAF_TEST
(
load
inspectors
support
optional
)
{
optional
<
int32_t
>
x
;
CAF_CHECK_EQUAL
(
inspect_object
(
f
,
x
),
true
);
CAF_CHECK_EQUAL
(
f
.
apply_object
(
x
),
true
);
CAF_CHECK_EQUAL
(
f
.
log
,
R"_(
begin object
optional
begin object
anonymous
begin optional field value
end field
end object)_"
);
...
...
libcaf_core/test/nasty.hpp
View file @
e2981877
...
...
@@ -23,36 +23,29 @@ std::string to_string(weekday x);
bool
parse
(
caf
::
string_view
input
,
weekday
&
dest
);
namespace
caf
{
template
<
>
struct
inspector_access
<
weekday
>
:
inspector_access_base
<
weekday
>
{
using
default_impl
=
default_inspector_access
<
weekday
>
;
template
<
class
Inspector
>
static
bool
apply_object
(
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
);
};
f
.
object
(
x
).
fields
(
f
.
field
(
"value"
,
get
,
set
));
}
else
{
return
default_impl
::
apply_object
(
f
,
x
);
}
template
<
class
Inspector
>
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
);
};
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
>
static
bool
apply
_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
{
return
default_impl
::
apply_value
(
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
);
}
};
}
// namespace caf
}
#define ADD_GET_SET_FIELD(type, name) \
private: \
...
...
libcaf_core/test/node_id.cpp
View file @
e2981877
...
...
@@ -33,7 +33,7 @@ node_id roundtrip(node_id nid) {
byte_buffer
buf
;
{
binary_serializer
sink
{
nullptr
,
buf
};
if
(
!
inspect_object
(
sink
,
nid
))
if
(
!
sink
.
apply_object
(
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
(
!
inspect_object
(
source
,
result
))
if
(
!
source
.
apply_object
(
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 @
e2981877
...
...
@@ -49,18 +49,6 @@ struct testee : serializer {
log
.
insert
(
log
.
end
(),
indent
,
' '
);
}
using
serializer
::
object
;
template
<
class
T
>
auto
object
(
optional
<
T
>&
)
{
return
object_t
<
testee
>
{
"optional"
,
this
};
}
template
<
class
...
Ts
>
auto
object
(
variant
<
Ts
...
>&
)
{
return
object_t
<
testee
>
{
"variant"
,
this
};
}
bool
inject_next_object_type
(
type_id_t
type
)
override
{
new_line
();
log
+=
"next object type: "
;
...
...
@@ -448,9 +436,9 @@ end object)_");
CAF_TEST
(
save
inspectors
support
optional
)
{
optional
<
int32_t
>
x
;
CAF_CHECK_EQUAL
(
inspect_object
(
f
,
x
),
true
);
CAF_CHECK_EQUAL
(
f
.
apply_object
(
x
),
true
);
CAF_CHECK_EQUAL
(
f
.
log
,
R"_(
begin object
optional
begin object
anonymous
begin optional field value
end field
end object)_"
);
...
...
libcaf_core/test/serialization.cpp
View file @
e2981877
...
...
@@ -111,7 +111,7 @@ struct fixture : test_coordinator_fixture<> {
byte_buffer
serialize
(
const
Ts
&
...
xs
)
{
byte_buffer
buf
;
binary_serializer
sink
{
sys
,
buf
};
if
(
!
inspect_objects
(
sink
,
xs
...))
if
(
!
sink
.
apply_objects
(
xs
...))
CAF_FAIL
(
"serialization failed: "
<<
sink
.
get_error
()
<<
", data: "
<<
deep_to_string
(
std
::
forward_as_tuple
(
xs
...)));
...
...
@@ -121,7 +121,7 @@ struct fixture : test_coordinator_fixture<> {
template
<
class
...
Ts
>
void
deserialize
(
const
byte_buffer
&
buf
,
Ts
&
...
xs
)
{
binary_deserializer
source
{
sys
,
buf
};
if
(
!
inspect_objects
(
source
,
xs
...))
if
(
!
source
.
apply_objects
(
xs
...))
CAF_FAIL
(
"deserialization failed: "
<<
source
.
get_error
());
}
...
...
libcaf_core/test/settings_writer.cpp
View file @
e2981877
...
...
@@ -44,7 +44,7 @@ struct fixture {
template
<
class
T
>
void
set
(
const
T
&
value
)
{
settings_writer
writer
{
&
xs
};
if
(
!
inspect_object
(
writer
,
value
))
if
(
!
writer
.
apply_object
(
value
))
CAF_FAIL
(
"failed two write to settings: "
<<
writer
.
get_error
());
}
...
...
libcaf_core/test/tracing_data.cpp
View file @
e2981877
...
...
@@ -47,11 +47,11 @@ public:
}
bool
serialize
(
serializer
&
sink
)
const
override
{
return
inspect_object
(
sink
,
value
);
return
sink
.
apply_object
(
value
);
}
bool
serialize
(
binary_serializer
&
sink
)
const
override
{
return
inspect_object
(
sink
,
value
);
return
sink
.
apply_object
(
value
);
}
};
...
...
@@ -72,7 +72,7 @@ private:
bool
deserialize_impl
(
Deserializer
&
source
,
std
::
unique_ptr
<
tracing_data
>&
dst
)
const
{
string
value
;
if
(
!
inspect_object
(
source
,
value
))
if
(
!
source
.
apply_object
(
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
(
inspect_object
(
sink
,
data
));
CAF_CHECK
(
sink
.
apply_object
(
data
));
binary_deserializer
source
{
sys
,
buf
};
tracing_data_ptr
copy
;
CAF_CHECK
(
inspect_object
(
source
,
copy
));
CAF_CHECK
(
source
.
apply_object
(
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 @
e2981877
...
...
@@ -133,7 +133,7 @@ struct fixture {
byte_buffer
serialize
(
uri
x
)
{
byte_buffer
buf
;
binary_serializer
sink
{
nullptr
,
buf
};
if
(
!
inspect_objects
(
sink
,
x
))
if
(
!
sink
.
apply_objects
(
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
(
!
inspect_objects
(
source
,
result
))
if
(
!
source
.
apply_objects
(
result
))
CAF_FAIL
(
"unable to deserialize from buffer: "
<<
source
.
get_error
());
return
result
;
}
...
...
libcaf_io/caf/io/basp/remote_message_handler.hpp
View file @
e2981877
...
...
@@ -75,12 +75,12 @@ public:
if
(
dref
.
hdr_
.
operation
==
basp
::
message_type
::
routed_message
)
{
node_id
src_node
;
node_id
dst_node
;
if
(
!
inspect_object
(
source
,
src_node
))
{
if
(
!
source
.
apply_object
(
src_node
))
{
CAF_LOG_ERROR
(
"failed to read source of routed message:"
<<
source
.
get_error
());
return
;
}
if
(
!
inspect_object
(
source
,
dst_node
))
{
if
(
!
source
.
apply_object
(
dst_node
))
{
CAF_LOG_ERROR
(
"failed to read destination of routed message:"
<<
source
.
get_error
());
return
;
...
...
@@ -104,11 +104,11 @@ public:
return
;
}
// Get the remainder of the message.
if
(
!
inspect_object
(
source
,
stages
))
{
if
(
!
source
.
apply_object
(
stages
))
{
CAF_LOG_ERROR
(
"failed to read stages:"
<<
source
.
get_error
());
return
;
}
if
(
!
inspect_objects
(
source
,
msg
))
{
if
(
!
source
.
apply_objects
(
msg
))
{
CAF_LOG_ERROR
(
"failed to read message content:"
<<
source
.
get_error
());
return
;
}
...
...
libcaf_io/src/io/basp/instance.cpp
View file @
e2981877
...
...
@@ -71,7 +71,7 @@ connection_state instance::handle(execution_unit* ctx, new_data_msg& dm,
}
}
else
{
binary_deserializer
source
{
ctx
,
dm
.
buf
};
if
(
!
inspect_object
(
source
,
hdr
))
{
if
(
!
source
.
apply_object
(
hdr
))
{
CAF_LOG_WARNING
(
"failed to receive header:"
<<
source
.
get_error
());
return
err
(
malformed_basp_message
);
}
...
...
@@ -183,7 +183,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
inspect_objects
(
sink
,
forwarding_stack
,
msg
);
return
sink
.
apply_objects
(
forwarding_stack
,
msg
);
});
write
(
ctx
,
callee_
.
get_buffer
(
path
->
hdl
),
hdr
,
&
writer
);
}
else
{
...
...
@@ -197,8 +197,7 @@ 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
inspect_objects
(
sink
,
source_node
,
dest_node
,
forwarding_stack
,
msg
);
return
sink
.
apply_objects
(
source_node
,
dest_node
,
forwarding_stack
,
msg
);
});
write
(
ctx
,
callee_
.
get_buffer
(
path
->
hdl
),
hdr
,
&
writer
);
}
...
...
@@ -222,7 +221,7 @@ void instance::write(execution_unit* ctx, byte_buffer& buf, header& hdr,
auto
payload_len
=
buf
.
size
()
-
(
header_offset
+
basp
::
header_size
);
hdr
.
payload_len
=
static_cast
<
uint32_t
>
(
payload_len
);
}
if
(
!
inspect_objects
(
sink
,
hdr
))
if
(
!
sink
.
apply_objects
(
hdr
))
CAF_LOG_ERROR
(
sink
.
get_error
());
}
...
...
@@ -251,7 +250,7 @@ void instance::write_server_handshake(execution_unit* ctx, byte_buffer& out_buf,
aid
=
pa
->
first
->
id
();
iface
=
pa
->
second
;
}
return
inspect_objects
(
sink
,
this_node_
,
app_ids
,
aid
,
iface
);
return
sink
.
apply_objects
(
this_node_
,
app_ids
,
aid
,
iface
);
});
header
hdr
{
message_type
::
server_handshake
,
0
,
...
...
@@ -264,7 +263,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
inspect_objects
(
sink
,
this_node_
);
return
sink
.
apply_objects
(
this_node_
);
});
header
hdr
{
message_type
::
client_handshake
,
0
,
...
...
@@ -279,7 +278,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
inspect_objects
(
sink
,
this_node_
,
dest_node
);
return
sink
.
apply_objects
(
this_node_
,
dest_node
);
});
header
hdr
{
message_type
::
monitor_message
,
0
,
0
,
0
,
invalid_actor_id
,
aid
};
write
(
ctx
,
buf
,
hdr
,
&
writer
);
...
...
@@ -290,7 +289,7 @@ void instance::write_down_message(execution_unit* ctx, byte_buffer& buf,
const
error
&
rsn
)
{
CAF_LOG_TRACE
(
CAF_ARG
(
dest_node
)
<<
CAF_ARG
(
aid
)
<<
CAF_ARG
(
rsn
));
auto
writer
=
make_callback
([
&
](
binary_serializer
&
sink
)
{
//
return
inspect_objects
(
sink
,
this_node_
,
dest_node
,
rsn
);
return
sink
.
apply_objects
(
this_node_
,
dest_node
,
rsn
);
});
header
hdr
{
message_type
::
down_message
,
0
,
0
,
0
,
aid
,
invalid_actor_id
};
write
(
ctx
,
buf
,
hdr
,
&
writer
);
...
...
@@ -326,7 +325,7 @@ 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
(
!
inspect_objects
(
source
,
source_node
,
app_ids
,
aid
,
sigs
))
{
if
(
!
source
.
apply_objects
(
source_node
,
app_ids
,
aid
,
sigs
))
{
CAF_LOG_WARNING
(
"unable to deserialize payload of server handshake:"
<<
source
.
get_error
());
return
serializing_basp_payload_failed
;
...
...
@@ -376,7 +375,7 @@ connection_state instance::handle(execution_unit* ctx, connection_handle hdl,
// Deserialize payload.
binary_deserializer
source
{
ctx
,
*
payload
};
node_id
source_node
;
if
(
!
inspect_objects
(
source
,
source_node
))
{
if
(
!
source
.
apply_objects
(
source_node
))
{
CAF_LOG_WARNING
(
"unable to deserialize payload of client handshake:"
<<
source
.
get_error
());
return
serializing_basp_payload_failed
;
...
...
@@ -399,7 +398,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
(
!
inspect_objects
(
source
,
source_node
,
dest_node
))
{
if
(
!
source
.
apply_objects
(
source_node
,
dest_node
))
{
CAF_LOG_WARNING
(
"unable to deserialize source and destination for routed message:"
<<
source
.
get_error
());
...
...
@@ -458,7 +457,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
(
!
inspect_objects
(
source
,
source_node
,
dest_node
))
{
if
(
!
source
.
apply_objects
(
source_node
,
dest_node
))
{
CAF_LOG_WARNING
(
"unable to deserialize payload of monitor message:"
<<
source
.
get_error
());
return
serializing_basp_payload_failed
;
...
...
@@ -475,7 +474,7 @@ connection_state instance::handle(execution_unit* ctx, connection_handle hdl,
node_id
source_node
;
node_id
dest_node
;
error
fail_state
;
if
(
!
inspect_objects
(
source
,
source_node
,
dest_node
,
fail_state
))
{
if
(
!
source
.
apply_objects
(
source_node
,
dest_node
,
fail_state
))
{
CAF_LOG_WARNING
(
"unable to deserialize payload of down message:"
<<
source
.
get_error
());
return
serializing_basp_payload_failed
;
...
...
@@ -512,12 +511,12 @@ void instance::forward(execution_unit* ctx, const node_id& dest_node,
CAF_LOG_TRACE
(
CAF_ARG
(
dest_node
)
<<
CAF_ARG
(
hdr
)
<<
CAF_ARG
(
payload
));
auto
path
=
lookup
(
dest_node
);
if
(
path
)
{
binary_serializer
bs
{
ctx
,
callee_
.
get_buffer
(
path
->
hdl
)};
if
(
!
inspect_objects
(
bs
,
hdr
))
{
CAF_LOG_ERROR
(
"unable to serialize BASP header:"
<<
bs
.
get_error
());
binary_serializer
sink
{
ctx
,
callee_
.
get_buffer
(
path
->
hdl
)};
if
(
!
sink
.
apply_object
(
hdr
))
{
CAF_LOG_ERROR
(
"unable to serialize BASP header:"
<<
sink
.
get_error
());
return
;
}
bs
.
value
(
span
<
const
byte
>
{
payload
.
data
(),
payload
.
size
()});
sink
.
value
(
span
<
const
byte
>
{
payload
.
data
(),
payload
.
size
()});
flush
(
*
path
);
}
else
{
CAF_LOG_WARNING
(
"cannot forward message, no route to destination"
);
...
...
libcaf_io/test/io/basp_broker.cpp
View file @
e2981877
...
...
@@ -163,7 +163,7 @@ public:
uint32_t
serialized_size
(
const
message
&
msg
)
{
byte_buffer
buf
;
binary_serializer
sink
{
mpx_
,
buf
};
if
(
!
inspect_objects
(
sink
,
msg
))
if
(
!
sink
.
apply_object
(
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
(
!
inspect_objects
(
sink
,
xs
...))
if
(
!
sink
.
apply_objects
(
xs
...))
CAF_FAIL
(
"failed to serialize payload: "
<<
sink
.
get_error
());
}
...
...
@@ -235,7 +235,7 @@ public:
auto
pw
=
make_callback
([
&
](
binary_serializer
&
sink
)
{
if
(
writer
!=
nullptr
&&
!
(
*
writer
)(
sink
))
return
false
;
return
inspect_objects
(
sink
,
x
,
xs
...);
return
sink
.
apply_objects
(
x
,
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
(
!
inspect_object
(
source
,
hdr
))
if
(
!
source
.
apply_object
(
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
(
!
inspect_objects
(
source
,
stages
,
msg
))
if
(
!
source
.
apply_objects
(
stages
,
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
(
!
inspect_objects
(
source
,
hdr
))
if
(
!
source
.
apply_objects
(
hdr
))
CAF_FAIL
(
"failed to deserialize header: "
<<
source
.
get_error
());
}
byte_buffer
payload
;
...
...
@@ -486,7 +486,7 @@ 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
(
!
inspect_objects
(
sink
,
instance
().
this_node
(),
app_ids
,
id
,
ifs
))
if
(
!
sink
.
apply_objects
(
instance
().
this_node
(),
app_ids
,
id
,
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 @
e2981877
...
...
@@ -49,7 +49,7 @@ struct fixture : test_coordinator_fixture<> {
auto
serialize
(
T
&
x
,
Ts
&
...
xs
)
{
byte_buffer
buf
;
binary_serializer
sink
{
sys
,
buf
};
if
(
!
inspect_objects
(
sink
,
x
,
xs
...))
if
(
!
sink
.
apply_objects
(
x
,
xs
...))
CAF_FAIL
(
"serialization failed: "
<<
sink
.
get_error
());
return
buf
;
}
...
...
@@ -57,7 +57,7 @@ struct fixture : test_coordinator_fixture<> {
template
<
class
Buffer
,
class
T
,
class
...
Ts
>
void
deserialize
(
const
Buffer
&
buf
,
T
&
x
,
Ts
&
...
xs
)
{
binary_deserializer
source
{
sys
,
buf
};
if
(
!
inspect_objects
(
source
,
x
,
xs
...))
if
(
!
source
.
apply_objects
(
x
,
xs
...))
CAF_FAIL
(
"serialization failed: "
<<
source
.
get_error
());
}
};
...
...
libcaf_io/test/io/worker.cpp
View file @
e2981877
...
...
@@ -109,7 +109,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
(
!
inspect_objects
(
sink
,
stages
,
msg
))
if
(
!
sink
.
apply_objects
(
stages
,
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 @
e2981877
...
...
@@ -843,7 +843,7 @@ public:
caf
::
byte_buffer
serialize
(
const
Ts
&
...
xs
)
{
caf
::
byte_buffer
buf
;
caf
::
binary_serializer
sink
{
sys
,
buf
};
if
(
!
inspect_objects
(
sink
,
xs
...))
if
(
!
sink
.
apply_objects
(
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
(
!
inspect_objects
(
source
,
xs
...))
if
(
!
source
.
apply_objects
(
xs
...))
CAF_FAIL
(
"deserialization failed: "
<<
source
.
get_error
());
}
...
...
manual/TypeInspection.rst
View file @
e2981877
...
...
@@ -8,6 +8,8 @@ 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`).
.. _type-inspection-data-model:
Data Model
----------
...
...
@@ -90,6 +92,92 @@ 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.
For example, consider the following ID type that simply wraps a string:
.. code-block:: C++
struct id { std::string value; };
template <class Inspector>
bool inspect(Inspector& f, id& x) {
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:
.. code-block:: none
object(type: "id") {
field(name: "value") {
value(type: "string")
}
}
Now, this type has little use on its own. Usually, we would use such a type to
compose other types such as the following type ``person``:
.. code-block:: C++
struct person { std::string name; id key; };
template <class Inspector>
bool inspect(Inspector& f, person& x) {
return f.object(x).fields(f.field("name", x.name), f.field("key", x.key));
}
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 the current implementation, we could read the key ``manager.ceo`` from a
configuration file with this content:
.. code-block:: none
manager {
ceo {
name = "Bob"
key = {
value = "TWFuIGlz"
}
}
}
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:
.. code-block:: C++
template <class Inspector>
bool inspect_value(Inspector& f, id& x) {
return f.apply_value(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:
.. code-block:: none
manager {
ceo {
name = "Bob"
key = "TWFuIGlz"
}
}
Specializing ``inspector_access``
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
...
...
@@ -128,9 +216,13 @@ The full interface of ``inspector_access`` looks as follows:
SetFallback& set_fallback);
};
For most types, we can implement ``apply_object`` and use default implementation
for the other member functions. For example, specializing ``inspector_access``
for our ``point_3d`` would look as follows:
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
implementation for the other member functions. For example, specializing
``inspector_access`` for our ``point_3d`` would look as follows:
.. code-block:: C++
...
...
@@ -170,9 +262,6 @@ 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.
For a non-trivial use case of ``apply_value``, see
:ref:`has-human-readable-format`.
Types with Getter and Setter Access
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
...
...
@@ -364,36 +453,29 @@ an ``enum class`` otherwise.
bool parse(std::string_view input, weekday& dest);
namespace caf {
template <>
struct inspector_access<weekday> : inspector_access_base<weekday> {
using default_impl = default_inspector_access<weekday>;
template <class Inspector>
static bool apply_object(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); };
f.object(x).fields(f.field("value", get, set));
} else {
return default_impl::apply_object(f, x);
}
template <class Inspector>
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); };
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>
static bool apply
_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 {
return default_impl::apply_value(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);
}
};
} // namespace caf
}
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
...
...
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