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
f4ecc9b4
Commit
f4ecc9b4
authored
Jul 26, 2020
by
Dominik Charousset
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Add scaffold for the new inspector API
parent
5930a041
Changes
8
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
8 changed files
with
1600 additions
and
105 deletions
+1600
-105
libcaf_core/CMakeLists.txt
libcaf_core/CMakeLists.txt
+2
-0
libcaf_core/caf/inspector_access.hpp
libcaf_core/caf/inspector_access.hpp
+71
-0
libcaf_core/caf/load_inspector.hpp
libcaf_core/caf/load_inspector.hpp
+363
-0
libcaf_core/caf/save_inspector.hpp
libcaf_core/caf/save_inspector.hpp
+157
-0
libcaf_core/test/load_inspector.cpp
libcaf_core/test/load_inspector.cpp
+343
-0
libcaf_core/test/save_inspector.cpp
libcaf_core/test/save_inspector.cpp
+352
-0
manual/ConfiguringActorApplications.rst
manual/ConfiguringActorApplications.rst
+2
-2
manual/TypeInspection.rst
manual/TypeInspection.rst
+310
-103
No files found.
libcaf_core/CMakeLists.txt
View file @
f4ecc9b4
...
@@ -280,6 +280,7 @@ caf_add_test_suites(caf-core-test
...
@@ -280,6 +280,7 @@ caf_add_test_suites(caf-core-test
ipv6_address
ipv6_address
ipv6_endpoint
ipv6_endpoint
ipv6_subnet
ipv6_subnet
load_inspector
local_group
local_group
logger
logger
mailbox_element
mailbox_element
...
@@ -302,6 +303,7 @@ caf_add_test_suites(caf-core-test
...
@@ -302,6 +303,7 @@ caf_add_test_suites(caf-core-test
policy.select_any
policy.select_any
request_timeout
request_timeout
result
result
save_inspector
selective_streaming
selective_streaming
serial_reply
serial_reply
serialization
serialization
...
...
libcaf_core/caf/inspector_access.hpp
0 → 100644
View file @
f4ecc9b4
/******************************************************************************
* ____ _ _____ *
* / ___| / \ | ___| 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 "caf/detail/inspect.hpp"
#include "caf/fwd.hpp"
namespace
caf
{
/// Customization point for adding support for a custom type. The default
/// implementation requires an `inspect` overload for `T` that is available via
/// ADL.
template
<
class
T
>
struct
inspector_access
{
template
<
class
Inspector
>
static
bool
apply
(
Inspector
&
f
,
T
&
x
)
{
using
detail
::
inspect
;
using
result_type
=
decltype
(
inspect
(
f
,
x
));
if
constexpr
(
std
::
is_same
<
result_type
,
bool
>::
value
)
return
inspect
(
f
,
x
);
else
return
apply_deprecated
(
f
,
x
);
}
template
<
class
Inspector
>
[[
deprecated
(
"inspect() overloads should return bool"
)]]
static
bool
apply_deprecated
(
Inspector
&
f
,
T
&
x
)
{
if
(
auto
err
=
inspect
(
f
,
x
))
{
f
.
set_error
(
std
::
move
(
err
));
return
false
;
}
return
true
;
}
};
/// Customization point to influence how inspectors treat fields of type `T`.
template
<
class
T
>
struct
inspector_access_traits
{
static
constexpr
bool
is_optional
=
false
;
static
constexpr
bool
is_sum_type
=
false
;
};
template
<
class
T
>
struct
inspector_access_traits
<
optional
<
T
>>
{
static
constexpr
bool
is_optional
=
true
;
static
constexpr
bool
is_sum_type
=
false
;
};
template
<
class
...
Ts
>
struct
inspector_access_traits
<
variant
<
Ts
...
>>
{
static
constexpr
bool
is_optional
=
false
;
static
constexpr
bool
is_sum_type
=
true
;
};
}
// namespace caf
libcaf_core/caf/load_inspector.hpp
0 → 100644
View file @
f4ecc9b4
This diff is collapsed.
Click to expand it.
libcaf_core/caf/save_inspector.hpp
0 → 100644
View file @
f4ecc9b4
/******************************************************************************
* ____ _ _____ *
* / ___| / \ | ___| 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 "caf/error.hpp"
#include "caf/inspector_access.hpp"
#include "caf/sec.hpp"
#include "caf/string_view.hpp"
namespace
caf
{
/// Base type for inspectors that save objects to some output sink. Deriving
/// from this class enables the inspector DSL.
/// @note The derived type still needs to provide an `object()` member function
/// for the DSL.
class
save_inspector
{
public:
// -- contants ---------------------------------------------------------------
/// 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
;
/// A save inspector only reads the state of an object.
static
constexpr
bool
reads_state
=
true
;
/// A load inspector never modifies the state of an object.
static
constexpr
bool
writes_state
=
false
;
// -- DSL types for regular fields -------------------------------------------
template
<
class
T
>
struct
field_t
{
string_view
field_name
;
T
*
val
;
template
<
class
Inspector
>
bool
operator
()(
string_view
,
Inspector
&
f
)
{
if
constexpr
(
inspector_access_traits
<
T
>::
is_optional
)
{
auto
&
ref
=
*
val
;
using
value_type
=
std
::
decay_t
<
decltype
(
*
ref
)
>
;
if
(
ref
)
{
return
f
.
begin_field
(
field_name
,
true
)
//
&&
inspector_access
<
value_type
>::
apply
(
f
,
*
ref
)
//
&&
f
.
end_field
();
}
else
{
return
f
.
begin_field
(
field_name
,
false
)
&&
f
.
end_field
();
}
}
else
{
return
f
.
begin_field
(
field_name
)
//
&&
inspector_access
<
T
>::
apply
(
f
,
*
val
)
//
&&
f
.
end_field
();
}
}
template
<
class
Unused
>
field_t
&
fallback
(
Unused
&&
)
{
return
*
this
;
}
template
<
class
Predicate
>
field_t
invariant
(
Predicate
&&
)
{
return
*
this
;
}
};
// -- DSL types for virtual fields (getter and setter access) ----------------
template
<
class
T
,
class
Get
>
struct
virt_field_t
{
string_view
field_name
;
Get
get
;
template
<
class
Inspector
>
bool
operator
()(
string_view
,
Inspector
&
f
)
{
if
(
!
f
.
begin_field
(
field_name
))
return
stop
;
auto
&&
value
=
get
();
using
value_type
=
std
::
remove_reference_t
<
decltype
(
value
)
>
;
if
constexpr
(
std
::
is_const
<
value_type
>::
value
)
{
// Force a mutable reference, because the inspect API requires it. This
// const_cast is always safe, because we never actually modify the
// object.
using
mutable_ref
=
std
::
remove_const_t
<
value_type
>&
;
if
(
!
inspector_access
<
T
>::
apply
(
f
,
const_cast
<
mutable_ref
>
(
value
)))
return
stop
;
}
else
{
if
(
!
inspector_access
<
T
>::
apply
(
f
,
value
))
return
stop
;
}
return
f
.
end_field
();
}
template
<
class
Unused
>
virt_field_t
&
fallback
(
Unused
&&
)
{
return
*
this
;
}
template
<
class
Predicate
>
virt_field_t
invariant
(
Predicate
&&
)
{
return
*
this
;
}
};
template
<
class
Inspector
>
struct
object_t
{
string_view
object_name
;
Inspector
*
f
;
template
<
class
...
Fields
>
bool
fields
(
Fields
&&
...
fs
)
{
return
f
->
begin_object
(
object_name
)
&&
(
fs
(
object_name
,
*
f
)
&&
...)
&&
f
->
end_object
();
}
auto
pretty_name
(
string_view
name
)
&&
{
return
object_t
{
name
,
f
};
}
};
// -- factory functions ------------------------------------------------------
template
<
class
T
>
static
auto
field
(
string_view
name
,
T
&
x
)
{
return
field_t
<
T
>
{
name
,
&
x
};
}
template
<
class
Get
,
class
Set
>
static
auto
field
(
string_view
name
,
Get
get
,
Set
&&
)
{
using
field_type
=
std
::
decay_t
<
decltype
(
get
())
>
;
return
virt_field_t
<
field_type
,
Get
>
{
name
,
get
};
}
};
}
// namespace caf
libcaf_core/test/load_inspector.cpp
0 → 100644
View file @
f4ecc9b4
/******************************************************************************
* ____ _ _____ *
* / ___| / \ | ___| 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. *
******************************************************************************/
#define CAF_SUITE load_inspector
#include "caf/load_inspector.hpp"
#include "caf/test/dsl.hpp"
#include <cstdint>
#include <string>
#include <vector>
namespace
caf
{
template
<
>
struct
inspector_access
<
std
::
string
>
{
template
<
class
Inspector
>
static
bool
apply
(
Inspector
&
f
,
std
::
string
&
x
)
{
return
f
.
value
(
x
);
}
};
template
<
>
struct
inspector_access
<
int32_t
>
{
template
<
class
Inspector
>
static
bool
apply
(
Inspector
&
f
,
int32_t
&
x
)
{
return
f
.
value
(
x
);
}
};
template
<
>
struct
inspector_access
<
double
>
{
template
<
class
Inspector
>
static
bool
apply
(
Inspector
&
f
,
double
&
x
)
{
return
f
.
value
(
x
);
}
};
}
// namespace caf
using
namespace
caf
;
namespace
{
using
string_list
=
std
::
vector
<
std
::
string
>
;
struct
point_3d
{
static
inline
string_view
tname
=
"point_3d"
;
int32_t
x
;
int32_t
y
;
int32_t
z
;
};
template
<
class
Inspector
>
bool
inspect
(
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
));
}
struct
line
{
static
inline
string_view
tname
=
"line"
;
point_3d
p1
;
point_3d
p2
;
};
template
<
class
Inspector
>
bool
inspect
(
Inspector
&
f
,
line
&
x
)
{
return
f
.
object
(
x
).
fields
(
f
.
field
(
"p1"
,
x
.
p1
),
f
.
field
(
"p2"
,
x
.
p2
));
}
struct
duration
{
static
inline
string_view
tname
=
"duration"
;
std
::
string
unit
;
double
count
;
};
bool
valid_time_unit
(
const
std
::
string
&
unit
)
{
return
unit
==
"seconds"
||
unit
==
"minutes"
;
}
template
<
class
Inspector
>
bool
inspect
(
Inspector
&
f
,
duration
&
x
)
{
return
f
.
object
(
x
).
fields
(
f
.
field
(
"unit"
,
x
.
unit
).
fallback
(
"seconds"
).
invariant
(
valid_time_unit
),
f
.
field
(
"count"
,
x
.
count
));
}
struct
person
{
static
inline
string_view
tname
=
"person"
;
std
::
string
name
;
optional
<
std
::
string
>
phone
;
};
template
<
class
Inspector
>
bool
inspect
(
Inspector
&
f
,
person
&
x
)
{
return
f
.
object
(
x
).
fields
(
f
.
field
(
"name"
,
x
.
name
),
f
.
field
(
"phone"
,
x
.
phone
));
}
class
foobar
{
public:
static
inline
string_view
tname
=
"foobar"
;
const
std
::
string
&
foo
()
{
return
foo_
;
}
void
foo
(
std
::
string
value
)
{
foo_
=
std
::
move
(
value
);
}
const
std
::
string
&
bar
()
{
return
bar_
;
}
void
bar
(
std
::
string
value
)
{
bar_
=
std
::
move
(
value
);
}
private:
std
::
string
foo_
;
std
::
string
bar_
;
};
template
<
class
Inspector
>
bool
inspect
(
Inspector
&
f
,
foobar
&
x
)
{
auto
get_foo
=
[
&
x
]()
->
decltype
(
auto
)
{
return
x
.
foo
();
};
auto
set_foo
=
[
&
x
](
std
::
string
value
)
{
x
.
foo
(
std
::
move
(
value
));
return
true
;
};
auto
get_bar
=
[
&
x
]()
->
decltype
(
auto
)
{
return
x
.
bar
();
};
auto
set_bar
=
[
&
x
](
std
::
string
value
)
{
x
.
bar
(
std
::
move
(
value
));
return
true
;
};
return
f
.
object
(
x
).
fields
(
f
.
field
(
"foo"
,
get_foo
,
set_foo
),
f
.
field
(
"bar"
,
get_bar
,
set_bar
));
}
struct
testee
:
load_inspector
{
std
::
string
log
;
error
err
;
void
set_error
(
error
x
)
{
err
=
std
::
move
(
x
);
}
size_t
indent
=
0
;
void
new_line
()
{
log
+=
'\n'
;
log
.
insert
(
log
.
end
(),
indent
,
' '
);
}
template
<
class
T
>
auto
object
(
T
&
)
{
return
object_t
<
testee
>
{
T
::
tname
,
this
};
}
bool
begin_object
(
string_view
object_name
)
{
new_line
();
indent
+=
2
;
log
+=
"begin object "
;
log
.
insert
(
log
.
end
(),
object_name
.
begin
(),
object_name
.
end
());
return
ok
;
}
bool
end_object
()
{
indent
-=
2
;
new_line
();
log
+=
"end object"
;
return
ok
;
}
bool
begin_field
(
string_view
name
)
{
new_line
();
indent
+=
2
;
log
+=
"begin field "
;
log
.
insert
(
log
.
end
(),
name
.
begin
(),
name
.
end
());
return
ok
;
}
bool
begin_field
(
string_view
name
,
bool
&
is_present
)
{
new_line
();
indent
+=
2
;
log
+=
"begin optional field "
;
log
.
insert
(
log
.
end
(),
name
.
begin
(),
name
.
end
());
is_present
=
false
;
return
ok
;
}
bool
end_field
()
{
indent
-=
2
;
new_line
();
log
+=
"end field"
;
return
ok
;
}
template
<
class
T
>
bool
value
(
T
&
x
)
{
new_line
();
log
+=
type_name_v
<
T
>
;
log
+=
" value"
;
x
=
T
{};
return
ok
;
}
};
struct
fixture
{
testee
f
;
};
}
// namespace
CAF_TEST_FIXTURE_SCOPE
(
load_inspector_tests
,
fixture
)
CAF_TEST
(
load
inspectors
can
visit
simple
POD
types
)
{
point_3d
p
{
1
,
1
,
1
};
CAF_CHECK_EQUAL
(
inspect
(
f
,
p
),
true
);
CAF_CHECK_EQUAL
(
p
.
x
,
0
);
CAF_CHECK_EQUAL
(
p
.
y
,
0
);
CAF_CHECK_EQUAL
(
p
.
z
,
0
);
CAF_CHECK_EQUAL
(
f
.
log
,
R"_(
begin object point_3d
begin field x
int32_t value
end field
begin field y
int32_t value
end field
begin field z
int32_t value
end field
end object)_"
);
}
CAF_TEST
(
load
inspectors
recurse
into
members
)
{
line
l
{
point_3d
{
1
,
1
,
1
},
point_3d
{
1
,
1
,
1
}};
CAF_CHECK_EQUAL
(
inspect
(
f
,
l
),
true
);
CAF_CHECK_EQUAL
(
l
.
p1
.
x
,
0
);
CAF_CHECK_EQUAL
(
l
.
p1
.
y
,
0
);
CAF_CHECK_EQUAL
(
l
.
p1
.
z
,
0
);
CAF_CHECK_EQUAL
(
l
.
p2
.
x
,
0
);
CAF_CHECK_EQUAL
(
l
.
p2
.
y
,
0
);
CAF_CHECK_EQUAL
(
l
.
p2
.
z
,
0
);
CAF_CHECK_EQUAL
(
f
.
log
,
R"_(
begin object line
begin field p1
begin object point_3d
begin field x
int32_t value
end field
begin field y
int32_t value
end field
begin field z
int32_t value
end field
end object
end field
begin field p2
begin object point_3d
begin field x
int32_t value
end field
begin field y
int32_t value
end field
begin field z
int32_t value
end field
end object
end field
end object)_"
);
}
CAF_TEST
(
load
inspectors
support
fields
with
fallbacks
and
invariants
)
{
duration
d
{
"minutes"
,
42
};
CAF_CHECK_EQUAL
(
inspect
(
f
,
d
),
true
);
CAF_CHECK_EQUAL
(
d
.
unit
,
"seconds"
);
CAF_CHECK_EQUAL
(
d
.
count
,
0.0
);
CAF_CHECK_EQUAL
(
f
.
log
,
R"_(
begin object duration
begin optional field unit
end field
begin field count
double value
end field
end object)_"
);
}
CAF_TEST
(
load
inspectors
support
fields
with
optional
values
)
{
person
p
{
"Bruce Almighty"
,
std
::
string
{
"776-2323"
}};
CAF_CHECK_EQUAL
(
inspect
(
f
,
p
),
true
);
CAF_CHECK_EQUAL
(
p
.
name
,
""
);
CAF_CHECK_EQUAL
(
p
.
phone
,
none
);
CAF_CHECK_EQUAL
(
f
.
log
,
R"_(
begin object person
begin field name
std::string value
end field
begin optional field phone
end field
end object)_"
);
}
CAF_TEST
(
load
inspectors
support
fields
with
getters
and
setters
)
{
foobar
fb
;
fb
.
foo
(
"hello"
);
fb
.
bar
(
"world"
);
CAF_CHECK_EQUAL
(
inspect
(
f
,
fb
),
true
);
CAF_CHECK_EQUAL
(
fb
.
foo
(),
""
);
CAF_CHECK_EQUAL
(
fb
.
bar
(),
""
);
CAF_CHECK_EQUAL
(
f
.
log
,
R"_(
begin object foobar
begin field foo
std::string value
end field
begin field bar
std::string value
end field
end object)_"
);
}
CAF_TEST_FIXTURE_SCOPE_END
()
libcaf_core/test/save_inspector.cpp
0 → 100644
View file @
f4ecc9b4
/******************************************************************************
* ____ _ _____ *
* / ___| / \ | ___| 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. *
******************************************************************************/
#define CAF_SUITE save_inspector
#include "caf/save_inspector.hpp"
#include "caf/test/dsl.hpp"
#include <cstdint>
#include <string>
#include <vector>
namespace
caf
{
template
<
>
struct
inspector_access
<
std
::
string
>
{
template
<
class
Inspector
>
static
bool
apply
(
Inspector
&
f
,
std
::
string
&
x
)
{
return
f
.
value
(
x
);
}
};
template
<
>
struct
inspector_access
<
int32_t
>
{
template
<
class
Inspector
>
static
bool
apply
(
Inspector
&
f
,
int32_t
&
x
)
{
return
f
.
value
(
x
);
}
};
template
<
>
struct
inspector_access
<
double
>
{
template
<
class
Inspector
>
static
bool
apply
(
Inspector
&
f
,
double
&
x
)
{
return
f
.
value
(
x
);
}
};
}
// namespace caf
using
namespace
caf
;
namespace
{
using
string_list
=
std
::
vector
<
std
::
string
>
;
struct
point_3d
{
static
inline
string_view
tname
=
"point_3d"
;
int32_t
x
;
int32_t
y
;
int32_t
z
;
};
template
<
class
Inspector
>
bool
inspect
(
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
));
}
struct
line
{
static
inline
string_view
tname
=
"line"
;
point_3d
p1
;
point_3d
p2
;
};
template
<
class
Inspector
>
bool
inspect
(
Inspector
&
f
,
line
&
x
)
{
return
f
.
object
(
x
).
fields
(
f
.
field
(
"p1"
,
x
.
p1
),
f
.
field
(
"p2"
,
x
.
p2
));
}
struct
duration
{
static
inline
string_view
tname
=
"duration"
;
std
::
string
unit
;
double
count
;
};
bool
valid_time_unit
(
const
std
::
string
&
unit
)
{
return
unit
==
"seconds"
||
unit
==
"minutes"
;
}
template
<
class
Inspector
>
bool
inspect
(
Inspector
&
f
,
duration
&
x
)
{
return
f
.
object
(
x
).
fields
(
f
.
field
(
"unit"
,
x
.
unit
).
fallback
(
"seconds"
).
invariant
(
valid_time_unit
),
f
.
field
(
"count"
,
x
.
count
));
}
struct
person
{
static
inline
string_view
tname
=
"person"
;
std
::
string
name
;
optional
<
std
::
string
>
phone
;
};
template
<
class
Inspector
>
bool
inspect
(
Inspector
&
f
,
person
&
x
)
{
return
f
.
object
(
x
).
fields
(
f
.
field
(
"name"
,
x
.
name
),
f
.
field
(
"phone"
,
x
.
phone
));
}
class
foobar
{
public:
static
inline
string_view
tname
=
"foobar"
;
const
std
::
string
&
foo
()
{
return
foo_
;
}
void
foo
(
std
::
string
value
)
{
foo_
=
std
::
move
(
value
);
}
const
std
::
string
&
bar
()
{
return
bar_
;
}
void
bar
(
std
::
string
value
)
{
bar_
=
std
::
move
(
value
);
}
private:
std
::
string
foo_
;
std
::
string
bar_
;
};
template
<
class
Inspector
>
bool
inspect
(
Inspector
&
f
,
foobar
&
x
)
{
auto
get_foo
=
[
&
x
]()
->
decltype
(
auto
)
{
return
x
.
foo
();
};
auto
set_foo
=
[
&
x
](
std
::
string
value
)
{
x
.
foo
(
std
::
move
(
value
));
return
true
;
};
auto
get_bar
=
[
&
x
]()
->
decltype
(
auto
)
{
return
x
.
bar
();
};
auto
set_bar
=
[
&
x
](
std
::
string
value
)
{
x
.
bar
(
std
::
move
(
value
));
return
true
;
};
return
f
.
object
(
x
).
fields
(
f
.
field
(
"foo"
,
get_foo
,
set_foo
),
f
.
field
(
"bar"
,
get_bar
,
set_bar
));
}
struct
testee
:
save_inspector
{
std
::
string
log
;
error
err
;
void
set_error
(
error
x
)
{
err
=
std
::
move
(
x
);
}
size_t
indent
=
0
;
void
new_line
()
{
log
+=
'\n'
;
log
.
insert
(
log
.
end
(),
indent
,
' '
);
}
template
<
class
T
>
auto
object
(
T
&
)
{
return
object_t
<
testee
>
{
T
::
tname
,
this
};
}
bool
begin_object
(
string_view
object_name
)
{
new_line
();
indent
+=
2
;
log
+=
"begin object "
;
log
.
insert
(
log
.
end
(),
object_name
.
begin
(),
object_name
.
end
());
return
ok
;
}
bool
end_object
()
{
indent
-=
2
;
new_line
();
log
+=
"end object"
;
return
ok
;
}
bool
begin_field
(
string_view
name
)
{
new_line
();
indent
+=
2
;
log
+=
"begin field "
;
log
.
insert
(
log
.
end
(),
name
.
begin
(),
name
.
end
());
return
ok
;
}
bool
begin_field
(
string_view
name
,
bool
)
{
new_line
();
indent
+=
2
;
log
+=
"begin optional field "
;
log
.
insert
(
log
.
end
(),
name
.
begin
(),
name
.
end
());
return
ok
;
}
bool
end_field
()
{
indent
-=
2
;
new_line
();
log
+=
"end field"
;
return
ok
;
}
template
<
class
T
>
bool
value
(
const
T
&
)
{
new_line
();
log
+=
type_name_v
<
T
>
;
log
+=
" value"
;
return
ok
;
}
};
struct
fixture
{
testee
f
;
};
}
// namespace
CAF_TEST_FIXTURE_SCOPE
(
load_inspector_tests
,
fixture
)
CAF_TEST
(
save
inspectors
can
visit
simple
POD
types
)
{
point_3d
p
{
1
,
1
,
1
};
CAF_CHECK_EQUAL
(
inspect
(
f
,
p
),
true
);
CAF_CHECK_EQUAL
(
p
.
x
,
1
);
CAF_CHECK_EQUAL
(
p
.
y
,
1
);
CAF_CHECK_EQUAL
(
p
.
z
,
1
);
CAF_CHECK_EQUAL
(
f
.
log
,
R"_(
begin object point_3d
begin field x
int32_t value
end field
begin field y
int32_t value
end field
begin field z
int32_t value
end field
end object)_"
);
}
CAF_TEST
(
save
inspectors
recurse
into
members
)
{
line
l
{
point_3d
{
1
,
1
,
1
},
point_3d
{
1
,
1
,
1
}};
CAF_CHECK_EQUAL
(
inspect
(
f
,
l
),
true
);
CAF_CHECK_EQUAL
(
l
.
p1
.
x
,
1
);
CAF_CHECK_EQUAL
(
l
.
p1
.
y
,
1
);
CAF_CHECK_EQUAL
(
l
.
p1
.
z
,
1
);
CAF_CHECK_EQUAL
(
l
.
p2
.
x
,
1
);
CAF_CHECK_EQUAL
(
l
.
p2
.
y
,
1
);
CAF_CHECK_EQUAL
(
l
.
p2
.
z
,
1
);
CAF_CHECK_EQUAL
(
f
.
log
,
R"_(
begin object line
begin field p1
begin object point_3d
begin field x
int32_t value
end field
begin field y
int32_t value
end field
begin field z
int32_t value
end field
end object
end field
begin field p2
begin object point_3d
begin field x
int32_t value
end field
begin field y
int32_t value
end field
begin field z
int32_t value
end field
end object
end field
end object)_"
);
}
CAF_TEST
(
save
inspectors
support
fields
with
fallbacks
and
invariants
)
{
duration
d
{
"minutes"
,
42.0
};
CAF_CHECK_EQUAL
(
inspect
(
f
,
d
),
true
);
CAF_CHECK_EQUAL
(
d
.
unit
,
"minutes"
);
CAF_CHECK_EQUAL
(
d
.
count
,
42.0
);
CAF_CHECK_EQUAL
(
f
.
log
,
R"_(
begin object duration
begin field unit
std::string value
end field
begin field count
double value
end field
end object)_"
);
}
CAF_TEST
(
save
inspectors
support
fields
with
optional
values
)
{
person
p1
{
"Eduard Example"
,
none
};
CAF_CHECK_EQUAL
(
inspect
(
f
,
p1
),
true
);
CAF_CHECK_EQUAL
(
f
.
log
,
R"_(
begin object person
begin field name
std::string value
end field
begin optional field phone
end field
end object)_"
);
f
.
log
.
clear
();
person
p2
{
"Bruce Almighty"
,
std
::
string
{
"776-2323"
}};
CAF_CHECK_EQUAL
(
inspect
(
f
,
p2
),
true
);
CAF_CHECK_EQUAL
(
f
.
log
,
R"_(
begin object person
begin field name
std::string value
end field
begin optional field phone
std::string value
end field
end object)_"
);
}
CAF_TEST
(
save
inspectors
support
fields
with
getters
and
setters
)
{
foobar
fb
;
fb
.
foo
(
"hello"
);
fb
.
bar
(
"world"
);
CAF_CHECK_EQUAL
(
inspect
(
f
,
fb
),
true
);
CAF_CHECK_EQUAL
(
fb
.
foo
(),
"hello"
);
CAF_CHECK_EQUAL
(
fb
.
bar
(),
"world"
);
CAF_CHECK_EQUAL
(
f
.
log
,
R"_(
begin object foobar
begin field foo
std::string value
end field
begin field bar
std::string value
end field
end object)_"
);
}
CAF_TEST_FIXTURE_SCOPE_END
()
manual/ConfiguringActorApplications.rst
View file @
f4ecc9b4
...
@@ -229,7 +229,7 @@ are usually detected at runtime and thus have no hard-coded default.
...
@@ -229,7 +229,7 @@ are usually detected at runtime and thus have no hard-coded default.
.. literalinclude:: /examples/caf-application.conf
.. literalinclude:: /examples/caf-application.conf
:language: none
:language: none
.. _
add-custom-message-type
:
.. _
custom-message-types
:
Adding Custom Message Types
Adding Custom Message Types
---------------------------
---------------------------
...
@@ -294,7 +294,7 @@ Adding the calculator actor type to our config is achieved by calling
...
@@ -294,7 +294,7 @@ Adding the calculator actor type to our config is achieved by calling
``add_actor_type``. After calling this in our config, we can spawn the
``add_actor_type``. After calling this in our config, we can spawn the
``calculator`` anywhere in the distributed actor system (assuming all nodes use
``calculator`` anywhere in the distributed actor system (assuming all nodes use
the same config). Note that the handle type still requires a type ID (see
the same config). Note that the handle type still requires a type ID (see
add-custom-message-type
_).
custom-message-types
_).
Our final example illustrates how to spawn a ``calculator`` locally by
Our final example illustrates how to spawn a ``calculator`` locally by
using its type name. Because the dynamic type name lookup can fail and the
using its type name. Because the dynamic type name lookup can fail and the
...
...
manual/TypeInspection.rst
View file @
f4ecc9b4
This diff is collapsed.
Click to expand it.
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