C++ Server-Side SDK
LaunchDarkly SDK
c_binding_helpers.hpp
1 #pragma once
2 
4 #include <launchdarkly/error.hpp>
5 
6 #include <tl/expected.hpp>
7 
8 #include <cassert>
9 #include <functional>
10 #include <optional>
11 
12 namespace launchdarkly::detail {
13 template <typename T, typename = void>
14 struct has_result_type : std::false_type {};
15 
16 template <typename T>
17 struct has_result_type<T, std::void_t<typename T::Result>> : std::true_type {};
18 
19 template <typename T, typename ReturnType, typename = void>
20 struct has_build_method : std::false_type {};
21 
22 template <typename T, typename ReturnType>
24  ReturnType,
25  std::void_t<decltype(std::declval<T>().Build())>>
26  : std::integral_constant<
27  bool,
28  std::is_same_v<decltype(std::declval<T>().Build()), ReturnType>> {};
29 
30 // NOLINTBEGIN cppcoreguidelines-pro-type-reinterpret-cast
31 
32 /*
33  * Given a Builder, calls the Build() method and converts it into an
34  * OpaqueResult if successful, or an LDError if unsuccessful.
35  *
36  * In the case of an error, out_result is set to nullptr.
37  *
38  * In all cases, the given builder is freed.
39  */
40 template <typename Builder, typename OpaqueBuilder, typename OpaqueResult>
41 LDStatus ConsumeBuilder(OpaqueBuilder opaque_builder,
42  OpaqueResult* out_result) {
43  using ReturnType =
44  tl::expected<typename Builder::Result, launchdarkly::Error>;
45 
46  static_assert(has_result_type<Builder>::value,
47  "Builder must have an associated type named Result");
48 
49  static_assert(
51  "Builder must have a Build method that returns "
52  "tl::expected<typename Builder::Result, launchdarkly::Error>");
53 
54  auto builder = reinterpret_cast<Builder*>(opaque_builder);
55 
56  tl::expected<typename Builder::Result, launchdarkly::Error> res =
57  builder->Build();
58 
59  delete builder;
60 
61  if (!res) {
62  *out_result = nullptr;
63  return reinterpret_cast<LDStatus>(new launchdarkly::Error(res.error()));
64  }
65 
66  *out_result = reinterpret_cast<OpaqueResult>(
67  new typename Builder::Result(std::move(res.value())));
68 
69  return LDStatus_Success();
70 }
71 
72 template <typename OptType, typename OutResult>
73 bool OptReturn(std::optional<OptType> const& opt, OutResult* out_param) {
74  if (opt) {
75  *out_param = *opt;
76  return true;
77  }
78  return false;
79 }
80 
81 template <typename OptType, typename OutResult>
82 bool OptReturnStaticCast(std::optional<OptType> const& opt,
83  OutResult* out_param) {
84  if (opt) {
85  *out_param = static_cast<OutResult>(*opt);
86  return true;
87  }
88  return false;
89 }
90 
91 template <typename OptType, typename OutResult>
92 bool OptReturnReinterpretCast(std::optional<OptType>& opt,
93  OutResult* out_param) {
94  if (opt) {
95  *out_param = reinterpret_cast<OutResult>(&(opt.value()));
96  return true;
97  }
98  return false;
99 }
100 
101 // Macro is named the same as in the C Server SDK.
102 
103 #ifdef LAUNCHDARKLY_USE_ASSERT
104 #define LD_ASSERT(cond) assert(cond)
105 #else
106 #define LD_ASSERT(cond)
107 #endif
108 
109 #define LD_ASSERT_NOT_NULL(param) LD_ASSERT(param != nullptr)
110 
111 } // namespace launchdarkly::detail
112 // NOLINTEND cppcoreguidelines-pro-type-reinterpret-cast
LDStatus_Success(void)
Definition: c_binding_helpers.hpp:20
Definition: c_binding_helpers.hpp:14