Skip to content

Commit

Permalink
Bugfixes (#55)
Browse files Browse the repository at this point in the history
* Some bugfixes

- Missed proper template indication for case where pointers were disabled
- Added back is_serializable and the related code branches for classes with public static serialize/deserialize methods
- Fixed non-escaped backslash in dispatch_gen.py
  • Loading branch information
jharmer95 authored Mar 12, 2021
1 parent 26624a4 commit 8ca8eb5
Show file tree
Hide file tree
Showing 11 changed files with 155 additions and 25 deletions.
2 changes: 1 addition & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ cmake_minimum_required(VERSION 3.1...3.19)

project(
"rpc.hpp"
VERSION 0.3.1
VERSION 0.3.2
DESCRIPTION "Simple RPC Header-Only Library"
LANGUAGES CXX)

Expand Down
2 changes: 1 addition & 1 deletion dispatch_gen.py
Original file line number Diff line number Diff line change
Expand Up @@ -79,5 +79,5 @@
"#define RPC_MULTI_ALIAS_CACHED_FUNC(FUNCNAME, FUNC_ALIAS,...) EXPAND(RPC_FOR_EACH2(RPC_ALIAS_CACHED_FUNC, FUNCNAME, FUNC_ALIAS, __VA_ARGS__))\n\n"
)
f.write(
'#define RPC_DEFAULT_DISPATCH(FUNCNAME, ...) EXPAND(template<typename Serial> void rpc::server::dispatch(typename Serial::doc_type& serial_obj) { const auto func_name = serial_adapter<Serial>::extract_func_name(serial_obj); RPC_ATTACH_FUNCS(FUNCNAME, __VA_ARGS__) throw std::runtime_error("RPC error: Called function: \"" + func_name + "\" not found!");})\n'
'#define RPC_DEFAULT_DISPATCH(FUNCNAME, ...) EXPAND(template<typename Serial> void rpc::server::dispatch(typename Serial::doc_type& serial_obj) { const auto func_name = serial_adapter<Serial>::extract_func_name(serial_obj); RPC_ATTACH_FUNCS(FUNCNAME, __VA_ARGS__) throw std::runtime_error("RPC error: Called function: \\\"" + func_name + "\\\" not found!");})\n'
)
97 changes: 93 additions & 4 deletions include/rpc.hpp
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
///@file rpc.hpp
///@author Jackson Harmer ([email protected])
///@brief Header-only library for serialized RPC usage
///@version 0.3.1
///@date 03-02-2021
///@version 0.3.2
///
///@copyright
///BSD 3-Clause License
Expand Down Expand Up @@ -58,6 +57,91 @@ namespace rpc
/// Using anything in this namespace in your project is discouraged
namespace details
{
/// @brief Default implementation for SFINAE struct
template<typename, typename T>
struct is_serializable_base
{
static_assert(std::integral_constant<T, false>::value,
"Second template parameter needs to be of function type");
};

/// @brief SFINAE struct checking a type for a 'serialize' member function
///
/// Checks whether the given type \c C has a member function to serialize it to the type given by \c R
/// @tparam C The type to check for 'serialize'
/// @tparam R The type to be serialized to
/// @tparam Args The types of arguments (generic)
template<typename C, typename R, typename... Args>
struct is_serializable_base<C, R(Args...)>
{
private:
template<typename T>
static constexpr auto check(T*) noexcept ->
typename std::is_same<decltype(std::declval<T>().serialize(std::declval<Args>()...)),
R>::type;

template<typename>
static constexpr std::false_type check(...) noexcept;

using type = decltype(check<C>(nullptr));

public:
static constexpr bool value = type::value;
};

/// @brief Default implementation for SFINAE struct
template<typename, typename T>
struct is_deserializable_base
{
static_assert(std::integral_constant<T, false>::value,
"Second template parameter needs to be of function type");
};

/// @brief SFINAE struct checking a type for a 'deserialize' member function
///
/// Checks whether the given type \c C has a member function to de-serialize it to the type given by \c R
/// @tparam C The type to check for 'deserialize'
/// @tparam R The type to be de-serialized to
/// @tparam Args They types of arguments (generic)
template<typename C, typename R, typename... Args>
struct is_deserializable_base<C, R(Args...)>
{
private:
template<typename T>
static constexpr auto check(T*) noexcept ->
typename std::is_same<decltype(std::declval<T>().deserialize(std::declval<Args>()...)),
R>::type;

template<typename>
static constexpr std::false_type check(...) noexcept;

using type = decltype(check<C>(nullptr));

public:
static constexpr bool value = type::value;
};

/// @brief SFINAE struct combining the logic of @ref is_serializable_base and @ref is_deserializable_base
///
/// Checks whether the given type \c Value can be serialized to and de-serialized from the serial type \c Serial
/// @tparam Serial The serial object type
/// @tparam Value The type of object to serialize/de-serialize
template<typename Serial, typename Value>
struct is_serializable
: std::integral_constant<bool,
is_serializable_base<Value, typename Serial::doc_type(const Value&)>::value
&& is_deserializable_base<Value,
Value(const typename Serial::value_type&)>::value>
{
};

/// @brief Helper variable for @ref is_serializable
///
/// @tparam Serial The serial object type
/// @tparam Value The type of object to serialize/de-serialize
template<typename Serial, typename Value>
inline constexpr bool is_serializable_v = is_serializable<Serial, Value>::value;

/// @brief SFINAE struct for checking a type for a 'begin' member function
///
/// Checks whether the given type \c C has a function 'begin' that returns an iterator type
Expand Down Expand Up @@ -941,6 +1025,11 @@ namespace details
serial_adapter<Serial>::populate_array(obj, container);
return container;
}
else if constexpr (details::is_serializable_v<Serial, no_ref_t>)
{
// Attempt to find static T::deserialize function
return no_ref_t::deserialize(obj);
}
else
{
// Attempt to find overloaded rpc::deserialize function
Expand Down Expand Up @@ -1265,7 +1354,7 @@ namespace server
serial_obj = serial_adapter<Serial>::from_packed_func(std::move(pack));
}
#else
auto pack = create_func(func, serial_obj);
auto pack = create_func<Serial>(func, serial_obj);
run_callback(func, pack);

# if defined(RPC_HPP_ENABLE_SERVER_CACHE)
Expand Down Expand Up @@ -1528,7 +1617,7 @@ inline namespace client
const auto serial_obj =
serialize_call<Serial, R, Args...>(std::move(func_name), std::forward<Args>(args)...);

send_to_server(serial_obj, client);
send_to_server<Serial>(serial_obj, client);
const auto resp_obj = get_server_response<Serial>(client);

return serial_adapter<Serial>::template to_packed_func<R, Args...>(resp_obj);
Expand Down
3 changes: 1 addition & 2 deletions include/rpc_adapters/rpc_boost_json.hpp
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
///@file rpc_adapters/rpc_boost_json.hpp
///@author Jackson Harmer ([email protected])
///@brief Implementation of adapting Boost.JSON (https://github.com/boostorg/json)
///@version 0.3.1
///@date 03-02-2021
///@version 0.3.2
///
///@copyright
///BSD 3-Clause License
Expand Down
7 changes: 5 additions & 2 deletions include/rpc_adapters/rpc_njson.hpp
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
///@file rpc_adapters/rpc_njson.hpp
///@author Jackson Harmer ([email protected])
///@brief Implementation of adapting nlohmann/json (https://github.com/nlohmann/json)
///@version 0.3.1
///@date 03-02-2021
///@version 0.3.2
///
///@copyright
///BSD 3-Clause License
Expand Down Expand Up @@ -126,6 +125,10 @@ void push_arg(T arg, njson& arg_list, const size_t arg_sz)

arg_list.push_back(arr);
}
else if constexpr (rpc::details::is_serializable_v<njson_serial_t, T>)
{
arg_list.push_back(T::serialize(arg));
}
else
{
arg_list.push_back(rpc::serialize<njson_serial_t, T>(arg));
Expand Down
54 changes: 49 additions & 5 deletions include/rpc_adapters/rpc_rapidjson.hpp
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
///@file rpc_adapters/rpc_rapidjson.hpp
///@author Jackson Harmer ([email protected])
///@brief Implementation of adapting rapidjson (https://github.com/Tencent/rapidjson)
///@version 0.3.1
///@date 03-02-2021
///@version 0.3.2
///
///@copyright
///BSD 3-Clause License
Expand Down Expand Up @@ -92,10 +91,34 @@ rpc::packed_func<R, Args...> rpdjson_adapter::to_packed_func(const rpdjson_doc&
return packed_func<R, Args...>(
serial_obj["func_name"].GetString(), container, args);
}
else
else if constexpr (std::is_arithmetic_v<R>)
{
if constexpr (std::is_same_v<R,
char> || std::is_same_v<R, int8_t> || std::is_same_v<R, int16_t>)
{
return packed_func<R, Args...>(
serial_obj["func_name"].GetString(), result.GetInt(), args);
}
else if constexpr (std::is_same_v<R, uint8_t> || std::is_same_v<R, uint16_t>)
{
return packed_func<R, Args...>(
serial_obj["func_name"].GetString(), result.GetUint(), args);
}
else
{
return packed_func<R, Args...>(
serial_obj["func_name"].GetString(), result.Get<R>(), args);
}
}
else if constexpr (details::is_serializable_v<rpdjson_serial_t, R>)
{
return packed_func<R, Args...>(
serial_obj["func_name"].GetString(), result.Get<R>(), args);
serial_obj["func_name"].GetString(), R::deserialize(result), args);
}
else
{
return packed_func<R, Args...>(serial_obj["func_name"].GetString(),
rpc::deserialize<rpdjson_serial_t, R>(result), args);
}
}

Expand Down Expand Up @@ -168,6 +191,13 @@ void push_arg(

arg_list.PushBack(sub_arr, alloc);
}
else if constexpr (rpc::details::is_serializable_v<rpdjson_serial_t, T>)
{
rpdjson_doc serialized = T::serialize(arg);
rpdjson_val arr_val;
arr_val.CopyFrom(serialized, alloc);
arg_list.PushBack(arr_val, alloc);
}
else
{
rpdjson_doc serialized = rpc::serialize<rpdjson_serial_t, T>(arg);
Expand Down Expand Up @@ -217,9 +247,15 @@ rpdjson_doc rpdjson_adapter::from_packed_func(packed_func<R, Args...>&& pack)
result.PushBack(val, alloc);
}
}
else if constexpr (details::is_serializable_v<rpdjson_serial_t, R>)
{
rpdjson_doc tmp = R::serialize(*pack.get_result());
result.CopyFrom(tmp, alloc);
}
else
{
result = serialize<rpdjson_serial_t, R>(*pack.get_result());
rpdjson_doc tmp = serialize<rpdjson_serial_t, R>(*pack.get_result());
result.CopyFrom(tmp, alloc);
}
}
else
Expand Down Expand Up @@ -328,6 +364,10 @@ T rpdjson_adapter::get_value(const rpdjson_val& obj)
return obj.Get<T>();
}
}
else if constexpr (details::is_serializable_v<rpdjson_serial_t, T>)
{
return T::deserialize(obj);
}
else
{
return rpc::deserialize<rpdjson_serial_t, T>(obj);
Expand Down Expand Up @@ -359,6 +399,10 @@ void rpdjson_adapter::set_result(rpdjson_doc& serial_obj, R val)
result.PushBack(v, alloc);
}
}
else if constexpr (details::is_serializable_v<rpdjson_serial_t, R>)
{
result = R::serialize(val);
}
else
{
result = serialize<rpdjson_serial_t, R>(val);
Expand Down
3 changes: 1 addition & 2 deletions tests/rpc.benchmark.cpp
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
///@file rpc.benchmark.cpp
///@author Jackson Harmer ([email protected])
///@brief Benchmarking source file for rpc.hpp
///@version 0.3.1
///@date 03-02-2021
///@version 0.3.2
///
///@copyright
///BSD 3-Clause License
Expand Down
3 changes: 1 addition & 2 deletions tests/rpc.client.hpp
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
///@file rpc.client.hpp
///@author Jackson Harmer ([email protected])
///@brief Example implementation of an RPC client class
///@version 0.3.1
///@date 03-02-2021
///@version 0.3.2
///
///@copyright
///BSD 3-Clause License
Expand Down
3 changes: 1 addition & 2 deletions tests/rpc.server.cpp
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
///@file rpc.server.cpp
///@author Jackson Harmer ([email protected])
///@brief Example implementation of an RPC server
///@version 0.3.1
///@date 03-02-2021
///@version 0.3.2
///
///@copyright
///BSD 3-Clause License
Expand Down
3 changes: 1 addition & 2 deletions tests/rpc.test.cpp
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
///@file rpc.test.cpp
///@author Jackson Harmer ([email protected])
///@brief Unit test source file for rpc.hpp
///@version 0.3.1
///@date 03-02-2021
///@version 0.3.2
///
///@copyright
///BSD 3-Clause License
Expand Down
3 changes: 1 addition & 2 deletions tests/test_structs.hpp
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
///@file test_structs.hpp
///@author Jackson Harmer ([email protected])
///@brief Structures/classes for use with rpc.hpp unit tests
///@version 0.3.1
///@date 03-02-2021
///@version 0.3.2
///
///@copyright
///BSD 3-Clause License
Expand Down

0 comments on commit 8ca8eb5

Please sign in to comment.