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
afb884bb
Unverified
Commit
afb884bb
authored
Feb 14, 2019
by
Joseph Noir
Committed by
GitHub
Feb 14, 2019
Browse files
Options
Browse Files
Download
Plain Diff
Merge pull request #818
Re-implement container-based binary serializers
parents
d208f93c
d04f510a
Changes
12
Show whitespace changes
Inline
Side-by-side
Showing
12 changed files
with
878 additions
and
272 deletions
+878
-272
libcaf_core/CMakeLists.txt
libcaf_core/CMakeLists.txt
+2
-0
libcaf_core/caf/all.hpp
libcaf_core/caf/all.hpp
+2
-0
libcaf_core/caf/binary_deserializer.hpp
libcaf_core/caf/binary_deserializer.hpp
+73
-6
libcaf_core/caf/binary_serializer.hpp
libcaf_core/caf/binary_serializer.hpp
+85
-6
libcaf_core/caf/data_processor.hpp
libcaf_core/caf/data_processor.hpp
+34
-31
libcaf_core/caf/detail/select_integer_type.hpp
libcaf_core/caf/detail/select_integer_type.hpp
+13
-10
libcaf_core/caf/stream_deserializer.hpp
libcaf_core/caf/stream_deserializer.hpp
+86
-73
libcaf_core/caf/stream_serializer.hpp
libcaf_core/caf/stream_serializer.hpp
+71
-55
libcaf_core/src/binary_deserializer.cpp
libcaf_core/src/binary_deserializer.cpp
+196
-0
libcaf_core/src/binary_serializer.cpp
libcaf_core/src/binary_serializer.cpp
+187
-0
libcaf_core/test/serialization.cpp
libcaf_core/test/serialization.cpp
+119
-75
libcaf_io/src/instance.cpp
libcaf_io/src/instance.cpp
+10
-16
No files found.
libcaf_core/CMakeLists.txt
View file @
afb884bb
...
...
@@ -30,6 +30,8 @@ set(LIBCAF_CORE_SRCS
src/behavior.cpp
src/behavior_impl.cpp
src/behavior_stack.cpp
src/binary_deserializer.cpp
src/binary_serializer.cpp
src/blocking_actor.cpp
src/blocking_behavior.cpp
src/chars.cpp
...
...
libcaf_core/caf/all.hpp
View file @
afb884bb
...
...
@@ -93,12 +93,14 @@
#include "caf/composed_behavior.hpp"
#include "caf/event_based_actor.hpp"
#include "caf/primitive_variant.hpp"
#include "caf/stream_serializer.hpp"
#include "caf/make_config_option.hpp"
#include "caf/timeout_definition.hpp"
#include "caf/actor_system_config.hpp"
#include "caf/binary_deserializer.hpp"
#include "caf/composable_behavior.hpp"
#include "caf/config_option_adder.hpp"
#include "caf/stream_deserializer.hpp"
#include "caf/typed_actor_pointer.hpp"
#include "caf/scoped_execution_unit.hpp"
#include "caf/typed_response_promise.hpp"
...
...
libcaf_core/caf/binary_deserializer.hpp
View file @
afb884bb
...
...
@@ -18,14 +18,81 @@
#pragma once
#include "caf/stream_deserializer.hpp"
#include "caf/streambuf.hpp"
#include <cstddef>
#include <cstdint>
#include <vector>
#include "caf/deserializer.hpp"
namespace
caf
{
/// A stream serializer that writes into an unbounded contiguous character
/// sequence.
using
binary_deserializer
=
stream_deserializer
<
charbuf
>
;
/// Implements the deserializer interface with a binary serialization protocol.
class
binary_deserializer
final
:
public
deserializer
{
public:
// -- member types -----------------------------------------------------------
}
// namespace caf
using
super
=
deserializer
;
using
buffer
=
std
::
vector
<
char
>
;
// -- constructors, destructors, and assignment operators --------------------
binary_deserializer
(
actor_system
&
sys
,
const
char
*
buf
,
size_t
buf_size
);
binary_deserializer
(
execution_unit
*
ctx
,
const
char
*
buf
,
size_t
buf_size
);
binary_deserializer
(
actor_system
&
sys
,
const
buffer
&
buf
);
binary_deserializer
(
execution_unit
*
ctx
,
const
buffer
&
buf
);
// -- overridden member functions --------------------------------------------
error
begin_object
(
uint16_t
&
typenr
,
std
::
string
&
name
)
override
;
error
end_object
()
override
;
error
begin_sequence
(
size_t
&
list_size
)
override
;
error
end_sequence
()
override
;
error
apply_raw
(
size_t
num_bytes
,
void
*
data
)
override
;
protected:
error
apply_impl
(
int8_t
&
)
override
;
error
apply_impl
(
uint8_t
&
)
override
;
error
apply_impl
(
int16_t
&
)
override
;
error
apply_impl
(
uint16_t
&
)
override
;
error
apply_impl
(
int32_t
&
)
override
;
error
apply_impl
(
uint32_t
&
)
override
;
error
apply_impl
(
int64_t
&
)
override
;
error
apply_impl
(
uint64_t
&
)
override
;
error
apply_impl
(
float
&
)
override
;
error
apply_impl
(
double
&
)
override
;
error
apply_impl
(
long
double
&
)
override
;
error
apply_impl
(
std
::
string
&
)
override
;
error
apply_impl
(
std
::
u16string
&
)
override
;
error
apply_impl
(
std
::
u32string
&
)
override
;
private:
bool
range_check
(
size_t
read_size
)
{
return
pos_
+
read_size
<=
end_
;
}
const
char
*
pos_
;
const
char
*
end_
;
};
}
// namespace caf
libcaf_core/caf/binary_serializer.hpp
View file @
afb884bb
...
...
@@ -18,14 +18,93 @@
#pragma once
#include "caf/stream_serializer.hpp"
#include "caf/streambuf.hpp"
#include <cstddef>
#include <cstdint>
#include <vector>
#include "caf/serializer.hpp"
namespace
caf
{
/// A stream serializer that writes into an unbounded contiguous character
/// sequence.
using
binary_serializer
=
stream_serializer
<
vectorbuf
>
;
/// Implements the serializer interface with a binary serialization protocol.
class
binary_serializer
final
:
public
serializer
{
public:
// -- member types -----------------------------------------------------------
}
// namespace caf
using
super
=
serializer
;
using
buffer
=
std
::
vector
<
char
>
;
// -- constructors, destructors, and assignment operators --------------------
binary_serializer
(
actor_system
&
sys
,
buffer
&
buf
);
binary_serializer
(
execution_unit
*
ctx
,
buffer
&
buf
);
// -- position management ----------------------------------------------------
/// Sets the write position to given offset.
/// @pre `offset <= buf.size()`
void
seek
(
size_t
offset
);
/// Jumps `num_bytes` forward. Resizes the buffer (filling it with zeros)
/// when skipping past the end.
void
skip
(
size_t
num_bytes
);
// -- overridden member functions --------------------------------------------
error
begin_object
(
uint16_t
&
typenr
,
std
::
string
&
name
)
override
;
error
end_object
()
override
;
error
begin_sequence
(
size_t
&
list_size
)
override
;
error
end_sequence
()
override
;
error
apply_raw
(
size_t
num_bytes
,
void
*
data
)
override
;
// -- properties -------------------------------------------------------------
buffer
&
buf
()
{
return
buf_
;
}
const
buffer
&
buf
()
const
{
return
buf_
;
}
protected:
error
apply_impl
(
int8_t
&
)
override
;
error
apply_impl
(
uint8_t
&
)
override
;
error
apply_impl
(
int16_t
&
)
override
;
error
apply_impl
(
uint16_t
&
)
override
;
error
apply_impl
(
int32_t
&
)
override
;
error
apply_impl
(
uint32_t
&
)
override
;
error
apply_impl
(
int64_t
&
)
override
;
error
apply_impl
(
uint64_t
&
)
override
;
error
apply_impl
(
float
&
)
override
;
error
apply_impl
(
double
&
)
override
;
error
apply_impl
(
long
double
&
)
override
;
error
apply_impl
(
std
::
string
&
)
override
;
error
apply_impl
(
std
::
u16string
&
)
override
;
error
apply_impl
(
std
::
u32string
&
)
override
;
private:
buffer
&
buf_
;
buffer
::
iterator
write_pos_
;
};
}
// namespace caf
libcaf_core/caf/data_processor.hpp
View file @
afb884bb
...
...
@@ -73,24 +73,6 @@ public:
std
::
u32string
>
;
/// List of builtin types for data processors as enum.
enum
builtin
{
i8_v
,
u8_v
,
i16_v
,
u16_v
,
i32_v
,
u32_v
,
i64_v
,
u64_v
,
float_v
,
double_v
,
ldouble_v
,
string8_v
,
string16_v
,
string32_v
};
// -- constructors, destructors, and assignment operators --------------------
data_processor
(
const
data_processor
&
)
=
delete
;
...
...
@@ -137,7 +119,7 @@ public:
apply
(
T
&
x
)
{
static
constexpr
auto
tlindex
=
detail
::
tl_index_of
<
builtin_t
,
T
>::
value
;
static_assert
(
tlindex
>=
0
,
"T not recognized as builtin type"
);
return
apply_
builtin
(
static_cast
<
builtin
>
(
tlindex
),
&
x
);
return
apply_
impl
(
x
);
}
template
<
class
T
>
...
...
@@ -147,25 +129,21 @@ public:
error
>::
type
apply
(
T
&
x
)
{
using
type
=
typename
detail
::
select_integer_type
<
static_cast
<
int
>
(
sizeof
(
T
))
*
(
std
::
is_signed
<
T
>::
value
?
-
1
:
1
)
>::
type
;
static
constexpr
auto
tlindex
=
detail
::
tl_index_of
<
builtin_t
,
type
>::
value
;
static_assert
(
tlindex
>=
0
,
"T not recognized as builtin type"
);
return
apply_builtin
(
static_cast
<
builtin
>
(
tlindex
),
&
x
);
using
type
=
detail
::
select_integer_type_t
<
sizeof
(
T
),
std
::
is_signed
<
T
>::
value
>
;
return
apply_impl
(
reinterpret_cast
<
type
&>
(
x
));
}
error
apply
(
std
::
string
&
x
)
{
return
apply_
builtin
(
string8_v
,
&
x
);
return
apply_
impl
(
x
);
}
error
apply
(
std
::
u16string
&
x
)
{
return
apply_
builtin
(
string16_v
,
&
x
);
return
apply_
impl
(
x
);
}
error
apply
(
std
::
u32string
&
x
)
{
return
apply_
builtin
(
string32_v
,
&
x
);
return
apply_
impl
(
x
);
}
template
<
class
D
,
atom_value
V
>
...
...
@@ -549,8 +527,33 @@ public:
}
protected
:
/// Applies this processor to a single builtin value.
virtual
error
apply_builtin
(
builtin
in_out_type
,
void
*
in_out
)
=
0
;
virtual
error
apply_impl
(
int8_t
&
)
=
0
;
virtual
error
apply_impl
(
uint8_t
&
)
=
0
;
virtual
error
apply_impl
(
int16_t
&
)
=
0
;
virtual
error
apply_impl
(
uint16_t
&
)
=
0
;
virtual
error
apply_impl
(
int32_t
&
)
=
0
;
virtual
error
apply_impl
(
uint32_t
&
)
=
0
;
virtual
error
apply_impl
(
int64_t
&
)
=
0
;
virtual
error
apply_impl
(
uint64_t
&
)
=
0
;
virtual
error
apply_impl
(
float
&
)
=
0
;
virtual
error
apply_impl
(
double
&
)
=
0
;
virtual
error
apply_impl
(
long
double
&
)
=
0
;
virtual
error
apply_impl
(
std
::
string
&
)
=
0
;
virtual
error
apply_impl
(
std
::
u16string
&
)
=
0
;
virtual
error
apply_impl
(
std
::
u32string
&
)
=
0
;
private
:
template
<
class
T
>
...
...
libcaf_core/caf/detail/select_integer_type.hpp
View file @
afb884bb
...
...
@@ -23,49 +23,52 @@
namespace
caf
{
namespace
detail
{
template
<
int
>
template
<
int
,
bool
>
struct
select_integer_type
;
template
<
>
struct
select_integer_type
<
-
1
>
{
struct
select_integer_type
<
1
,
true
>
{
using
type
=
int8_t
;
};
template
<
>
struct
select_integer_type
<
1
>
{
struct
select_integer_type
<
1
,
false
>
{
using
type
=
uint8_t
;
};
template
<
>
struct
select_integer_type
<
-
2
>
{
struct
select_integer_type
<
2
,
true
>
{
using
type
=
int16_t
;
};
template
<
>
struct
select_integer_type
<
2
>
{
struct
select_integer_type
<
2
,
false
>
{
using
type
=
uint16_t
;
};
template
<
>
struct
select_integer_type
<
-
4
>
{
struct
select_integer_type
<
4
,
true
>
{
using
type
=
int32_t
;
};
template
<
>
struct
select_integer_type
<
4
>
{
struct
select_integer_type
<
4
,
false
>
{
using
type
=
uint32_t
;
};
template
<
>
struct
select_integer_type
<
-
8
>
{
struct
select_integer_type
<
8
,
true
>
{
using
type
=
int64_t
;
};
template
<
>
struct
select_integer_type
<
8
>
{
struct
select_integer_type
<
8
,
false
>
{
using
type
=
uint64_t
;
};
template
<
int
Size
,
bool
IsSigned
>
using
select_integer_type_t
=
typename
select_integer_type
<
Size
,
IsSigned
>::
type
;
}
// namespace detail
}
// namespace caf
libcaf_core/caf/stream_deserializer.hpp
View file @
afb884bb
...
...
@@ -18,22 +18,21 @@
#pragma once
#include <limits>
#include <string>
#include <sstream>
#include <cstddef>
#include <cstdint>
#include <cstring>
#include <iomanip>
#include <limits>
#include <sstream>
#include <stdexcept>
#include <string>
#include <type_traits>
#include "caf/sec.hpp"
#include "caf/logger.hpp"
#include "caf/deserializer.hpp"
#include "caf/detail/ieee_754.hpp"
#include "caf/detail/network_order.hpp"
#include "caf/logger.hpp"
#include "caf/sec.hpp"
namespace
caf
{
...
...
@@ -127,66 +126,82 @@ protected:
return
none
;
}
error
apply_builtin
(
builtin
type
,
void
*
val
)
override
{
CAF_ASSERT
(
val
!=
nullptr
);
switch
(
type
)
{
default:
// i8_v or u8_v
CAF_ASSERT
(
type
==
i8_v
||
type
==
u8_v
);
return
apply_raw
(
sizeof
(
uint8_t
),
val
);
case
i16_v
:
case
u16_v
:
return
apply_int
(
*
reinterpret_cast
<
uint16_t
*>
(
val
));
case
i32_v
:
case
u32_v
:
return
apply_int
(
*
reinterpret_cast
<
uint32_t
*>
(
val
));
case
i64_v
:
case
u64_v
:
return
apply_int
(
*
reinterpret_cast
<
uint64_t
*>
(
val
));
case
float_v
:
return
apply_float
(
*
reinterpret_cast
<
float
*>
(
val
));
case
double_v
:
return
apply_float
(
*
reinterpret_cast
<
double
*>
(
val
));
case
ldouble_v
:
{
// the IEEE-754 conversion does not work for long double
// => fall back to string serialization (even though it sucks)
error
apply_impl
(
int8_t
&
x
)
override
{
return
apply_raw
(
sizeof
(
int8_t
),
&
x
);
}
error
apply_impl
(
uint8_t
&
x
)
override
{
return
apply_raw
(
sizeof
(
uint8_t
),
&
x
);
}
error
apply_impl
(
int16_t
&
x
)
override
{
return
apply_int
(
x
);
}
error
apply_impl
(
uint16_t
&
x
)
override
{
return
apply_int
(
x
);
}
error
apply_impl
(
int32_t
&
x
)
override
{
return
apply_int
(
x
);
}
error
apply_impl
(
uint32_t
&
x
)
override
{
return
apply_int
(
x
);
}
error
apply_impl
(
int64_t
&
x
)
override
{
return
apply_int
(
x
);
}
error
apply_impl
(
uint64_t
&
x
)
override
{
return
apply_int
(
x
);
}
error
apply_impl
(
float
&
x
)
override
{
return
apply_float
(
x
);
}
error
apply_impl
(
double
&
x
)
override
{
return
apply_float
(
x
);
}
error
apply_impl
(
long
double
&
x
)
override
{
// The IEEE-754 conversion does not work for long double
// => fall back to string serialization (even though it sucks).
std
::
string
tmp
;
auto
e
=
apply
(
tmp
);
if
(
e
)
return
e
;
if
(
auto
err
=
apply
(
tmp
))
return
err
;
std
::
istringstream
iss
{
std
::
move
(
tmp
)};
iss
>>
*
reinterpret_cast
<
long
double
*>
(
val
)
;
iss
>>
x
;
return
none
;
}
case
string8_v
:
{
auto
&
str
=
*
reinterpret_cast
<
std
::
string
*>
(
val
);
error
apply_impl
(
std
::
string
&
x
)
override
{
size_t
str_size
;
return
error
::
eval
([
&
]
{
return
begin_sequence
(
str_size
);
},
[
&
]
{
str
.
resize
(
str_size
);
auto
p
=
&
str
[
0
];
auto
data
=
reinterpret_cast
<
char_type
*>
(
p
);
if
(
auto
err
=
begin_sequence
(
str_size
))
return
err
;
x
.
resize
(
str_size
);
auto
s
=
static_cast
<
streamsize
>
(
str_size
);
return
range_check
(
streambuf_
.
sgetn
(
data
,
s
),
str_size
);
},
[
&
]
{
return
end_sequence
();
});
auto
data
=
reinterpret_cast
<
char_type
*>
(
&
x
[
0
]);
if
(
auto
err
=
range_check
(
streambuf_
.
sgetn
(
data
,
s
),
str_size
))
return
err
;
return
end_sequence
();
}
case
string16_v
:
{
auto
&
str
=
*
reinterpret_cast
<
std
::
u16string
*>
(
val
);
str
.
clear
();
size_t
ns
;
return
error
::
eval
([
&
]
{
return
begin_sequence
(
ns
);
},
[
&
]
{
return
fill_range_c
<
uint16_t
>
(
str
,
ns
);
},
error
apply_impl
(
std
::
u16string
&
x
)
override
{
size_t
str_size
;
return
error
::
eval
([
&
]
{
return
begin_sequence
(
str_size
);
},
[
&
]
{
return
fill_range_c
<
uint16_t
>
(
x
,
str_size
);
},
[
&
]
{
return
end_sequence
();
});
}
case
string32_v
:
{
auto
&
str
=
*
reinterpret_cast
<
std
::
u32string
*>
(
val
);
str
.
clear
();
size_t
ns
;
return
error
::
eval
([
&
]
{
return
begin_sequence
(
ns
);
},
[
&
]
{
return
fill_range_c
<
uint32_t
>
(
str
,
ns
);
},
error
apply_impl
(
std
::
u32string
&
x
)
override
{
size_t
str_size
;
return
error
::
eval
([
&
]
{
return
begin_sequence
(
str_size
);
},
[
&
]
{
return
fill_range_c
<
uint32_t
>
(
x
,
str_size
);
},
[
&
]
{
return
end_sequence
();
});
}
}
}
error
range_check
(
std
::
streamsize
got
,
size_t
need
)
{
if
(
got
>=
0
&&
static_cast
<
size_t
>
(
got
)
==
need
)
...
...
@@ -197,20 +212,18 @@ protected:
template
<
class
T
>
error
apply_int
(
T
&
x
)
{
T
tmp
;
auto
e
=
apply_raw
(
sizeof
(
T
),
&
tmp
);
if
(
e
)
return
e
;
x
=
detail
::
from_network_order
(
tmp
);
typename
std
::
make_unsigned
<
T
>::
type
tmp
=
0
;
if
(
auto
err
=
apply_raw
(
sizeof
(
T
),
&
tmp
))
return
err
;
x
=
static_cast
<
T
>
(
detail
::
from_network_order
(
tmp
));
return
none
;
}
template
<
class
T
>
error
apply_float
(
T
&
x
)
{
typename
detail
::
ieee_754_trait
<
T
>::
packed_type
tmp
=
0
;
auto
e
=
apply_int
(
tmp
);
if
(
e
)
return
e
;
if
(
auto
err
=
apply_int
(
tmp
))
return
err
;
x
=
detail
::
unpack754
(
tmp
);
return
none
;
}
...
...
libcaf_core/caf/stream_serializer.hpp
View file @
afb884bb
...
...
@@ -125,65 +125,81 @@ protected:
return
none
;
}
error
apply_builtin
(
builtin
type
,
void
*
val
)
override
{
CAF_ASSERT
(
val
!=
nullptr
);
switch
(
type
)
{
default:
// i8_v or u8_v
CAF_ASSERT
(
type
==
i8_v
||
type
==
u8_v
);
return
apply_raw
(
sizeof
(
uint8_t
),
val
);
case
i16_v
:
case
u16_v
:
return
apply_int
(
*
reinterpret_cast
<
uint16_t
*>
(
val
));
case
i32_v
:
case
u32_v
:
return
apply_int
(
*
reinterpret_cast
<
uint32_t
*>
(
val
));
case
i64_v
:
case
u64_v
:
return
apply_int
(
*
reinterpret_cast
<
uint64_t
*>
(
val
));
case
float_v
:
return
apply_int
(
detail
::
pack754
(
*
reinterpret_cast
<
float
*>
(
val
)));
case
double_v
:
return
apply_int
(
detail
::
pack754
(
*
reinterpret_cast
<
double
*>
(
val
)));
case
ldouble_v
:
{
// the IEEE-754 conversion does not work for long double
// => fall back to string serialization (event though it sucks)
error
apply_impl
(
int8_t
&
x
)
override
{
return
apply_raw
(
sizeof
(
int8_t
),
&
x
);
}
error
apply_impl
(
uint8_t
&
x
)
override
{
return
apply_raw
(
sizeof
(
uint8_t
),
&
x
);
}
error
apply_impl
(
int16_t
&
x
)
override
{
return
apply_int
(
x
);
}
error
apply_impl
(
uint16_t
&
x
)
override
{
return
apply_int
(
x
);
}
error
apply_impl
(
int32_t
&
x
)
override
{
return
apply_int
(
x
);
}
error
apply_impl
(
uint32_t
&
x
)
override
{
return
apply_int
(
x
);
}
error
apply_impl
(
int64_t
&
x
)
override
{
return
apply_int
(
x
);
}
error
apply_impl
(
uint64_t
&
x
)
override
{
return
apply_int
(
x
);
}
error
apply_impl
(
float
&
x
)
override
{
return
apply_int
(
detail
::
pack754
(
x
));
}
error
apply_impl
(
double
&
x
)
override
{
return
apply_int
(
detail
::
pack754
(
x
));
}
error
apply_impl
(
long
double
&
x
)
override
{
// The IEEE-754 conversion does not work for long double
// => fall back to string serialization (event though it sucks).
std
::
ostringstream
oss
;
oss
<<
std
::
setprecision
(
std
::
numeric_limits
<
long
double
>::
digits
)
<<
*
reinterpret_cast
<
long
double
*>
(
val
);
oss
<<
std
::
setprecision
(
std
::
numeric_limits
<
long
double
>::
digits
)
<<
x
;
auto
tmp
=
oss
.
str
();
return
apply
(
tmp
);
}
case
string8_v
:
{
auto
str
=
reinterpret_cast
<
std
::
string
*>
(
val
);
auto
s
=
str
->
size
();
auto
data
=
reinterpret_cast
<
char_type
*>
(
const_cast
<
std
::
string
::
value_type
*>
(
str
->
data
()));
return
error
::
eval
([
&
]
{
return
begin_sequence
(
s
);
},
[
&
]
{
return
apply_raw
(
str
->
size
(),
data
);
},
[
&
]
{
return
end_sequence
();
});
return
apply_impl
(
tmp
);
}
case
string16_v
:
{
auto
str
=
reinterpret_cast
<
std
::
u16string
*>
(
val
);
auto
s
=
str
->
size
();
// the standard does not guarantee that char16_t is exactly 16 bits...
return
error
::
eval
([
&
]
{
return
begin_sequence
(
s
);
},
[
&
]
{
return
consume_range_c
<
uint16_t
>
(
*
str
);
},
error
apply_impl
(
std
::
string
&
x
)
override
{
auto
str_size
=
x
.
size
();
auto
data
=
const_cast
<
char
*>
(
x
.
c_str
());
return
error
::
eval
([
&
]
{
return
begin_sequence
(
str_size
);
},
[
&
]
{
return
apply_raw
(
x
.
size
(),
data
);
},
[
&
]
{
return
end_sequence
();
});
}
case
string32_v
:
{
auto
str
=
reinterpret_cast
<
std
::
u32string
*>
(
val
);
auto
s
=
str
->
size
();
// the standard does not guarantee that char32_t is exactly 32 bits...
return
error
::
eval
([
&
]
{
return
begin_sequence
(
s
);
},
[
&
]
{
return
consume_range_c
<
uint32_t
>
(
*
str
);
},
error
apply_impl
(
std
::
u16string
&
x
)
override
{
auto
str_size
=
x
.
size
();
return
error
::
eval
([
&
]
{
return
begin_sequence
(
str_size
);
},
[
&
]
{
return
consume_range_c
<
uint16_t
>
(
x
);
},
[
&
]
{
return
end_sequence
();
});
}
}
error
apply_impl
(
std
::
u32string
&
x
)
override
{
auto
str_size
=
x
.
size
();
return
error
::
eval
([
&
]
{
return
begin_sequence
(
str_size
);
},
[
&
]
{
return
consume_range_c
<
uint32_t
>
(
x
);
},
[
&
]
{
return
end_sequence
();
});
}
template
<
class
T
>
error
apply_int
(
T
x
)
{
auto
y
=
detail
::
to_network_order
(
x
);
using
unsigned_type
=
typename
std
::
make_unsigned
<
T
>::
type
;
auto
y
=
detail
::
to_network_order
(
static_cast
<
unsigned_type
>
(
x
));
return
apply_raw
(
sizeof
(
T
),
&
y
);
}
...
...
libcaf_core/src/binary_deserializer.cpp
0 → 100644
View file @
afb884bb
/******************************************************************************
* ____ _ _____ *
* / ___| / \ | ___| C++ *
* | | / _ \ | |_ Actor *
* | |___ / ___ \| _| Framework *
* \____/_/ \_|_| *
* *
* Copyright 2011-2018 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. *
******************************************************************************/
#include "caf/binary_deserializer.hpp"
#include <iomanip>
#include <sstream>
#include <type_traits>
#include "caf/detail/ieee_754.hpp"
#include "caf/detail/network_order.hpp"
#include "caf/sec.hpp"
namespace
caf
{
namespace
{
template
<
class
T
>
error
apply_int
(
binary_deserializer
&
bs
,
T
&
x
)
{
typename
std
::
make_unsigned
<
T
>::
type
tmp
;
if
(
auto
err
=
bs
.
apply_raw
(
sizeof
(
T
),
&
tmp
))
return
err
;
x
=
static_cast
<
T
>
(
detail
::
from_network_order
(
tmp
));
return
none
;
}
template
<
class
T
>
error
apply_float
(
binary_deserializer
&
bs
,
T
&
x
)
{
typename
detail
::
ieee_754_trait
<
T
>::
packed_type
tmp
;
if
(
auto
err
=
apply_int
(
bs
,
tmp
))
return
err
;
x
=
detail
::
unpack754
(
tmp
);
return
none
;
}
}
// namespace <anonmyous>
binary_deserializer
::
binary_deserializer
(
actor_system
&
sys
,
const
char
*
buf
,
size_t
buf_size
)
:
super
(
sys
),
pos_
(
buf
),
end_
(
buf
+
buf_size
)
{
// nop
}
binary_deserializer
::
binary_deserializer
(
execution_unit
*
ctx
,
const
char
*
buf
,
size_t
buf_size
)
:
super
(
ctx
),
pos_
(
buf
),
end_
(
buf
+
buf_size
)
{
// nop
}
binary_deserializer
::
binary_deserializer
(
actor_system
&
sys
,
const
buffer
&
buf
)
:
binary_deserializer
(
sys
,
buf
.
data
(),
buf
.
size
())
{
// nop
}
binary_deserializer
::
binary_deserializer
(
execution_unit
*
ctx
,
const
buffer
&
buf
)
:
binary_deserializer
(
ctx
,
buf
.
data
(),
buf
.
size
())
{
// nop
}
error
binary_deserializer
::
begin_object
(
uint16_t
&
nr
,
std
::
string
&
name
)
{
if
(
auto
err
=
apply
(
nr
))
return
err
;
if
(
nr
!=
0
)
return
none
;
return
apply
(
name
);
}
error
binary_deserializer
::
end_object
()
{
return
none
;
}
error
binary_deserializer
::
begin_sequence
(
size_t
&
list_size
)
{
auto
s
=
static_cast
<
uint32_t
>
(
list_size
);
if
(
auto
err
=
apply
(
s
))
return
err
;
list_size
=
s
;
return
none
;
}
error
binary_deserializer
::
end_sequence
()
{
return
none
;
}
error
binary_deserializer
::
apply_raw
(
size_t
num_bytes
,
void
*
storage
)
{
if
(
!
range_check
(
num_bytes
))
return
sec
::
end_of_stream
;
memcpy
(
storage
,
pos_
,
num_bytes
);
pos_
+=
num_bytes
;
return
none
;
}
error
binary_deserializer
::
apply_impl
(
int8_t
&
x
)
{
return
apply_raw
(
sizeof
(
int8_t
),
&
x
);
}
error
binary_deserializer
::
apply_impl
(
uint8_t
&
x
)
{
return
apply_raw
(
sizeof
(
uint8_t
),
&
x
);
}
error
binary_deserializer
::
apply_impl
(
int16_t
&
x
)
{
return
apply_int
(
*
this
,
x
);
}
error
binary_deserializer
::
apply_impl
(
uint16_t
&
x
)
{
return
apply_int
(
*
this
,
x
);
}
error
binary_deserializer
::
apply_impl
(
int32_t
&
x
)
{
return
apply_int
(
*
this
,
x
);
}
error
binary_deserializer
::
apply_impl
(
uint32_t
&
x
)
{
return
apply_int
(
*
this
,
x
);
}
error
binary_deserializer
::
apply_impl
(
int64_t
&
x
)
{
return
apply_int
(
*
this
,
x
);
}
error
binary_deserializer
::
apply_impl
(
uint64_t
&
x
)
{
return
apply_int
(
*
this
,
x
);
}
error
binary_deserializer
::
apply_impl
(
float
&
x
)
{
return
apply_float
(
*
this
,
x
);
}
error
binary_deserializer
::
apply_impl
(
double
&
x
)
{
return
apply_float
(
*
this
,
x
);
}
error
binary_deserializer
::
apply_impl
(
long
double
&
x
)
{
// The IEEE-754 conversion does not work for long double
// => fall back to string serialization (even though it sucks).
std
::
string
tmp
;
if
(
auto
err
=
apply
(
tmp
))
return
err
;
std
::
istringstream
iss
{
std
::
move
(
tmp
)};
iss
>>
x
;
return
none
;
}
error
binary_deserializer
::
apply_impl
(
std
::
string
&
x
)
{
size_t
str_size
;
if
(
auto
err
=
begin_sequence
(
str_size
))
return
err
;
if
(
!
range_check
(
str_size
))
return
sec
::
end_of_stream
;
x
.
assign
(
pos_
,
pos_
+
str_size
);
pos_
+=
str_size
;
return
end_sequence
();
}
error
binary_deserializer
::
apply_impl
(
std
::
u16string
&
x
)
{
auto
str_size
=
x
.
size
();
if
(
auto
err
=
begin_sequence
(
str_size
))
return
err
;
for
(
size_t
i
=
0
;
i
<
str_size
;
++
i
)
{
// The standard does not guarantee that char16_t is exactly 16 bits.
uint16_t
tmp
;
if
(
auto
err
=
apply_int
(
*
this
,
tmp
))
return
err
;
x
.
push_back
(
static_cast
<
char16_t
>
(
tmp
));
}
return
none
;
}
error
binary_deserializer
::
apply_impl
(
std
::
u32string
&
x
)
{
auto
str_size
=
x
.
size
();
if
(
auto
err
=
begin_sequence
(
str_size
))
return
err
;
for
(
size_t
i
=
0
;
i
<
str_size
;
++
i
)
{
// The standard does not guarantee that char32_t is exactly 32 bits.
uint32_t
tmp
;
if
(
auto
err
=
apply_int
(
*
this
,
tmp
))
return
err
;
x
.
push_back
(
static_cast
<
char32_t
>
(
tmp
));
}
return
none
;
}
}
// namespace caf
libcaf_core/src/binary_serializer.cpp
0 → 100644
View file @
afb884bb
/******************************************************************************
* ____ _ _____ *
* / ___| / \ | ___| C++ *
* | | / _ \ | |_ Actor *
* | |___ / ___ \| _| Framework *
* \____/_/ \_|_| *
* *
* Copyright 2011-2018 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. *
******************************************************************************/
#include "caf/binary_serializer.hpp"
#include <cstring>
#include <iomanip>
#include <sstream>
#include "caf/detail/ieee_754.hpp"
#include "caf/detail/network_order.hpp"
namespace
caf
{
namespace
{
template
<
class
T
>
error
apply_int
(
binary_serializer
&
bs
,
T
x
)
{
auto
y
=
detail
::
to_network_order
(
x
);
return
bs
.
apply_raw
(
sizeof
(
T
),
&
y
);
}
}
// namespace <anonmyous>
binary_serializer
::
binary_serializer
(
actor_system
&
sys
,
buffer
&
buf
)
:
super
(
sys
),
buf_
(
buf
),
write_pos_
(
buf
.
end
())
{
// nop
}
binary_serializer
::
binary_serializer
(
execution_unit
*
ctx
,
buffer
&
buf
)
:
super
(
ctx
),
buf_
(
buf
),
write_pos_
(
buf
.
end
())
{
// nop
}
void
binary_serializer
::
seek
(
size_t
offset
)
{
write_pos_
=
buf_
.
begin
()
+
offset
;
}
void
binary_serializer
::
skip
(
size_t
num_bytes
)
{
auto
last
=
buf_
.
end
();
auto
remaining
=
static_cast
<
size_t
>
(
std
::
distance
(
write_pos_
,
last
));
if
(
remaining
>=
num_bytes
)
{
write_pos_
+=
num_bytes
;
}
else
{
buf_
.
insert
(
last
,
num_bytes
-
remaining
,
0
);
write_pos_
=
buf_
.
end
();
}
}
error
binary_serializer
::
begin_object
(
uint16_t
&
nr
,
std
::
string
&
name
)
{
if
(
nr
!=
0
)
return
apply
(
nr
);
if
(
auto
err
=
apply
(
nr
))
return
err
;
return
apply
(
name
);
}
error
binary_serializer
::
end_object
()
{
return
none
;
}
error
binary_serializer
::
begin_sequence
(
size_t
&
list_size
)
{
auto
s
=
static_cast
<
uint32_t
>
(
list_size
);
return
apply
(
s
);
}
error
binary_serializer
::
end_sequence
()
{
return
none
;
}
error
binary_serializer
::
apply_raw
(
size_t
num_bytes
,
void
*
data
)
{
auto
ptr
=
reinterpret_cast
<
char
*>
(
data
);
auto
last
=
buf_
.
end
();
if
(
write_pos_
==
last
)
{
buf_
.
insert
(
last
,
ptr
,
ptr
+
num_bytes
);
write_pos_
=
buf_
.
end
();
}
else
if
(
write_pos_
+
num_bytes
<
last
)
{
memcpy
(
&
(
*
write_pos_
),
ptr
,
num_bytes
);
write_pos_
+=
num_bytes
;
}
else
{
auto
remaining
=
static_cast
<
size_t
>
(
last
-
write_pos_
);
memcpy
(
&
(
*
write_pos_
),
ptr
,
remaining
);
buf_
.
insert
(
last
,
ptr
+
remaining
,
ptr
+
num_bytes
);
write_pos_
=
buf_
.
end
();
}
return
none
;
}
error
binary_serializer
::
apply_impl
(
int8_t
&
x
)
{
return
apply_raw
(
sizeof
(
int8_t
),
&
x
);
}
error
binary_serializer
::
apply_impl
(
uint8_t
&
x
)
{
return
apply_raw
(
sizeof
(
uint8_t
),
&
x
);
}
error
binary_serializer
::
apply_impl
(
int16_t
&
x
)
{
return
apply_int
(
*
this
,
static_cast
<
uint16_t
>
(
x
));
}
error
binary_serializer
::
apply_impl
(
uint16_t
&
x
)
{
return
apply_int
(
*
this
,
x
);
}
error
binary_serializer
::
apply_impl
(
int32_t
&
x
)
{
return
apply_int
(
*
this
,
static_cast
<
uint32_t
>
(
x
));
}
error
binary_serializer
::
apply_impl
(
uint32_t
&
x
)
{
return
apply_int
(
*
this
,
x
);
}
error
binary_serializer
::
apply_impl
(
int64_t
&
x
)
{
return
apply_int
(
*
this
,
static_cast
<
uint64_t
>
(
x
));
}
error
binary_serializer
::
apply_impl
(
uint64_t
&
x
)
{
return
apply_int
(
*
this
,
x
);
}
error
binary_serializer
::
apply_impl
(
float
&
x
)
{
return
apply_int
(
*
this
,
detail
::
pack754
(
x
));
}
error
binary_serializer
::
apply_impl
(
double
&
x
)
{
return
apply_int
(
*
this
,
detail
::
pack754
(
x
));
}
error
binary_serializer
::
apply_impl
(
long
double
&
x
)
{
// The IEEE-754 conversion does not work for long double
// => fall back to string serialization (event though it sucks).
std
::
ostringstream
oss
;
oss
<<
std
::
setprecision
(
std
::
numeric_limits
<
long
double
>::
digits
)
<<
x
;
auto
tmp
=
oss
.
str
();
return
apply_impl
(
tmp
);
}
error
binary_serializer
::
apply_impl
(
std
::
string
&
x
)
{
auto
str_size
=
x
.
size
();
if
(
str_size
==
0
)
return
error
::
eval
([
&
]
{
return
begin_sequence
(
str_size
);
},
[
&
]
{
return
end_sequence
();
});
auto
data
=
const_cast
<
char
*>
(
x
.
c_str
());
return
error
::
eval
([
&
]
{
return
begin_sequence
(
str_size
);
},
[
&
]
{
return
apply_raw
(
str_size
,
data
);
},
[
&
]
{
return
end_sequence
();
});
}
error
binary_serializer
::
apply_impl
(
std
::
u16string
&
x
)
{
auto
str_size
=
x
.
size
();
if
(
auto
err
=
begin_sequence
(
str_size
))
return
err
;
for
(
auto
c
:
x
)
{
// The standard does not guarantee that char16_t is exactly 16 bits.
if
(
auto
err
=
apply_int
(
*
this
,
static_cast
<
uint16_t
>
(
c
)))
return
err
;
}
return
none
;
}
error
binary_serializer
::
apply_impl
(
std
::
u32string
&
x
)
{
auto
str_size
=
x
.
size
();
if
(
auto
err
=
begin_sequence
(
str_size
))
return
err
;
for
(
auto
c
:
x
)
{
// The standard does not guarantee that char16_t is exactly 16 bits.
if
(
auto
err
=
apply_int
(
*
this
,
static_cast
<
uint32_t
>
(
c
)))
return
err
;
}
return
none
;
}
}
// namespace caf
libcaf_core/test/serialization.cpp
View file @
afb884bb
...
...
@@ -21,51 +21,52 @@
#define CAF_SUITE serialization
#include "caf/test/unit_test.hpp"
#include <new>
#include <set>
#include <algorithm>
#include <cassert>
#include <cstdint>
#include <cstring>
#include <functional>
#include <iostream>
#include <iterator>
#include <limits>
#include <list>
#include <stack>
#include <tuple>
#include <locale>
#include <memory>
#include <string>
#include <limits>
#include <vector>
#include <cstring>
#include <new>
#include <set>
#include <sstream>
#include <cstdint>
#include <cstring>
#include <cassert>
#include <iterator>
#include <typeinfo>
#include <iostream>
#include <stack>
#include <stdexcept>
#include <
algorithm
>
#include <
functional
>
#include <
string
>
#include <
tuple
>
#include <type_traits>
#include <typeinfo>
#include <vector>
#include "caf/message.hpp"
#include "caf/streambuf.hpp"
#include "caf/serializer.hpp"
#include "caf/ref_counted.hpp"
#include "caf/deserializer.hpp"
#include "caf/actor_system.hpp"
#include "caf/proxy_registry.hpp"
#include "caf/message_handler.hpp"
#include "caf/event_based_actor.hpp"
#include "caf/primitive_variant.hpp"
#include "caf/binary_serializer.hpp"
#include "caf/binary_deserializer.hpp"
#include "caf/actor_system_config.hpp"
#include "caf/make_type_erased_view.hpp"
#include "caf/binary_deserializer.hpp"
#include "caf/binary_serializer.hpp"
#include "caf/deserializer.hpp"
#include "caf/event_based_actor.hpp"
#include "caf/make_type_erased_tuple_view.hpp"
#include "caf/make_type_erased_view.hpp"
#include "caf/message.hpp"
#include "caf/message_handler.hpp"
#include "caf/primitive_variant.hpp"
#include "caf/proxy_registry.hpp"
#include "caf/ref_counted.hpp"
#include "caf/serializer.hpp"
#include "caf/stream_deserializer.hpp"
#include "caf/stream_serializer.hpp"
#include "caf/streambuf.hpp"
#include "caf/detail/enum_to_string.hpp"
#include "caf/detail/get_mac_addresses.hpp"
#include "caf/detail/ieee_754.hpp"
#include "caf/detail/int_list.hpp"
#include "caf/detail/safe_equal.hpp"
#include "caf/detail/type_traits.hpp"
#include "caf/detail/enum_to_string.hpp"
#include "caf/detail/get_mac_addresses.hpp"
using
namespace
std
;
using
namespace
caf
;
...
...
@@ -138,6 +139,7 @@ public:
}
};
template
<
class
Serializer
,
class
Deserializer
>
struct
fixture
{
int32_t
i32
=
-
345
;
int64_t
i64
=
-
1234567890123456789ll
;
...
...
@@ -159,21 +161,25 @@ struct fixture {
config
cfg
;
actor_system
system
;
scoped_execution_unit
context
;
message
msg
;
message
recursive
;
template
<
class
T
,
class
...
Ts
>
vector
<
char
>
serialize
(
T
&
x
,
Ts
&
...
xs
)
{
vector
<
char
>
buf
;
binary_serializer
bs
{
&
context
,
buf
};
bs
(
x
,
xs
...);
binary_serializer
sink
{
system
,
buf
};
if
(
auto
err
=
sink
(
x
,
xs
...))
CAF_FAIL
(
"serialization failed: "
<<
system
.
render
(
err
)
<<
", data: "
<<
deep_to_string
(
std
::
forward_as_tuple
(
x
,
xs
...)));
return
buf
;
}
template
<
class
T
,
class
...
Ts
>
void
deserialize
(
const
vector
<
char
>&
buf
,
T
&
x
,
Ts
&
...
xs
)
{
binary_deserializer
bd
{
&
context
,
buf
};
bd
(
x
,
xs
...);
binary_deserializer
source
{
system
,
buf
};
if
(
auto
err
=
source
(
x
,
xs
...))
CAF_FAIL
(
"deserialization failed: "
<<
system
.
render
(
err
));
}
// serializes `x` and then deserializes and returns the serialized value
...
...
@@ -191,15 +197,20 @@ struct fixture {
message
result
;
auto
tmp
=
make_message
(
x
);
deserialize
(
serialize
(
tmp
),
result
);
CAF_REQUIRE
(
result
.
match_elements
<
T
>
());
if
(
!
result
.
match_elements
<
T
>
())
CAF_FAIL
(
"expected: "
<<
x
<<
", got: "
<<
result
);
return
result
.
get_as
<
T
>
(
0
);
}
fixture
()
:
system
(
cfg
),
context
(
&
system
)
{
fixture
()
:
system
(
cfg
)
{
rs
.
str
.
assign
(
string
(
str
.
rbegin
(),
str
.
rend
()));
msg
=
make_message
(
i32
,
i64
,
dur
,
ts
,
te
,
str
,
rs
);
config_value
::
dictionary
dict
;
put
(
dict
,
"scheduler.policy"
,
atom
(
"none"
));
put
(
dict
,
"scheduler.max-threads"
,
42
);
put
(
dict
,
"nodes.preload"
,
make_config_value_list
(
"sun"
,
"venus"
,
"mercury"
,
"earth"
,
"mars"
));
recursive
=
make_message
(
config_value
{
std
::
move
(
dict
)});
}
};
...
...
@@ -227,9 +238,43 @@ struct is_message {
}
// namespace <anonymous>
CAF_TEST_FIXTURE_SCOPE
(
serialization_tests
,
fixture
)
CAF_TEST
(
ieee_754_conversion
)
{
#define SERIALIZATION_TEST(name) \
template <class Serializer, class Deserializer> \
struct name##_tpl : fixture<Serializer, Deserializer> { \
using super = fixture<Serializer, Deserializer>; \
using super::i32; \
using super::i64; \
using super::f32; \
using super::f64; \
using super::dur; \
using super::ts; \
using super::te; \
using super::str; \
using super::rs; \
using super::ta; \
using super::ra; \
using super::system; \
using super::msg; \
using super::recursive; \
using super::serialize; \
using super::deserialize; \
using super::roundtrip; \
using super::msg_roundtrip; \
void run_test_impl(); \
}; \
namespace { \
using name##_binary = name##_tpl<binary_serializer, binary_deserializer>; \
using name##_stream = name##_tpl<stream_serializer<vectorbuf>, \
stream_deserializer<charbuf>>; \
::caf::test::detail::adder<::caf::test::test_impl<name##_binary>> \
CAF_UNIQUE(a_binary){CAF_XSTR(CAF_SUITE), CAF_XSTR(name##_binary), false}; \
::caf::test::detail::adder<::caf::test::test_impl<name##_stream>> \
CAF_UNIQUE(a_stream){CAF_XSTR(CAF_SUITE), CAF_XSTR(name##_stream), false}; \
} \
template <class Serializer, class Deserializer> \
void name##_tpl<Serializer, Deserializer>::run_test_impl()
SERIALIZATION_TEST
(
ieee_754_conversion
)
{
// check conversion of float
float
f1
=
3.1415925
f
;
// float value
auto
p1
=
caf
::
detail
::
pack754
(
f1
);
// packet value
...
...
@@ -244,70 +289,70 @@ CAF_TEST(ieee_754_conversion) {
CAF_CHECK_EQUAL
(
f2
,
u2
);
}
CAF
_TEST
(
i32_values
)
{
SERIALIZATION
_TEST
(
i32_values
)
{
auto
buf
=
serialize
(
i32
);
int32_t
x
;
deserialize
(
buf
,
x
);
CAF_CHECK_EQUAL
(
i32
,
x
);
}
CAF
_TEST
(
i64_values
)
{
SERIALIZATION
_TEST
(
i64_values
)
{
auto
buf
=
serialize
(
i64
);
int64_t
x
;
deserialize
(
buf
,
x
);
CAF_CHECK_EQUAL
(
i64
,
x
);
}
CAF
_TEST
(
float_values
)
{
SERIALIZATION
_TEST
(
float_values
)
{
auto
buf
=
serialize
(
f32
);
float
x
;
deserialize
(
buf
,
x
);
CAF_CHECK_EQUAL
(
f32
,
x
);
}
CAF
_TEST
(
double_values
)
{
SERIALIZATION
_TEST
(
double_values
)
{
auto
buf
=
serialize
(
f64
);
double
x
;
deserialize
(
buf
,
x
);
CAF_CHECK_EQUAL
(
f64
,
x
);
}
CAF
_TEST
(
duration_values
)
{
SERIALIZATION
_TEST
(
duration_values
)
{
auto
buf
=
serialize
(
dur
);
duration
x
;
deserialize
(
buf
,
x
);
CAF_CHECK_EQUAL
(
dur
,
x
);
}
CAF
_TEST
(
timestamp_values
)
{
SERIALIZATION
_TEST
(
timestamp_values
)
{
auto
buf
=
serialize
(
ts
);
timestamp
x
;
deserialize
(
buf
,
x
);
CAF_CHECK_EQUAL
(
ts
,
x
);
}
CAF
_TEST
(
enum_classes
)
{
SERIALIZATION
_TEST
(
enum_classes
)
{
auto
buf
=
serialize
(
te
);
test_enum
x
;
deserialize
(
buf
,
x
);
CAF_CHECK_EQUAL
(
te
,
x
);
}
CAF
_TEST
(
strings
)
{
SERIALIZATION
_TEST
(
strings
)
{
auto
buf
=
serialize
(
str
);
string
x
;
deserialize
(
buf
,
x
);
CAF_CHECK_EQUAL
(
str
,
x
);
}
CAF
_TEST
(
custom_struct
)
{
SERIALIZATION
_TEST
(
custom_struct
)
{
auto
buf
=
serialize
(
rs
);
raw_struct
x
;
deserialize
(
buf
,
x
);
CAF_CHECK_EQUAL
(
rs
,
x
);
}
CAF
_TEST
(
atoms
)
{
SERIALIZATION
_TEST
(
atoms
)
{
auto
foo
=
atom
(
"foo"
);
CAF_CHECK_EQUAL
(
foo
,
roundtrip
(
foo
));
CAF_CHECK_EQUAL
(
foo
,
msg_roundtrip
(
foo
));
...
...
@@ -316,7 +361,7 @@ CAF_TEST(atoms) {
CAF_CHECK_EQUAL
(
bar_atom
::
value
,
msg_roundtrip
(
atom
(
"bar"
)));
}
CAF
_TEST
(
raw_arrays
)
{
SERIALIZATION
_TEST
(
raw_arrays
)
{
auto
buf
=
serialize
(
ra
);
int
x
[
3
];
deserialize
(
buf
,
x
);
...
...
@@ -324,7 +369,7 @@ CAF_TEST(raw_arrays) {
CAF_CHECK_EQUAL
(
ra
[
i
],
x
[
i
]);
}
CAF
_TEST
(
arrays
)
{
SERIALIZATION
_TEST
(
arrays
)
{
auto
buf
=
serialize
(
ta
);
test_array
x
;
deserialize
(
buf
,
x
);
...
...
@@ -335,7 +380,7 @@ CAF_TEST(arrays) {
CAF_CHECK_EQUAL
(
ta
.
value2
[
i
][
j
],
x
.
value2
[
i
][
j
]);
}
CAF
_TEST
(
empty_non_pods
)
{
SERIALIZATION
_TEST
(
empty_non_pods
)
{
test_empty_non_pod
x
;
auto
buf
=
serialize
(
x
);
CAF_REQUIRE
(
buf
.
empty
());
...
...
@@ -354,7 +399,7 @@ std::string hexstr(const std::vector<char>& buf) {
return
oss
.
str
();
}
CAF
_TEST
(
messages
)
{
SERIALIZATION
_TEST
(
messages
)
{
// serialize original message which uses tuple_vals internally and
// deserialize into a message which uses type_erased_value pointers
message
x
;
...
...
@@ -369,9 +414,10 @@ CAF_TEST(messages) {
deserialize
(
buf2
,
y
);
CAF_CHECK_EQUAL
(
to_string
(
msg
),
to_string
(
y
));
CAF_CHECK
(
is_message
(
y
).
equal
(
i32
,
i64
,
dur
,
ts
,
te
,
str
,
rs
));
CAF_CHECK_EQUAL
(
to_string
(
recursive
),
to_string
(
roundtrip
(
recursive
)));
}
CAF
_TEST
(
multiple_messages
)
{
SERIALIZATION
_TEST
(
multiple_messages
)
{
auto
m
=
make_message
(
rs
,
te
);
auto
buf
=
serialize
(
te
,
m
,
msg
);
test_enum
t
;
...
...
@@ -385,15 +431,15 @@ CAF_TEST(multiple_messages) {
}
CAF
_TEST
(
type_erased_value
)
{
SERIALIZATION
_TEST
(
type_erased_value
)
{
auto
buf
=
serialize
(
str
);
type_erased_value_ptr
ptr
{
new
type_erased_value_impl
<
std
::
string
>
};
binary_deserializer
bd
{
&
context
,
buf
.
data
(),
buf
.
size
()
};
ptr
->
load
(
bd
);
binary_deserializer
source
{
system
,
buf
};
ptr
->
load
(
source
);
CAF_CHECK_EQUAL
(
str
,
*
reinterpret_cast
<
const
std
::
string
*>
(
ptr
->
get
()));
}
CAF
_TEST
(
type_erased_view
)
{
SERIALIZATION
_TEST
(
type_erased_view
)
{
auto
str_view
=
make_type_erased_view
(
str
);
auto
buf
=
serialize
(
str_view
);
std
::
string
res
;
...
...
@@ -401,7 +447,7 @@ CAF_TEST(type_erased_view) {
CAF_CHECK_EQUAL
(
str
,
res
);
}
CAF
_TEST
(
type_erased_tuple
)
{
SERIALIZATION
_TEST
(
type_erased_tuple
)
{
auto
tview
=
make_type_erased_tuple_view
(
str
,
i32
);
CAF_CHECK_EQUAL
(
to_string
(
tview
),
deep_to_string
(
std
::
make_tuple
(
str
,
i32
)));
auto
buf
=
serialize
(
tview
);
...
...
@@ -415,7 +461,7 @@ CAF_TEST(type_erased_tuple) {
CAF_CHECK_EQUAL
(
to_string
(
tview
),
deep_to_string
(
std
::
make_tuple
(
str
,
i32
)));
}
CAF
_TEST
(
streambuf_serialization
)
{
SERIALIZATION
_TEST
(
streambuf_serialization
)
{
auto
data
=
std
::
string
{
"The quick brown fox jumps over the lazy dog"
};
std
::
vector
<
char
>
buf
;
// First, we check the standard use case in CAF where stream serializers own
...
...
@@ -443,7 +489,7 @@ CAF_TEST(streambuf_serialization) {
CAF_CHECK
(
data
==
target
);
}
CAF
_TEST
(
byte_sequence_optimization
)
{
SERIALIZATION
_TEST
(
byte_sequence_optimization
)
{
std
::
vector
<
uint8_t
>
data
(
42
);
std
::
fill
(
data
.
begin
(),
data
.
end
(),
0x2a
);
std
::
vector
<
uint8_t
>
buf
;
...
...
@@ -462,7 +508,7 @@ CAF_TEST(byte_sequence_optimization) {
[](
uint8_t
c
)
{
return
c
==
0x2a
;
}));
}
CAF
_TEST
(
long_sequences
)
{
SERIALIZATION
_TEST
(
long_sequences
)
{
std
::
vector
<
char
>
data
;
binary_serializer
sink
{
nullptr
,
data
};
size_t
n
=
std
::
numeric_limits
<
uint32_t
>::
max
();
...
...
@@ -475,7 +521,7 @@ CAF_TEST(long_sequences) {
CAF_CHECK_EQUAL
(
n
,
m
);
}
CAF_TEST
(
non
-
empty
vector
)
{
SERIALIZATION_TEST
(
non_empty_
vector
)
{
CAF_MESSAGE
(
"deserializing into a non-empty vector overrides any content"
);
std
::
vector
<
int
>
foo
{
1
,
2
,
3
};
std
::
vector
<
int
>
bar
{
0
};
...
...
@@ -487,21 +533,21 @@ CAF_TEST(non-empty vector) {
// -- our vector<bool> serialization packs into an uint64_t. Hence, the
// critical sizes to test are 0, 1, 63, 64, and 65.
CAF
_TEST
(
bool_vector_size_0
)
{
SERIALIZATION
_TEST
(
bool_vector_size_0
)
{
std
::
vector
<
bool
>
xs
;
CAF_CHECK_EQUAL
(
deep_to_string
(
xs
),
"[]"
);
CAF_CHECK_EQUAL
(
xs
,
roundtrip
(
xs
));
CAF_CHECK_EQUAL
(
xs
,
msg_roundtrip
(
xs
));
}
CAF
_TEST
(
bool_vector_size_1
)
{
SERIALIZATION
_TEST
(
bool_vector_size_1
)
{
std
::
vector
<
bool
>
xs
{
true
};
CAF_CHECK_EQUAL
(
deep_to_string
(
xs
),
"[1]"
);
CAF_CHECK_EQUAL
(
xs
,
roundtrip
(
xs
));
CAF_CHECK_EQUAL
(
xs
,
msg_roundtrip
(
xs
));
}
CAF
_TEST
(
bool_vector_size_63
)
{
SERIALIZATION
_TEST
(
bool_vector_size_63
)
{
std
::
vector
<
bool
>
xs
;
for
(
int
i
=
0
;
i
<
63
;
++
i
)
xs
.
push_back
(
i
%
3
==
0
);
...
...
@@ -514,7 +560,7 @@ CAF_TEST(bool_vector_size_63) {
CAF_CHECK_EQUAL
(
xs
,
msg_roundtrip
(
xs
));
}
CAF
_TEST
(
bool_vector_size_64
)
{
SERIALIZATION
_TEST
(
bool_vector_size_64
)
{
std
::
vector
<
bool
>
xs
;
for
(
int
i
=
0
;
i
<
64
;
++
i
)
xs
.
push_back
(
i
%
5
==
0
);
...
...
@@ -527,7 +573,7 @@ CAF_TEST(bool_vector_size_64) {
CAF_CHECK_EQUAL
(
xs
,
msg_roundtrip
(
xs
));
}
CAF
_TEST
(
bool_vector_size_65
)
{
SERIALIZATION
_TEST
(
bool_vector_size_65
)
{
std
::
vector
<
bool
>
xs
;
for
(
int
i
=
0
;
i
<
65
;
++
i
)
xs
.
push_back
(
!
(
i
%
7
==
0
));
...
...
@@ -539,5 +585,3 @@ CAF_TEST(bool_vector_size_65) {
CAF_CHECK_EQUAL
(
xs
,
roundtrip
(
xs
));
CAF_CHECK_EQUAL
(
xs
,
msg_roundtrip
(
xs
));
}
CAF_TEST_FIXTURE_SCOPE_END
()
libcaf_io/src/instance.cpp
View file @
afb884bb
...
...
@@ -198,24 +198,18 @@ bool instance::dispatch(execution_unit* ctx, const strong_actor_ptr& sender,
void
instance
::
write
(
execution_unit
*
ctx
,
buffer_type
&
buf
,
header
&
hdr
,
payload_writer
*
pw
)
{
CAF_LOG_TRACE
(
CAF_ARG
(
hdr
));
error
err
;
binary_serializer
sink
{
ctx
,
buf
}
;
if
(
pw
!=
nullptr
)
{
auto
pos
=
buf
.
size
();
// write payload first (skip first 72 bytes and write header later)
char
placeholder
[
basp
::
header_size
];
buf
.
insert
(
buf
.
end
(),
std
::
begin
(
placeholder
),
std
::
end
(
placeholder
));
binary_serializer
bs
{
ctx
,
buf
};
(
*
pw
)(
bs
);
auto
plen
=
buf
.
size
()
-
pos
-
basp
::
header_size
;
CAF_ASSERT
(
plen
<=
std
::
numeric_limits
<
uint32_t
>::
max
());
hdr
.
payload_len
=
static_cast
<
uint32_t
>
(
plen
);
stream_serializer
<
charbuf
>
out
{
ctx
,
buf
.
data
()
+
pos
,
basp
::
header_size
};
err
=
out
(
hdr
);
}
else
{
binary_serializer
bs
{
ctx
,
buf
};
err
=
bs
(
hdr
);
// Write the BASP header after the payload.
auto
header_offset
=
buf
.
size
();
sink
.
skip
(
header_size
);
if
(
auto
err
=
(
*
pw
)(
sink
))
CAF_LOG_ERROR
(
CAF_ARG
(
err
));
sink
.
seek
(
header_offset
);
auto
payload_len
=
buf
.
size
()
-
(
header_offset
+
basp
::
header_size
);
hdr
.
payload_len
=
static_cast
<
uint32_t
>
(
payload_len
);
}
if
(
err
)
if
(
auto
err
=
sink
(
hdr
)
)
CAF_LOG_ERROR
(
CAF_ARG
(
err
));
}
...
...
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