Files
2026-08-09 22:47:14 +08:00

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;
}
}