FastLED 3.9.15
Loading...
Searching...
No Matches
json_arg_converter.h
Go to the documentation of this file.
1#pragma once
2
3#include "fl/stl/json.h"
4#include "fl/stl/stdint.h"
5#include "fl/stl/string.h"
6#include "fl/stl/tuple.h"
10#include "fl/stl/span.h"
11
12namespace fl {
13
14// Type mapper for RPC parameters:
15// - const char* / char* → ConstCharPtrWrapper (stores string, converts to ptr)
16// - span<const T> → ConstSpanWrapper<T> (stores vector, provides span view)
17// - Other types → strip const/reference
18template <typename T>
22
23template <>
24struct rpc_storage_type<const char*> {
26};
27
28template <>
29struct rpc_storage_type<char*> {
31};
32
33// Specializations for span<const T>
34template <typename T>
35struct rpc_storage_type<fl::span<const T>> {
37};
38
39// Common span specializations for explicit types
40template <>
41struct rpc_storage_type<fl::span<const int>> {
43};
44
45template <>
46struct rpc_storage_type<fl::span<const float>> {
48};
49
50template <>
51struct rpc_storage_type<fl::span<const double>> {
53};
54
55template <>
56struct rpc_storage_type<fl::span<const fl::string>> {
58};
59
60// =============================================================================
61// JsonArgConverter - Convert JSON array to typed tuple
62// =============================================================================
63
64template <typename Signature>
66
67template <typename R, typename... Args>
68class JsonArgConverter<R(Args...)> {
69public:
70 // Map Args to storage types (handles const char* → ConstCharPtrWrapper)
72 static constexpr fl::size argCount() { return sizeof...(Args); }
73
74 static fl::tuple<args_tuple, TypeConversionResult> convert(const json& jsonArgs) {
76 // Value-init so the early-return branches below (not an array,
77 // arg-count mismatch) don't return an indeterminate tuple —
78 // convertArgs() is the only writer and runs after the bail-outs. #2722
79 args_tuple tuple{};
80
81 if (!jsonArgs.is_array()) {
82 result.setError("arguments must be a JSON array");
83 return fl::make_tuple(tuple, result);
84 }
85
86 fl::size count = jsonArgs.size();
87 if (count != sizeof...(Args)) {
88 result.setError("argument count mismatch: expected " +
89 fl::to_string(static_cast<i64>(sizeof...(Args))) +
90 ", got " + fl::to_string(static_cast<i64>(count)));
91 return fl::make_tuple(tuple, result);
92 }
93
94 convertArgs(jsonArgs, tuple, result, make_index_sequence<sizeof...(Args)>{});
95 return fl::make_tuple(tuple, result);
96 }
97
98private:
99 template <fl::size... Is>
100 static void convertArgs(const json& jsonArgs, args_tuple& tuple,
101 TypeConversionResult& result, index_sequence<Is...>) {
102 // Fold expression equivalent using initializer list
103 int dummy[] = {0, (convertArg<Is>(jsonArgs, tuple, result), 0)...};
104 (void)dummy;
105 }
106
107 template <fl::size I>
108 static void convertArg(const json& jsonArgs, args_tuple& tuple, TypeConversionResult& result) {
109 if (result.hasError()) return;
110
111 // Use the stripped type (no const/ref) for conversion and storage
112 using StorageType = typename fl::tuple_element<I, args_tuple>::type;
113 // C++11 compatible: avoid structured bindings
114 fl::tuple<StorageType, TypeConversionResult> convTuple = detail::JsonToType<StorageType>::convert(jsonArgs[I]);
115 StorageType value = fl::get<0>(convTuple);
116 TypeConversionResult convResult = fl::get<1>(convTuple);
117
118 fl::get<I>(tuple) = value;
119
120 // Add argument index to warnings/errors
121 for (fl::size i = 0; i < convResult.warnings().size(); i++) {
122 result.addWarning("arg " + fl::to_string(static_cast<i64>(I)) + ": " + convResult.warnings()[i]);
123 }
124 if (convResult.hasError()) {
125 result.setError("arg " + fl::to_string(static_cast<i64>(I)) + ": " + convResult.errorMessage());
126 }
127 }
128};
129
130// Specialization for void() - no arguments
131template <typename R>
133public:
134 using args_tuple = fl::tuple<>;
135 static constexpr fl::size argCount() { return 0; }
136
139 // Value-init so the early-return branches below (not an array,
140 // arg-count mismatch) don't return an indeterminate tuple —
141 // convertArgs() is the only writer and runs after the bail-outs. #2722
143
144 if (!jsonArgs.is_array()) {
145 result.setError("arguments must be a JSON array");
146 return fl::make_tuple(tuple, result);
147 }
148
149 if (jsonArgs.size() != 0) {
150 result.setError("argument count mismatch: expected 0, got " +
151 fl::to_string(static_cast<i64>(jsonArgs.size())));
152 }
153
154 return fl::make_tuple(tuple, result);
155 }
156};
157
158} // namespace fl
static constexpr fl::size argCount()
static fl::tuple< args_tuple, TypeConversionResult > convert(const json &jsonArgs)
bool is_array() const FL_NOEXCEPT
Definition json.h:246
size_t size() const FL_NOEXCEPT
Definition json.h:633
FastLED's Elegant JSON Library: fl::json
string to_string(T value) FL_NOEXCEPT
Definition string.h:450
constexpr int type_rank< T >::value
fl::i64 i64
Definition s16x16x4.h:222
tuple< typename fl::decay< Ts >::type... > make_tuple(Ts &&... args) FL_NOEXCEPT
Definition tuple.h:104
expected< T, E > result
Alias for expected (Rust-style naming)
Definition result.h:31
typename make_index_sequence_impl< N >::type make_index_sequence
pair_element< I, T1, T2 >::type & get(pair< T1, T2 > &p) FL_NOEXCEPT
Definition pair.h:115
Base definition for an LED controller.
Definition crgb.hpp:179
typename fl::remove_cv< typename fl::remove_reference< T >::type >::type type
static fl::tuple< T, TypeConversionResult > convert(const json &j)