Skip to content

Commit b2558d5

Browse files
xDimonIgor Egorov
andauthored
Feature: vcpkg compatibility (#31)
* feature: vcpkg compatibility feature: std::variant support feature: boost::variant support as feature Signed-off-by: Dmitriy Khaustov aka xDimon <[email protected]> * refactor: boost::variant support Signed-off-by: Dmitriy Khaustov aka xDimon <[email protected]> * refactor: rename `test` feature for unifying Signed-off-by: Dmitriy Khaustov aka xDimon <[email protected]> * refactor: off building of tests by default Signed-off-by: Dmitriy Khaustov aka xDimon <[email protected]> * update: qtils Signed-off-by: Dmitriy Khaustov aka xDimon <[email protected]> * Try fix build * Fix typo --------- Signed-off-by: Dmitriy Khaustov aka xDimon <[email protected]> Co-authored-by: Igor Egorov <[email protected]>
1 parent 6b39217 commit b2558d5

File tree

11 files changed

+279
-23
lines changed

11 files changed

+279
-23
lines changed

CMakeLists.txt

Lines changed: 42 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -6,16 +6,44 @@
66

77
cmake_minimum_required(VERSION 3.12)
88

9+
option(JAM_COMPATIBLE "Build compatible with JAM-codec" OFF)
10+
option(CUSTOM_CONFIG_SUPPORT "Support custom config of streams" OFF)
11+
12+
option(BUILD_TESTS "Whether to include the test suite in build" OFF)
13+
14+
if (PACKAGE_MANAGER)
15+
if(PACKAGE_MANAGER NOT MATCHES "^(hunter|vcpkg)$")
16+
message(FATAL_ERROR "PACKAGE_MANAGER must be set to 'hunter', 'vcpkg' or isn't set")
17+
endif ()
18+
else ()
19+
set(PACKAGE_MANAGER "hunter")
20+
if (CMAKE_TOOLCHAIN_FILE)
21+
get_filename_component(ACTUAL_NAME ${CMAKE_TOOLCHAIN_FILE} NAME)
22+
if(ACTUAL_NAME STREQUAL "vcpkg.cmake")
23+
message(STATUS "vcpkg will be used because vcpkg.cmake has found")
24+
set(PACKAGE_MANAGER "vcpkg")
25+
endif ()
26+
endif ()
27+
endif ()
28+
message(STATUS "Selected package manager: ${PACKAGE_MANAGER}")
29+
930
if (${CMAKE_VERSION} VERSION_GREATER_EQUAL "3.27")
1031
cmake_policy(SET CMP0144 NEW)
1132
endif ()
1233

13-
include(${CMAKE_CURRENT_LIST_DIR}/cmake/HunterGate.cmake)
34+
if (PACKAGE_MANAGER STREQUAL "hunter")
35+
include(cmake/HunterGate.cmake)
36+
HunterGate(
37+
URL https://github.com/qdrvm/hunter/archive/refs/tags/v0.25.3-qdrvm28.tar.gz
38+
SHA1 a4f1b0f42464e07790b7f90b783a822d71be6c6d
39+
)
40+
endif ()
1441

15-
HunterGate(
16-
URL https://github.com/qdrvm/hunter/archive/refs/tags/v0.25.3-qdrvm25.tar.gz
17-
SHA1 bf5742041306c4b2c8b65b9c2d2af712a36ac3f9
18-
)
42+
if(BUILD_TESTS)
43+
if (PACKAGE_MANAGER STREQUAL "vcpkg")
44+
list(APPEND VCPKG_MANIFEST_FEATURES scale-tests)
45+
endif()
46+
endif()
1947

2048
project(Scale LANGUAGES CXX VERSION 1.1.0)
2149

@@ -25,15 +53,16 @@ set(CMAKE_CXX_EXTENSIONS OFF)
2553

2654
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
2755

28-
option(JAM_COMPATIBLE "Build compatible with JAM-codec" OFF)
29-
option(CUSTOM_CONFIG_SUPPORT "Support custom config of streams" OFF)
30-
31-
option(BUILD_TESTS "Whether to include the test suite in build" OFF)
32-
33-
hunter_add_package(Boost)
34-
find_package(Boost CONFIG REQUIRED)
56+
if (PACKAGE_MANAGER STREQUAL "hunter")
57+
hunter_add_package(Boost)
58+
find_package(Boost)
59+
else()
60+
find_package(Boost CONFIG REQUIRED COMPONENTS endian multiprecision)
61+
endif ()
3562

36-
hunter_add_package(qtils)
63+
if (PACKAGE_MANAGER STREQUAL "hunter")
64+
hunter_add_package(qtils)
65+
endif ()
3766
find_package(qtils CONFIG REQUIRED)
3867

3968
set(DEFINITION_PATH "${CMAKE_CURRENT_SOURCE_DIR}/include/scale/definitions.hpp")

include/scale/scale_decoder_stream.hpp

Lines changed: 47 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,9 +11,15 @@
1111
#include <optional>
1212
#include <type_traits>
1313
#include <utility>
14+
#include <variant>
1415
#include <vector>
1516

17+
#ifdef __has_include
18+
#if __has_include(<boost/variant.hpp>)
1619
#include <boost/variant.hpp>
20+
#define USE_BOOST_VARIANT
21+
#endif
22+
#endif
1723

1824
#include <scale/bitvec.hpp>
1925
#include <scale/definitions.hpp>
@@ -91,7 +97,29 @@ namespace scale {
9197

9298
/**
9399
* @brief scale-decoding of variant
94-
* @tparam T enumeration of various types
100+
* @tparam Ts enumeration of various types
101+
* @param v reference to variant
102+
* @return reference to stream
103+
*/
104+
template <class... Ts>
105+
ScaleDecoderStream &operator>>(std::variant<Ts...> &v) {
106+
// first byte means type index
107+
uint8_t type_index = 0u;
108+
*this >> type_index; // decode type index
109+
110+
// ensure that index is in [0, types_count)
111+
if (type_index >= sizeof...(Ts)) {
112+
raise(DecodeError::WRONG_TYPE_INDEX);
113+
}
114+
115+
tryDecodeAsOneOfVariant<0>(v, type_index);
116+
return *this;
117+
}
118+
119+
#ifdef USE_BOOST_VARIANT
120+
/**
121+
* @brief scale-decoding of variant
122+
* @tparam Ts enumeration of various types
95123
* @param v reference to variant
96124
* @return reference to stream
97125
*/
@@ -109,6 +137,7 @@ namespace scale {
109137
tryDecodeAsOneOfVariant<0>(v, type_index);
110138
return *this;
111139
}
140+
#endif // USE_BOOST_VARIANT
112141

113142
/**
114143
* @brief scale-decodes shared_ptr value
@@ -382,6 +411,22 @@ namespace scale {
382411
}
383412
}
384413

414+
template <size_t I, class... Ts>
415+
void tryDecodeAsOneOfVariant(std::variant<Ts...> &v, size_t i) {
416+
using T = std::remove_const_t<std::tuple_element_t<I, std::tuple<Ts...>>>;
417+
static_assert(std::is_default_constructible_v<T>);
418+
if (I == i) {
419+
T val;
420+
*this >> val;
421+
v = std::forward<T>(val);
422+
return;
423+
}
424+
if constexpr (sizeof...(Ts) > I + 1) {
425+
tryDecodeAsOneOfVariant<I + 1>(v, i);
426+
}
427+
}
428+
429+
#ifdef USE_BOOST_VARIANT
385430
template <size_t I, class... Ts>
386431
void tryDecodeAsOneOfVariant(boost::variant<Ts...> &v, size_t i) {
387432
using T = std::remove_const_t<std::tuple_element_t<I, std::tuple<Ts...>>>;
@@ -396,6 +441,7 @@ namespace scale {
396441
tryDecodeAsOneOfVariant<I + 1>(v, i);
397442
}
398443
}
444+
#endif // USE_BOOST_VARIANT
399445

400446
ByteSpan span_;
401447

include/scale/scale_encoder_stream.hpp

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,9 +11,15 @@
1111
#include <optional>
1212
#include <string>
1313
#include <utility>
14+
#include <variant>
1415
#include <vector>
1516

17+
#ifdef __has_include
18+
#if __has_include(<boost/variant.hpp>)
1619
#include <boost/variant.hpp>
20+
#define USE_BOOST_VARIANT
21+
#endif
22+
#endif
1723

1824
#include <scale/bitvec.hpp>
1925
#include <scale/definitions.hpp>
@@ -117,6 +123,19 @@ namespace scale {
117123
return *this;
118124
}
119125

126+
/**
127+
* @brief scale-encodes variant value
128+
* @tparam T type list
129+
* @param v value to encode
130+
* @return reference to stream
131+
*/
132+
template <class... T>
133+
ScaleEncoderStream &operator<<(const std::variant<T...> &v) {
134+
tryEncodeAsOneOfVariant<0>(v);
135+
return *this;
136+
}
137+
138+
#ifdef USE_BOOST_VARIANT
120139
/**
121140
* @brief scale-encodes variant value
122141
* @tparam T type list
@@ -128,6 +147,7 @@ namespace scale {
128147
tryEncodeAsOneOfVariant<0>(v);
129148
return *this;
130149
}
150+
#endif // USE_BOOST_VARIANT
131151

132152
/**
133153
* @brief scale-encodes sharead_ptr value
@@ -260,6 +280,19 @@ namespace scale {
260280
}
261281
}
262282

283+
template <uint8_t I, class... Ts>
284+
void tryEncodeAsOneOfVariant(const std::variant<Ts...> &v) {
285+
using T = std::tuple_element_t<I, std::tuple<Ts...>>;
286+
if (v.index() == I) {
287+
*this << I << std::get<T>(v);
288+
return;
289+
}
290+
if constexpr (sizeof...(Ts) > I + 1) {
291+
tryEncodeAsOneOfVariant<I + 1>(v);
292+
}
293+
}
294+
295+
#ifdef USE_BOOST_VARIANT
263296
template <uint8_t I, class... Ts>
264297
void tryEncodeAsOneOfVariant(const boost::variant<Ts...> &v) {
265298
using T = std::tuple_element_t<I, std::tuple<Ts...>>;
@@ -271,6 +304,7 @@ namespace scale {
271304
tryEncodeAsOneOfVariant<I + 1>(v);
272305
}
273306
}
307+
#endif // USE_BOOST_VARIANT
274308

275309
/**
276310
* @brief scale-encodes any dynamic collection

test/CMakeLists.txt

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,9 @@ if (POLICY CMP0076)
99
cmake_policy(SET CMP0076 NEW)
1010
endif ()
1111

12-
hunter_add_package(GTest)
12+
if (PACKAGE_MANAGER STREQUAL "hunter")
13+
hunter_add_package(GTest)
14+
endif ()
1315
find_package(GTest CONFIG REQUIRED)
1416

1517
function(disable_clang_tidy target)
@@ -104,7 +106,8 @@ target_link_libraries(scale_collection_test
104106
)
105107

106108
addtest(scale_variant_test
107-
scale_variant_test.cpp
109+
scale_std_variant_test.cpp
110+
scale_boost_variant_test.cpp
108111
)
109112
target_link_libraries(scale_variant_test
110113
scale

test/installation/CMakeLists.txt

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,10 @@ set(CMAKE_CXX_STANDARD 20)
1414
list(APPEND CMAKE_PREFIX_PATH "${CMAKE_CURRENT_LIST_DIR}/scale-install/")
1515
find_package(scale REQUIRED)
1616

17-
hunter_add_package(Boost COMPONENTS random)
18-
find_package(Boost CONFIG REQUIRED random)
17+
if (PACKAGE_MANAGER STREQUAL "hunter")
18+
hunter_add_package(Boost COMPONENTS random)
19+
endif ()
20+
find_package(Boost CONFIG REQUIRED COMPONENTS random)
1921

2022
add_executable(scale_test scale_test.cpp)
2123
target_link_libraries(scale_test
Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -7,13 +7,15 @@
77
#include <gtest/gtest.h>
88
#include <scale/scale.hpp>
99

10+
#ifdef USE_BOOST_VARIANT
11+
1012
using scale::ByteArray;
1113
using scale::decode;
1214
using scale::encode;
1315
using scale::ScaleDecoderStream;
1416
using scale::ScaleEncoderStream;
1517

16-
class VariantFixture
18+
class BoostVariantFixture
1719
: public testing::TestWithParam<
1820
std::pair<boost::variant<uint8_t, uint32_t>, ByteArray>> {
1921
protected:
@@ -32,14 +34,14 @@ namespace {
3234
* @when value is scale-encoded
3335
* @then encoded bytes match predefined byte array
3436
*/
35-
TEST_P(VariantFixture, EncodeSuccessTest) {
37+
TEST_P(BoostVariantFixture, EncodeSuccessTest) {
3638
const auto &[value, match] = GetParam();
3739
ASSERT_NO_THROW(s << value);
3840
ASSERT_EQ(s.to_vector(), match);
3941
}
4042

4143
INSTANTIATE_TEST_SUITE_P(CompactTestCases,
42-
VariantFixture,
44+
BoostVariantFixture,
4345
::testing::Values(make_pair(uint8_t(1), {0, 1}),
4446
make_pair(uint32_t(2),
4547
{1, 2, 0, 0, 0})));
@@ -51,7 +53,7 @@ INSTANTIATE_TEST_SUITE_P(CompactTestCases,
5153
* @then obtained varian has alternative type uint8_t and is equal to encoded
5254
* uint8_t value
5355
*/
54-
TEST(ScaleVariant, DecodeU8Success) {
56+
TEST(ScaleBoostVariant, DecodeU8Success) {
5557
ByteArray match = {0, 1}; // uint8_t{1}
5658
ScaleDecoderStream s(match);
5759
boost::variant<uint8_t, uint32_t> val{};
@@ -66,10 +68,12 @@ TEST(ScaleVariant, DecodeU8Success) {
6668
* @then obtained varian has alternative type uint32_t and is equal to encoded
6769
* uint32_t value
6870
*/
69-
TEST(ScaleVariant, DecodeU32Success) {
71+
TEST(ScaleBoostVariant, DecodeU32Success) {
7072
ByteArray match = {1, 1, 0, 0, 0}; // uint32_t{1}
7173
ScaleDecoderStream s(match);
7274
boost::variant<uint8_t, uint32_t> val{};
7375
ASSERT_NO_THROW(s >> val);
7476
ASSERT_EQ(boost::get<uint32_t>(val), 1);
7577
}
78+
79+
#endif

test/scale_std_variant_test.cpp

Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
/**
2+
* Copyright Quadrivium LLC
3+
* All Rights Reserved
4+
* SPDX-License-Identifier: Apache-2.0
5+
*/
6+
7+
#include <gtest/gtest.h>
8+
#include <scale/scale.hpp>
9+
10+
using scale::ByteArray;
11+
using scale::decode;
12+
using scale::encode;
13+
using scale::ScaleDecoderStream;
14+
using scale::ScaleEncoderStream;
15+
16+
class StdVariantFixture
17+
: public testing::TestWithParam<
18+
std::pair<std::variant<uint8_t, uint32_t>, ByteArray>> {
19+
protected:
20+
ScaleEncoderStream s;
21+
};
22+
namespace {
23+
std::pair<std::variant<uint8_t, uint32_t>, ByteArray> make_pair(
24+
std::variant<uint8_t, uint32_t> v, ByteArray m) {
25+
return {v, std::move(m)};
26+
}
27+
} // namespace
28+
29+
/**
30+
* @given variant value and byte array
31+
* @when value is scale-encoded
32+
* @then encoded bytes match predefined byte array
33+
*/
34+
TEST_P(StdVariantFixture, EncodeSuccessTest) {
35+
const auto &[value, match] = GetParam();
36+
ASSERT_NO_THROW(s << value);
37+
ASSERT_EQ(s.to_vector(), match);
38+
}
39+
40+
INSTANTIATE_TEST_SUITE_P(CompactTestCases,
41+
StdVariantFixture,
42+
::testing::Values(make_pair(uint8_t(1), {0, 1}),
43+
make_pair(uint32_t(2),
44+
{1, 2, 0, 0, 0})));
45+
46+
/**
47+
* @given byte array of encoded variant of types uint8_t and uint32_t
48+
* containing uint8_t value
49+
* @when variant decoded from scale decoder stream
50+
* @then obtained varian has alternative type uint8_t and is equal to encoded
51+
* uint8_t value
52+
*/
53+
TEST(ScaleStdVariant, DecodeU8Success) {
54+
ByteArray match = {0, 1}; // uint8_t{1}
55+
ScaleDecoderStream s(match);
56+
std::variant<uint8_t, uint32_t> val{};
57+
ASSERT_NO_THROW(s >> val);
58+
ASSERT_EQ(std::get<uint8_t>(val), 1);
59+
}
60+
61+
/**
62+
* @given byte array of encoded variant of types uint8_t and uint32_t
63+
* containing uint32_t value
64+
* @when variant decoded from scale decoder stream
65+
* @then obtained varian has alternative type uint32_t and is equal to encoded
66+
* uint32_t value
67+
*/
68+
TEST(ScaleStdVariant, DecodeU32Success) {
69+
ByteArray match = {1, 1, 0, 0, 0}; // uint32_t{1}
70+
ScaleDecoderStream s(match);
71+
std::variant<uint8_t, uint32_t> val{};
72+
ASSERT_NO_THROW(s >> val);
73+
ASSERT_EQ(std::get<uint32_t>(val), 1);
74+
}

0 commit comments

Comments
 (0)