Commit 95f22c6e authored by Jan Koniarik's avatar Jan Koniarik
Browse files

refactored internals of rptocool lib for speed improvements

parent 97242970
Pipeline #100034 failed with stage
in 1 minute and 1 second
......@@ -13,15 +13,29 @@ namespace emlabcpp
// Strucutre used as result of deserialization in the internal mechanisms of protocol handling.
// Contains parsed value and bounded value of how much bytes were used.
template < bounded_derived size_type, typename T >
template < typename T >
struct protocol_result
{
size_type used;
T val;
};
std::size_t used = 0;
std::variant< T, const protocol_mark* > res;
template < bounded_derived size_type, typename T >
protocol_result( size_type, T ) -> protocol_result< size_type, T >;
protocol_result() = default;
protocol_result( std::size_t u, std::variant< T, const protocol_mark* > v )
: used( u )
, res( v )
{
}
protocol_result( std::size_t u, T v )
: used( u )
, res( v )
{
}
protocol_result( std::size_t u, const protocol_mark* m )
: used( u )
, res( m )
{
}
};
// Concept that matches types considered base - serialized directly by using byte shifting.
template < typename T >
......
......@@ -152,8 +152,8 @@ template <>
struct protocol_decl< protocol_error_record >
{
using value_type = protocol_error_record;
static constexpr std::size_t max_size = 18;
static constexpr std::size_t max_size =
protocol_decl< protocol_mark >::max_size + protocol_decl< std::size_t >::max_size;
};
} // namespace emlabcpp
This diff is collapsed.
......@@ -18,14 +18,8 @@ struct protocol_mark : std::array< char, 16 >
struct protocol_error_record
{
const protocol_mark* err;
uint16_t byte_index;
friend constexpr bool
operator==( const protocol_error_record& lh, const protocol_error_record& rh )
{
return lh.byte_index == rh.byte_index && lh.err == rh.err;
}
protocol_mark mark;
std::size_t offset;
};
// Creates protocol_mark from simple string literal.
......@@ -37,6 +31,7 @@ inline constexpr protocol_mark make_protocol_mark( const char ( &msg )[17] )
return res;
}
static constexpr auto SIZE_ERR = make_protocol_mark( "EMLABCPPSIZE " );
// not enough bytes left in the message for the item
static constexpr auto LOWSIZE_ERR = make_protocol_mark( "EMLABCPPLOWSIZE " );
// too much bytes left in the message for the item
......
......@@ -13,24 +13,31 @@ namespace emlabcpp
template < typename T >
struct protocol_handler
{
using decl = protocol_def< T, PROTOCOL_BIG_ENDIAN >;
using value_type = typename decl::value_type;
using message_type = protocol_message< decl::max_size >;
using def = protocol_def< T, PROTOCOL_BIG_ENDIAN >;
using value_type = typename def::value_type;
using message_type = protocol_message< def::max_size >;
static message_type serialize( value_type val )
{
std::array< uint8_t, decl::max_size > buffer{};
std::array< uint8_t, def::max_size > buffer{};
bounded used = decl::serialize_at( buffer, val );
EMLABCPP_ASSERT( *used <= decl::max_size );
bounded used = def::serialize_at( buffer, val );
EMLABCPP_ASSERT( *used <= def::max_size );
return *message_type::make( view_n( buffer.begin(), *used ) );
};
static either< value_type, protocol_error_record > extract( const message_type& msg )
{
return decl::deserialize( msg ).convert_left( [&]( auto sub_res ) {
return sub_res.val;
} );
auto opt_view = bounded_view< const uint8_t*, typename def::size_type >::make(
view_n( msg.begin(), min( def::max_size, msg.size() ) ) );
if ( !opt_view ) {
return protocol_error_record{ SIZE_ERR, 0 };
}
auto [used, res] = def::deserialize( *opt_view );
if ( std::holds_alternative< const protocol_mark* >( res ) ) {
return protocol_error_record{ *std::get< 1 >( res ), used };
}
return std::get< 0 >( res );
}
};
......
......@@ -49,9 +49,16 @@ struct protocol_register_handler
using def =
protocol_def< typename map_type::reg_def_type< Key >, PROTOCOL_BIG_ENDIAN >;
return def::deserialize( msg ).convert_left( [&]( auto sub_res ) {
return sub_res.val;
} );
auto opt_view = bounded_view< const uint8_t*, typename def::size_type >::make(
view_n( msg.begin(), min( def::max_size, msg.size() ) ) );
if ( !opt_view ) {
return protocol_error_record{ SIZE_ERR, 0 };
}
auto [used, res] = def::deserialize( *opt_view );
if ( std::holds_alternative< const protocol_mark* >( res ) ) {
return protocol_error_record{ *std::get< 1 >( res ), used };
}
return std::get< 0 >( res );
}
template < typename Buffer >
......
......@@ -36,7 +36,7 @@ inline std::ostream& operator<<( std::ostream& os, const protocol_mark& m )
inline std::ostream& operator<<( std::ostream& os, const protocol_error_record& rec )
{
return os << rec.err << " (" << rec.byte_index << ")";
return os << rec.mark << "(" << rec.offset << ")";
}
inline std::ostream& operator<<( std::ostream& os, const protocol_endianess_enum& val )
......
......@@ -29,25 +29,26 @@ struct valid_test_case : protocol_test_fixture
std::array< uint8_t, pitem::max_size > buffer{};
std::span bspan{ buffer };
std::size_t used =
*pitem::serialize_at( bspan.template first< pitem::max_size >(), val );
bounded used =
pitem::serialize_at( bspan.template first< pitem::max_size >(), val );
EXPECT_EQ( used, expected_buffer.size() );
auto serialized = convert_view_n< int >( buffer.begin(), used );
EXPECT_EQ( *used, expected_buffer.size() );
auto serialized = convert_view_n< int >( buffer.begin(), *used );
EXPECT_EQ( serialized, view{ expected_buffer } )
<< std::hex //
<< "serialized : " << serialized << "\n"
<< "expected : " << convert_view< int >( expected_buffer ) << "\n";
pitem::deserialize( view_n( buffer.begin(), used ) )
.match(
[&]( auto res ) {
EXPECT_EQ( *res.used, expected_buffer.size() );
EXPECT_EQ( res.val, val );
},
[&]( protocol_error_record ) {
FAIL();
} );
auto [pused, res] = pitem::deserialize(
*bounded_view< const uint8_t*, typename pitem::size_type >::make(
view_n( buffer.begin(), *used ) ) );
EXPECT_EQ( pused, expected_buffer.size() );
if ( std::holds_alternative< const protocol_mark* >( res ) ) {
FAIL() << std::get< 1 >( res );
} else {
auto rval = std::get< 0 >( res );
EXPECT_EQ( rval, val );
}
}
void generate_name( std::ostream& os ) const final
......@@ -98,14 +99,17 @@ struct invalid_test_case : protocol_test_fixture
ASSERT_LE( inpt.size(), tmp.size() );
std::copy( inpt.begin(), inpt.end(), tmp.begin() );
pitem::deserialize( view_n( tmp.begin(), inpt.size() ) )
.match(
[&]( auto ) {
FAIL();
},
[&]( protocol_error_record rec ) {
EXPECT_EQ( rec, expected_rec );
} );
auto opt_view = bounded_view< const uint8_t*, typename pitem::size_type >::make(
view_n( tmp.begin(), inpt.size() ) );
EXPECT_TRUE( opt_view );
auto [used, res] = pitem::deserialize( *opt_view );
if ( std::holds_alternative< const protocol_mark* >( res ) ) {
EXPECT_EQ( expected_rec.mark, *std::get< 1 >( res ) );
EXPECT_EQ( expected_rec.offset, used );
} else {
FAIL() << "deserialization passed";
}
}
void generate_name( std::ostream& os ) const final
......@@ -138,29 +142,16 @@ int main( int argc, char** argv )
make_valid_test_case< PROTOCOL_LITTLE_ENDIAN >( uint16_t{ 666 }, { 154, 2 } ),
make_valid_test_case< PROTOCOL_BIG_ENDIAN >( uint16_t{ 666 }, { 2, 154 } ),
make_valid_test_case< PROTOCOL_LITTLE_ENDIAN >( int32_t{ -1 }, { 255, 255, 255, 255 } ),
make_invalid_test_case< int16_t >( { 255 }, protocol_error_record{ &LOWSIZE_ERR, 0 } ),
make_invalid_test_case< uint32_t >(
{ 255, 255, 255 }, protocol_error_record{ &LOWSIZE_ERR, 0 } ),
// std::array
make_valid_test_case< PROTOCOL_LITTLE_ENDIAN >(
std::array< int16_t, 3 >{ -1, 1, 666 }, { 255, 255, 1, 0, 154, 2 } ),
make_valid_test_case< PROTOCOL_BIG_ENDIAN >(
std::array< int16_t, 3 >{ -1, 1, 666 }, { 255, 255, 0, 1, 2, 154 } ),
make_invalid_test_case< std::array< uint32_t, 2 > >(
{ 12, 12, 12 }, protocol_error_record{ &LOWSIZE_ERR, 0 } ),
make_invalid_test_case< std::array< uint32_t, 2 > >(
{ 12, 12, 12, 12 }, protocol_error_record{ &LOWSIZE_ERR, 4 } ),
make_invalid_test_case< std::array< uint32_t, 2 > >(
{ 12, 12, 12, 12, 12, 12 }, protocol_error_record{ &LOWSIZE_ERR, 4 } ),
// std::tuple
make_valid_test_case< PROTOCOL_LITTLE_ENDIAN >(
std::tuple< uint8_t, int16_t, int8_t >{ 1u, 666u, -3u }, { 1, 154, 2, 253 } ),
make_valid_test_case< PROTOCOL_BIG_ENDIAN >(
std::tuple< uint8_t, int16_t, int8_t >{ 1u, 666u, -3u }, { 1, 2, 154, 253 } ),
make_invalid_test_case< std::tuple< uint32_t > >(
{ 0, 0, 12 }, protocol_error_record{ &LOWSIZE_ERR, 0 } ),
make_invalid_test_case< std::tuple< int8_t, uint16_t, int8_t, int8_t > >(
{ 0, 0, 12, 0 }, protocol_error_record{ &LOWSIZE_ERR, 4 } ),
// std::variant
make_valid_test_case< PROTOCOL_LITTLE_ENDIAN >(
std::variant< uint8_t, int16_t, uint16_t >{ int16_t{ -3 } }, { 1, 253, 255 } ),
......@@ -169,11 +160,9 @@ int main( int argc, char** argv )
make_valid_test_case< PROTOCOL_LITTLE_ENDIAN >(
std::variant< uint8_t, int16_t, uint16_t >{ uint8_t{ 42 } }, { 0, 42 } ),
make_invalid_test_case< std::variant< uint8_t, int16_t, uint16_t > >(
{ 3, 0, 0 }, protocol_error_record{ &UNDEFVAR_ERR, 0 } ),
{ 3, 0, 0 }, protocol_error_record{ UNDEFVAR_ERR, 0 } ),
make_invalid_test_case< std::variant< uint8_t, int16_t, uint16_t > >(
{ 0 }, protocol_error_record{ &LOWSIZE_ERR, 1 } ),
make_invalid_test_case< std::variant< uint8_t, int16_t, uint16_t > >(
{ 1, 0 }, protocol_error_record{ &LOWSIZE_ERR, 1 } ),
{ 1, 0 }, protocol_error_record{ SIZE_ERR, 0 } ),
// std::bitset
make_valid_test_case< PROTOCOL_LITTLE_ENDIAN >(
std::bitset< 3 >{ 0b00000111 }, { 0b00000111 } ),
......@@ -185,10 +174,6 @@ int main( int argc, char** argv )
std::bitset< 15 >{ 0xFF55 }, { 0x55, 0b01111111 } ),
make_valid_test_case< PROTOCOL_LITTLE_ENDIAN >(
std::bitset< 16 >{ 0xFFFF }, { 0xFF, 0xFF } ),
make_invalid_test_case< std::bitset< 7 > >(
{}, protocol_error_record{ &LOWSIZE_ERR, 0 } ),
make_invalid_test_case< std::bitset< 9 > >(
{ 0x0 }, protocol_error_record{ &LOWSIZE_ERR, 0 } ),
// protocol_sizeless_message
make_valid_test_case< PROTOCOL_LITTLE_ENDIAN >(
*protocol_sizeless_message< 8 >::make( std::vector{ 1, 2, 3, 4, 5 } ),
......@@ -196,8 +181,6 @@ int main( int argc, char** argv )
make_valid_test_case< PROTOCOL_BIG_ENDIAN >(
*protocol_sizeless_message< 8 >::make( std::vector{ 1, 2, 3, 4, 5 } ),
{ 1, 2, 3, 4, 5 } ),
make_invalid_test_case< protocol_sizeless_message< 4 > >(
{ 0, 0, 0, 0, 0 }, protocol_error_record{ &BIGSIZE_ERR, 0 } ),
// protocol_offset
make_specific_valid_test_case< PROTOCOL_LITTLE_ENDIAN, protocol_offset< uint16_t, 0 > >(
666u, { 154, 2 } ),
......@@ -207,15 +190,11 @@ int main( int argc, char** argv )
666u, { 158, 2 } ),
make_specific_valid_test_case< PROTOCOL_BIG_ENDIAN, protocol_offset< uint16_t, 4 > >(
666u, { 2, 158 } ),
make_invalid_test_case< protocol_offset< uint16_t, 4 > >(
{ 255 }, protocol_error_record{ &LOWSIZE_ERR, 0 } ),
// quantity
make_valid_test_case< PROTOCOL_LITTLE_ENDIAN >(
tagged_quantity< struct offtag, uint16_t >{ 666u }, { 154, 2 } ),
make_valid_test_case< PROTOCOL_BIG_ENDIAN >(
tagged_quantity< struct offtag, uint16_t >{ 666u }, { 2, 154 } ),
make_invalid_test_case< tagged_quantity< struct offtag, uint16_t > >(
{ 255 }, protocol_error_record{ &LOWSIZE_ERR, 0 } ),
// bounded
make_valid_test_case< PROTOCOL_LITTLE_ENDIAN >(
bounded< uint16_t, 0, 1024u >::get< 666u >(), { 154, 2 } ),
......@@ -224,9 +203,7 @@ int main( int argc, char** argv )
make_valid_test_case< PROTOCOL_BIG_ENDIAN >(
bounded< int16_t, -1, 1 >::get< -1 >(), { 255, 255 } ),
make_invalid_test_case< bounded< int16_t, -1, 1 > >(
{ 128 }, protocol_error_record{ &LOWSIZE_ERR, 0 } ),
make_invalid_test_case< bounded< int16_t, -1, 1 > >(
{ 0, 128 }, protocol_error_record{ &BOUNDS_ERR, 0 } ),
{ 0, 128 }, protocol_error_record{ BOUNDS_ERR, 0 } ),
// sized_buffer
make_specific_valid_test_case<
PROTOCOL_LITTLE_ENDIAN,
......@@ -249,14 +226,12 @@ int main( int argc, char** argv )
protocol_sized_buffer< protocol_offset< uint16_t, 2 >, uint16_t > >(
666u, { 0, 4, 2, 154 } ),
make_invalid_test_case< protocol_sized_buffer< uint16_t, uint16_t > >(
{ 0, 2, 2 }, protocol_error_record{ &LOWSIZE_ERR, 0 } ),
make_invalid_test_case< protocol_sized_buffer< uint16_t, uint16_t > >(
{ 0, 1, 2, 2 }, protocol_error_record{ &LOWSIZE_ERR, 2 } ),
{ 0, 1, 2, 2 }, protocol_error_record{ SIZE_ERR, 2 } ),
// tag
make_valid_test_case< PROTOCOL_LITTLE_ENDIAN >( tag< 666u >{}, { 154, 2, 0, 0 } ),
make_valid_test_case< PROTOCOL_BIG_ENDIAN >( tag< 666u >{}, { 0, 0, 2, 154 } ),
make_invalid_test_case< tag< 666u > >(
{ 0, 0, 2, 152 }, protocol_error_record{ &BADVAL_ERR, 0 } ),
{ 0, 0, 2, 152 }, protocol_error_record{ BADVAL_ERR, 0 } ),
// group is tested as part of command group
// endianess change
make_specific_valid_test_case<
......
#include "emlabcpp/iterators/convert.h"
#include "emlabcpp/protocol/command_group.h"
#include "emlabcpp/protocol/handler.h"
#include "emlabcpp/protocol/streams.h"
#include "emlabcpp/protocol/tuple.h"
#include "util.h"
......@@ -86,8 +87,8 @@ struct valid_test_case : protocol_test_fixture
[&]( auto var ) {
EXPECT_EQ( var, val );
},
[&]( auto ) {
FAIL();
[&]( auto rec ) {
FAIL() << rec;
} );
}
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment