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
56d43a75
Commit
56d43a75
authored
Oct 03, 2022
by
Dominik Charousset
Browse files
Options
Browse Files
Download
Plain Diff
Merge topic/neverlord/type-id-mapper
parents
4b8d5abf
251b128f
Changes
10
Hide whitespace changes
Inline
Side-by-side
Showing
10 changed files
with
151 additions
and
11 deletions
+151
-11
CHANGELOG.md
CHANGELOG.md
+5
-0
libcaf_core/caf/json_reader.hpp
libcaf_core/caf/json_reader.hpp
+16
-0
libcaf_core/caf/json_writer.hpp
libcaf_core/caf/json_writer.hpp
+17
-0
libcaf_core/caf/timestamp.hpp
libcaf_core/caf/timestamp.hpp
+7
-3
libcaf_core/caf/type_id.hpp
libcaf_core/caf/type_id.hpp
+23
-2
libcaf_core/src/json_reader.cpp
libcaf_core/src/json_reader.cpp
+2
-2
libcaf_core/src/json_writer.cpp
libcaf_core/src/json_writer.cpp
+3
-3
libcaf_core/src/timestamp.cpp
libcaf_core/src/timestamp.cpp
+11
-1
libcaf_core/src/type_id.cpp
libcaf_core/src/type_id.cpp
+12
-0
libcaf_core/test/json_reader.cpp
libcaf_core/test/json_reader.cpp
+55
-0
No files found.
CHANGELOG.md
View file @
56d43a75
...
@@ -5,6 +5,11 @@ is based on [Keep a Changelog](https://keepachangelog.com).
...
@@ -5,6 +5,11 @@ is based on [Keep a Changelog](https://keepachangelog.com).
## [Unreleased]
## [Unreleased]
### Added
-
JSON inspectors now allow users to use a custom
`type_id_mapper`
to generate
and parse JSON text that uses different names for the types than the C++ API.
### Fixed
### Fixed
-
Passing a response promise to a run-delayed continuation could result in a
-
Passing a response promise to a run-delayed continuation could result in a
...
...
libcaf_core/caf/json_reader.hpp
View file @
56d43a75
...
@@ -112,6 +112,16 @@ public:
...
@@ -112,6 +112,16 @@ public:
field_type_suffix_
=
suffix
;
field_type_suffix_
=
suffix
;
}
}
/// Returns the type ID mapper used by the writer.
[[
nodiscard
]]
const
type_id_mapper
*
mapper
()
const
noexcept
{
return
mapper_
;
}
/// Changes the type ID mapper for the writer.
void
mapper
(
const
type_id_mapper
*
ptr
)
noexcept
{
mapper_
=
ptr
;
}
// -- modifiers --------------------------------------------------------------
// -- modifiers --------------------------------------------------------------
/// Parses @p json_text into an internal representation. After loading the
/// Parses @p json_text into an internal representation. After loading the
...
@@ -247,6 +257,12 @@ private:
...
@@ -247,6 +257,12 @@ private:
/// Keeps track of the current field for better debugging output.
/// Keeps track of the current field for better debugging output.
std
::
vector
<
std
::
string_view
>
field_
;
std
::
vector
<
std
::
string_view
>
field_
;
/// The mapper implementation we use by default.
default_type_id_mapper
default_mapper_
;
/// Configures which ID mapper we use to translate between type IDs and names.
const
type_id_mapper
*
mapper_
=
&
default_mapper_
;
};
};
}
// namespace caf
}
// namespace caf
libcaf_core/caf/json_writer.hpp
View file @
56d43a75
...
@@ -115,6 +115,16 @@ public:
...
@@ -115,6 +115,16 @@ public:
field_type_suffix_
=
suffix
;
field_type_suffix_
=
suffix
;
}
}
/// Returns the type ID mapper used by the writer.
[[
nodiscard
]]
const
type_id_mapper
*
mapper
()
const
noexcept
{
return
mapper_
;
}
/// Changes the type ID mapper for the writer.
void
mapper
(
const
type_id_mapper
*
ptr
)
noexcept
{
mapper_
=
ptr
;
}
// -- modifiers --------------------------------------------------------------
// -- modifiers --------------------------------------------------------------
/// Removes all characters from the buffer and restores the writer to its
/// Removes all characters from the buffer and restores the writer to its
...
@@ -280,7 +290,14 @@ private:
...
@@ -280,7 +290,14 @@ private:
// Configures whether we omit the top-level '@type' annotation.
// Configures whether we omit the top-level '@type' annotation.
bool
skip_object_type_annotation_
=
false
;
bool
skip_object_type_annotation_
=
false
;
// Configures how we generate type annotations for fields.
std
::
string_view
field_type_suffix_
=
field_type_suffix_default
;
std
::
string_view
field_type_suffix_
=
field_type_suffix_default
;
// The mapper implementation we use by default.
default_type_id_mapper
default_mapper_
;
// Configures which ID mapper we use to translate between type IDs and names.
const
type_id_mapper
*
mapper_
=
&
default_mapper_
;
};
};
}
// namespace caf
}
// namespace caf
libcaf_core/caf/timestamp.hpp
View file @
56d43a75
...
@@ -4,13 +4,14 @@
...
@@ -4,13 +4,14 @@
#pragma once
#pragma once
#include "caf/detail/core_export.hpp"
#include "caf/fwd.hpp"
#include "caf/timespan.hpp"
#include <chrono>
#include <chrono>
#include <cstdint>
#include <cstdint>
#include <string>
#include <string>
#include "caf/detail/core_export.hpp"
#include "caf/timespan.hpp"
namespace
caf
{
namespace
caf
{
/// A portable timestamp with nanosecond resolution anchored at the UNIX epoch.
/// A portable timestamp with nanosecond resolution anchored at the UNIX epoch.
...
@@ -23,6 +24,9 @@ CAF_CORE_EXPORT timestamp make_timestamp();
...
@@ -23,6 +24,9 @@ CAF_CORE_EXPORT timestamp make_timestamp();
/// Prints `x` in ISO 8601 format, e.g., `2018-11-15T06:25:01.462`.
/// Prints `x` in ISO 8601 format, e.g., `2018-11-15T06:25:01.462`.
CAF_CORE_EXPORT
std
::
string
timestamp_to_string
(
timestamp
x
);
CAF_CORE_EXPORT
std
::
string
timestamp_to_string
(
timestamp
x
);
/// Converts an ISO 8601 formatted timestamp into its native representation.
CAF_CORE_EXPORT
expected
<
timestamp
>
timestamp_from_string
(
std
::
string_view
str
);
/// Appends the timestamp `x` in ISO 8601 format, e.g.,
/// Appends the timestamp `x` in ISO 8601 format, e.g.,
/// `2018-11-15T06:25:01.462`, to `y`.
/// `2018-11-15T06:25:01.462`, to `y`.
CAF_CORE_EXPORT
void
append_timestamp_to_string
(
std
::
string
&
x
,
timestamp
y
);
CAF_CORE_EXPORT
void
append_timestamp_to_string
(
std
::
string
&
x
,
timestamp
y
);
...
...
libcaf_core/caf/type_id.hpp
View file @
56d43a75
...
@@ -96,13 +96,34 @@ type_id_t type_id_or_invalid() {
...
@@ -96,13 +96,34 @@ type_id_t type_id_or_invalid() {
return
invalid_type_id
;
return
invalid_type_id
;
}
}
/// Returns the type name
of given `type` or an empty string if `type`
is an
/// Returns the type name
for @p type or an empty string if @p type
is an
/// invalid ID.
/// invalid ID.
CAF_CORE_EXPORT
std
::
string_view
query_type_name
(
type_id_t
type
);
CAF_CORE_EXPORT
std
::
string_view
query_type_name
(
type_id_t
type
);
/// Returns the type
of given `name` or `invalid_type_id` if no type matches
.
/// Returns the type
for @p name or `invalid_type_id` if @p name is unknown
.
CAF_CORE_EXPORT
type_id_t
query_type_id
(
std
::
string_view
name
);
CAF_CORE_EXPORT
type_id_t
query_type_id
(
std
::
string_view
name
);
/// Translates between human-readable type names and type IDs.
class
CAF_CORE_EXPORT
type_id_mapper
{
public:
virtual
~
type_id_mapper
();
/// Returns the type name for @p type or an empty string if @p type is an
/// invalid ID.
virtual
std
::
string_view
operator
()(
type_id_t
type
)
const
=
0
;
/// Returns the type for @p name or `invalid_type_id` if @p name is unknown.
virtual
type_id_t
operator
()(
std
::
string_view
name
)
const
=
0
;
};
/// Dispatches to @ref query_type_name and @ref query_type_id.
class
default_type_id_mapper
:
public
type_id_mapper
{
public:
std
::
string_view
operator
()(
type_id_t
type
)
const
override
;
type_id_t
operator
()(
std
::
string_view
name
)
const
override
;
};
}
// namespace caf
}
// namespace caf
// -- CAF_BEGIN_TYPE_ID_BLOCK --------------------------------------------------
// -- CAF_BEGIN_TYPE_ID_BLOCK --------------------------------------------------
...
...
libcaf_core/src/json_reader.cpp
View file @
56d43a75
...
@@ -182,7 +182,7 @@ void json_reader::reset() {
...
@@ -182,7 +182,7 @@ void json_reader::reset() {
bool
json_reader
::
fetch_next_object_type
(
type_id_t
&
type
)
{
bool
json_reader
::
fetch_next_object_type
(
type_id_t
&
type
)
{
std
::
string_view
type_name
;
std
::
string_view
type_name
;
if
(
fetch_next_object_name
(
type_name
))
{
if
(
fetch_next_object_name
(
type_name
))
{
if
(
auto
id
=
query_type_id
(
type_name
);
id
!=
invalid_type_id
)
{
if
(
auto
id
=
(
*
mapper_
)
(
type_name
);
id
!=
invalid_type_id
)
{
type
=
id
;
type
=
id
;
return
true
;
return
true
;
}
else
{
}
else
{
...
@@ -311,7 +311,7 @@ bool json_reader::begin_field(std::string_view name, bool& is_present,
...
@@ -311,7 +311,7 @@ bool json_reader::begin_field(std::string_view name, bool& is_present,
member
!=
nullptr
member
!=
nullptr
&&
member
->
val
->
data
.
index
()
!=
detail
::
json
::
value
::
null_index
)
{
&&
member
->
val
->
data
.
index
()
!=
detail
::
json
::
value
::
null_index
)
{
auto
ft
=
field_type
(
top
<
position
::
object
>
(),
name
,
field_type_suffix_
);
auto
ft
=
field_type
(
top
<
position
::
object
>
(),
name
,
field_type_suffix_
);
if
(
auto
id
=
query_type_id
(
ft
);
id
!=
invalid_type_id
)
{
if
(
auto
id
=
(
*
mapper_
)
(
ft
);
id
!=
invalid_type_id
)
{
if
(
auto
i
=
std
::
find
(
types
.
begin
(),
types
.
end
(),
id
);
if
(
auto
i
=
std
::
find
(
types
.
begin
(),
types
.
end
(),
id
);
i
!=
types
.
end
())
{
i
!=
types
.
end
())
{
index
=
static_cast
<
size_t
>
(
std
::
distance
(
types
.
begin
(),
i
));
index
=
static_cast
<
size_t
>
(
std
::
distance
(
types
.
begin
(),
i
));
...
...
libcaf_core/src/json_writer.cpp
View file @
56d43a75
...
@@ -92,7 +92,7 @@ bool json_writer::begin_object(type_id_t id, std::string_view name) {
...
@@ -92,7 +92,7 @@ bool json_writer::begin_object(type_id_t id, std::string_view name) {
add
(
R"_("@type": )_"
);
add
(
R"_("@type": )_"
);
pop
();
pop
();
CAF_ASSERT
(
top
()
==
type
::
element
);
CAF_ASSERT
(
top
()
==
type
::
element
);
if
(
auto
tname
=
query_type_name
(
id
);
!
tname
.
empty
())
{
if
(
auto
tname
=
(
*
mapper_
)
(
id
);
!
tname
.
empty
())
{
add
(
'"'
);
add
(
'"'
);
add
(
tname
);
add
(
tname
);
add
(
'"'
);
add
(
'"'
);
...
@@ -177,12 +177,12 @@ bool json_writer::begin_field(std::string_view name,
...
@@ -177,12 +177,12 @@ bool json_writer::begin_field(std::string_view name,
pop
();
pop
();
CAF_ASSERT
(
top
()
==
type
::
element
);
CAF_ASSERT
(
top
()
==
type
::
element
);
pop
();
pop
();
if
(
auto
tname
=
query_type_name
(
types
[
index
]);
!
tname
.
empty
())
{
if
(
auto
tname
=
(
*
mapper_
)
(
types
[
index
]);
!
tname
.
empty
())
{
add
(
'"'
);
add
(
'"'
);
add
(
tname
);
add
(
tname
);
add
(
'"'
);
add
(
'"'
);
}
else
{
}
else
{
emplace_error
(
sec
::
runtime_error
,
"
query_type_name failed
"
);
emplace_error
(
sec
::
runtime_error
,
"
failed to retrieve type name
"
);
return
false
;
return
false
;
}
}
return
end_key_value_pair
()
&&
begin_field
(
name
);
return
end_key_value_pair
()
&&
begin_field
(
name
);
...
...
libcaf_core/src/timestamp.cpp
View file @
56d43a75
...
@@ -2,8 +2,10 @@
...
@@ -2,8 +2,10 @@
// the main distribution directory for license terms and copyright or visit
// the main distribution directory for license terms and copyright or visit
// https://github.com/actor-framework/actor-framework/blob/master/LICENSE.
// https://github.com/actor-framework/actor-framework/blob/master/LICENSE.
#include "caf/deep_to_string.hpp"
#include "caf/timestamp.hpp"
#include "caf/timestamp.hpp"
#include "caf/deep_to_string.hpp"
#include "caf/detail/parse.hpp"
#include "caf/expected.hpp"
namespace
caf
{
namespace
caf
{
...
@@ -15,6 +17,14 @@ std::string timestamp_to_string(timestamp x) {
...
@@ -15,6 +17,14 @@ std::string timestamp_to_string(timestamp x) {
return
deep_to_string
(
x
.
time_since_epoch
().
count
());
return
deep_to_string
(
x
.
time_since_epoch
().
count
());
}
}
expected
<
timestamp
>
timestamp_from_string
(
std
::
string_view
str
)
{
timestamp
result
;
if
(
auto
err
=
detail
::
parse
(
str
,
result
);
!
err
)
return
result
;
else
return
err
;
}
void
append_timestamp_to_string
(
std
::
string
&
x
,
timestamp
y
)
{
void
append_timestamp_to_string
(
std
::
string
&
x
,
timestamp
y
)
{
x
+=
timestamp_to_string
(
y
);
x
+=
timestamp_to_string
(
y
);
}
}
...
...
libcaf_core/src/type_id.cpp
View file @
56d43a75
...
@@ -22,4 +22,16 @@ type_id_t query_type_id(std::string_view name) {
...
@@ -22,4 +22,16 @@ type_id_t query_type_id(std::string_view name) {
return
invalid_type_id
;
return
invalid_type_id
;
}
}
type_id_mapper
::~
type_id_mapper
()
{
// nop
}
std
::
string_view
default_type_id_mapper
::
operator
()(
type_id_t
type
)
const
{
return
query_type_name
(
type
);
}
type_id_t
default_type_id_mapper
::
operator
()(
std
::
string_view
name
)
const
{
return
query_type_id
(
name
);
}
}
// namespace caf
}
// namespace caf
libcaf_core/test/json_reader.cpp
View file @
56d43a75
...
@@ -12,6 +12,8 @@
...
@@ -12,6 +12,8 @@
using
namespace
caf
;
using
namespace
caf
;
using
namespace
std
::
literals
;
namespace
{
namespace
{
struct
fixture
{
struct
fixture
{
...
@@ -124,4 +126,57 @@ CAF_TEST(json baselines) {
...
@@ -124,4 +126,57 @@ CAF_TEST(json baselines) {
}
}
}
}
SCENARIO
(
"mappers enable custom type names in JSON input"
)
{
GIVEN
(
"a custom mapper"
)
{
class
custom_mapper
:
public
type_id_mapper
{
std
::
string_view
operator
()(
type_id_t
type
)
const
override
{
switch
(
type
)
{
case
type_id_v
<
std
:
:
string
>:
return
"String"
;
case
type_id_v
<
int32_t
>
:
return
"Int"
;
default:
return
query_type_name
(
type
);
}
}
type_id_t
operator
()(
std
::
string_view
name
)
const
override
{
if
(
name
==
"String"
)
return
type_id_v
<
std
::
string
>
;
else
if
(
name
==
"Int"
)
return
type_id_v
<
int32_t
>
;
else
return
query_type_id
(
name
);
}
};
custom_mapper
mapper_instance
;
WHEN
(
"reading a variant from JSON"
)
{
using
value_type
=
std
::
variant
<
int32_t
,
std
::
string
>
;
THEN
(
"the custom mapper translates between external and internal names"
)
{
json_reader
reader
;
reader
.
mapper
(
&
mapper_instance
);
auto
value
=
value_type
{};
auto
input1
=
R"_({"@value-type": "String", "value": "hello world"})_"
s
;
if
(
CHECK
(
reader
.
load
(
input1
)))
{
if
(
!
CHECK
(
reader
.
apply
(
value
)))
MESSAGE
(
"reader reported error: "
<<
reader
.
get_error
());
if
(
CHECK
(
std
::
holds_alternative
<
std
::
string
>
(
value
)))
CHECK_EQ
(
std
::
get
<
std
::
string
>
(
value
),
"hello world"
s
);
}
else
{
MESSAGE
(
"reader reported error: "
<<
reader
.
get_error
());
}
reader
.
reset
();
auto
input2
=
R"_({"@value-type": "Int", "value": 42})_"
sv
;
if
(
CHECK
(
reader
.
load
(
input2
)))
{
if
(
!
CHECK
(
reader
.
apply
(
value
)))
MESSAGE
(
"reader reported error: "
<<
reader
.
get_error
());
if
(
CHECK
(
std
::
holds_alternative
<
int32_t
>
(
value
)))
CHECK_EQ
(
std
::
get
<
int32_t
>
(
value
),
42
);
}
else
{
MESSAGE
(
"reader reported error: "
<<
reader
.
get_error
());
}
}
}
}
}
END_FIXTURE_SCOPE
()
END_FIXTURE_SCOPE
()
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