From 46e2695beae1681fa6977478ed76c42d8b2f5f5e Mon Sep 17 00:00:00 2001 From: Dmitriy Khaustov Date: Thu, 26 Oct 2023 16:11:52 +0300 Subject: [PATCH] Update for C++20 (#18) * update: copyright comments * update: hunter * update: bump C++ standard up to C++20 * refactor: gsl::span replaced by std::span * refactor: containers replaced by range (where it possible) * refactor: clang-format * refactor: replace include-guards by pragma-once * feature: concepts for static and dynamic collections * feature: concepts for static and dynamic span * update: bump version to 1.1.0 * fix: review issues Signed-off-by: Dmitriy Khaustov aka xDimon * fix: CI issues Signed-off-by: Dmitriy Khaustov aka xDimon * fix: remove remaining mentions of GSL Signed-off-by: Dmitriy Khaustov aka xDimon * remove unused buffer * remove unused hex * remove concept * fix: remove redundant data structures Signed-off-by: Dmitriy Khaustov aka xDimon * update: .gitignore Signed-off-by: Dmitriy Khaustov aka xDimon * update: .gitignore Signed-off-by: Dmitriy Khaustov aka xDimon * refactor: prohibit potentially dangerous implementation Signed-off-by: Dmitriy Khaustov aka xDimon * refactor: return implementation for vector Signed-off-by: Dmitriy Khaustov aka xDimon --------- Signed-off-by: Dmitriy Khaustov aka xDimon Co-authored-by: turuslan --- .gitignore | 6 +- CMakeLists.txt | 16 +- README.md | 2 +- include/scale/bitvec.hpp | 8 +- include/scale/buffer/buffer.hpp | 284 ------------------ .../buffer/buffer_back_insert_iterator.hpp | 81 ----- include/scale/buffer/hexutil.hpp | 112 ------- include/scale/detail/fixed_width_integer.hpp | 10 +- include/scale/detail/variant.hpp | 20 +- include/scale/encode_append.hpp | 12 +- include/scale/enum_traits.hpp | 8 +- include/scale/outcome/outcome-register.hpp | 130 ++++---- include/scale/outcome/outcome.hpp | 23 +- include/scale/outcome/outcome_throw.hpp | 8 +- include/scale/scale.hpp | 17 +- include/scale/scale_decoder_stream.hpp | 210 +++++-------- include/scale/scale_encoder_stream.hpp | 154 +++------- include/scale/scale_error.hpp | 18 +- include/scale/types.hpp | 138 ++++++++- include/scale/unreachable.hpp | 12 +- include/scale/visitor.hpp | 14 +- src/CMakeLists.txt | 4 - src/buffer/CMakeLists.txt | 12 - src/buffer/buffer.cpp | 189 ------------ src/buffer/hexutil.cpp | 100 ------ src/compact_len_utils.hpp | 10 +- src/encode_append.cpp | 5 +- src/scale_decoder_stream.cpp | 16 +- src/scale_encoder_stream.cpp | 3 +- src/scale_error.cpp | 7 +- test/CMakeLists.txt | 185 ++++++------ test/append_test_data.hpp | 8 +- test/installation/CMakeLists.txt | 4 +- test/scale_array_test.cpp | 3 +- test/scale_boolean_test.cpp | 10 +- test/scale_collection_test.cpp | 136 ++++++++- test/scale_compact_test.cpp | 13 +- test/scale_convenience_functions_test.cpp | 10 +- test/scale_decoder_stream_test.cpp | 3 +- test/scale_encode_append_test.cpp | 3 +- test/scale_encode_counter_test.cpp | 7 +- test/scale_enum_test.cpp | 3 +- test/scale_fixed_test.cpp | 3 +- test/scale_optional_test.cpp | 3 +- test/scale_pair_test.cpp | 3 +- test/scale_strings_test.cpp | 29 +- test/scale_tuple_test.cpp | 6 +- test/scale_variant_test.cpp | 4 +- test/util/literals.hpp | 35 --- test/util/outcome.hpp | 10 +- 50 files changed, 658 insertions(+), 1449 deletions(-) delete mode 100644 include/scale/buffer/buffer.hpp delete mode 100644 include/scale/buffer/buffer_back_insert_iterator.hpp delete mode 100644 include/scale/buffer/hexutil.hpp delete mode 100644 src/buffer/CMakeLists.txt delete mode 100644 src/buffer/buffer.cpp delete mode 100644 src/buffer/hexutil.cpp delete mode 100644 test/util/literals.hpp diff --git a/.gitignore b/.gitignore index ce212f2..241838c 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,6 @@ -build .vscode .idea -cmake-build-*/ \ No newline at end of file +**/build/ +**/build-*/ +**/cmake-build-*/ +Testing diff --git a/CMakeLists.txt b/CMakeLists.txt index bf9e32c..6f28fd4 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,5 +1,6 @@ # -# Copyright Soramitsu Co., Ltd. All Rights Reserved. +# Copyright Quadrivium LLC +# All Rights Reserved # SPDX-License-Identifier: Apache-2.0 # @@ -8,13 +9,13 @@ cmake_minimum_required(VERSION 3.12) include(${CMAKE_CURRENT_LIST_DIR}/cmake/HunterGate.cmake) HunterGate( - URL "https://github.com/soramitsu/soramitsu-hunter/archive/v0.23.257-soramitsu42.tar.gz" - SHA1 "6f54ad82c2322ff0e234ab96a44a12da1478f1be" + URL https://github.com/qdrvm/hunter/archive/refs/tags/v0.23.257-qdrvm10.tar.gz + SHA1 72b446a4424ba28ea90f9a68a9134b0f8e44b5b2 ) -project(Scale LANGUAGES CXX VERSION 1.0.0) +project(Scale LANGUAGES CXX VERSION 1.1.0) -set(CMAKE_CXX_STANDARD 17) +set(CMAKE_CXX_STANDARD 20) set(CMAKE_CXX_STANDARD_REQUIRED ON) set(CMAKE_CXX_EXTENSIONS OFF) @@ -25,9 +26,6 @@ option(BUILD_TESTS "Whether to include the test suite in build" OFF) hunter_add_package(Boost) find_package(Boost CONFIG REQUIRED) -hunter_add_package(Microsoft.GSL) -find_package(Microsoft.GSL CONFIG REQUIRED) - add_subdirectory(src) if (BUILD_TESTS) @@ -41,7 +39,7 @@ endif () include(GNUInstallDirs) -install(TARGETS scale buffer scale_encode_append EXPORT scaleConfig +install(TARGETS scale scale_encode_append EXPORT scaleConfig LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} diff --git a/README.md b/README.md index b84d492..1fb63c7 100644 --- a/README.md +++ b/README.md @@ -118,7 +118,7 @@ template outcome::result> encode(T &&t); template -outcome::result decode(gsl::span span) +outcome::result decode(const RangeOfBytes auto& span) template outcome::result decode(ScaleDecoderStream &s) diff --git a/include/scale/bitvec.hpp b/include/scale/bitvec.hpp index 995d22e..7e65490 100644 --- a/include/scale/bitvec.hpp +++ b/include/scale/bitvec.hpp @@ -1,10 +1,10 @@ /** - * Copyright Soramitsu Co., Ltd. All Rights Reserved. + * Copyright Quadrivium LLC + * All Rights Reserved * SPDX-License-Identifier: Apache-2.0 */ -#ifndef SCALE_BITVEC_HPP -#define SCALE_BITVEC_HPP +#pragma once #include @@ -23,5 +23,3 @@ namespace scale { } }; } // namespace scale - -#endif // SCALE_BITVEC_HPP diff --git a/include/scale/buffer/buffer.hpp b/include/scale/buffer/buffer.hpp deleted file mode 100644 index b734473..0000000 --- a/include/scale/buffer/buffer.hpp +++ /dev/null @@ -1,284 +0,0 @@ -/** - * Copyright Soramitsu Co., Ltd. All Rights Reserved. - * SPDX-License-Identifier: Apache-2.0 - */ - -#ifndef SCALE_BUFFER_HPP -#define SCALE_BUFFER_HPP - -#include -#include - -#include -#include -#include - -#include - -namespace scale { - -/** - * @brief Class represents arbitrary (including empty) byte buffer. - */ -class Buffer : public boost::equality_comparable, - public boost::equality_comparable>, - public boost::equality_comparable>, - public boost::less_than_comparable { -public: - using iterator = std::vector::iterator; - using const_iterator = std::vector::const_iterator; - using value_type = uint8_t; - // with this gsl::span can be built from Buffer - using pointer = typename std::vector::pointer; - using const_pointer = typename std::vector::const_pointer; - - /** - * @brief allocates buffer of size={@param size}, filled with {@param byte} - */ - Buffer(size_t size, uint8_t byte); - - ~Buffer() = default; - - /** - * @brief lvalue construct buffer from a byte vector - */ - explicit Buffer(std::vector v); - explicit Buffer(gsl::span s); - - Buffer(const uint8_t *begin, const uint8_t *end); - - Buffer() = default; - Buffer(const Buffer &b) = default; - Buffer(Buffer &&b) noexcept = default; - Buffer(std::initializer_list b); - - Buffer &reserve(size_t size); - Buffer &resize(size_t size); - - Buffer &operator=(const Buffer &other) = default; - Buffer &operator=(Buffer &&other) noexcept = default; - - Buffer &operator+=(const Buffer &other) noexcept; - - /** - * @brief Accessor of byte elements given {@param index} in bytearray - */ - uint8_t operator[](size_t index) const; - - /** - * @brief Accessor of byte elements given {@param index} in bytearray - */ - uint8_t &operator[](size_t index); - - /** - * @brief Lexicographical comparison of two buffers - */ - bool operator==(const Buffer &b) const noexcept; - - /** - * @brief Lexicographical comparison of buffer and vector of bytes - */ - bool operator==(const std::vector &b) const noexcept; - - /** - * @brief Lexicographical comparison of buffer and vector of bytes - */ - bool operator==(gsl::span s) const noexcept; - - /** - * @brief Lexicographical comparison of two buffers - */ - bool operator<(const Buffer &b) const noexcept; - - /** - * @brief Iterator, which points to begin of this buffer. - */ - iterator begin(); - - /** - * @brief Iterator, which points to the element next to the last in this - * buffer. - */ - iterator end(); - - /** - * @brief Iterator, which points to begin of this buffer. - */ - const_iterator begin() const; - - /** - * @brief Iterator, which points to the element next to the last in this - * buffer. - */ - const_iterator end() const; - - /** - * @brief Getter for size of this buffer. - */ - size_t size() const; - - /** - * @brief Put a 8-bit {@param n} in this buffer. - * @return this buffer, suitable for chaining. - */ - Buffer &putUint8(uint8_t n); - - /** - * @brief Put a 32-bit {@param n} number in this buffer. Will be serialized - * as big-endian number. - * @return this buffer, suitable for chaining. - */ - Buffer &putUint32(uint32_t n); - - /** - * @brief Put a 64-bit {@param n} number in this buffer. Will be serialized - * as big-endian number. - * @return this buffer, suitable for chaining. - */ - Buffer &putUint64(uint64_t n); - - /** - * @brief Put a string into byte buffer - * @param s arbitrary string - * @return this buffer, suitable for chaining. - */ - Buffer &put(std::string_view str); - - /** - * @brief Put a vector of bytes into byte buffer - * @param s arbitrary vector of bytes - * @return this buffer, suitable for chaining. - */ - Buffer &put(const std::vector &v); - - /** - * @brief Put a sequence of bytes into byte buffer - * @param s arbitrary span of bytes - * @return this buffer, suitable for chaining. - */ - Buffer &put(gsl::span s); - - /** - * @brief Put a array of bytes bounded by pointers into byte buffer - * @param begin pointer to the array start - * end pointer to the address after the last element - * @return this buffer, suitable for chaining. - */ - Buffer &putBytes(const uint8_t *begin, const uint8_t *end); - - /** - * @brief Put another buffer content at the end of current one - * @param buf another buffer - * @return this buffer suitable for chaining. - */ - Buffer &putBuffer(const Buffer &buf); - - /** - * Clear the contents of the Buffer - */ - void clear(); - - /** - * @brief getter for raw array of bytes - */ - const uint8_t *data() const; - uint8_t *data(); - - /** - * @brief getter for vector of bytes - */ - const std::vector &toVector() const; - - std::vector &toVector(); - - /** - * Returns a copy of a part of the buffer - * Works alike subspan() of gsl::span - */ - Buffer subbuffer(size_t offset = 0, size_t length = -1) const; - - /** - * @brief encode bytearray as hex - * @return hex-encoded string - */ - std::string toHex() const; - - /** - * Check if this buffer is empty - * @return true, if buffer is empty, false otherwise - */ - bool empty() const; - - /** - * @brief Construct Buffer from hex string - * @param hex hex-encoded string - * @return result containing constructed buffer if input string is - * hex-encoded string. - */ - static outcome::result fromHex(std::string_view hex); - - /** - * @brief return content of bytearray as string - * @note Does not ensure correct encoding - * @return string - */ - std::string_view toString() const; - - /** - * @brief return content of bytearray as a string copy data - * @note Does not ensure correct encoding - * @return string - */ - std::string asString() const; - - /** - * @brief stores content of a string to byte array - */ - static outcome::result fromString(const std::string &src); - -private: - std::vector data_; - - template Buffer &putRange(const T &begin, const T &end); -}; - -/** - * @brief override operator<< for all streams except std::ostream - * @tparam Stream stream type - * @param s stream reference - * @param buffer value to encode - * @return reference to stream - */ -template > -Stream &operator<<(Stream &s, const Buffer &buffer) { - return s << buffer.toVector(); -} - -/** - * @brief decodes buffer object from stream - * @tparam Stream input stream type - * @param s stream reference - * @param buffer value to decode - * @return reference to stream - */ -template > -Stream &operator>>(Stream &s, Buffer &buffer) { - std::vector data; - s >> data; - buffer.put(data); - return s; -} - -std::ostream &operator<<(std::ostream &os, const Buffer &buffer); - -} // namespace scale::common - -namespace std { -template <> struct hash { - size_t operator()(const scale::Buffer &x) const { - return boost::hash_range(x.begin(), x.end()); - } -}; -} // namespace std - -#endif // SCALE_BUFFER_HPP diff --git a/include/scale/buffer/buffer_back_insert_iterator.hpp b/include/scale/buffer/buffer_back_insert_iterator.hpp deleted file mode 100644 index 9aa62a0..0000000 --- a/include/scale/buffer/buffer_back_insert_iterator.hpp +++ /dev/null @@ -1,81 +0,0 @@ -/** - * Copyright Soramitsu Co., Ltd. All Rights Reserved. - * SPDX-License-Identifier: Apache-2.0 - */ - -#include "common/buffer.hpp" - -using scale::Buffer; - -namespace std { - -/* - * std::back_insert_iterator is an output iterator - * that appends to a container for which it was constructed. - */ -template <> -class back_insert_iterator { -public: - using value_type = Buffer::value_type; - using difference_type = typename std::vector::difference_type; - using pointer = Buffer::pointer; - using reference = typename std::vector::reference; - using iterator_category = std::random_access_iterator_tag; - - constexpr explicit back_insert_iterator(Buffer &c): - buf_ {c} { - } - - back_insert_iterator& - operator=(uint8_t value) { - buf_.putUint8(value); - return *this; - } - - back_insert_iterator& - operator=(uint32_t value) { - buf_.putUint32(value); - return *this; - } - - back_insert_iterator& - operator=(uint64_t value) { - buf_.putUint64(value); - return *this; - } - - back_insert_iterator& - operator=(std::string_view value) { - buf_.put(value); - return *this; - } - - back_insert_iterator& - operator=(gsl::span s) { - buf_.put(s); - return *this; - } - - back_insert_iterator& - operator=(const std::vector& v) { - buf_.put(v); - return *this; - } - - constexpr back_insert_iterator& operator*() { - return *this; - } - - constexpr back_insert_iterator& operator++() { - return *this; - } - - constexpr back_insert_iterator& operator++(int) { - return *this; - } - -private: - Buffer& buf_; -}; - -} diff --git a/include/scale/buffer/hexutil.hpp b/include/scale/buffer/hexutil.hpp deleted file mode 100644 index f65a17b..0000000 --- a/include/scale/buffer/hexutil.hpp +++ /dev/null @@ -1,112 +0,0 @@ -/** - * Copyright Soramitsu Co., Ltd. All Rights Reserved. - * SPDX-License-Identifier: Apache-2.0 - */ - -#ifndef SCALE_HEXUTIL_HPP -#define SCALE_HEXUTIL_HPP - -#include -#include - -#include - -#include - -namespace scale { - - /** - * @brief error codes for exceptions that may occur during unhexing - */ - enum class UnhexError { - NOT_ENOUGH_INPUT = 1, - NON_HEX_INPUT, - VALUE_OUT_OF_RANGE, - MISSING_0X_PREFIX, - UNKNOWN - }; - - /** - * @brief Converts an integer to an uppercase hex representation - */ - std::string int_to_hex(uint64_t n, size_t fixed_width = 2) noexcept; - - /** - * @brief Converts bytes to uppercase hex representation - * @param array bytes - * @param len length of bytes - * @return hexstring - */ - std::string hex_upper(gsl::span bytes) noexcept; - - /** - * @brief Converts bytes to hex representation - * @param array bytes - * @param len length of bytes - * @return hexstring - */ - std::string hex_lower(gsl::span bytes) noexcept; - - /** - * @brief Converts bytes to hex representation with prefix 0x - * @param array bytes - * @return hexstring - */ - std::string hex_lower_0x(gsl::span bytes) noexcept; - - /** - * @brief Converts hex representation to bytes - * @param array individual chars - * @param len length of chars - * @return result containing array of bytes if input string is hex encoded and - * has even length - * - * @note reads both uppercase and lowercase hexstrings - * - * @see - * https://www.boost.org/doc/libs/1_51_0/libs/algorithm/doc/html/the_boost_algorithm_library/Misc/hex.html - */ - outcome::result> unhex(std::string_view hex); - - /** - * @brief Unhex hex-string with 0x in the begining - * @param hex hex string with 0x in the beginning - * @return unhexed buffer - */ - outcome::result> unhexWith0x(std::string_view hex); - - /** - * @brief unhex hex-string with 0x or without it in the beginning - * @tparam T unsigned integer value type to decode - * @param value source hex string - * @return unhexed value - */ - template >> - outcome::result unhexNumber(std::string_view value) { - std::vector bytes; - OUTCOME_TRY(bts, unhexWith0x(value)); - bytes = std::move(bts); - - if (bytes.size() > sizeof(T)) { - return UnhexError::VALUE_OUT_OF_RANGE; - } - - T result{0u}; - for (auto b : bytes) { - // check if `multiply by 10` will cause overflow - if constexpr (sizeof(T) > 1) { - result <<= 8u; - } else { - result = 0; - } - result += b; - } - - return result; - } - -} // namespace scale::common - -OUTCOME_HPP_DECLARE_ERROR_2(scale, UnhexError) - -#endif // SCALE_HEXUTIL_HPP diff --git a/include/scale/detail/fixed_width_integer.hpp b/include/scale/detail/fixed_width_integer.hpp index 19aabb0..b0c0201 100644 --- a/include/scale/detail/fixed_width_integer.hpp +++ b/include/scale/detail/fixed_width_integer.hpp @@ -1,10 +1,10 @@ /** - * Copyright Soramitsu Co., Ltd. All Rights Reserved. + * Copyright Quadrivium LLC + * All Rights Reserved * SPDX-License-Identifier: Apache-2.0 */ -#ifndef SCALE_SCALE_UTIL_HPP -#define SCALE_SCALE_UTIL_HPP +#pragma once #include #include @@ -101,6 +101,4 @@ namespace scale::detail { I sv = -static_cast((~v) + 1); return sv; } -} // namespace scale::detail - -#endif // SCALE_SCALE_UTIL_HPP +} // namespace scale::detail diff --git a/include/scale/detail/variant.hpp b/include/scale/detail/variant.hpp index c8c944e..c65ed86 100644 --- a/include/scale/detail/variant.hpp +++ b/include/scale/detail/variant.hpp @@ -1,10 +1,10 @@ /** - * Copyright Soramitsu Co., Ltd. All Rights Reserved. + * Copyright Quadrivium LLC + * All Rights Reserved * SPDX-License-Identifier: Apache-2.0 */ -#ifndef SCALE_SCALE_DETAIL_VARIANT_HPP -#define SCALE_SCALE_DETAIL_VARIANT_HPP +#pragma once #include @@ -37,12 +37,12 @@ namespace scale::detail { template void apply(uint8_t index) { // if type matches alternative in variant then encode - scale::visit_in_place(v_, - [this, index](const H &h) { - s_ << index - << h; // first byte means type index - }, - [](const auto & /*unused*/) {}); + scale::visit_in_place( + v_, + [this, index](const H &h) { + s_ << index << h; // first byte means type index + }, + [](const auto & /*unused*/) {}); } private: @@ -116,5 +116,3 @@ namespace scale::detail { } } // namespace scale::detail - -#endif // SCALE_SCALE_DETAIL_VARIANT_HPP diff --git a/include/scale/encode_append.hpp b/include/scale/encode_append.hpp index 6291662..3c7d842 100644 --- a/include/scale/encode_append.hpp +++ b/include/scale/encode_append.hpp @@ -1,10 +1,10 @@ /** - * Copyright Soramitsu Co., Ltd. All Rights Reserved. + * Copyright Quadrivium LLC + * All Rights Reserved * SPDX-License-Identifier: Apache-2.0 */ -#ifndef SCALE_CORE_SCALE_ENCODE_APPEND_HPP -#define SCALE_CORE_SCALE_ENCODE_APPEND_HPP +#pragma once #include @@ -14,7 +14,7 @@ namespace scale { * Vector wrapper, that is scale encoded without prepended CompactInteger */ struct EncodeOpaqueValue { - gsl::span v; + ConstSpanOfBytes v; }; template append_or_new_vec(std::vector &self_encoded, - gsl::span input); + ConstSpanOfBytes input); } // namespace scale - -#endif // SCALE_CORE_SCALE_ENCODE_APPEND_HPP diff --git a/include/scale/enum_traits.hpp b/include/scale/enum_traits.hpp index 44b28a3..fb2f1b8 100644 --- a/include/scale/enum_traits.hpp +++ b/include/scale/enum_traits.hpp @@ -1,10 +1,10 @@ /** - * Copyright Soramitsu Co., Ltd. All Rights Reserved. + * Copyright Quadrivium LLC + * All Rights Reserved * SPDX-License-Identifier: Apache-2.0 */ -#ifndef SCALE_ENUM_TRAITS_HPP -#define SCALE_ENUM_TRAITS_HPP +#pragma once #include @@ -100,5 +100,3 @@ namespace scale { } } // namespace scale - -#endif // SCALE_ENUM_TRAITS_HPP diff --git a/include/scale/outcome/outcome-register.hpp b/include/scale/outcome/outcome-register.hpp index 2aaa96e..214c10e 100644 --- a/include/scale/outcome/outcome-register.hpp +++ b/include/scale/outcome/outcome-register.hpp @@ -1,15 +1,15 @@ /** - * Copyright Soramitsu Co., Ltd. All Rights Reserved. + * Copyright Quadrivium LLC + * All Rights Reserved * SPDX-License-Identifier: Apache-2.0 */ -#ifndef SCALE_OUTCOME_REGISTER_HPP -#define SCALE_OUTCOME_REGISTER_HPP +#pragma once #include -#include // bring in std::error_code et al +#include // bring in std::error_code et al -#include // for BOOST_SYMBOL_EXPORT +#include // for BOOST_SYMBOL_EXPORT #ifndef SCALE_EXPORT #if defined(BOOST_SYMBOL_EXPORT) @@ -23,78 +23,87 @@ namespace scale::__outcome_detail { -template class Category : public std::error_category { -public: - const char *name() const noexcept final { - return typeid(T).name(); // enum Errc -> 4Errc + template + class Category : public std::error_category { + public: + const char *name() const noexcept final { + return typeid(T).name(); // enum Errc -> 4Errc + } + + std::string message(int c) const final { + return toString(static_cast(c)); + } + + static std::string toString(T t) { + static_assert( + !std::is_same::value, + "toString() was not specialised for the type T supplied"); + return ""; + } + + SCALE_EXPORT static const Category &get() { + static const Category c; + return c; + } + + ~Category() override = default; + Category(const Category &) = delete; + Category &operator=(const Category &) = delete; + Category(Category &&) = delete; + Category &operator=(Category &&) = delete; + + private: + Category() = default; + }; /* end of class */ + +} // namespace scale::__outcome_detail + +#define __OUTCOME_DEFINE_MAKE_ERROR_CODE(Enum) \ + extern std::error_code make_error_code(Enum e) { \ + return {static_cast(e), \ + scale::__outcome_detail::Category::get()}; \ } - std::string message(int c) const final { return toString(static_cast(c)); } - - static std::string toString(T t) { - static_assert(!std::is_same::value, - "toString() was not specialised for the type T supplied"); - return ""; - } - - SCALE_EXPORT static const Category &get() { - static const Category c; - return c; - } - - ~Category() override = default; - Category(const Category &) = delete; - Category &operator=(const Category &) = delete; - Category(Category &&) = delete; - Category &operator=(Category &&) = delete; - -private: - Category() = default; -}; /* end of class */ - -} // namespace scale::__outcome_detail - -#define __OUTCOME_DEFINE_MAKE_ERROR_CODE(Enum) \ - extern std::error_code make_error_code(Enum e) { \ - return {static_cast(e), scale::__outcome_detail::Category::get()}; \ - } - -#define __OUTCOME_DECLARE_MAKE_ERROR_CODE(Enum) \ +#define __OUTCOME_DECLARE_MAKE_ERROR_CODE(Enum) \ std::error_code make_error_code(Enum e); /// MUST BE EXECUTED A FILE LEVEL (no namespace) in HPP // ns - fully qualified enum namespace. Example: libp2p::common // Enum - enum name. Example: EncodeError -#define OUTCOME_HPP_DECLARE_ERROR_2(ns, Enum) \ - namespace ns { \ - __OUTCOME_DECLARE_MAKE_ERROR_CODE(Enum) \ - } \ - \ - template <> struct std::is_error_code_enum : std::true_type {}; +#define OUTCOME_HPP_DECLARE_ERROR_2(ns, Enum) \ + namespace ns { \ + __OUTCOME_DECLARE_MAKE_ERROR_CODE(Enum) \ + } \ + \ + template <> \ + struct std::is_error_code_enum : std::true_type {}; /// MUST BE EXECUTED A FILE LEVEL (global namespace) in HPP // Enum - enum name. Example: EncodeError -#define OUTCOME_HPP_DECLARE_ERROR_1(Enum) \ - __OUTCOME_DECLARE_MAKE_ERROR_CODE(Enum) \ - template <> struct std::is_error_code_enum : std::true_type {}; +#define OUTCOME_HPP_DECLARE_ERROR_1(Enum) \ + __OUTCOME_DECLARE_MAKE_ERROR_CODE(Enum) \ + template <> \ + struct std::is_error_code_enum : std::true_type {}; /// MUST BE EXECUTED AT FILE LEVEL(no namespace) IN CPP // ns - fully qualified enum namespace. Example: libp2p::common // Enum - enum name. Example: EncodeError // Name - variable name. Example: e -#define OUTCOME_CPP_DEFINE_CATEGORY_3(ns, Enum, Name) \ - namespace ns { \ - __OUTCOME_DEFINE_MAKE_ERROR_CODE(Enum) \ - }; \ - template <> \ - std::string scale::__outcome_detail::Category::toString(ns::Enum Name) +#define OUTCOME_CPP_DEFINE_CATEGORY_3(ns, Enum, Name) \ + namespace ns { \ + __OUTCOME_DEFINE_MAKE_ERROR_CODE(Enum) \ + }; \ + template <> \ + std::string scale::__outcome_detail::Category::toString( \ + ns::Enum Name) /// MUST BE EXECUTED AT FILE LEVEL(global namespace) IN CPP // Enum - enum name. Example: EncodeError // Name - variable name. Example: e -#define OUTCOME_CPP_DEFINE_CATEGORY_2(Enum, Name) \ - __OUTCOME_DEFINE_MAKE_ERROR_CODE(Enum) \ - template <> std::string scale::__outcome_detail::Category::toString(Enum Name) +#define OUTCOME_CPP_DEFINE_CATEGORY_2(Enum, Name) \ + __OUTCOME_DEFINE_MAKE_ERROR_CODE(Enum) \ + template <> \ + std::string scale::__outcome_detail::Category::toString(Enum Name) // kind of "macro overloading" #define __GET_MACRO_3(_1, _2, _3, NAME, ...) NAME @@ -102,13 +111,10 @@ template class Category : public std::error_category { /// with 3 args: OUTCOME_CPP_DEFINE_CATEGORY_3 /// with 2 args: OUTCOME_CPP_DEFINE_CATEGORY_2 -#define OUTCOME_CPP_DEFINE_CATEGORY(...) \ +#define OUTCOME_CPP_DEFINE_CATEGORY(...) \ OUTCOME_CPP_DEFINE_CATEGORY_3(__VA_ARGS__) /// with 2 args: OUTCOME_CPP_DEFINE_CATEGORY_2 /// with 1 arg : OUTCOME_CPP_DEFINE_CATEGORY_1 #define OUTCOME_HPP_DECLARE_ERROR(...) \ OUTCOME_HPP_DECLARE_ERROR_2(__VA_ARGS__) - - -#endif // SCALE_OUTCOME_REGISTER_HPP diff --git a/include/scale/outcome/outcome.hpp b/include/scale/outcome/outcome.hpp index 1c0c291..299ab57 100644 --- a/include/scale/outcome/outcome.hpp +++ b/include/scale/outcome/outcome.hpp @@ -1,14 +1,14 @@ /** - * Copyright Soramitsu Co., Ltd. All Rights Reserved. + * Copyright Quadrivium LLC + * All Rights Reserved * SPDX-License-Identifier: Apache-2.0 */ -#ifndef SCALE_OUTCOME_OUTCOME -#define SCALE_OUTCOME_OUTCOME +#pragma once #pragma warning(push) -#pragma warning(disable:4583) -#pragma warning(disable:4582) +#pragma warning(disable : 4583) +#pragma warning(disable : 4582) #include #include #pragma warning(pop) @@ -17,13 +17,14 @@ namespace scale::outcome { -using namespace BOOST_OUTCOME_V2_NAMESPACE; + using namespace BOOST_OUTCOME_V2_NAMESPACE; -template > -using result = basic_result; + template > + using result = basic_result; -} // namespace scale::outcome +} // namespace scale::outcome // To define OUTCOME_TRY macro, we will need to create OUTCOME_TRY_1 and // OUTCOME_TRY_2 depending on number of arguments @@ -34,5 +35,3 @@ using result = basic_result; #define GET_MACRO(_1, _2, NAME, ...) NAME #define OUTCOME_TRY(...) \ GET_MACRO(__VA_ARGS__, OUTCOME_TRY_2, OUTCOME_TRY_1)(__VA_ARGS__) - -#endif // SCALE_OUTCOME_OUTCOME diff --git a/include/scale/outcome/outcome_throw.hpp b/include/scale/outcome/outcome_throw.hpp index c6b9dcc..9b876fd 100644 --- a/include/scale/outcome/outcome_throw.hpp +++ b/include/scale/outcome/outcome_throw.hpp @@ -1,10 +1,10 @@ /** - * Copyright Soramitsu Co., Ltd. All Rights Reserved. + * Copyright Quadrivium LLC + * All Rights Reserved * SPDX-License-Identifier: Apache-2.0 */ -#ifndef SCALE_COMMON_OUTCOME_THROW_HPP -#define SCALE_COMMON_OUTCOME_THROW_HPP +#pragma once #include #include @@ -31,5 +31,3 @@ namespace scale { boost::throw_exception(std::system_error(t.value(), t.category())); } } // namespace scale - -#endif // SCALE_COMMON_OUTCOME_THROW_HPP diff --git a/include/scale/scale.hpp b/include/scale/scale.hpp index 61156fc..53923d4 100644 --- a/include/scale/scale.hpp +++ b/include/scale/scale.hpp @@ -1,21 +1,20 @@ /** - * Copyright Soramitsu Co., Ltd. All Rights Reserved. + * Copyright Quadrivium LLC + * All Rights Reserved * SPDX-License-Identifier: Apache-2.0 */ -#ifndef SCALE_SCALE_HPP -#define SCALE_SCALE_HPP +#pragma once #include #include #include -#include +#include #include #include #include -#include #define SCALE_EMPTY_DECODER(TargetType) \ template - outcome::result> encode(Args &&... args) { + outcome::result> encode(Args &&...args) { ScaleEncoderStream s{}; try { (s << ... << std::forward(args)); @@ -60,9 +59,9 @@ namespace scale { * @return decoded T */ template - outcome::result decode(gsl::span span) { + outcome::result decode(ConstSpanOfBytes data) { T t{}; - ScaleDecoderStream s(span); + ScaleDecoderStream s(data); try { s >> t; } catch (std::system_error &e) { @@ -72,5 +71,3 @@ namespace scale { return outcome::success(std::move(t)); } } // namespace scale - -#endif // SCALE_SCALE_HPP diff --git a/include/scale/scale_decoder_stream.hpp b/include/scale/scale_decoder_stream.hpp index cf21e10..9314c81 100644 --- a/include/scale/scale_decoder_stream.hpp +++ b/include/scale/scale_decoder_stream.hpp @@ -1,25 +1,24 @@ /** - * Copyright Soramitsu Co., Ltd. All Rights Reserved. + * Copyright Quadrivium LLC + * All Rights Reserved * SPDX-License-Identifier: Apache-2.0 */ -#ifndef SCALE_CORE_SCALE_SCALE_DECODER_STREAM_HPP -#define SCALE_CORE_SCALE_SCALE_DECODER_STREAM_HPP +#pragma once #include #include #include #include #include +#include #include -#include #include #include +#include #include -#include -#include "scale/types.hpp" namespace scale { class ScaleDecoderStream { @@ -27,7 +26,8 @@ namespace scale { // special tag to differentiate decoding streams from others static constexpr auto is_decoder_stream = true; - explicit ScaleDecoderStream(gsl::span span); + explicit ScaleDecoderStream(ConstSpanOfBytes data) + : span_{data}, current_iterator_{span_.begin()}, current_index_{0} {} /** * @brief scale-decodes pair of values @@ -174,92 +174,43 @@ namespace scale { ScaleDecoderStream &operator>>(CompactInteger &v); /** - * @brief decodes custom container with is_static_collection bool class - * member - * @tparam C container type - * @param c reference to container + * @brief scale-decodes to any static (fixed-size) collection + * @param collection decoding collection to * @return reference to stream */ - template > - ScaleDecoderStream &operator>>(C &c) { - using mutableT = std::remove_const_t; - using size_type = S; - - static_assert(std::is_default_constructible_v); - - if constexpr (C::is_static_collection) { - C container; - for (auto &el : container) { - *this >> el; - } - - c = std::move(container); - return *this; - } else { - return decodeVectorLike(c); + ScaleDecoderStream &operator>>(StaticCollection auto &container) { + for (auto &item : container) { + *this >> item; } + return *this; } /** - * @brief decodes vector - * @tparam T item type - * @param v reference to container - * @return reference to stream - */ - template - ScaleDecoderStream &operator>>(std::vector &v) { - return decodeVectorLike(v); - } - /** - * @brief decodes deque - * @tparam T item type - * @param v reference to container - * @return reference to stream - */ - template - ScaleDecoderStream &operator>>(std::deque &v) { - return decodeVectorLike(v); - } - - /** - * @brief decodes random access resizable container - * @tparam T item type - * @param v reference to container + * @brief scale-decodes to resizeable collection (which can be resized first + * and rewrite elements while decoding) + * @param collection decoding collection to * @return reference to stream */ - template - ScaleDecoderStream &decodeVectorLike(C &v) { - using mutableT = std::remove_const_t; - using size_type = S; - - static_assert(std::is_default_constructible_v); + ScaleDecoderStream &operator>>(ResizeableCollection auto &collection) { + using size_type = decltype(collection.size()); CompactInteger size{0u}; *this >> size; auto item_count = size.convert_to(); - if (item_count > v.max_size()) { + if (item_count > collection.max_size()) { raise(DecodeError::TOO_MANY_ITEMS); } - C container; try { - container.resize(item_count); + collection.resize(item_count); } catch (const std::bad_alloc &) { raise(DecodeError::TOO_MANY_ITEMS); } - for (size_type i = 0u; i < item_count; ++i) { - *this >> container[i]; + for (auto &item : collection) { + *this >> item; } - - v = std::move(container); return *this; } @@ -268,23 +219,27 @@ namespace scale { * @param v reference to container * @return reference to stream */ - ScaleDecoderStream &operator>>(std::vector &v) { + ScaleDecoderStream &operator>>(std::vector &collection) { CompactInteger size{0u}; *this >> size; auto item_count = size.convert_to(); - if (item_count > v.max_size()) { + if (item_count > collection.max_size()) { raise(DecodeError::TOO_MANY_ITEMS); } - std::vector container; - bool el; + try { + collection.resize(item_count); + } catch (const std::bad_alloc &) { + raise(DecodeError::TOO_MANY_ITEMS); + } + + bool item; for (size_t i = 0u; i < item_count; ++i) { - *this >> el; - container.push_back(el); + *this >> item; + collection[i] = item; } - v = std::move(container); return *this; } @@ -293,103 +248,74 @@ namespace scale { */ ScaleDecoderStream &operator>>(BitVec &v); + /// @note Implementation prohibited as potentially dangerous. + /// Use manual decoding instead + ScaleDecoderStream &operator>>(DynamicSpan auto &collection) = delete; + /** - * @brief decodes list of items - * @tparam T item type - * @param v reference to collection + * @brief scale-decodes to sequential collection (which can be reserved + * space first and push element by element back while decoding) * @return reference to stream */ - template - ScaleDecoderStream &operator>>(std::list &v) { - using mutableT = std::remove_const_t; - using size_type = typename std::list::size_type; - - static_assert(std::is_default_constructible_v); + ScaleDecoderStream &operator>>(ExtensibleBackCollection auto &collection) { + using size_type = typename std::decay_t::size_type; CompactInteger size{0u}; *this >> size; auto item_count = size.convert_to(); - if (item_count > v.max_size()) { + if (item_count > collection.max_size()) { raise(DecodeError::TOO_MANY_ITEMS); } - std::list lst; + collection.clear(); try { - lst.reserve(item_count); + collection.reserve(item_count); } catch (const std::bad_alloc &) { raise(DecodeError::TOO_MANY_ITEMS); } for (size_type i = 0u; i < item_count; ++i) { - lst.emplace_back(); - *this >> lst.back(); + collection.emplace_back(); + *this >> collection.back(); } - v = std::move(lst); return *this; } - template - struct is_map_like : std::false_type {}; - - template - struct is_map_like()[std::declval< - const typename T::key_type &>()])>> - : std::true_type {}; - /** - * @brief decodes associative containers - * @tparam C item type - * @param c reference to the map + * @brief scale-decodes to non-sequential collection (which can not be + * reserved space or resize, but each element can be emplaced while + * decoding) * @return reference to stream */ - template ::value>> - ScaleDecoderStream &operator>>(C &c) { + ScaleDecoderStream &operator>>( + RandomExtensibleCollection auto &collection) { + using size_type = typename std::decay_t::size_type; + using value_type = + typename std::decay_t::value_type; + CompactInteger size{0u}; *this >> size; - auto item_count = size.convert_to(); - if (item_count > c.max_size()) { + auto item_count = size.convert_to(); + if (item_count > collection.max_size()) { raise(DecodeError::TOO_MANY_ITEMS); } - C container; - typename C::value_type pair; - for (size_t i = 0u; i < item_count; ++i) { - *this >> pair; - container.emplace(pair); - } + value_type item; - c = std::move(container); - return *this; - } - - /** - * @brief decodes array of items - * @tparam T item type - * @tparam size of the array - * @param a reference to the array - * @return reference to stream - */ - template - ScaleDecoderStream &operator>>(std::array &a) { - using mutableT = std::remove_const_t; - for (size_t i = 0u; i < size; ++i) { - *this >> const_cast(a[i]); // NOLINT + collection.clear(); + for (size_type i = 0u; i < item_count; ++i) { + *this >> item; + try { + collection.emplace(std::move(item)); + } catch (const std::bad_alloc &) { + raise(DecodeError::TOO_MANY_ITEMS); + } } return *this; } - /** - * @brief decodes string from stream - * @param v value to decode - * @return reference to stream - */ - ScaleDecoderStream &operator>>(std::string &v); - /** * @brief hasMore Checks whether n more bytes are available * @param n Number of bytes to check @@ -404,7 +330,7 @@ namespace scale { */ uint8_t nextByte(); - using ByteSpan = gsl::span; + using ByteSpan = ConstSpanOfBytes; using SpanIterator = ByteSpan::iterator; using SizeType = ByteSpan::size_type; @@ -453,5 +379,3 @@ namespace scale { }; } // namespace scale - -#endif // SCALE_CORE_SCALE_SCALE_DECODER_STREAM_HPP diff --git a/include/scale/scale_encoder_stream.hpp b/include/scale/scale_encoder_stream.hpp index 1b439e2..78fd7bd 100644 --- a/include/scale/scale_encoder_stream.hpp +++ b/include/scale/scale_encoder_stream.hpp @@ -1,20 +1,20 @@ /** - * Copyright Soramitsu Co., Ltd. All Rights Reserved. + * Copyright Quadrivium LLC + * All Rights Reserved * SPDX-License-Identifier: Apache-2.0 */ -#ifndef SCALE_CORE_SCALE_SCALE_ENCODER_STREAM_HPP -#define SCALE_CORE_SCALE_SCALE_ENCODER_STREAM_HPP +#pragma once #include #include #include #include -#include #include #include +#include namespace scale { @@ -47,90 +47,16 @@ namespace scale { size_t size() const; /** - * @brief scale-encodes std::vector - * @tparam T type of item - * @param c collection to encode + * @brief scale-encodes range + * @param collection range to encode * @return reference to stream */ - template - ScaleEncoderStream &operator<<(const std::vector &c) { - return encodeDynamicCollection(std::size(c), std::begin(c), std::end(c)); - } - /** - * @brief scale-encodes std::deque - * @tparam T type of item - * @param c collection to encode - * @return reference to stream - */ - template - ScaleEncoderStream &operator<<(const std::deque &c) { - return encodeDynamicCollection(std::size(c), std::begin(c), std::end(c)); - } - /** - * @brief scale-encodes std::list - * @tparam T type of item - * @param c collection to encode - * @return reference to stream - */ - template - ScaleEncoderStream &operator<<(const std::list &c) { - return encodeDynamicCollection(std::size(c), std::begin(c), std::end(c)); - } - /** - * @brief scale-encodes std::map - * @tparam K key type - * @tparam V mapped type - * @param c collection to encode - * @return reference to stream - */ - template - ScaleEncoderStream &operator<<(const std::map &c) { - return encodeDynamicCollection(std::size(c), std::begin(c), std::end(c)); + ScaleEncoderStream &operator<<(const DynamicCollection auto &collection) { + return encodeDynamicCollection(collection); } - /** - * @brief scale-encodes gsl::span - * @tparam T type of item - * @tparam S container size (-1 for dynamic) - * @param span span to encode - * @return reference to stream - */ - template - ScaleEncoderStream &operator<<(const gsl::span &span) { - if constexpr (S == -1) { - return encodeDynamicCollection( - std::size(span), std::begin(span), std::end(span)); - } else { - return encodeStaticCollection(span); - } - } - - /** - * @brief scale-encodes collection of same type items, requires bool tag - * is_static_collection - * @tparam C container type, T type of item - * @param c collection to encode - * @return reference to stream - */ - template > - ScaleEncoderStream &operator<<(const C &c) { - if constexpr (C::is_static_collection) { - return encodeStaticCollection(c); - } else { - return encodeDynamicCollection( - std::size(c), std::begin(c), std::end(c)); - } - } - - ScaleEncoderStream &operator<<(const std::vector &v) { - *this << CompactInteger{v.size()}; - for (bool el : v) { - *this << el; - } - return *this; + ScaleEncoderStream &operator<<(const StaticCollection auto &collection) { + return encodeStaticCollection(collection); } /** @@ -233,18 +159,6 @@ namespace scale { return putByte(0u); } - /** - * @brief scale-encodes array of items - * @tparam T item type - * @tparam size of the array - * @param a reference to the array - * @return reference to stream - */ - template - ScaleEncoderStream &operator<<(const std::array &a) { - return encodeStaticCollection(a); - } - /** * @brief scale-encodes std::reference_wrapper of a type * @tparam T underlying type @@ -262,7 +176,20 @@ namespace scale { * @return reference to stream */ ScaleEncoderStream &operator<<(std::string_view sv) { - return encodeDynamicCollection(sv.size(), sv.begin(), sv.end()); + return encodeDynamicCollection(ExplicitlyDynamic{sv}); + } + + /** + * @brief scale-encodes a vector of bool + * @param v vector of bool + * @return reference to stream + */ + ScaleEncoderStream &operator<<(const std::vector &v) { + *this << CompactInteger{v.size()}; + for (bool el : v) { + *this << el; + } + return *this; } /** @@ -320,34 +247,27 @@ namespace scale { /** * @brief scale-encodes any dynamic collection - * @tparam It iterator over collection of bytes - * @param size size of the collection - * @param begin iterator pointing to the begin of collection - * @param end iterator pointing to the end of collection + * @param collection encoding collection * @return reference to stream */ - template - ScaleEncoderStream &encodeDynamicCollection(const CompactInteger &size, - It &&begin, - It &&end) { - *this << size; - // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic) - for (auto &&it = begin; it != end; ++it) { - *this << *it; + ScaleEncoderStream &encodeDynamicCollection( + const DynamicCollection auto &collection) { + *this << CompactInteger{collection.size()}; + for (const auto &item : collection) { + *this << item; } return *this; } /** - * @brief scale-encodes any fixed-size collection (std::array) - * @tparam C collection type - * @param c collection + * @brief scale-encodes any static (fixed-size) collection + * @param collection encoding collection * @return reference to stream */ - template - ScaleEncoderStream &encodeStaticCollection(const C &c) { - for (const auto &e : c) { - *this << e; + ScaleEncoderStream &encodeStaticCollection( + const StaticCollection auto &collection) { + for (const auto &item : collection) { + *this << item; } return *this; } @@ -385,5 +305,3 @@ namespace scale { } } // namespace scale - -#endif // SCALE_CORE_SCALE_SCALE_ENCODER_STREAM_HPP diff --git a/include/scale/scale_error.hpp b/include/scale/scale_error.hpp index cea1683..65a7a1d 100644 --- a/include/scale/scale_error.hpp +++ b/include/scale/scale_error.hpp @@ -1,10 +1,10 @@ /** - * Copyright Soramitsu Co., Ltd. All Rights Reserved. + * Copyright Quadrivium LLC + * All Rights Reserved * SPDX-License-Identifier: Apache-2.0 */ -#ifndef SCALE_SCALE_ERROR_HPP -#define SCALE_SCALE_ERROR_HPP +#pragma once #include @@ -25,16 +25,14 @@ namespace scale { * @brief DecoderError enum provides codes of errors for Decoder methods */ enum class DecodeError { - NOT_ENOUGH_DATA = 1, ///< not enough data to decode value - UNEXPECTED_VALUE, ///< unexpected value - TOO_MANY_ITEMS, ///< too many items, cannot address them in memory - WRONG_TYPE_INDEX, ///< wrong type index, cannot decode variant - INVALID_ENUM_VALUE ///< enum value which doesn't belong to the enum + NOT_ENOUGH_DATA = 1, ///< not enough data to decode value + UNEXPECTED_VALUE, ///< unexpected value + TOO_MANY_ITEMS, ///< too many items, cannot address them in memory + WRONG_TYPE_INDEX, ///< wrong type index, cannot decode variant + INVALID_ENUM_VALUE ///< enum value which doesn't belong to the enum }; } // namespace scale OUTCOME_HPP_DECLARE_ERROR_2(scale, EncodeError) OUTCOME_HPP_DECLARE_ERROR_2(scale, DecodeError) - -#endif // SCALE_SCALE_ERROR_HPP diff --git a/include/scale/types.hpp b/include/scale/types.hpp index d684ec7..a0e8cc4 100644 --- a/include/scale/types.hpp +++ b/include/scale/types.hpp @@ -1,33 +1,143 @@ /** - * Copyright Soramitsu Co., Ltd. All Rights Reserved. + * Copyright Quadrivium LLC + * All Rights Reserved * SPDX-License-Identifier: Apache-2.0 */ -#ifndef SCALE_SCALE_TYPES_HPP -#define SCALE_SCALE_TYPES_HPP +#pragma once +#include +#include +#include #include #include #include namespace scale { - /** - * @brief convenience alias for arrays of bytes - */ + + /// @brief convenience alias for arrays of bytes using ByteArray = std::vector; - /** - * @brief represents compact integer value - */ + + /// @brief convenience alias for immutable span of bytes + using ConstSpanOfBytes = std::span; + + /// @brief convenience alias for mutable span of bytes + using MutSpanOfBytes = std::span; + + /// @brief represents compact integer value using CompactInteger = boost::multiprecision::cpp_int; - /** - * @brief OptionalBool is internal extended bool type - */ - enum class OptionalBool : uint8_t { NONE = 0u, OPT_TRUE = 1u, OPT_FALSE = 2u }; + /// @brief OptionalBool is internal extended bool type + enum class OptionalBool : uint8_t { + NONE = 0u, + OPT_TRUE = 1u, + OPT_FALSE = 2u, + }; + + template + struct ExplicitlyStatic : public T { + static constexpr bool is_static_collection = true; + }; + + template + struct ExplicitlyDynamic : public T { + static constexpr bool is_static_collection = false; + }; + + template + concept ExplicitlyDefinedAsStaticOrDynamic = + requires(T) { T::is_static_collection; }; + + template + struct __is_derived_of_span_impl { + template + static constexpr std::true_type test(const std::span *); + static constexpr std::false_type test(...); + using type = decltype(test(std::declval())); + }; + + template + using __is_derived_of_span = typename __is_derived_of_span_impl::type; + + template + concept SomeSpan = __is_derived_of_span::value // + and requires(T) { T::extent; }; + + template + concept ExplicitlyDefinedAsStatic = ExplicitlyDefinedAsStaticOrDynamic // + and T::is_static_collection; + + template + concept ExplicitlyDefinedAsDynamic = ExplicitlyDefinedAsStaticOrDynamic // + and not(T::is_static_collection); + + template + concept HasSomeInsertMethod = + requires(T v) { v.insert(v.end(), *v.begin()); } + or requires(T v) { v.insert_after(v.end(), *v.begin()); }; + + template + concept HasResizeMethod = requires(T v) { v.resize(v.size()); }; + + template + concept HasReserveMethod = requires(T v) { v.reserve(v.size()); }; + + template + concept HasEmplaceMethod = requires(T v) { v.emplace(*v.begin()); }; + + template + concept HasEmplaceBackMethod = requires(T v) { v.emplace_back(*v.begin()); }; + + template + concept ImplicitlyDefinedAsStatic = + not(ExplicitlyDefinedAsStaticOrDynamic) and // + not(SomeSpan) and // + not(HasSomeInsertMethod); + + template + concept ImplicitlyDefinedAsDynamic = + not(ExplicitlyDefinedAsStaticOrDynamic) and // + not(SomeSpan) and // + HasSomeInsertMethod; + + template + concept StaticSpan = SomeSpan // + and (T::extent != std::dynamic_extent); + + template + concept DynamicSpan = SomeSpan // + and (T::extent == std::dynamic_extent); + + template + concept StaticCollection = std::ranges::range + and (ExplicitlyDefinedAsStatic // + or ImplicitlyDefinedAsStatic // + or StaticSpan); + + template + concept DynamicCollection = std::ranges::sized_range + and (ExplicitlyDefinedAsDynamic // + or ImplicitlyDefinedAsDynamic // + or DynamicSpan); + + template + concept ResizeableCollection = DynamicCollection // + and HasResizeMethod; + + template + concept ExtensibleBackCollection = DynamicCollection // + and not(HasResizeMethod) // + and HasEmplaceBackMethod; + + template + concept RandomExtensibleCollection = DynamicCollection // + and HasEmplaceMethod; + } // namespace scale namespace scale::compact { + /** * @brief categories of compact encoding */ @@ -39,5 +149,5 @@ namespace scale::compact { // min integer encoded as multibyte constexpr static size_t kMinBigInteger = (1ul << 30u); }; + } // namespace scale::compact -#endif // SCALE_SCALE_TYPES_HPP diff --git a/include/scale/unreachable.hpp b/include/scale/unreachable.hpp index e194c74..bd5e6fc 100644 --- a/include/scale/unreachable.hpp +++ b/include/scale/unreachable.hpp @@ -1,10 +1,10 @@ /** -* Copyright Soramitsu Co., Ltd. All Rights Reserved. -* SPDX-License-Identifier: Apache-2.0 -*/ + * Copyright Quadrivium LLC + * All Rights Reserved + * SPDX-License-Identifier: Apache-2.0 + */ -#ifndef SCALE_UNREACHABLE_HPP -#define SCALE_UNREACHABLE_HPP +#pragma once /** * @brief This file declares UNREACHABLE macro. Use it to prevent compiler @@ -22,5 +22,3 @@ class Unreachable_At_Line {}; #endif #undef GCC_VERSION - -#endif // SCALE_UNREACHABLE_HPP diff --git a/include/scale/visitor.hpp b/include/scale/visitor.hpp index 5bdbf92..d43e779 100644 --- a/include/scale/visitor.hpp +++ b/include/scale/visitor.hpp @@ -1,10 +1,10 @@ /** - * Copyright Soramitsu Co., Ltd. All Rights Reserved. + * Copyright Quadrivium LLC + * All Rights Reserved * SPDX-License-Identifier: Apache-2.0 */ -#ifndef SCALE_VISITOR_HPP -#define SCALE_VISITOR_HPP +#pragma once #include // for std::decay #include // for std::forward @@ -57,7 +57,7 @@ namespace scale { * @return visitor */ template - constexpr auto make_visitor(Fs &&... fs) { + constexpr auto make_visitor(Fs &&...fs) { using visitor_type = lambda_visitor...>; return visitor_type(std::forward(fs)...); } @@ -79,7 +79,7 @@ namespace scale { */ template constexpr decltype(auto) visit_in_place(TVariant &&variant, - TVisitors &&... visitors) { + TVisitors &&...visitors) { return boost::apply_visitor( make_visitor(std::forward(visitors)...), std::forward(variant)); @@ -94,9 +94,7 @@ namespace scale { /// construct visitor from Fs and apply it to optional T template - constexpr decltype(auto) match_in_place(T &&t, Fs &&... fs) { + constexpr decltype(auto) match_in_place(T &&t, Fs &&...fs) { return match(std::forward(t), make_visitor(std::forward(fs)...)); } } // namespace scale - -#endif // SCALE_VISITOR_HPP diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index cadfcb4..e4aa95c 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -1,6 +1,3 @@ - -add_subdirectory(buffer) - add_library(scale scale_decoder_stream.cpp scale_encoder_stream.cpp @@ -13,7 +10,6 @@ target_include_directories(scale PUBLIC ) target_link_libraries(scale Boost::boost - buffer ) add_library(scale_encode_append diff --git a/src/buffer/CMakeLists.txt b/src/buffer/CMakeLists.txt deleted file mode 100644 index d91d52b..0000000 --- a/src/buffer/CMakeLists.txt +++ /dev/null @@ -1,12 +0,0 @@ - -add_library(buffer - buffer.cpp - hexutil.cpp - ) -target_include_directories(buffer PUBLIC - $ - $ - ) -target_link_libraries(buffer - Boost::boost - ) diff --git a/src/buffer/buffer.cpp b/src/buffer/buffer.cpp deleted file mode 100644 index d4dee0a..0000000 --- a/src/buffer/buffer.cpp +++ /dev/null @@ -1,189 +0,0 @@ -/** - * Copyright Soramitsu Co., Ltd. All Rights Reserved. - * SPDX-License-Identifier: Apache-2.0 - */ - -#include - -#include - -#include - -namespace scale { - - size_t Buffer::size() const { - return data_.size(); - } - - Buffer &Buffer::putUint32(uint32_t n) { - data_.push_back(static_cast((n >> 24) & 0xFF)); - data_.push_back(static_cast((n >> 16) & 0xFF)); - data_.push_back(static_cast((n >> 8) & 0xFF)); - data_.push_back(static_cast((n)&0xFF)); - - return *this; - } - - Buffer &Buffer::putUint64(uint64_t n) { - data_.push_back(static_cast((n >> 56u) & 0xFF)); - data_.push_back(static_cast((n >> 48u) & 0xFF)); - data_.push_back(static_cast((n >> 40u) & 0xFF)); - data_.push_back(static_cast((n >> 32u) & 0xFF)); - data_.push_back(static_cast((n >> 24u) & 0xFF)); - data_.push_back(static_cast((n >> 16u) & 0xFF)); - data_.push_back(static_cast((n >> 8u) & 0xFF)); - data_.push_back(static_cast((n)&0xFF)); - - return *this; - } - - std::string Buffer::toHex() const { - return hex_lower(data_); - } - - std::string_view Buffer::toString() const { - return std::string_view(reinterpret_cast(data_.data()), data_.size()); // NOLINT - } - - bool Buffer::empty() const { - return data_.empty(); - } - - Buffer::Buffer(std::initializer_list b) : data_(b) {} - - Buffer::iterator Buffer::begin() { - return data_.begin(); - } - - Buffer::iterator Buffer::end() { - return data_.end(); - } - - Buffer &Buffer::putUint8(uint8_t n) { - data_.push_back(n); - return *this; - } - - uint8_t Buffer::operator[](size_t index) const { - return data_[index]; - } - - uint8_t &Buffer::operator[](size_t index) { - return data_[index]; - } - - outcome::result Buffer::fromHex(std::string_view hex) { - OUTCOME_TRY(bytes, unhex(hex)); - return Buffer{std::move(bytes)}; - } - - Buffer::Buffer(std::vector v) : data_(std::move(v)) {} - Buffer::Buffer(gsl::span s) : data_(s.begin(), s.end()) {} - - const std::vector &Buffer::toVector() const { - return data_; - } - - bool Buffer::operator==(const Buffer &b) const noexcept { - return data_ == b.data_; - } - - Buffer::const_iterator Buffer::begin() const { - return data_.begin(); - } - - Buffer::const_iterator Buffer::end() const { - return data_.end(); - } - - const uint8_t *Buffer::data() const { - return data_.data(); - } - - uint8_t *Buffer::data() { - return data_.data(); - } - - Buffer::Buffer(size_t size, uint8_t byte) : data_(size, byte) {} - - bool Buffer::operator==(const std::vector &b) const noexcept { - return data_ == b; - } - - bool Buffer::operator==(gsl::span s) const noexcept { - return std::equal(data_.begin(), data_.end(), s.begin(), s.end()); - } - - bool Buffer::operator<(const Buffer &b) const noexcept { - return std::lexicographical_compare(begin(), end(), b.begin(), b.end()); - } - - template - Buffer &Buffer::putRange(const T &begin, const T &end) { - static_assert(sizeof(*begin) == 1); - data_.insert(std::end(data_), begin, end); - return *this; - } - - Buffer &Buffer::put(std::string_view s) { - return putRange(s.begin(), s.end()); - } - - Buffer &Buffer::put(const std::vector &v) { - return putRange(v.begin(), v.end()); - } - - Buffer &Buffer::put(gsl::span s) { - return putRange(s.begin(), s.end()); - } - - Buffer &Buffer::putBytes(const uint8_t *begin, const uint8_t *end) { - return putRange(begin, end); - } - - Buffer &Buffer::putBuffer(const Buffer &buf) { - return put(buf.toVector()); - } - - void Buffer::clear() { - data_.clear(); - } - - Buffer::Buffer(const uint8_t *begin, const uint8_t *end) - : data_{begin, end} {} - - std::vector &Buffer::toVector() { - return data_; - } - - Buffer &Buffer::reserve(size_t size) { - data_.reserve(size); - return *this; - } - - Buffer &Buffer::resize(size_t size) { - data_.resize(size); - return *this; - } - - std::string Buffer::asString() const { - return std::string{data_.begin(), data_.end()}; - } - - outcome::result Buffer::fromString(const std::string &src) { - return Buffer({src.begin(), src.end()}); - } - - Buffer Buffer::subbuffer(size_t offset, size_t length) const { - return Buffer(gsl::make_span(*this).subspan(offset, length)); - } - - Buffer &Buffer::operator+=(const Buffer &other) noexcept { - return this->putBuffer(other); - } - - std::ostream &operator<<(std::ostream &os, const Buffer &buffer) { - return os << buffer.toHex(); - } - -} // namespace scale::common diff --git a/src/buffer/hexutil.cpp b/src/buffer/hexutil.cpp deleted file mode 100644 index 9bce4b1..0000000 --- a/src/buffer/hexutil.cpp +++ /dev/null @@ -1,100 +0,0 @@ -/** - * Copyright Soramitsu Co., Ltd. All Rights Reserved. - * SPDX-License-Identifier: Apache-2.0 - */ - -#include "scale/buffer/hexutil.hpp" - -#include - -#include - -OUTCOME_CPP_DEFINE_CATEGORY_3(scale, UnhexError, e) { - using scale::UnhexError; - switch (e) { - case UnhexError::NON_HEX_INPUT: - return "Input contains non-hex characters"; - case UnhexError::NOT_ENOUGH_INPUT: - return "Input contains odd number of characters"; - case UnhexError::VALUE_OUT_OF_RANGE: - return "Decoded value is out of range of requested type"; - case UnhexError::MISSING_0X_PREFIX: - return "Missing expected 0x prefix"; - case UnhexError::UNKNOWN: - return "Unknown error"; - } - return "Unknown error (error id not listed)"; -} - -namespace scale { - - std::string int_to_hex(uint64_t n, size_t fixed_width) noexcept { - std::stringstream result; - result.width(fixed_width); - result.fill('0'); - result << std::hex << std::uppercase << n; - auto str = result.str(); - if (str.length() % 2 != 0) { - str.push_back('\0'); - for (int64_t i = str.length() - 2; i >= 0; --i) { - str[i + 1] = str[i]; - } - str[0] = '0'; - } - return str; - } - - std::string hex_upper(const gsl::span bytes) noexcept { - std::string res(bytes.size() * 2, '\x00'); - boost::algorithm::hex(bytes.begin(), bytes.end(), res.begin()); - return res; - } - - std::string hex_lower(const gsl::span bytes) noexcept { - std::string res(bytes.size() * 2, '\x00'); - boost::algorithm::hex_lower(bytes.begin(), bytes.end(), res.begin()); - return res; - } - - std::string hex_lower_0x(gsl::span bytes) noexcept { - constexpr size_t prefix_len = sizeof("0x") - 1; - - std::string res(bytes.size() * 2 + prefix_len, '\x00'); - res.replace(0, prefix_len, "0x", prefix_len); - - boost::algorithm::hex_lower(bytes.begin(), bytes.end(), res.begin() + prefix_len); - return res; - } - - outcome::result> unhex(std::string_view hex) { - std::vector blob; - blob.reserve((hex.size() + 1) / 2); - - try { - boost::algorithm::unhex(hex.begin(), hex.end(), std::back_inserter(blob)); - return blob; - - } catch (const boost::algorithm::not_enough_input &) { - return UnhexError::NOT_ENOUGH_INPUT; - - } catch (const boost::algorithm::non_hex_input &) { - return UnhexError::NON_HEX_INPUT; - - } catch (const std::exception &) { - return UnhexError::UNKNOWN; - } - } - - outcome::result> unhexWith0x( - std::string_view hex_with_prefix) { - const static std::string leading_chrs = "0x"; - - if (hex_with_prefix.substr(0, leading_chrs.size()) != leading_chrs) { - return UnhexError::MISSING_0X_PREFIX; - } - - auto without_prefix = hex_with_prefix.substr(leading_chrs.size()); - - return unhex(without_prefix); - } -} // namespace scale diff --git a/src/compact_len_utils.hpp b/src/compact_len_utils.hpp index aa79b51..cecef40 100644 --- a/src/compact_len_utils.hpp +++ b/src/compact_len_utils.hpp @@ -1,10 +1,10 @@ /** - * Copyright Soramitsu Co., Ltd. All Rights Reserved. + * Copyright Quadrivium LLC + * All Rights Reserved * SPDX-License-Identifier: Apache-2.0 */ -#ifndef SCALE_CORE_SCALE_COMPACT_LEN_UTILS_HPP -#define SCALE_CORE_SCALE_COMPACT_LEN_UTILS_HPP +#pragma once #include "scale/types.hpp" @@ -14,7 +14,7 @@ namespace scale::compact { size_t counter = 0; do { ++counter; - } while((v >>= 8) != 0); + } while ((v >>= 8) != 0); return counter; } @@ -31,5 +31,3 @@ namespace scale::compact { return countBytes(val); } } // namespace scale::compact - -#endif // SCALE_CORE_SCALE_COMPACT_LEN_UTILS_HPP diff --git a/src/encode_append.cpp b/src/encode_append.cpp index 8542513..2e02591 100644 --- a/src/encode_append.cpp +++ b/src/encode_append.cpp @@ -1,5 +1,6 @@ /** - * Copyright Soramitsu Co., Ltd. All Rights Reserved. + * Copyright Quadrivium LLC + * All Rights Reserved * SPDX-License-Identifier: Apache-2.0 */ @@ -28,7 +29,7 @@ namespace scale { } outcome::result append_or_new_vec(std::vector &self_encoded, - gsl::span input) { + ConstSpanOfBytes input) { EncodeOpaqueValue opaque_value{.v = input}; // No data present, just encode the given input data. diff --git a/src/scale_decoder_stream.cpp b/src/scale_decoder_stream.cpp index fb7c734..7a8a612 100644 --- a/src/scale_decoder_stream.cpp +++ b/src/scale_decoder_stream.cpp @@ -1,12 +1,11 @@ /** - * Copyright Soramitsu Co., Ltd. All Rights Reserved. + * Copyright Quadrivium LLC + * All Rights Reserved * SPDX-License-Identifier: Apache-2.0 */ #include "scale/scale_decoder_stream.hpp" -#include - #include "scale/scale_error.hpp" #include "scale/types.hpp" @@ -77,9 +76,6 @@ namespace scale { } } // namespace - ScaleDecoderStream::ScaleDecoderStream(gsl::span span) - : span_{span}, current_iterator_{span_.begin()}, current_index_{0} {} - std::optional ScaleDecoderStream::decodeOptionalBool() { auto byte = nextByte(); switch (static_cast(byte)) { @@ -128,14 +124,6 @@ namespace scale { return *this; } - ScaleDecoderStream &ScaleDecoderStream::operator>>(std::string &v) { - std::vector collection; - *this >> collection; - v.clear(); - v.append(collection.begin(), collection.end()); - return *this; - } - bool ScaleDecoderStream::hasMore(uint64_t n) const { return static_cast(current_index_ + n) <= span_.size(); } diff --git a/src/scale_encoder_stream.cpp b/src/scale_encoder_stream.cpp index 3537550..9bbc082 100644 --- a/src/scale_encoder_stream.cpp +++ b/src/scale_encoder_stream.cpp @@ -1,5 +1,6 @@ /** - * Copyright Soramitsu Co., Ltd. All Rights Reserved. + * Copyright Quadrivium LLC + * All Rights Reserved * SPDX-License-Identifier: Apache-2.0 */ diff --git a/src/scale_error.cpp b/src/scale_error.cpp index c60748a..aa8ae9d 100644 --- a/src/scale_error.cpp +++ b/src/scale_error.cpp @@ -1,5 +1,6 @@ /** - * Copyright Soramitsu Co., Ltd. All Rights Reserved. + * Copyright Quadrivium LLC + * All Rights Reserved * SPDX-License-Identifier: Apache-2.0 */ @@ -26,8 +27,8 @@ OUTCOME_CPP_DEFINE_CATEGORY_3(scale, DecodeError, e) { case DecodeError::UNEXPECTED_VALUE: return "SCALE decode: unexpected value occurred"; case DecodeError::TOO_MANY_ITEMS: - return "SCALE decode: collection has too many items or memory is out or data is " - "damaged, unable to unpack"; + return "SCALE decode: collection has too many items or memory is out or " + "data is damaged, unable to unpack"; case DecodeError::WRONG_TYPE_INDEX: return "SCALE decode: wrong type index, cannot decode variant"; case DecodeError::INVALID_ENUM_VALUE: diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 8b6fba1..e711fed 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -1,160 +1,153 @@ ## -# Copyright Soramitsu Co., Ltd. All Rights Reserved. +# Copyright Quadrivium LLC +# All Rights Reserved # SPDX-License-Identifier: Apache-2.0 ## # The target_sources() command converts relative paths to absolute. if (POLICY CMP0076) - cmake_policy(SET CMP0076 NEW) + cmake_policy(SET CMP0076 NEW) endif () hunter_add_package(GTest) find_package(GTest CONFIG REQUIRED) function(disable_clang_tidy target) - set_target_properties(${target} PROPERTIES - C_CLANG_TIDY "" - CXX_CLANG_TIDY "" - ) + set_target_properties(${target} PROPERTIES + C_CLANG_TIDY "" + CXX_CLANG_TIDY "" + ) endfunction() function(addtest test_name) - add_executable(${test_name} ${ARGN}) - target_sources(${test_name} PUBLIC - ${ARGN} - ) - target_link_libraries(${test_name} - GTest::gtest - GTest::gmock_main - ) - target_include_directories(${test_name} PRIVATE - ${PROJECT_SOURCE_DIR}/include - ) - set(xml_output "--gtest_output=xml:${CMAKE_BINARY_DIR}/xunit/xunit-${test_name}.xml") - add_test( - NAME ${test_name} - COMMAND $ ${xml_output} - ) - set_target_properties(${test_name} PROPERTIES - RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/tests_bin - ARCHIVE_OUTPUT_PATH ${CMAKE_BINARY_DIR}/tests_lib - LIBRARY_OUTPUT_PATH ${CMAKE_BINARY_DIR}/tests_lib - ) - disable_clang_tidy(${test_name}) + add_executable(${test_name} ${ARGN}) + target_sources(${test_name} PUBLIC + ${ARGN} + ) + target_link_libraries(${test_name} + GTest::gtest + GTest::gmock_main + ) + target_include_directories(${test_name} PRIVATE + ${PROJECT_SOURCE_DIR}/include + ) + set(xml_output "--gtest_output=xml:${CMAKE_BINARY_DIR}/xunit/xunit-${test_name}.xml") + add_test( + NAME ${test_name} + COMMAND $ ${xml_output} + ) + set_target_properties(${test_name} PROPERTIES + RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/tests_bin + ARCHIVE_OUTPUT_PATH ${CMAKE_BINARY_DIR}/tests_lib + LIBRARY_OUTPUT_PATH ${CMAKE_BINARY_DIR}/tests_lib + ) + disable_clang_tidy(${test_name}) endfunction() # for tests' XML reports file(MAKE_DIRECTORY ${CMAKE_BINARY_DIR}/xunit) addtest(scale_decoder_stream_test - scale_decoder_stream_test.cpp - ) + scale_decoder_stream_test.cpp +) target_link_libraries(scale_decoder_stream_test - scale - ) + scale +) addtest(scale_encode_append_test - scale_encode_append_test.cpp - ) + scale_encode_append_test.cpp +) target_link_libraries(scale_encode_append_test - scale_encode_append - ) + scale_encode_append +) addtest(scale_compact_test - scale_compact_test.cpp - ) + scale_compact_test.cpp +) target_link_libraries(scale_compact_test - scale - buffer - ) + scale +) addtest(scale_enum_test - scale_enum_test.cpp - ) + scale_enum_test.cpp +) target_link_libraries(scale_enum_test - scale - buffer - ) + scale +) addtest(scale_fixed_test - scale_fixed_test.cpp - ) + scale_fixed_test.cpp +) target_link_libraries(scale_fixed_test - scale - buffer - ) + scale +) addtest(scale_boolean_test - scale_boolean_test.cpp - ) + scale_boolean_test.cpp +) target_link_libraries(scale_boolean_test - scale - buffer - ) + scale +) addtest(scale_optional_test - scale_optional_test.cpp - ) + scale_optional_test.cpp +) target_link_libraries(scale_optional_test - scale - buffer - ) + scale +) addtest(scale_collection_test - scale_collection_test.cpp - ) + scale_collection_test.cpp +) target_link_libraries(scale_collection_test - scale - buffer - ) + scale +) addtest(scale_variant_test - scale_variant_test.cpp - ) + scale_variant_test.cpp +) target_link_libraries(scale_variant_test - scale - buffer - ) + scale +) addtest(scale_pair_test - scale_pair_test.cpp - ) + scale_pair_test.cpp +) target_link_libraries(scale_pair_test - scale - buffer - ) + scale +) addtest(scale_strings_test - scale_strings_test.cpp - ) + scale_strings_test.cpp +) target_link_libraries(scale_strings_test - scale - ) + scale +) addtest(scale_convenience_functions_test - scale_convenience_functions_test.cpp - ) + scale_convenience_functions_test.cpp +) target_link_libraries(scale_convenience_functions_test - scale - ) + scale +) addtest(scale_tuple_test - scale_tuple_test.cpp - ) + scale_tuple_test.cpp +) target_link_libraries(scale_tuple_test - scale - ) + scale +) addtest(scale_array_test - scale_array_test.cpp - ) + scale_array_test.cpp +) target_link_libraries(scale_array_test - scale - ) + scale +) addtest(scale_encode_counter_test - scale_encode_counter_test.cpp - ) + scale_encode_counter_test.cpp +) target_link_libraries(scale_encode_counter_test - scale - ) + scale +) diff --git a/test/append_test_data.hpp b/test/append_test_data.hpp index 213915d..365c094 100644 --- a/test/append_test_data.hpp +++ b/test/append_test_data.hpp @@ -1,10 +1,10 @@ /** - * Copyright Soramitsu Co., Ltd. All Rights Reserved. + * Copyright Quadrivium LLC + * All Rights Reserved * SPDX-License-Identifier: Apache-2.0 */ -#ifndef SCALE_APPEND_TEST_DATA_HPP -#define SCALE_APPEND_TEST_DATA_HPP +#pragma once namespace data { constexpr auto append_bytes = @@ -15785,5 +15785,3 @@ namespace data { "000000"); } // namespace data - -#endif // SCALE_APPEND_TEST_DATA_HPP diff --git a/test/installation/CMakeLists.txt b/test/installation/CMakeLists.txt index f9e3151..6eb5124 100644 --- a/test/installation/CMakeLists.txt +++ b/test/installation/CMakeLists.txt @@ -3,8 +3,8 @@ cmake_minimum_required(VERSION 3.12) include(../../cmake/HunterGate.cmake) HunterGate( - URL https://github.com/soramitsu/soramitsu-hunter/archive/master.tar.gz - SHA1 39113c56b1d6be190b13995348816710dc1715f7 + URL https://github.com/qdrvm/hunter/archive/refs/tags/v0.23.257-qdrvm10.tar.gz + SHA1 72b446a4424ba28ea90f9a68a9134b0f8e44b5b2 ) project(ScaleTest CXX) diff --git a/test/scale_array_test.cpp b/test/scale_array_test.cpp index 48161d2..9acbae4 100644 --- a/test/scale_array_test.cpp +++ b/test/scale_array_test.cpp @@ -1,5 +1,6 @@ /** - * Copyright Soramitsu Co., Ltd. All Rights Reserved. + * Copyright Quadrivium LLC + * All Rights Reserved * SPDX-License-Identifier: Apache-2.0 */ diff --git a/test/scale_boolean_test.cpp b/test/scale_boolean_test.cpp index c6638ca..ad08ba5 100644 --- a/test/scale_boolean_test.cpp +++ b/test/scale_boolean_test.cpp @@ -1,5 +1,6 @@ /** - * Copyright Soramitsu Co., Ltd. All Rights Reserved. + * Copyright Quadrivium LLC + * All Rights Reserved * SPDX-License-Identifier: Apache-2.0 */ @@ -10,7 +11,6 @@ #include "scale/scale_encoder_stream.hpp" #include "scale/scale_error.hpp" -#include "util/literals.hpp" #include "util/outcome.hpp" using scale::ByteArray; @@ -46,13 +46,11 @@ struct ThreeBooleans { bool b3 = false; }; -template > - Stream &operator>>(Stream &s, ThreeBooleans &v) { +template > +Stream &operator>>(Stream &s, ThreeBooleans &v) { return s >> v.b1 >> v.b2 >> v.b3; } - /** * @given byte array containing values {0, 1, 2} * @when scale::decode function is applied sequentially diff --git a/test/scale_collection_test.cpp b/test/scale_collection_test.cpp index e03c1d5..731fd23 100644 --- a/test/scale_collection_test.cpp +++ b/test/scale_collection_test.cpp @@ -1,5 +1,6 @@ /** - * Copyright Soramitsu Co., Ltd. All Rights Reserved. + * Copyright Quadrivium LLC + * All Rights Reserved * SPDX-License-Identifier: Apache-2.0 */ @@ -45,7 +46,7 @@ TEST(Scale, encodeVectorOfBool) { ASSERT_NO_THROW((s << collection)); auto &&out = s.to_vector(); - auto stream = ScaleDecoderStream(gsl::make_span(out)); + auto stream = ScaleDecoderStream(out); std::vector decoded; stream >> decoded; ASSERT_TRUE(std::equal( @@ -83,7 +84,7 @@ TEST(Scale, encodeCollectionUint16) { ASSERT_NO_THROW((s << collection)); auto &&out = s.to_vector(); - auto stream = ScaleDecoderStream(gsl::make_span(out)); + auto stream = ScaleDecoderStream(out); std::vector decoded; stream >> decoded; ASSERT_TRUE(std::equal( @@ -104,6 +105,7 @@ TEST(Scale, encodeCollectionUint16) { struct TestStruct : std::vector { static constexpr bool is_static_collection = false; }; + /** * @given collection of items of type uint16_t, derived from std::vector * @when encodeCollection is applied @@ -120,7 +122,7 @@ TEST(Scale, encodeDerivedCollectionUint16) { ASSERT_NO_THROW((s << collection)); auto &&out = s.to_vector(); - auto stream = ScaleDecoderStream(gsl::make_span(out)); + auto stream = ScaleDecoderStream(out); TestStruct decoded; stream >> decoded; ASSERT_TRUE(std::equal( @@ -149,7 +151,7 @@ TEST(Scale, encodeDequeUint16) { ASSERT_NO_THROW((s << collection)); auto &&out = s.to_vector(); - auto stream = ScaleDecoderStream(gsl::make_span(out)); + auto stream = ScaleDecoderStream(out); std::deque decoded; stream >> decoded; ASSERT_TRUE(std::equal( @@ -236,7 +238,7 @@ TEST(Scale, encodeLongCollectionUint16) { // header takes 4 byte, // first 4 bytes represent le-encoded value 2^16 + 2 // which is compact-encoded value 2^14 = 16384 - auto stream = ScaleDecoderStream(gsl::make_span(out)); + auto stream = ScaleDecoderStream(out); CompactInteger res{}; ASSERT_NO_THROW(stream >> res); ASSERT_EQ(res, 16384); @@ -284,7 +286,7 @@ TEST(Scale, encodeVeryLongCollectionUint8) { // which means that number of items requires 4 bytes // 3 next bytes are 0, and the last 4-th == 2^6 == 64 // which is compact-encoded value 2^14 = 16384 - auto stream = ScaleDecoderStream(gsl::make_span(out)); + auto stream = ScaleDecoderStream(out); CompactInteger bi{}; ASSERT_NO_THROW(stream >> bi); ASSERT_EQ(bi, 1048576); @@ -304,9 +306,9 @@ TEST(Scale, encodeVeryLongCollectionUint8) { // following test takes too much time, don't run it /** - * @given very long collection of items of type uint8_t containing 2^30 == - * 1073741824 items this number takes ~ 1 Gb of data where collection[i] == i % - * 256 + * @given very long collection of items of type uint8_t containing + * 2^30 == 1073741824 items this number takes ~ 1 Gb of data where + * collection[i] == i % 256 * @when encodeCollection is applied * @then obtain byte array of length 1073741824 + 5 bytes (header) bytes * where first bytes represent header, other are data itself @@ -330,7 +332,7 @@ TEST(Scale, DISABLED_encodeVeryLongCollectionUint8) { // requires 4 bytes // 3 next bytes are 0, and the last 4-th == 2^6 == 64 // which is compact-encoded value 2^14 = 16384 - auto stream = ScaleDecoderStream(gsl::make_span(out)); + auto stream = ScaleDecoderStream(out); CompactInteger bi{}; ASSERT_NO_THROW(stream >> bi); ASSERT_EQ(bi, length); @@ -360,7 +362,7 @@ TEST(Scale, encodeMapTest) { ASSERT_NO_THROW((s << collection)); auto &&out = s.to_vector(); - auto stream = ScaleDecoderStream(gsl::make_span(out)); + auto stream = ScaleDecoderStream(out); std::map decoded; stream >> decoded; ASSERT_TRUE(std::equal( @@ -400,21 +402,21 @@ TEST(Scale, decodeSizeLimitedCollection) { auto &&out = s.to_vector(); { - auto stream = ScaleDecoderStream(gsl::make_span(out)); + auto stream = ScaleDecoderStream(out); SizeLimitedVector<4, int> decoded; ASSERT_NO_THROW((stream >> decoded)); ASSERT_TRUE(std::equal( decoded.begin(), decoded.end(), collection.begin(), collection.end())); } { - auto stream = ScaleDecoderStream(gsl::make_span(out)); + auto stream = ScaleDecoderStream(out); SizeLimitedVector<3, int> decoded; ASSERT_NO_THROW((stream >> decoded)); ASSERT_TRUE(std::equal( decoded.begin(), decoded.end(), collection.begin(), collection.end())); } { - auto stream = ScaleDecoderStream(gsl::make_span(out)); + auto stream = ScaleDecoderStream(out); SizeLimitedVector<2, int> decoded; try { @@ -425,3 +427,107 @@ TEST(Scale, decodeSizeLimitedCollection) { } } } + +struct ExplicitlyDefinedAsStatic : public std::vector { + static constexpr bool is_static_collection = true; + using Collection = std::vector; + using Collection::Collection; +}; + +TEST(Scale, encodeExplicitlyDefinedAsStatic) { + using TestCollection = ExplicitlyDefinedAsStatic; + + const TestCollection collection{1, 2, 3, 4, 5}; + + ScaleEncoderStream s; + ASSERT_NO_THROW((s << collection)); + auto &&out = s.to_vector(); + + auto stream = ScaleDecoderStream(out); + TestCollection decoded{0xff, 0xff, 0xff, 0xff, 0xff}; + stream >> decoded; + ASSERT_TRUE(std::equal( + decoded.begin(), decoded.end(), collection.begin(), collection.end())); +} + +struct ExplicitlyDefinedAsDynamic : public std::vector { + static constexpr bool is_static_collection = false; + using Collection = std::vector; + using Collection::Collection; +}; + +TEST(Scale, encodeExplicitlyDefinedAsDynamic) { + using TestCollection = ExplicitlyDefinedAsDynamic; + + const TestCollection collection{1, 2, 3, 4, 5}; + ScaleEncoderStream s; + ASSERT_NO_THROW((s << collection)); + auto &&out = s.to_vector(); + + auto stream = ScaleDecoderStream(out); + TestCollection decoded{0xff, 0xff, 0xff}; + stream >> decoded; + ASSERT_TRUE(std::equal( + decoded.begin(), decoded.end(), collection.begin(), collection.end())); +} + +struct ImplicitlyDefinedAsStatic : public std::array { + using Collection = std::array; +}; + +TEST(Scale, encodeImplicitlyDefinedAsStatic) { + using TestCollection = ImplicitlyDefinedAsStatic; + + const TestCollection collection{1, 2, 3, 4, 5}; + ScaleEncoderStream s; + ASSERT_NO_THROW((s << collection)); + auto &&out = s.to_vector(); + + auto stream = ScaleDecoderStream(out); + TestCollection decoded{0xff, 0xff, 0xff, 0xff, 0xff}; + stream >> decoded; + ASSERT_TRUE(std::equal( + decoded.begin(), decoded.end(), collection.begin(), collection.end())); +} + +struct ImplicitlyDefinedAsDynamic : public std::vector { + using Collection = std::vector; + using Collection::Collection; +}; + +TEST(Scale, encodeImplicitlyDefinedAsDynamic) { + using TestCollection = ImplicitlyDefinedAsDynamic; + + const TestCollection collection{1, 2, 3, 4, 5}; + ScaleEncoderStream s; + ASSERT_NO_THROW((s << collection)); + auto &&out = s.to_vector(); + + auto stream = ScaleDecoderStream(out); + TestCollection decoded{0xff, 0xff, 0xff}; + stream >> decoded; + ASSERT_TRUE(std::equal( + decoded.begin(), decoded.end(), collection.begin(), collection.end())); +} + +struct StaticSpan : public std::span { + using Collection = std::span; + using Collection::Collection; +}; + +TEST(Scale, encodeStaticSpan) { + using TestCollection = StaticSpan; + + std::array original_data{1, 2, 3, 4, 5}; + const TestCollection collection(original_data); + ScaleEncoderStream s; + ASSERT_NO_THROW((s << collection)); + auto &&out = s.to_vector(); + + auto stream = ScaleDecoderStream(out); + std::array data{0xff, 0xff, 0xff, 0xff, 0xff}; + TestCollection decoded{data}; + stream >> decoded; + ASSERT_TRUE(std::equal( + decoded.begin(), decoded.end(), collection.begin(), collection.end())); +} diff --git a/test/scale_compact_test.cpp b/test/scale_compact_test.cpp index 3cef639..8a1caac 100644 --- a/test/scale_compact_test.cpp +++ b/test/scale_compact_test.cpp @@ -1,17 +1,18 @@ /** - * Copyright Soramitsu Co., Ltd. All Rights Reserved. + * Copyright Quadrivium LLC + * All Rights Reserved * SPDX-License-Identifier: Apache-2.0 */ +#include + #include #include #include -#include "util/literals.hpp" #include "util/outcome.hpp" -using scale::Buffer; using scale::ByteArray; using scale::CompactInteger; using scale::decode; @@ -51,7 +52,7 @@ TEST_P(CompactTest, EncodeSuccess) { */ TEST_P(CompactTest, DecodeSuccess) { const auto &[value_match, bytes] = GetParam(); - ScaleDecoderStream s(gsl::make_span(bytes)); + ScaleDecoderStream s(bytes); CompactInteger v{}; ASSERT_NO_THROW(s >> v); ASSERT_EQ(v, value_match); @@ -110,9 +111,7 @@ INSTANTIATE_TEST_SUITE_P( "224945689727159819140526925384299092943484855915095831" "655037778630591879033574393515952034305194542857496045" "531676044756160413302774714984450425759043258192756735"), - "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF" - "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF" - "FFFF"_unhex))); + std::vector(68, 0xFF)))); /** * Negative tests diff --git a/test/scale_convenience_functions_test.cpp b/test/scale_convenience_functions_test.cpp index ac16fa6..5add77e 100644 --- a/test/scale_convenience_functions_test.cpp +++ b/test/scale_convenience_functions_test.cpp @@ -1,5 +1,6 @@ /** - * Copyright Soramitsu Co., Ltd. All Rights Reserved. + * Copyright Quadrivium LLC + * All Rights Reserved * SPDX-License-Identifier: Apache-2.0 */ @@ -22,13 +23,12 @@ struct TestStruct { }; template > - Stream &operator<<(Stream &s, const TestStruct &test_struct) { +Stream &operator<<(Stream &s, const TestStruct &test_struct) { return s << test_struct.a << test_struct.b; } -template > - Stream &operator>>(Stream &s, TestStruct &test_struct) { +template > +Stream &operator>>(Stream &s, TestStruct &test_struct) { return s >> test_struct.a >> test_struct.b; } diff --git a/test/scale_decoder_stream_test.cpp b/test/scale_decoder_stream_test.cpp index acbe832..40fce01 100644 --- a/test/scale_decoder_stream_test.cpp +++ b/test/scale_decoder_stream_test.cpp @@ -1,5 +1,6 @@ /** - * Copyright Soramitsu Co., Ltd. All Rights Reserved. + * Copyright Quadrivium LLC + * All Rights Reserved * SPDX-License-Identifier: Apache-2.0 */ #include diff --git a/test/scale_encode_append_test.cpp b/test/scale_encode_append_test.cpp index 6cc837f..8e024c3 100644 --- a/test/scale_encode_append_test.cpp +++ b/test/scale_encode_append_test.cpp @@ -1,5 +1,6 @@ /** - * Copyright Soramitsu Co., Ltd. All Rights Reserved. + * Copyright Quadrivium LLC + * All Rights Reserved * SPDX-License-Identifier: Apache-2.0 */ diff --git a/test/scale_encode_counter_test.cpp b/test/scale_encode_counter_test.cpp index 8362c2f..8f134f4 100644 --- a/test/scale_encode_counter_test.cpp +++ b/test/scale_encode_counter_test.cpp @@ -1,14 +1,15 @@ /** - * Copyright Soramitsu Co., Ltd. All Rights Reserved. + * Copyright Quadrivium LLC + * All Rights Reserved * SPDX-License-Identifier: Apache-2.0 */ #include -#include #include +#include -#include "scale/scale_encoder_stream.hpp" +#include using scale::ScaleEncoderStream; diff --git a/test/scale_enum_test.cpp b/test/scale_enum_test.cpp index 807fe6a..409579b 100644 --- a/test/scale_enum_test.cpp +++ b/test/scale_enum_test.cpp @@ -1,5 +1,6 @@ /** - * Copyright Soramitsu Co., Ltd. All Rights Reserved. + * Copyright Quadrivium LLC + * All Rights Reserved * SPDX-License-Identifier: Apache-2.0 */ diff --git a/test/scale_fixed_test.cpp b/test/scale_fixed_test.cpp index 50bec84..ba7db5d 100644 --- a/test/scale_fixed_test.cpp +++ b/test/scale_fixed_test.cpp @@ -1,5 +1,6 @@ /** - * Copyright Soramitsu Co., Ltd. All Rights Reserved. + * Copyright Quadrivium LLC + * All Rights Reserved * SPDX-License-Identifier: Apache-2.0 */ diff --git a/test/scale_optional_test.cpp b/test/scale_optional_test.cpp index 1312501..1a79918 100644 --- a/test/scale_optional_test.cpp +++ b/test/scale_optional_test.cpp @@ -1,5 +1,6 @@ /** - * Copyright Soramitsu Co., Ltd. All Rights Reserved. + * Copyright Quadrivium LLC + * All Rights Reserved * SPDX-License-Identifier: Apache-2.0 */ diff --git a/test/scale_pair_test.cpp b/test/scale_pair_test.cpp index 59233fa..a33cd85 100644 --- a/test/scale_pair_test.cpp +++ b/test/scale_pair_test.cpp @@ -1,5 +1,6 @@ /** - * Copyright Soramitsu Co., Ltd. All Rights Reserved. + * Copyright Quadrivium LLC + * All Rights Reserved * SPDX-License-Identifier: Apache-2.0 */ diff --git a/test/scale_strings_test.cpp b/test/scale_strings_test.cpp index 478cb1f..b0f4d36 100644 --- a/test/scale_strings_test.cpp +++ b/test/scale_strings_test.cpp @@ -1,5 +1,6 @@ /** - * Copyright Soramitsu Co., Ltd. All Rights Reserved. + * Copyright Quadrivium LLC + * All Rights Reserved * SPDX-License-Identifier: Apache-2.0 */ @@ -18,10 +19,10 @@ using scale::ScaleEncoderStream; * @then encoded value meets expectations */ TEST(Scale, RawStringEncodeSuccess) { -auto * v = "asdadad"; -ScaleEncoderStream s{}; -ASSERT_NO_THROW((s << v)); -ASSERT_EQ(s.to_vector(), (ByteArray{28, 'a', 's', 'd', 'a', 'd', 'a', 'd'})); + auto *v = "asdadad"; + ScaleEncoderStream s{}; + ASSERT_NO_THROW((s << v)); + ASSERT_EQ(s.to_vector(), (ByteArray{28, 'a', 's', 'd', 'a', 'd', 'a', 'd'})); } /** @@ -30,10 +31,10 @@ ASSERT_EQ(s.to_vector(), (ByteArray{28, 'a', 's', 'd', 'a', 'd', 'a', 'd'})); * @then encoded value meets expectations */ TEST(Scale, StdStringEncodeSuccess) { -std::string v = "asdadad"; -ScaleEncoderStream s; -ASSERT_NO_THROW((s << v)); -ASSERT_EQ(s.to_vector(), (ByteArray{28, 'a', 's', 'd', 'a', 'd', 'a', 'd'})); + std::string v = "asdadad"; + ScaleEncoderStream s; + ASSERT_NO_THROW((s << v)); + ASSERT_EQ(s.to_vector(), (ByteArray{28, 'a', 's', 'd', 'a', 'd', 'a', 'd'})); } /** @@ -42,9 +43,9 @@ ASSERT_EQ(s.to_vector(), (ByteArray{28, 'a', 's', 'd', 'a', 'd', 'a', 'd'})); * @then decoded string matches expectations */ TEST(Scale, StringDecodeSuccess) { -auto bytes = ByteArray{28, 'a', 's', 'd', 'a', 'd', 'a', 'd'}; -ScaleDecoderStream s(bytes); -std::string v; -ASSERT_NO_THROW(s >> v); -ASSERT_EQ(v, "asdadad"); + auto bytes = ByteArray{28, 'a', 's', 'd', 'a', 'd', 'a', 'd'}; + ScaleDecoderStream s(bytes); + std::string v; + ASSERT_NO_THROW(s >> v); + ASSERT_EQ(v, "asdadad"); } diff --git a/test/scale_tuple_test.cpp b/test/scale_tuple_test.cpp index e3f8d37..2159bb7 100644 --- a/test/scale_tuple_test.cpp +++ b/test/scale_tuple_test.cpp @@ -1,5 +1,6 @@ /** - * Copyright Soramitsu Co., Ltd. All Rights Reserved. + * Copyright Quadrivium LLC + * All Rights Reserved * SPDX-License-Identifier: Apache-2.0 */ @@ -57,7 +58,6 @@ TEST(Scale, EncodeDecodeTupleSuccess) { std::make_tuple(uint8_t(1), uint16_t(3), uint8_t(2), uint32_t(4)); EXPECT_OUTCOME_TRUE(actual_bytes, scale::encode(tuple)); - EXPECT_OUTCOME_TRUE(decoded, - scale::decode(actual_bytes)); + EXPECT_OUTCOME_TRUE(decoded, scale::decode(actual_bytes)); ASSERT_EQ(decoded, tuple); } diff --git a/test/scale_variant_test.cpp b/test/scale_variant_test.cpp index f419247..e54236b 100644 --- a/test/scale_variant_test.cpp +++ b/test/scale_variant_test.cpp @@ -1,5 +1,6 @@ /** - * Copyright Soramitsu Co., Ltd. All Rights Reserved. + * Copyright Quadrivium LLC + * All Rights Reserved * SPDX-License-Identifier: Apache-2.0 */ @@ -7,7 +8,6 @@ #include "scale/scale.hpp" -#include #include "util/outcome.hpp" using scale::ByteArray; diff --git a/test/util/literals.hpp b/test/util/literals.hpp deleted file mode 100644 index 0381e74..0000000 --- a/test/util/literals.hpp +++ /dev/null @@ -1,35 +0,0 @@ -/** - * Copyright Soramitsu Co., Ltd. All Rights Reserved. - * SPDX-License-Identifier: Apache-2.0 - */ - -#ifndef SCALE_TESTUTIL_LITERALS_HPP -#define SCALE_TESTUTIL_LITERALS_HPP - -#include -#include - -/// creates a buffer filled with characters from the original string -/// mind that it does not perform unhexing, there is ""_unhex for it -inline scale::Buffer operator"" _buf(const char *c, size_t s) { - std::vector chars(c, c + s); - return scale::Buffer(std::move(chars)); -} - -inline std::vector operator"" _v(const char *c, size_t s) { - std::vector chars(c, c + s); - return chars; -} - -inline scale::Buffer operator"" _hex2buf(const char *c, size_t s) { - return scale::Buffer::fromHex(std::string_view(c, s)).value(); -} - -inline std::vector operator""_unhex(const char *c, size_t s) { - if (s > 2 and c[0] == '0' and c[1] == 'x') - return scale::unhexWith0x(std::string_view(c, s)).value(); - return scale::unhex(std::string_view(c, s)).value(); -} - - -#endif // SCAKE_TESTUTIL_LITERALS_HPP diff --git a/test/util/outcome.hpp b/test/util/outcome.hpp index b3bc667..593ce6b 100644 --- a/test/util/outcome.hpp +++ b/test/util/outcome.hpp @@ -1,15 +1,15 @@ /** - * Copyright Soramitsu Co., Ltd. All Rights Reserved. + * Copyright Quadrivium LLC + * All Rights Reserved * SPDX-License-Identifier: Apache-2.0 */ -#ifndef SCALE_GTEST_OUTCOME_UTIL_HPP -#define SCALE_GTEST_OUTCOME_UTIL_HPP +#pragma once #include -#include #include +#include #define PP_CAT(a, b) PP_CAT_I(a, b) #define PP_CAT_I(a, b) PP_CAT_II(~, a##b) @@ -203,5 +203,3 @@ << "Expected: Error '" \ << outcome::result(_error_).error().message() << "'"; \ } - -#endif // SCALE_GTEST_OUTCOME_UTIL_HPP