拆分核心库和服务
This commit is contained in:
@@ -0,0 +1,294 @@
|
||||
#include "adminive/adminive.hpp"
|
||||
#include <cassert>
|
||||
#include <cstdint>
|
||||
#include <map>
|
||||
#include <optional>
|
||||
#include <stdexcept>
|
||||
#include <string>
|
||||
#include <string_view>
|
||||
#include <type_traits>
|
||||
#include <utility>
|
||||
#include <variant>
|
||||
#include <vector>
|
||||
namespace adapter_test {
|
||||
struct Mini_Json;
|
||||
using Mini_Object = std::map<std::string, Mini_Json>;
|
||||
using Mini_Array = std::vector<Mini_Json>;
|
||||
struct Mini_Json {
|
||||
using Storage = std::variant<std::nullptr_t, bool, std::int64_t, std::uint64_t, long double, std::string, Mini_Object, Mini_Array>;
|
||||
Storage value{};
|
||||
};
|
||||
struct External_Atomic {
|
||||
int value{};
|
||||
};
|
||||
enum class Mode {
|
||||
primary = 10,
|
||||
secondary = 20
|
||||
};
|
||||
struct Runtime_Base {
|
||||
External_Atomic worker_count{4};
|
||||
};
|
||||
struct Mode_Base {
|
||||
Mode mode{Mode::primary};
|
||||
};
|
||||
struct Config : Runtime_Base, Mode_Base {
|
||||
std::string name{"default"};
|
||||
};
|
||||
}
|
||||
namespace adminive {
|
||||
template <>
|
||||
struct Json_Adapter<adapter_test::Mini_Json> {
|
||||
using Json = adapter_test::Mini_Json;
|
||||
static Json object() {
|
||||
return Json{adapter_test::Mini_Object{}};
|
||||
}
|
||||
static Json array() {
|
||||
return Json{adapter_test::Mini_Array{}};
|
||||
}
|
||||
static Json null() {
|
||||
return Json{nullptr};
|
||||
}
|
||||
static Json parse(std::string_view) {
|
||||
throw std::runtime_error("parse is not implemented by the test adapter");
|
||||
}
|
||||
static std::string dump(const Json&, int) {
|
||||
return {};
|
||||
}
|
||||
static bool is_null(const Json& value) noexcept {
|
||||
return std::holds_alternative<std::nullptr_t>(value.value);
|
||||
}
|
||||
static bool is_object(const Json& value) noexcept {
|
||||
return std::holds_alternative<adapter_test::Mini_Object>(value.value);
|
||||
}
|
||||
static bool is_array(const Json& value) noexcept {
|
||||
return std::holds_alternative<adapter_test::Mini_Array>(value.value);
|
||||
}
|
||||
static bool is_string(const Json& value) noexcept {
|
||||
return std::holds_alternative<std::string>(value.value);
|
||||
}
|
||||
static bool is_signed_integer(const Json& value) noexcept {
|
||||
return std::holds_alternative<std::int64_t>(value.value);
|
||||
}
|
||||
static bool is_unsigned_integer(const Json& value) noexcept {
|
||||
return std::holds_alternative<std::uint64_t>(value.value);
|
||||
}
|
||||
static bool is_floating_point(const Json& value) noexcept {
|
||||
return std::holds_alternative<long double>(value.value);
|
||||
}
|
||||
static bool is_number(const Json& value) noexcept {
|
||||
return is_signed_integer(value) || is_unsigned_integer(value) || is_floating_point(value);
|
||||
}
|
||||
static bool is_boolean(const Json& value) noexcept {
|
||||
return std::holds_alternative<bool>(value.value);
|
||||
}
|
||||
static std::int64_t signed_integer(const Json& value) {
|
||||
return std::get<std::int64_t>(value.value);
|
||||
}
|
||||
static std::uint64_t unsigned_integer(const Json& value) {
|
||||
return std::get<std::uint64_t>(value.value);
|
||||
}
|
||||
static long double number(const Json& value) {
|
||||
if(is_signed_integer(value)) {
|
||||
return static_cast<long double>(signed_integer(value));
|
||||
}
|
||||
if(is_unsigned_integer(value)) {
|
||||
return static_cast<long double>(unsigned_integer(value));
|
||||
}
|
||||
return std::get<long double>(value.value);
|
||||
}
|
||||
static bool contains(const Json& value, std::string_view name) {
|
||||
const auto& object_value = std::get<adapter_test::Mini_Object>(value.value);
|
||||
return object_value.contains(std::string(name));
|
||||
}
|
||||
static std::size_t size(const Json& value) {
|
||||
if(is_object(value)) {
|
||||
return std::get<adapter_test::Mini_Object>(value.value).size();
|
||||
}
|
||||
if(is_array(value)) {
|
||||
return std::get<adapter_test::Mini_Array>(value.value).size();
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
static std::vector<std::string> keys(const Json& value) {
|
||||
std::vector<std::string> result;
|
||||
for(const auto& [name, item] : std::get<adapter_test::Mini_Object>(value.value)) {
|
||||
static_cast<void>(item);
|
||||
result.push_back(name);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
static Json& at(Json& value, std::string_view name) {
|
||||
return std::get<adapter_test::Mini_Object>(value.value).at(std::string(name));
|
||||
}
|
||||
static const Json& at(const Json& value, std::string_view name) {
|
||||
return std::get<adapter_test::Mini_Object>(value.value).at(std::string(name));
|
||||
}
|
||||
static Json& at(Json& value, std::size_t index) {
|
||||
return std::get<adapter_test::Mini_Array>(value.value).at(index);
|
||||
}
|
||||
static const Json& at(const Json& value, std::size_t index) {
|
||||
return std::get<adapter_test::Mini_Array>(value.value).at(index);
|
||||
}
|
||||
static void set(Json& value, std::string_view name, Json item) {
|
||||
std::get<adapter_test::Mini_Object>(value.value).insert_or_assign(std::string(name), std::move(item));
|
||||
}
|
||||
static void append(Json& value, Json item) {
|
||||
std::get<adapter_test::Mini_Array>(value.value).push_back(std::move(item));
|
||||
}
|
||||
static void erase(Json& value, std::string_view name) {
|
||||
std::get<adapter_test::Mini_Object>(value.value).erase(std::string(name));
|
||||
}
|
||||
template <class T>
|
||||
static Json make(T&& value) {
|
||||
using Value = std::remove_cvref_t<T>;
|
||||
if constexpr(std::same_as<Value, bool>) {
|
||||
return Json{value};
|
||||
} else if constexpr(std::signed_integral<Value>) {
|
||||
return Json{static_cast<std::int64_t>(value)};
|
||||
} else if constexpr(std::unsigned_integral<Value>) {
|
||||
return Json{static_cast<std::uint64_t>(value)};
|
||||
} else if constexpr(std::floating_point<Value>) {
|
||||
return Json{static_cast<long double>(value)};
|
||||
} else if constexpr(std::same_as<Value, std::string>) {
|
||||
return Json{std::forward<T>(value)};
|
||||
} else if constexpr(std::same_as<Value, std::string_view>) {
|
||||
return Json{std::string(value)};
|
||||
} else if constexpr(std::is_convertible_v<T, const char*>) {
|
||||
return Json{std::string(value)};
|
||||
} else {
|
||||
static_assert(!sizeof(T), "unsupported Mini_Json scalar");
|
||||
}
|
||||
}
|
||||
template <class T>
|
||||
static T get(const Json& value) {
|
||||
if constexpr(std::same_as<T, bool>) {
|
||||
return std::get<bool>(value.value);
|
||||
} else if constexpr(std::signed_integral<T>) {
|
||||
return static_cast<T>(std::get<std::int64_t>(value.value));
|
||||
} else if constexpr(std::unsigned_integral<T>) {
|
||||
return static_cast<T>(std::get<std::uint64_t>(value.value));
|
||||
} else if constexpr(std::floating_point<T>) {
|
||||
return static_cast<T>(number(value));
|
||||
} else if constexpr(std::same_as<T, std::string>) {
|
||||
return std::get<std::string>(value.value);
|
||||
} else {
|
||||
static_assert(!sizeof(T), "unsupported Mini_Json conversion");
|
||||
}
|
||||
}
|
||||
};
|
||||
template <class Json>
|
||||
struct Value_Adapter<adapter_test::External_Atomic, Json> {
|
||||
using value_type = int;
|
||||
static int read(const adapter_test::External_Atomic& value) noexcept {
|
||||
return value.value;
|
||||
}
|
||||
static void write(adapter_test::External_Atomic& target, int value) noexcept {
|
||||
target.value = value;
|
||||
}
|
||||
};
|
||||
template <>
|
||||
struct Enum_Adapter<adapter_test::Mode> {
|
||||
static std::vector<adapter_test::Mode> values() {
|
||||
return {adapter_test::Mode::primary, adapter_test::Mode::secondary};
|
||||
}
|
||||
static std::string_view name(adapter_test::Mode value) {
|
||||
return value == adapter_test::Mode::primary ? "primary" : "secondary";
|
||||
}
|
||||
static std::optional<adapter_test::Mode> cast(std::string_view value) {
|
||||
if(value == "primary") {
|
||||
return adapter_test::Mode::primary;
|
||||
}
|
||||
if(value == "secondary") {
|
||||
return adapter_test::Mode::secondary;
|
||||
}
|
||||
return std::nullopt;
|
||||
}
|
||||
static std::optional<adapter_test::Mode> cast(std::underlying_type_t<adapter_test::Mode> value) {
|
||||
if(value == 10) {
|
||||
return adapter_test::Mode::primary;
|
||||
}
|
||||
if(value == 20) {
|
||||
return adapter_test::Mode::secondary;
|
||||
}
|
||||
return std::nullopt;
|
||||
}
|
||||
};
|
||||
template <>
|
||||
struct Reflection_Adapter<adapter_test::Config> {
|
||||
static constexpr std::size_t field_count = 3;
|
||||
template <std::size_t Index>
|
||||
static decltype(auto) get(adapter_test::Config& value) noexcept {
|
||||
if constexpr(Index == 0) {
|
||||
return (value.worker_count);
|
||||
} else if constexpr(Index == 1) {
|
||||
return (value.mode);
|
||||
} else {
|
||||
return (value.name);
|
||||
}
|
||||
}
|
||||
template <std::size_t Index>
|
||||
static decltype(auto) get(const adapter_test::Config& value) noexcept {
|
||||
if constexpr(Index == 0) {
|
||||
return (value.worker_count);
|
||||
} else if constexpr(Index == 1) {
|
||||
return (value.mode);
|
||||
} else {
|
||||
return (value.name);
|
||||
}
|
||||
}
|
||||
template <std::size_t Index>
|
||||
static constexpr std::string_view name() noexcept {
|
||||
if constexpr(Index == 0) {
|
||||
return "worker_count";
|
||||
} else if constexpr(Index == 1) {
|
||||
return "mode";
|
||||
} else {
|
||||
return "name";
|
||||
}
|
||||
}
|
||||
};
|
||||
template <>
|
||||
struct Type_Descriptor<adapter_test::Config> {
|
||||
static auto get() {
|
||||
using T = adapter_test::Config;
|
||||
return reflected_object_with<T>("config", "配置", []<std::size_t Index>(auto field) {
|
||||
if constexpr(Index == 0) {
|
||||
return field.label("线程数").editable().required();
|
||||
} else if constexpr(Index == 1) {
|
||||
return field.label("模式").editable().template enum_label<adapter_test::Mode::primary>("主用").template enum_label<adapter_test::Mode::secondary>("备用");
|
||||
} else {
|
||||
return field.label("名称").editable();
|
||||
}
|
||||
});
|
||||
}
|
||||
};
|
||||
}
|
||||
int main() {
|
||||
using Json = adapter_test::Mini_Json;
|
||||
using Config = adapter_test::Config;
|
||||
const Json descriptor = adminive::to_descriptor_json_with_defaults<Json, Config>();
|
||||
const auto& fields = adminive::Json_Adapter<Json>::at(descriptor, "fields");
|
||||
assert((adminive::json_get<Json, std::string>(adminive::Json_Adapter<Json>::at(adminive::Json_Adapter<Json>::at(fields, 0), "name")) == "worker_count"));
|
||||
assert((adminive::json_get<Json, int>(adminive::Json_Adapter<Json>::at(adminive::Json_Adapter<Json>::at(fields, 0), "default")) == 4));
|
||||
const auto& options = adminive::Json_Adapter<Json>::at(adminive::Json_Adapter<Json>::at(fields, 1), "options");
|
||||
assert((adminive::json_get<Json, std::string>(adminive::Json_Adapter<Json>::at(adminive::Json_Adapter<Json>::at(options, 0), "label")) == "主用"));
|
||||
Config config;
|
||||
Json patch = adminive::json_object<Json>();
|
||||
adminive::json_set(patch, "worker_count", 12);
|
||||
adminive::json_set(patch, "mode", "secondary");
|
||||
adminive::json_set(patch, "name", "updated");
|
||||
const auto result = adminive::apply_frontend_patch<Json>(config, patch);
|
||||
assert(result.success);
|
||||
assert(config.worker_count.value == 12);
|
||||
assert(config.mode == adapter_test::Mode::secondary);
|
||||
assert(config.name == "updated");
|
||||
const Json encoded = adminive::to_json<Json>(config);
|
||||
assert((adminive::json_get<Json, int>(adminive::Json_Adapter<Json>::at(encoded, "worker_count")) == 12));
|
||||
assert((adminive::json_get<Json, std::string>(adminive::Json_Adapter<Json>::at(encoded, "mode")) == "secondary"));
|
||||
adminive::Collection_Service<Config, Json, adminive::Empty_Lock> collection("/configs", {Config{}});
|
||||
const auto list = collection.list_response();
|
||||
assert(list.status == 200);
|
||||
const auto& data = adminive::Json_Adapter<Json>::at(list.body, "data");
|
||||
assert((adminive::json_get<Json, std::uint64_t>(adminive::Json_Adapter<Json>::at(data, "total")) == 1));
|
||||
return 0;
|
||||
}
|
||||
Reference in New Issue
Block a user