FastLED 3.10.6
Loading...
Searching...
No Matches
runtime_rpc_binding.cpp.hpp
Go to the documentation of this file.
1
8
10
11#include "fl/stl/string.h"
12#include "fl/stl/vector.h"
13
14namespace fl {
15namespace detail {
16
17namespace {
18
19// RAII cleanup for partially-constructed arg slots. Destroys + frees only
20// the slots actually constructed (tracked by `constructed`).
22 const RpcTypeOps* const* arg_types;
24 fl::size constructed;
25
29
31 for (fl::size i = 0; i < slots.size(); ++i) {
32 if (!slots[i]) continue;
33 if (i < constructed) arg_types[i]->destroy(slots[i]);
34 delete[] slots[i]; // ok bare allocation
35 }
36 }
37};
38
39} // namespace
40
43
44 if (!jsonArgs.is_array()) {
45 result.setError("arguments must be a JSON array");
46 return fl::make_tuple(result, json(nullptr));
47 }
48
49 fl::size received = jsonArgs.size();
50 if (received != mArgCount) {
51 result.setError("argument count mismatch: expected " +
52 fl::to_string(static_cast<fl::i64>(mArgCount)) +
53 ", got " + fl::to_string(static_cast<fl::i64>(received)));
54 return fl::make_tuple(result, json(nullptr));
55 }
56
58 fl::vector<void*> slot_ptrs;
59 raw_slots.reserve(mArgCount);
60 slot_ptrs.reserve(mArgCount);
61
62 RuntimeRpcSlotCleanup cleanup(mArgTypes, raw_slots);
63
64 for (fl::size i = 0; i < mArgCount; ++i) {
65 const RpcTypeOps* ops = mArgTypes[i];
66 // `operator new[]` on `unsigned char` returns memory aligned to at
67 // least alignof(max_align_t), which is sufficient for every type
68 // currently routable through `rpc_storage_type<T>::type`
69 // (fl::string, ints, floats, ConstCharPtrWrapper, ConstSpanWrapper).
70 // Raw byte buffer for placement-new of `T` -- ops drives lifetime.
71 unsigned char* buf = new unsigned char[ops->storage_size]; // ok bare allocation
72 raw_slots.push_back(buf);
73 slot_ptrs.push_back(buf);
74 ops->default_construct(buf);
75 cleanup.constructed = i + 1;
76
77 TypeConversionResult convResult = ops->decode(jsonArgs[i], buf);
78 for (fl::size w = 0; w < convResult.warnings().size(); ++w) {
79 result.addWarning("arg " + fl::to_string(static_cast<fl::i64>(i)) +
80 ": " + convResult.warnings()[w]);
81 }
82 if (convResult.hasError()) {
83 result.setError("arg " + fl::to_string(static_cast<fl::i64>(i)) +
84 ": " + convResult.errorMessage());
85 return fl::make_tuple(result, json(nullptr));
86 }
87 }
88
89 if (mResultType) {
90 // Raw byte buffer for placement-new of `R`; same pattern as arg slots.
91 unsigned char* result_buf = new unsigned char[mResultType->storage_size]; // ok bare allocation
92 mResultType->default_construct(result_buf);
93 mTrampoline(mUserFn, result_buf, slot_ptrs.data());
94 json jsonResult = mResultType->encode(result_buf);
95 mResultType->destroy(result_buf);
96 delete[] result_buf; // ok bare allocation
97 return fl::make_tuple(result, jsonResult);
98 }
99
100 mTrampoline(mUserFn, nullptr, slot_ptrs.data());
101 return fl::make_tuple(result, json(nullptr));
102}
103
104} // namespace detail
105} // namespace fl
const fl::string & errorMessage() const
const fl::vector< fl::string > & warnings() const
const RpcTypeOps *const * mArgTypes
fl::tuple< TypeConversionResult, json > invoke(const json &jsonArgs) FL_NO_EXCEPT override
void reserve(fl::size n) FL_NO_EXCEPT
Definition vector.h:591
T * data() FL_NO_EXCEPT
Definition vector.h:619
void push_back(const T &value) FL_NO_EXCEPT
Definition vector.h:624
Compile-time linker keep-alive hook for a single fl::Bus.
Definition bus_info.h:57
TypeConversionResult(* decode)(const json &src, void *dst)
void(* default_construct)(void *p)
expected< T, E > result
Alias for expected (Rust-style naming)
Definition result.h:31
InputGamut g FL_NO_EXCEPT
Definition rgbw.h:121
string to_string(T value) FL_NO_EXCEPT
Definition string.h:459
tuple< typename fl::decay< Ts >::type... > make_tuple(Ts &&... args) FL_NO_EXCEPT
Definition tuple.h:104
Base definition for an LED controller.
Definition crgb.hpp:179
RuntimeRpcSlotCleanup(const RpcTypeOps *const *types, fl::vector< unsigned char * > &s) FL_NO_EXCEPT