mirror of
https://github.com/oatpp/oatpp.git
synced 2025-02-11 17:20:52 +08:00
dto::Enum. Enum interpreters POC.
This commit is contained in:
parent
66d34683f7
commit
bfcb159b48
@ -48,7 +48,7 @@ namespace __class {
|
||||
|
||||
};
|
||||
|
||||
template<class T>
|
||||
template<class T, class Interpreter>
|
||||
class Enum;
|
||||
|
||||
}
|
||||
@ -63,19 +63,24 @@ struct EnumValueInfo {
|
||||
template<typename T>
|
||||
struct EnumInfo {
|
||||
public:
|
||||
const char* nameQualifier;
|
||||
const char* nameQualifier = nullptr;
|
||||
std::unordered_map<data::share::StringKeyLabel, EnumValueInfo<T>> byName;
|
||||
std::unordered_map<v_uint64, EnumValueInfo<T>> byValue;
|
||||
std::vector<EnumValueInfo<T>> byIndex;
|
||||
};
|
||||
|
||||
template<class T>
|
||||
class Enum; // FWD
|
||||
template<class T, class Interpreter>
|
||||
class EnumObjectWrapper; // FWD
|
||||
|
||||
template<class T>
|
||||
class EnumMeta {
|
||||
friend __class::Enum<T>;
|
||||
friend Enum<T>;
|
||||
|
||||
template<class Type, class Interpreter>
|
||||
friend class __class::Enum;
|
||||
|
||||
template<class Type, class Interpreter>
|
||||
friend class EnumObjectWrapper;
|
||||
|
||||
public:
|
||||
typedef T EnumType;
|
||||
protected:
|
||||
@ -85,10 +90,40 @@ protected:
|
||||
template<class T>
|
||||
EnumInfo<T> EnumMeta<T>::__info;
|
||||
|
||||
template<class T>
|
||||
class Enum : public ObjectWrapper<T, __class::Enum<T>>{
|
||||
template<class T, bool nullable>
|
||||
class EnumInterpreterAsString {
|
||||
public:
|
||||
template <bool N>
|
||||
using InterpreterType = EnumInterpreterAsString<T, N>;
|
||||
public:
|
||||
constexpr static bool isNullable = nullable;
|
||||
public:
|
||||
static Void toInterpretation(T value);
|
||||
static T fromInterpretation(const Void& value);
|
||||
};
|
||||
|
||||
template<class T, bool nullable>
|
||||
class EnumInterpreterAsInteger {
|
||||
public:
|
||||
template <bool N>
|
||||
using InterpreterType = EnumInterpreterAsInteger<T, N>;
|
||||
public:
|
||||
constexpr static bool isNullable = nullable;
|
||||
public:
|
||||
static Void toInterpretation(T value);
|
||||
static T fromInterpretation(const Void& value);
|
||||
};
|
||||
|
||||
template<class T, class EnumInterpreter>
|
||||
class EnumObjectWrapper : public ObjectWrapper<T, __class::Enum<T, EnumInterpreter>>{
|
||||
public:
|
||||
typedef typename std::underlying_type<T>::type UnderlyingType;
|
||||
typedef __class::Enum<T, EnumInterpreter> EnumObjectClass;
|
||||
typedef EnumInterpreter Interpreter;
|
||||
public:
|
||||
typedef EnumObjectWrapper<T, EnumInterpreterAsString<T, true>> AsString;
|
||||
typedef EnumObjectWrapper<T, EnumInterpreterAsInteger<T, true>> AsInteger;
|
||||
typedef EnumObjectWrapper<T, typename EnumInterpreter::template InterpreterType<false>> NotNull;
|
||||
public:
|
||||
|
||||
static EnumValueInfo<T> getEntryByName(const String& name) {
|
||||
@ -128,9 +163,49 @@ public:
|
||||
|
||||
};
|
||||
|
||||
template <class T>
|
||||
using Enum = EnumObjectWrapper<T, EnumInterpreterAsString<T, true>>;
|
||||
|
||||
template<class T, bool nullable>
|
||||
Void EnumInterpreterAsString<T, nullable>::toInterpretation(T value) {
|
||||
const auto& entry = EnumObjectWrapper<T, EnumInterpreterAsString<T, nullable>>::getEntryByValue(value);
|
||||
return entry.name.toString();
|
||||
}
|
||||
|
||||
template<class T, bool nullable>
|
||||
T EnumInterpreterAsString<T, nullable>::fromInterpretation(const Void& value) {
|
||||
if(value.valueType != String::Class::getType()) {
|
||||
throw std::runtime_error("[oatpp::data::mapping::type::EnumInterpreterAsString::fromInterpretation()]: Error. Interpretation must be a String.");
|
||||
}
|
||||
const auto& entry = EnumObjectWrapper<T, EnumInterpreterAsString<T, nullable>>::getEntryByName(value.staticCast<String>());
|
||||
return entry.value;
|
||||
}
|
||||
|
||||
template<class T, bool nullable>
|
||||
Void EnumInterpreterAsInteger<T, nullable>::toInterpretation(T value) {
|
||||
const auto& entry = EnumObjectWrapper<T, EnumInterpreterAsString<T, nullable>>::getEntryByValue(value);
|
||||
typedef typename std::underlying_type<T>::type EnumUT;
|
||||
typedef typename ObjectWrapperByUnderlyingType<EnumUT>::ObjectWrapper OW;
|
||||
OW result(static_cast<EnumUT>(value));
|
||||
return result;
|
||||
}
|
||||
|
||||
template<class T, bool nullable>
|
||||
T EnumInterpreterAsInteger<T, nullable>::fromInterpretation(const Void& value) {
|
||||
|
||||
typedef typename std::underlying_type<T>::type EnumUT;
|
||||
typedef typename ObjectWrapperByUnderlyingType<EnumUT>::ObjectWrapper OW;
|
||||
|
||||
if(value.valueType != OW::Class::getType()) {
|
||||
throw std::runtime_error("[oatpp::data::mapping::type::EnumInterpreterAsInteger::fromInterpretation()]: Error. Interpretation value type doesn't match.");
|
||||
}
|
||||
const auto& entry = EnumObjectWrapper<T, EnumInterpreterAsString<T, nullable>>::getEntryByUnderlyingValue(value.staticCast<OW>());
|
||||
return entry.value;
|
||||
}
|
||||
|
||||
namespace __class {
|
||||
|
||||
template<class T>
|
||||
template<class T, class Interpreter>
|
||||
class Enum : public AbstractEnum {
|
||||
private:
|
||||
|
||||
|
@ -166,6 +166,8 @@ String operator + (const String& a, const String& b);
|
||||
*/
|
||||
template<typename TValueType, class Clazz>
|
||||
class Primitive : public type::ObjectWrapper<TValueType, Clazz> {
|
||||
public:
|
||||
typedef TValueType UnderlyingType;
|
||||
public:
|
||||
|
||||
OATPP_DEFINE_OBJECT_WRAPPER_DEFAULTS(Primitive, TValueType, Clazz)
|
||||
@ -239,6 +241,8 @@ public:
|
||||
* ObjectWrapper for Boolean.
|
||||
*/
|
||||
class Boolean : public type::ObjectWrapper<bool, __class::Boolean> {
|
||||
public:
|
||||
typedef bool UnderlyingType;
|
||||
public:
|
||||
|
||||
OATPP_DEFINE_OBJECT_WRAPPER_DEFAULTS(Boolean, bool, __class::Boolean)
|
||||
@ -354,6 +358,52 @@ typedef Primitive<v_float32, __class::Float32> Float32;
|
||||
* Float64 is an ObjectWrapper over `v_float64` and __class::Float64.
|
||||
*/
|
||||
typedef Primitive<v_float64, __class::Float64> Float64;
|
||||
|
||||
|
||||
template<>
|
||||
struct ObjectWrapperByUnderlyingType <v_int8> {
|
||||
typedef Int8 ObjectWrapper;
|
||||
};
|
||||
|
||||
template<>
|
||||
struct ObjectWrapperByUnderlyingType <v_uint8> {
|
||||
typedef UInt8 ObjectWrapper;
|
||||
};
|
||||
|
||||
template<>
|
||||
struct ObjectWrapperByUnderlyingType <v_int16> {
|
||||
typedef Int16 ObjectWrapper;
|
||||
};
|
||||
|
||||
template<>
|
||||
struct ObjectWrapperByUnderlyingType <v_uint16> {
|
||||
typedef UInt16 ObjectWrapper;
|
||||
};
|
||||
|
||||
template<>
|
||||
struct ObjectWrapperByUnderlyingType <v_int32> {
|
||||
typedef Int32 ObjectWrapper;
|
||||
};
|
||||
|
||||
template<>
|
||||
struct ObjectWrapperByUnderlyingType <v_uint32> {
|
||||
typedef UInt32 ObjectWrapper;
|
||||
};
|
||||
|
||||
template<>
|
||||
struct ObjectWrapperByUnderlyingType <v_int64> {
|
||||
typedef Int64 ObjectWrapper;
|
||||
};
|
||||
|
||||
template<>
|
||||
struct ObjectWrapperByUnderlyingType <v_uint64> {
|
||||
typedef UInt64 ObjectWrapper;
|
||||
};
|
||||
|
||||
template<>
|
||||
struct ObjectWrapperByUnderlyingType <bool> {
|
||||
typedef Boolean ObjectWrapper;
|
||||
};
|
||||
|
||||
namespace __class {
|
||||
|
||||
|
@ -219,6 +219,9 @@ public:
|
||||
|
||||
typedef ObjectWrapper<void, __class::Void> Void;
|
||||
|
||||
template <typename T>
|
||||
struct ObjectWrapperByUnderlyingType {};
|
||||
|
||||
/**
|
||||
* Object type data.
|
||||
*/
|
||||
|
@ -15,6 +15,8 @@ add_executable(oatppAllTests
|
||||
oatpp/core/data/buffer/ProcessorTest.hpp
|
||||
oatpp/core/data/mapping/type/AnyTest.cpp
|
||||
oatpp/core/data/mapping/type/AnyTest.hpp
|
||||
oatpp/core/data/mapping/type/EnumTest.cpp
|
||||
oatpp/core/data/mapping/type/EnumTest.hpp
|
||||
oatpp/core/data/mapping/type/ListTest.cpp
|
||||
oatpp/core/data/mapping/type/ListTest.hpp
|
||||
oatpp/core/data/mapping/type/ObjectWrapperTest.cpp
|
||||
|
@ -47,6 +47,7 @@
|
||||
#include "oatpp/core/data/mapping/type/ObjectWrapperTest.hpp"
|
||||
#include "oatpp/core/data/mapping/type/TypeTest.hpp"
|
||||
#include "oatpp/core/data/mapping/type/AnyTest.hpp"
|
||||
#include "oatpp/core/data/mapping/type/EnumTest.hpp"
|
||||
|
||||
#include "oatpp/core/base/collection/LinkedListTest.hpp"
|
||||
#include "oatpp/core/base/memory/MemoryPoolTest.hpp"
|
||||
@ -91,31 +92,6 @@ void runTests() {
|
||||
OATPP_LOGD("aaa", "coroutine size=%d", sizeof(oatpp::async::AbstractCoroutine));
|
||||
OATPP_LOGD("aaa", "action size=%d", sizeof(oatpp::async::Action));
|
||||
|
||||
v_uint16 v = static_cast<v_uint16>(MyEnum1::CODE_3);
|
||||
|
||||
OATPP_LOGD("AAA", "name='%s'", oatpp::Enum<MyEnum1>::Class::getType()->nameQualifier);
|
||||
OATPP_LOGD("AAA", "name='%s'", oatpp::Enum<MyEnum2>::Class::getType()->nameQualifier);
|
||||
|
||||
{
|
||||
auto entry = oatpp::Enum<MyEnum1>::getEntryByName("Error - code 1");
|
||||
OATPP_LOGD("Entry", "name='%s', value=%d, index=%d", entry.name.toString()->getData(), entry.value, entry.index);
|
||||
}
|
||||
|
||||
{
|
||||
auto entry = oatpp::Enum<MyEnum1>::getEntryByValue(MyEnum1::CODE_3);
|
||||
OATPP_LOGD("Entry", "name='%s', value=%d, index=%d", entry.name.toString()->getData(), entry.value, entry.index);
|
||||
}
|
||||
|
||||
{
|
||||
auto entry = oatpp::Enum<MyEnum1>::getEntryByIndex(2);
|
||||
OATPP_LOGD("Entry", "name='%s', value=%d, index=%d", entry.name.toString()->getData(), entry.value, entry.index);
|
||||
}
|
||||
|
||||
{
|
||||
auto entry = oatpp::Enum<MyEnum1>::getEntryByUnderlyingValue(1003);
|
||||
OATPP_LOGD("Entry", "name='%s', value=%d, index=%d", entry.name.toString()->getData(), entry.value, entry.index);
|
||||
}
|
||||
|
||||
/*
|
||||
OATPP_RUN_TEST(oatpp::test::base::CommandLineArgumentsTest);
|
||||
|
||||
@ -135,14 +111,16 @@ void runTests() {
|
||||
|
||||
OATPP_RUN_TEST(oatpp::test::core::data::mapping::type::ObjectWrapperTest);
|
||||
OATPP_RUN_TEST(oatpp::test::core::data::mapping::type::TypeTest);
|
||||
OATPP_RUN_TEST(oatpp::test::core::data::mapping::type::AnyTest);
|
||||
OATPP_RUN_TEST(oatpp::test::core::data::mapping::type::StringTest);
|
||||
OATPP_RUN_TEST(oatpp::test::core::data::mapping::type::PrimitiveTest);
|
||||
OATPP_RUN_TEST(oatpp::test::core::data::mapping::type::ListTest);
|
||||
OATPP_RUN_TEST(oatpp::test::core::data::mapping::type::VectorTest);
|
||||
OATPP_RUN_TEST(oatpp::test::core::data::mapping::type::PairListTest);
|
||||
OATPP_RUN_TEST(oatpp::test::core::data::mapping::type::UnorderedMapTest);
|
||||
|
||||
OATPP_RUN_TEST(oatpp::test::core::data::mapping::type::AnyTest);
|
||||
*/
|
||||
OATPP_RUN_TEST(oatpp::test::core::data::mapping::type::EnumTest);
|
||||
/*
|
||||
OATPP_RUN_TEST(oatpp::test::async::LockTest);
|
||||
|
||||
OATPP_RUN_TEST(oatpp::test::parser::CaretTest);
|
||||
|
85
test/oatpp/core/data/mapping/type/EnumTest.cpp
Normal file
85
test/oatpp/core/data/mapping/type/EnumTest.cpp
Normal file
@ -0,0 +1,85 @@
|
||||
/***************************************************************************
|
||||
*
|
||||
* Project _____ __ ____ _ _
|
||||
* ( _ ) /__\ (_ _)_| |_ _| |_
|
||||
* )(_)( /(__)\ )( (_ _)(_ _)
|
||||
* (_____)(__)(__)(__) |_| |_|
|
||||
*
|
||||
*
|
||||
* Copyright 2018-present, Leonid Stryzhevskyi <lganzzzo@gmail.com>
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
***************************************************************************/
|
||||
|
||||
#include "EnumTest.hpp"
|
||||
|
||||
#include "oatpp/core/Types.hpp"
|
||||
#include "oatpp/core/macro/codegen.hpp"
|
||||
|
||||
namespace oatpp { namespace test { namespace core { namespace data { namespace mapping { namespace type {
|
||||
|
||||
#include OATPP_CODEGEN_BEGIN(DTO)
|
||||
|
||||
ENUM(Enum1, v_int32,
|
||||
VALUE(NAME_1, 1, "name-1"),
|
||||
VALUE(NAME_2, 2, "name-2"),
|
||||
VALUE(NAME_3, 3, "name-3")
|
||||
)
|
||||
|
||||
#include OATPP_CODEGEN_END(DTO)
|
||||
|
||||
void EnumTest::onRun() {
|
||||
|
||||
{
|
||||
OATPP_LOGI(TAG, "Declaration...");
|
||||
OATPP_ASSERT(oatpp::Enum<Enum1>::Interpreter::isNullable == true);
|
||||
OATPP_ASSERT(oatpp::Enum<Enum1>::NotNull::Interpreter::isNullable == false);
|
||||
|
||||
OATPP_ASSERT(oatpp::Enum<Enum1>::AsString::Interpreter::isNullable == true);
|
||||
OATPP_ASSERT(oatpp::Enum<Enum1>::AsString::NotNull::Interpreter::isNullable == false);
|
||||
|
||||
OATPP_ASSERT(oatpp::Enum<Enum1>::AsInteger::Interpreter::isNullable == true);
|
||||
OATPP_ASSERT(oatpp::Enum<Enum1>::AsInteger::NotNull::Interpreter::isNullable == false);
|
||||
OATPP_LOGI(TAG, "OK");
|
||||
}
|
||||
|
||||
{
|
||||
OATPP_LOGI(TAG, "Test Interpreter AsString...");
|
||||
auto inter = oatpp::Enum<Enum1>::AsString::Interpreter::toInterpretation(Enum1::NAME_1);
|
||||
OATPP_ASSERT(inter.valueType == oatpp::String::Class::getType());
|
||||
|
||||
auto interValue = inter.staticCast<oatpp::String>();
|
||||
OATPP_ASSERT(interValue == "name-1");
|
||||
|
||||
Enum1 value = oatpp::Enum<Enum1>::AsString::Interpreter::fromInterpretation(interValue);
|
||||
OATPP_ASSERT(value == Enum1::NAME_1);
|
||||
OATPP_LOGI(TAG, "OK");
|
||||
}
|
||||
|
||||
{
|
||||
OATPP_LOGI(TAG, "Test Interpreter AsInteger...");
|
||||
auto inter = oatpp::Enum<Enum1>::AsInteger::Interpreter::toInterpretation(Enum1::NAME_1);
|
||||
OATPP_ASSERT(inter.valueType == oatpp::Int32::Class::getType());
|
||||
|
||||
auto interValue = inter.staticCast<oatpp::Int32>();
|
||||
OATPP_ASSERT(interValue == static_cast<v_int32>(Enum1::NAME_1));
|
||||
|
||||
Enum1 value = oatpp::Enum<Enum1>::AsInteger::Interpreter::fromInterpretation(interValue);
|
||||
OATPP_ASSERT(value == Enum1::NAME_1);
|
||||
OATPP_LOGI(TAG, "OK");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}}}}}}
|
42
test/oatpp/core/data/mapping/type/EnumTest.hpp
Normal file
42
test/oatpp/core/data/mapping/type/EnumTest.hpp
Normal file
@ -0,0 +1,42 @@
|
||||
/***************************************************************************
|
||||
*
|
||||
* Project _____ __ ____ _ _
|
||||
* ( _ ) /__\ (_ _)_| |_ _| |_
|
||||
* )(_)( /(__)\ )( (_ _)(_ _)
|
||||
* (_____)(__)(__)(__) |_| |_|
|
||||
*
|
||||
*
|
||||
* Copyright 2018-present, Leonid Stryzhevskyi <lganzzzo@gmail.com>
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
***************************************************************************/
|
||||
|
||||
#ifndef oatpp_test_core_data_mapping_type_EnumTest_hpp
|
||||
#define oatpp_test_core_data_mapping_type_EnumTest_hpp
|
||||
|
||||
#include "oatpp-test/UnitTest.hpp"
|
||||
|
||||
namespace oatpp { namespace test { namespace core { namespace data { namespace mapping { namespace type {
|
||||
|
||||
class EnumTest : public UnitTest{
|
||||
public:
|
||||
|
||||
EnumTest():UnitTest("TEST[core::data::mapping::type::EnumTest]"){}
|
||||
void onRun() override;
|
||||
|
||||
};
|
||||
|
||||
}}}}}}
|
||||
|
||||
#endif /* oatpp_test_core_data_mapping_type_EnumTest_hpp */
|
Loading…
Reference in New Issue
Block a user