87 lines
3.1 KiB
C++
87 lines
3.1 KiB
C++
#pragma once
|
|
#include "adminive/json.hpp"
|
|
#include <string>
|
|
#include <string_view>
|
|
#include <type_traits>
|
|
#include <utility>
|
|
namespace adminive {
|
|
inline constexpr std::string_view status_protocol = "adminive.status";
|
|
inline constexpr int status_protocol_version = 1;
|
|
|
|
template <class T>
|
|
struct Status_Value {
|
|
using value_type = T;
|
|
T value{};
|
|
std::string color;
|
|
};
|
|
template <class T>
|
|
Status_Value<std::remove_cvref_t<T>> status_value(T&& value, std::string color = {}) {
|
|
return Status_Value<std::remove_cvref_t<T>>{std::forward<T>(value), std::move(color)};
|
|
}
|
|
template <class T>
|
|
struct Is_Status_Value : std::false_type {};
|
|
template <class T>
|
|
struct Is_Status_Value<Status_Value<T>> : std::true_type {};
|
|
template <class T>
|
|
concept Status_Value_Type = Is_Status_Value<std::remove_cvref_t<T>>::value;
|
|
template <class T>
|
|
struct Status_Inner_Value {
|
|
using type = std::remove_cvref_t<T>;
|
|
};
|
|
template <class T>
|
|
struct Status_Inner_Value<Status_Value<T>> {
|
|
using type = T;
|
|
};
|
|
template <class T>
|
|
using Status_Inner_Value_Type = typename Status_Inner_Value<std::remove_cvref_t<T>>::type;
|
|
template <Json_Type Json, class T>
|
|
Json encode_status_field(const T& value) {
|
|
Json result = json_object<Json>();
|
|
if constexpr(Status_Value_Type<T>) {
|
|
json_set(result, "value", encode_json_value<Json>(value.value));
|
|
json_set(result, "color", value.color);
|
|
} else {
|
|
json_set(result, "value", encode_json_value<Json>(value));
|
|
}
|
|
return result;
|
|
}
|
|
template <Json_Type Json, Described_Type T>
|
|
Json to_status_descriptor_json() {
|
|
const auto descriptor = describe<T>();
|
|
Json fields = json_array<Json>();
|
|
std::apply([&](const auto&... item) {
|
|
([&] {
|
|
using Field = std::remove_cvref_t<decltype(item)>;
|
|
using Member = typename Field::member_type;
|
|
using Value = Status_Inner_Value_Type<Member>;
|
|
Json field = json_object<Json>();
|
|
json_set(field, "name", item.name());
|
|
json_set(field, "label", item.label());
|
|
json_set(field, "value_type", value_type_name<Json, Value>());
|
|
json_set(field, "color", Status_Value_Type<Member>);
|
|
if(!item.description().empty()) {
|
|
json_set(field, "description", item.description());
|
|
}
|
|
json_append(fields, std::move(field));
|
|
}(), ...);
|
|
}, descriptor.fields());
|
|
Json result = json_object<Json>();
|
|
json_set(result, "protocol", status_protocol);
|
|
json_set(result, "protocol_version", status_protocol_version);
|
|
json_set(result, "name", descriptor.name());
|
|
json_set(result, "label", descriptor.label());
|
|
json_set(result, "value_type", "status_object");
|
|
json_set(result, "fields", std::move(fields));
|
|
return result;
|
|
}
|
|
template <Json_Type Json, Described_Type T>
|
|
Json to_status_json(const T& value) {
|
|
const auto descriptor = describe<T>();
|
|
Json result = json_object<Json>();
|
|
std::apply([&](const auto&... item) {
|
|
(json_set(result, item.name(), encode_status_field<Json>(item.get(value))), ...);
|
|
}, descriptor.fields());
|
|
return result;
|
|
}
|
|
}
|