Files
Adminive/backend/include/adminive/status.hpp
T
2026-08-06 16:01:04 +08:00

95 lines
3.3 KiB
C++

#pragma once
#include "adminive/json.hpp"
#include <functional>
#include <string>
#include <type_traits>
#include <utility>
namespace adminive {
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 <class T>
Json encode_status_field(const T& value) {
if constexpr(Status_Value_Type<T>) {
return Json{{"value", encode_json_value(value.value)}, {"color", value.color}};
} else {
return Json{{"value", encode_json_value(value)}};
}
}
template <Described_Type T>
Json to_status_descriptor_json() {
const auto descriptor = describe<T>();
Json fields = Json::array();
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{{"name", item.name()}, {"label", item.label()}, {"value_type", value_type_name<Value>()}, {"color", Status_Value_Type<Member>}};
if(!item.description().empty()) {
field_json["description"] = item.description();
}
fields.push_back(std::move(field_json));
}(), ...);
}, descriptor.fields());
return Json{{"protocol", "adminive.status"}, {"protocol_version", 1}, {"name", descriptor.name()}, {"label", descriptor.label()}, {"value_type", "status_object"}, {"fields", std::move(fields)}};
}
template <Described_Type T>
Json to_status_json(const T& value) {
const auto descriptor = describe<T>();
Json result = Json::object();
std::apply([&](const auto&... item) {
([&] {
using Field = std::remove_cvref_t<decltype(item)>;
result[item.name()] = encode_status_field(value.*Field::member);
}(), ...);
}, descriptor.fields());
return result;
}
template <auto Function>
struct Member_Function_Traits;
template <class Owner, class Result, Result (Owner::*Function)()>
struct Member_Function_Traits<Function> {
using owner_type = Owner;
using result_type = Result;
};
template <class Owner, class Result, Result (Owner::*Function)() const>
struct Member_Function_Traits<Function> {
using owner_type = Owner;
using result_type = Result;
};
template <class Owner, class Result, Result (Owner::*Function)() noexcept>
struct Member_Function_Traits<Function> {
using owner_type = Owner;
using result_type = Result;
};
template <class Owner, class Result, Result (Owner::*Function)() const noexcept>
struct Member_Function_Traits<Function> {
using owner_type = Owner;
using result_type = Result;
};
}