Clio
develop
The XRP Ledger API server.
Theme:
Default
Round
Robot
Toggle main menu visibility
Loading...
Searching...
No Matches
Tuple.hpp
1
#pragma once
2
3
#include "data/cassandra/impl/ManagedObject.hpp"
4
#include "util/UnsupportedType.hpp"
5
6
#include <cassandra.h>
7
#include <xrpl/basics/base_uint.h>
8
9
#include <cstddef>
10
#include <cstdint>
11
#include <functional>
12
#include <stdexcept>
13
#include <string>
14
#include <string_view>
15
#include <tuple>
16
#include <type_traits>
17
18
namespace
data::cassandra::impl {
19
20
class
Tuple :
public
ManagedObject<CassTuple> {
21
static
constexpr
auto
kDeleter = [](CassTuple* ptr) { cass_tuple_free(ptr); };
22
23
public
:
24
/* implicit */
Tuple(CassTuple* ptr);
25
26
template
<
typename
... Types>
27
explicit
Tuple(std::tuple<Types...>&& value)
28
: ManagedObject{cass_tuple_new(std::tuple_size<std::tuple<Types...>>{}), kDeleter}
29
{
30
std::apply(std::bind_front(&Tuple::bind<Types...>,
this
), std::move(value));
31
}
32
33
template
<
typename
... Args>
34
void
35
bind(Args&&... args)
const
36
{
37
std::size_t idx = 0;
38
(this->bindAt<Args>(idx++, std::forward<Args>(args)), ...);
39
}
40
41
template
<
typename
Type>
42
void
43
bindAt(std::size_t
const
idx, Type&& value)
const
44
{
45
using
std::to_string;
46
auto
const
throwErrorIfNeeded = [idx](CassError rc, std::string_view label) {
47
if
(rc != CASS_OK) {
48
auto
const
tag =
'['
+ std::string{label} +
']'
;
49
throw
std::logic_error(
50
tag +
" at idx "
+ to_string(idx) +
": "
+ cass_error_desc(rc)
51
);
52
}
53
};
54
55
using
DecayedType = std::decay_t<Type>;
56
57
if
constexpr
(std::is_same_v<DecayedType, bool>) {
58
auto
const
rc = cass_tuple_set_bool(*
this
, idx, value ? cass_true : cass_false);
59
throwErrorIfNeeded(rc,
"Bind bool"
);
60
}
61
// clio only uses bigint (int64_t) so we convert any incoming type
62
else
if
constexpr
(std::is_convertible_v<DecayedType, int64_t>) {
63
auto
const
rc = cass_tuple_set_int64(*
this
, idx, std::forward<Type>(value));
64
throwErrorIfNeeded(rc,
"Bind int64"
);
65
}
else
if
constexpr
(std::is_same_v<DecayedType, xrpl::uint256>) {
66
auto
const
rc = cass_tuple_set_bytes(
67
*
this
,
68
idx,
69
static_cast<
cass_byte_t const*
>
(
static_cast<
unsigned
char
const*
>
(value.data())),
70
value.size()
71
);
72
throwErrorIfNeeded(rc,
"Bind xrpl::uint256"
);
73
}
else
{
74
// type not supported for binding
75
static_assert
(
util::Unsupported<DecayedType>
);
76
}
77
}
78
};
79
80
class
TupleIterator :
public
ManagedObject<CassIterator> {
81
public
:
82
/* implicit */
TupleIterator(CassIterator* ptr);
83
84
[[nodiscard]]
static
TupleIterator
85
fromTuple(CassValue
const
* value);
86
87
template
<
typename
... Types>
88
[[nodiscard]] std::tuple<Types...>
89
extract()
const
90
{
91
return
{extractNext<Types>()...};
92
}
93
94
private
:
95
template
<
typename
Type>
96
[[nodiscard]] Type
97
extractNext()
const
98
{
99
using
std::to_string;
100
Type output;
101
102
if
(not cass_iterator_next(*
this
))
103
throw
std::logic_error(
"Could not extract next value from tuple iterator"
);
104
105
auto
const
throwErrorIfNeeded = [](CassError rc, std::string_view label) {
106
if
(rc != CASS_OK) {
107
auto
const
tag =
'['
+ std::string{label} +
']'
;
108
throw
std::logic_error(tag +
": "
+ cass_error_desc(rc));
109
}
110
};
111
112
using
DecayedType = std::decay_t<Type>;
113
114
// clio only uses bigint (int64_t) so we convert any incoming type
115
if
constexpr
(std::is_convertible_v<DecayedType, int64_t>) {
116
int64_t out = 0;
117
auto
const
rc = cass_value_get_int64(cass_iterator_get_value(*
this
), &out);
118
throwErrorIfNeeded(rc,
"Extract int64 from tuple"
);
119
output =
static_cast<
DecayedType
>
(out);
120
}
else
{
121
// type not supported for extraction
122
static_assert
(
util::Unsupported<DecayedType>
);
123
}
124
125
return
output;
126
}
127
};
128
129
}
// namespace data::cassandra::impl
util::Unsupported
static constexpr bool Unsupported
used for compile time checking of unsupported types
Definition
UnsupportedType.hpp:9
src
data
cassandra
impl
Tuple.hpp
Generated by
1.17.0