Procházet zdrojové kódy

修复读写可选字段时未使用默认值的问题

akemimadoka před 7 roky
rodič
revize
ce46695682
5 změnil soubory, kde provedl 62 přidání a 53 odebrání
  1. 1 1
      Extern/NatsuLib
  2. 1 0
      YumeBot.Test/JceTest.cpp
  3. 53 50
      YumeBot/Jce.h
  4. 1 0
      YumeBot/TlvCodeDef.h
  5. 6 2
      YumeBot/Utility.h

+ 1 - 1
Extern/NatsuLib

@@ -1 +1 @@
-Subproject commit 3870862a4a3bb06b627aa1395983435fbd8952fa
+Subproject commit 7aa160ed8497d8914da38858bb31fd139e1b1cd3

+ 1 - 0
YumeBot.Test/JceTest.cpp

@@ -38,5 +38,6 @@ TEST_CASE("Jce", "[Jce]")
 		CHECK(ptr->GetTestFloat() == test->GetTestFloat());
 		CHECK(ptr->GetTestInt() == test->GetTestInt());
 		CHECK(ptr->GetTestMap() == test->GetTestMap());
+		CHECK(ptr->GetTestList() == std::vector{ 1.0, 2.0, 3.0 });
 	}
 }

+ 53 - 50
YumeBot/Jce.h

@@ -48,52 +48,10 @@ namespace YumeBot::Jce
 	};
 
 	template <typename T>
-	struct TlvDeserializer;
+	struct JceDeserializer;
 
 	template <typename T>
-	struct TlvSerializer;
-
-	struct NoOp
-	{
-		template <typename T>
-		struct Apply
-			: Utility::ResultType<T>
-		{
-		};
-	};
-
-	struct IsOptional
-	{
-		template <typename T>
-		struct Apply
-			: Utility::ResultType<std::conditional_t<Utility::IsTemplateOf<T, NatsuLib::natRefPointer>::value, T, std::optional<T>>>
-		{
-		};
-	};
-
-	template <typename... Args>
-	struct TemplateArgs
-	{
-		template <template <typename...> class Template>
-		struct Apply
-			: Utility::ResultType<Template<Args...>>
-		{
-		};
-	};
-
-	template <JceStruct::TypeEnum Type, typename AttributeSet>
-	struct FieldTypeBuilder;
-
-#define FIELD_TYPE_BUILDER_OP(name, code, type) \
-	template <typename... Attributes>\
-	struct FieldTypeBuilder<JceStruct::TypeEnum::name, std::tuple<Attributes...>>\
-		: decltype(Utility::RecursiveApply<type, Attributes...>())\
-	{\
-	};
-
-	JCE_FIELD_TYPE(FIELD_TYPE_BUILDER_OP)
-
-#undef FIELD_TYPE_BUILDER_OP
+	struct JceSerializer;
 
 	namespace Detail
 	{
@@ -666,7 +624,7 @@ namespace YumeBot::Jce
 						nat_Throw(JceDecodeException, u8"Type mismatch, got unexpected {0}", static_cast<std::uint32_t>(head.Type));
 					}
 
-					value = TlvDeserializer<T>::Deserialize(self);
+					value = JceDeserializer<T>::Deserialize(self);
 
 					self.SkipToStructEnd();
 
@@ -885,7 +843,7 @@ namespace YumeBot::Jce
 			static void DoWrite(JceOutputStream& self, std::uint32_t tag, NatsuLib::natRefPointer<T> const& value)
 			{
 				self.WriteHead({ tag, JceStruct::TypeEnum::StructBegin });
-				TlvSerializer<T>::Serialize(self, value);
+				JceSerializer<T>::Serialize(self, value);
 				self.WriteHead({ 0, JceStruct::TypeEnum::StructEnd });
 			}
 		};
@@ -897,6 +855,48 @@ namespace YumeBot::Jce
 #include "TlvCodeDef.h"
 	};
 
+	struct NoOp
+	{
+		template <typename T>
+		struct Apply
+			: Utility::ResultType<T>
+		{
+		};
+	};
+
+	struct IsOptional
+	{
+		template <typename T>
+		struct Apply
+			: Utility::ResultType<std::conditional_t<Utility::IsTemplateOf<T, NatsuLib::natRefPointer>::value, T, std::optional<T>>>
+		{
+		};
+	};
+
+	template <typename... Args>
+	struct TemplateArgs
+	{
+		template <template <typename...> class Template>
+		struct Apply
+			: Utility::ResultType<Template<Args...>>
+		{
+		};
+	};
+
+	template <JceStruct::TypeEnum Type, typename AttributeSet>
+	struct FieldTypeBuilder;
+
+#define FIELD_TYPE_BUILDER_OP(name, code, type) \
+	template <typename... Attributes>\
+	struct FieldTypeBuilder<JceStruct::TypeEnum::name, std::tuple<Attributes...>>\
+		: decltype(Utility::RecursiveApply<type, Attributes...>())\
+	{\
+	};
+
+JCE_FIELD_TYPE(FIELD_TYPE_BUILDER_OP)
+
+#undef FIELD_TYPE_BUILDER_OP
+
 #define NO_OP NoOp
 
 #define IS_OPTIONAL(defaultValue) IsOptional
@@ -948,12 +948,12 @@ namespace YumeBot::Jce
 
 #define IS_OPTIONAL(defaultValue) defaultValue
 
-	// 读取 optional 的时候不会返回 false
+// 读取 optional 的时候不会返回 false
 #define FIELD(name, tag, type, ...) \
 	{\
 		using FieldType = typename Utility::MayRemoveTemplate<Utility::RemoveCvRef<decltype(ret->Get##name())>, std::optional>::Type;\
 		if (!stream.Read(tag, ret->Get##name(),\
-			Utility::ReturnFirst<Utility::ConcatTrait<Utility::BindTrait<std::is_same, Detail::NoneType>::template Result, std::negation>::template Result, Detail::NoneType>(__VA_ARGS__)))\
+			Utility::ReturnFirst<Utility::ConcatTrait<Utility::ConcatTrait<Utility::RemoveCvRef, Utility::BindTrait<std::is_same, Detail::NoneType>::Result>::Result, std::negation>::Result, Detail::NoneType>(__VA_ARGS__)))\
 		{\
 			nat_Throw(JceDecodeException, u8"Deserializing failed : Failed to read field \"" #name "\" which is not optional.");\
 		}\
@@ -961,7 +961,7 @@ namespace YumeBot::Jce
 
 #define TLV_CODE(name, code) \
 	template <>\
-	struct TlvDeserializer<name>\
+	struct JceDeserializer<name>\
 	{\
 		static NatsuLib::natRefPointer<name> Deserialize(JceInputStream& stream)\
 		{\
@@ -978,7 +978,7 @@ namespace YumeBot::Jce
 
 #define TLV_CODE(name, code) \
 	template <>\
-	struct TlvSerializer<name>\
+	struct JceSerializer<name>\
 	{\
 		static void Serialize(JceOutputStream& stream, NatsuLib::natRefPointer<name> const& value)\
 		{
@@ -989,4 +989,7 @@ namespace YumeBot::Jce
 
 #include "TlvCodeDef.h"
 
+//static_assert(Utility::ConcatTrait<Utility::RemoveCvRef, Utility::BindTrait<std::is_same, Detail::NoneType>::Result>::Result<Detail::NoneType&&>::value);
+//static_assert(Utility::ConcatTrait<Utility::BindTrait<std::is_same, Detail::NoneType>::Result, std::negation>::Result<bool>::value);
+//static_assert(Utility::ReturnFirst<Utility::ConcatTrait<Utility::BindTrait<std::is_same, Detail::NoneType>::Result, std::negation>::Result, Detail::NoneType>(Detail::None, false));
 }

+ 1 - 0
YumeBot/TlvCodeDef.h

@@ -78,6 +78,7 @@ TLV_CODE(TlvTest, 0)
 	INT(TestInt, 0)
 	FLOAT(TestFloat, 1, IS_OPTIONAL(1.0f))
 	MAP(TestMap, 2, TEMPLATE_ARGUMENT(std::int32_t, float))
+	LIST(TestList, 3, TEMPLATE_ARGUMENT(double), IS_OPTIONAL((FieldType{ 1.0, 2.0, 3.0 })))
 END_TLV_CODE(TlvTest)
 
 #undef SIMPLE_LIST

+ 6 - 2
YumeBot/Utility.h

@@ -155,8 +155,12 @@ namespace YumeBot::Utility
 		using Result = Template2<Template1<Args...>>;
 	};
 
-	template <typename T>
-	using RemoveCvRef = std::remove_cv_t<std::remove_reference_t<T>>;
+	template <template <typename...> class Trait, typename... T>
+	using GetType = typename Trait<T...>::type;
+
+	// Workaround: 临时糊掉 C2210:pack expansions cannot be used as arguments to non-packed parameters in alias templates
+	template <typename... T>
+	using RemoveCvRef = std::remove_cv_t<GetType<std::remove_reference, T...>>;
 
 	template <typename T, template <typename> class Template>
 	struct MayRemoveTemplate