diff --git a/src/contract/abi.h b/src/contract/abi.h index d907fdbe..b4dec511 100644 --- a/src/contract/abi.h +++ b/src/contract/abi.h @@ -750,6 +750,12 @@ namespace ABI { // TODO: docs template inline T decode(const BytesArrView& bytes, uint64_t& index); + // Helper to check if a type is a std::tuple + template + struct is_tuple : std::false_type {}; + + template + struct is_tuple> : std::true_type {}; /** * Decode a uint256. * @param bytes The data string to decode. @@ -768,15 +774,52 @@ namespace ABI { */ int256_t decodeInt(const BytesArrView& bytes, uint64_t& index); + template + struct tuple_type_sequence {}; + + template + struct tuple_type_sequence> { + using type = std::tuple; + }; + /** - * Specialization for decoding any type of uint or int. - * @tparam T Any supported uint or int. + * Decode a packed std::tuple individually + * This function takes advante of std::tuple_element and template recurssion + * in order to parse all the items within that given tuple. + * @param TupleLike The std::tuple structure + * @param I - the current tuple index * @param bytes The data string to decode. * @param index The point on the encoded string to start decoding. - * @return The decoded data. - * @throw std::runtime_error if type is not found. + * @param ret The tuple object to return, needs to be a reference and create outside the function due to recursion + * Doesn't return, use the referenced TupleLike object.. */ + template + void decodeTuple(const BytesArrView& bytes, uint64_t& index, TupleLike& ret) { + if constexpr (I < std::tuple_size_v) + { + using SelectedType = typename std::tuple_element::type; + std::get(ret) = decode(bytes, index); + decodeTuple(bytes, index, ret); + } + } + + /** + * Specialization for decoding any type of uint or int. + * This function is also used by std::tuple and std::vector> + * Due to incapability of partially specializing the decode function for std::tuple + * @tparam T Any supported uint or int. + * @param bytes The data string to decode. + * @param index The point on the encoded string to start decoding. + * @return The decoded data. + * @throw std::runtime_error if type is not found. + */ template inline T decode(const BytesArrView& bytes, uint64_t& index) { + if constexpr (is_tuple::value) { + T ret; + decodeTuple(bytes, index, ret); + return ret; + } + if constexpr ( std::is_same_v || std::is_same_v || std::is_same_v || std::is_same_v || std::is_same_v || std::is_same_v ||