Jce.h 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992
  1. #pragma once
  2. #include <natBinary.h>
  3. #include <optional>
  4. #include "Utility.h"
  5. namespace YumeBot::Jce
  6. {
  7. DeclareException(JceException, NatsuLib::natException, u8"YumeBot::Jce::JceException");
  8. DeclareException(JceDecodeException, JceException, u8"YumeBot::Jce::JceDecodeException");
  9. DeclareException(JceEncodeException, JceException, u8"YumeBot::Jce::JceEncodeException");
  10. enum class JceCode;
  11. // Jce 中 Byte 是有符号的,此处表示为无符号,使用时需注意
  12. class JceStruct
  13. : public NatsuLib::natRefObj
  14. {
  15. public:
  16. #define JCE_FIELD_TYPE(OP)\
  17. OP(Byte, 0x00, std::uint8_t)\
  18. OP(Short, 0x01, std::int16_t)\
  19. OP(Int, 0x02, std::int32_t)\
  20. OP(Long, 0x03, std::int64_t)\
  21. OP(Float, 0x04, float)\
  22. OP(Double, 0x05, double)\
  23. OP(String1, 0x06, std::string)\
  24. OP(String4, 0x07, std::string)\
  25. OP(Map, 0x08, std::unordered_map)\
  26. OP(List, 0x09, std::vector)\
  27. OP(StructBegin, 0x0A, NatsuLib::natRefPointer)\
  28. OP(StructEnd, 0x0B, void)\
  29. OP(ZeroTag, 0x0C, (std::integral_constant<std::size_t, 0>))\
  30. OP(SimpleList, 0x0D, std::vector<std::uint8_t>)
  31. enum class TypeEnum : std::uint8_t
  32. {
  33. #define ENUM_OP(name, code, type) name = code,
  34. JCE_FIELD_TYPE(ENUM_OP)
  35. #undef ENUM_OP
  36. };
  37. static constexpr std::size_t MaxStringLength = 0x06400000;
  38. ~JceStruct();
  39. virtual std::string_view GetJceStructName() const noexcept = 0;
  40. virtual JceCode GetJceStructType() const noexcept = 0;
  41. };
  42. template <typename T>
  43. struct TlvDeserializer;
  44. template <typename T>
  45. struct TlvSerializer;
  46. struct NoOp
  47. {
  48. template <typename T>
  49. struct Apply
  50. : Utility::ResultType<T>
  51. {
  52. };
  53. };
  54. struct IsOptional
  55. {
  56. template <typename T>
  57. struct Apply
  58. : Utility::ResultType<std::conditional_t<Utility::IsTemplateOf<T, NatsuLib::natRefPointer>::value, T, std::optional<T>>>
  59. {
  60. };
  61. };
  62. template <typename... Args>
  63. struct TemplateArgs
  64. {
  65. template <template <typename...> class Template>
  66. struct Apply
  67. : Utility::ResultType<Template<Args...>>
  68. {
  69. };
  70. };
  71. template <JceStruct::TypeEnum Type, typename AttributeSet>
  72. struct FieldTypeBuilder;
  73. #define FIELD_TYPE_BUILDER_OP(name, code, type) \
  74. template <typename... Attributes>\
  75. struct FieldTypeBuilder<JceStruct::TypeEnum::name, std::tuple<Attributes...>>\
  76. : decltype(Utility::RecursiveApply<type, Attributes...>())\
  77. {\
  78. };
  79. JCE_FIELD_TYPE(FIELD_TYPE_BUILDER_OP)
  80. #undef FIELD_TYPE_BUILDER_OP
  81. namespace Detail
  82. {
  83. struct NoneType
  84. {
  85. };
  86. constexpr NoneType None{};
  87. }
  88. struct HeadData
  89. {
  90. std::uint32_t Tag;
  91. JceStruct::TypeEnum Type;
  92. };
  93. class JceInputStream
  94. : NatsuLib::noncopyable
  95. {
  96. public:
  97. explicit JceInputStream(NatsuLib::natRefPointer<NatsuLib::natBinaryReader> reader);
  98. ~JceInputStream();
  99. std::pair<HeadData, std::size_t> ReadHead() const
  100. {
  101. const auto byte = m_Reader->ReadPod<std::uint8_t>();
  102. const auto type = static_cast<JceStruct::TypeEnum>(static_cast<std::uint8_t>(byte & 0x0F));
  103. const auto tag = static_cast<std::uint32_t>((byte & 0xF0) >> 4);
  104. if (tag != 0x0F)
  105. {
  106. return { { tag, type }, 1 };
  107. }
  108. return { { m_Reader->ReadPod<std::uint8_t>(), type }, 2 };
  109. }
  110. std::pair<HeadData, std::size_t> PeekHead() const
  111. {
  112. const auto underlyingStream = m_Reader->GetUnderlyingStream();
  113. const auto pos = underlyingStream->GetPosition();
  114. const auto head = ReadHead();
  115. underlyingStream->SetPositionFromBegin(pos);
  116. return head;
  117. }
  118. void Skip(nLen len)
  119. {
  120. m_Reader->Skip(len);
  121. }
  122. void SkipToStructEnd()
  123. {
  124. while (true)
  125. {
  126. const auto [head, headSize] = ReadHead();
  127. SkipField(head.Type);
  128. if (head.Type == JceStruct::TypeEnum::StructEnd)
  129. {
  130. return;
  131. }
  132. }
  133. }
  134. void SkipField()
  135. {
  136. const auto [head, headSize] = ReadHead();
  137. SkipField(head.Type);
  138. }
  139. void SkipField(JceStruct::TypeEnum type)
  140. {
  141. switch (type)
  142. {
  143. case JceStruct::TypeEnum::Byte:
  144. Skip(1);
  145. break;
  146. case JceStruct::TypeEnum::Short:
  147. Skip(2);
  148. break;
  149. case JceStruct::TypeEnum::Int:
  150. Skip(4);
  151. break;
  152. case JceStruct::TypeEnum::Long:
  153. Skip(8);
  154. break;
  155. case JceStruct::TypeEnum::Float:
  156. Skip(4);
  157. break;
  158. case JceStruct::TypeEnum::Double:
  159. Skip(8);
  160. break;
  161. case JceStruct::TypeEnum::String1:
  162. Skip(m_Reader->ReadPod<std::uint8_t>());
  163. break;
  164. case JceStruct::TypeEnum::String4:
  165. Skip(m_Reader->ReadPod<std::uint32_t>());
  166. break;
  167. case JceStruct::TypeEnum::Map:
  168. {
  169. int size;
  170. if (!Read(0, size))
  171. {
  172. nat_Throw(JceDecodeException, u8"Read size failed.");
  173. }
  174. for (std::size_t i = 0, iterationTime = static_cast<std::size_t>(size) * 2; i < iterationTime; ++i)
  175. {
  176. SkipField();
  177. }
  178. break;
  179. }
  180. case JceStruct::TypeEnum::List:
  181. {
  182. int size;
  183. if (!Read(0, size))
  184. {
  185. nat_Throw(JceDecodeException, u8"Read size failed.");
  186. }
  187. for (std::size_t i = 0, iterationTime = static_cast<std::size_t>(size); i < iterationTime; ++i)
  188. {
  189. SkipField();
  190. }
  191. break;
  192. }
  193. case JceStruct::TypeEnum::StructBegin:
  194. SkipToStructEnd();
  195. break;
  196. case JceStruct::TypeEnum::StructEnd:
  197. case JceStruct::TypeEnum::ZeroTag:
  198. break;
  199. case JceStruct::TypeEnum::SimpleList:
  200. {
  201. const auto [head, headSize] = ReadHead();
  202. if (head.Type != JceStruct::TypeEnum::Byte)
  203. {
  204. nat_Throw(JceDecodeException, u8"Type mismatch, expected 0, got {0}", static_cast<std::uint32_t>(head.Type));
  205. }
  206. std::uint8_t size;
  207. if (!Read(0, size))
  208. {
  209. nat_Throw(JceDecodeException, u8"Read size failed.");
  210. }
  211. Skip(size);
  212. break;
  213. }
  214. default:
  215. nat_Throw(JceDecodeException, u8"Invalid type ({0}).", static_cast<std::uint32_t>(type));
  216. }
  217. }
  218. bool SkipToTag(std::uint32_t tag)
  219. try
  220. {
  221. HeadData head; // NOLINT
  222. while (true)
  223. {
  224. std::size_t headSize;
  225. std::tie(head, headSize) = PeekHead();
  226. if (head.Type == JceStruct::TypeEnum::StructEnd)
  227. {
  228. return false;
  229. }
  230. if (tag <= head.Tag)
  231. {
  232. break;
  233. }
  234. Skip(headSize);
  235. SkipField(head.Type);
  236. }
  237. return head.Tag == tag;
  238. }
  239. catch (JceDecodeException&)
  240. {
  241. return false;
  242. }
  243. template <typename T>
  244. bool Read(std::uint32_t tag, T& value, Detail::NoneType = Detail::None)
  245. {
  246. return Reader<T>::DoRead(*this, tag, value);
  247. }
  248. template <typename T, typename U>
  249. std::enable_if_t<std::is_assignable_v<T&, U&&>, std::true_type> Read(std::uint32_t tag, T& value, U&& defaultValue)
  250. {
  251. bool readSucceed;
  252. if constexpr (Utility::IsTemplateOf<T, std::optional>::value)
  253. {
  254. value.emplace();
  255. readSucceed = Read(tag, value.value());
  256. }
  257. else
  258. {
  259. readSucceed = Read(tag, value);
  260. }
  261. if (!readSucceed)
  262. {
  263. value = std::forward<U>(defaultValue);
  264. }
  265. return {};
  266. }
  267. private:
  268. NatsuLib::natRefPointer<NatsuLib::natBinaryReader> m_Reader;
  269. template <typename T, typename = void>
  270. struct Reader;
  271. template <>
  272. struct Reader<std::uint8_t>
  273. {
  274. static bool DoRead(JceInputStream& self, std::uint32_t tag, std::uint8_t& value)
  275. {
  276. if (self.SkipToTag(tag))
  277. {
  278. const auto [head, headSize] = self.ReadHead();
  279. switch (head.Type)
  280. {
  281. case JceStruct::TypeEnum::Byte:
  282. self.m_Reader->ReadPod(value);
  283. break;
  284. case JceStruct::TypeEnum::ZeroTag:
  285. value = 0;
  286. break;
  287. default:
  288. nat_Throw(JceDecodeException, u8"Type mismatch, got unexpected {0}", static_cast<std::uint32_t>(head.Type));
  289. }
  290. return true;
  291. }
  292. return false;
  293. }
  294. };
  295. template <>
  296. struct Reader<std::int16_t>
  297. {
  298. static bool DoRead(JceInputStream& self, std::uint32_t tag, std::int16_t& value)
  299. {
  300. if (self.SkipToTag(tag))
  301. {
  302. const auto [head, headSize] = self.ReadHead();
  303. switch (head.Type)
  304. {
  305. case JceStruct::TypeEnum::Byte:
  306. value = self.m_Reader->ReadPod<std::int8_t>();
  307. break;
  308. case JceStruct::TypeEnum::Short:
  309. self.m_Reader->ReadPod(value);
  310. break;
  311. case JceStruct::TypeEnum::ZeroTag:
  312. value = 0;
  313. break;
  314. default:
  315. nat_Throw(JceDecodeException, u8"Type mismatch, got unexpected {0}", static_cast<std::uint32_t>(head.Type));
  316. }
  317. return true;
  318. }
  319. return false;
  320. }
  321. };
  322. template <>
  323. struct Reader<std::int32_t>
  324. {
  325. static bool DoRead(JceInputStream& self, std::uint32_t tag, std::int32_t& value)
  326. {
  327. if (self.SkipToTag(tag))
  328. {
  329. const auto [head, headSize] = self.ReadHead();
  330. switch (head.Type)
  331. {
  332. case JceStruct::TypeEnum::Byte:
  333. value = self.m_Reader->ReadPod<std::int8_t>();
  334. break;
  335. case JceStruct::TypeEnum::Short:
  336. value = self.m_Reader->ReadPod<std::int16_t>();
  337. break;
  338. case JceStruct::TypeEnum::Int:
  339. self.m_Reader->ReadPod(value);
  340. break;
  341. case JceStruct::TypeEnum::ZeroTag:
  342. value = 0;
  343. break;
  344. default:
  345. nat_Throw(JceDecodeException, u8"Type mismatch, got unexpected {0}", static_cast<std::uint32_t>(head.Type));
  346. }
  347. return true;
  348. }
  349. return false;
  350. }
  351. };
  352. template <>
  353. struct Reader<std::int64_t>
  354. {
  355. static bool DoRead(JceInputStream& self, std::uint32_t tag, std::int64_t& value)
  356. {
  357. if (self.SkipToTag(tag))
  358. {
  359. const auto[head, headSize] = self.ReadHead();
  360. switch (head.Type)
  361. {
  362. case JceStruct::TypeEnum::Byte:
  363. value = self.m_Reader->ReadPod<std::int8_t>();
  364. break;
  365. case JceStruct::TypeEnum::Short:
  366. value = self.m_Reader->ReadPod<std::int16_t>();
  367. break;
  368. case JceStruct::TypeEnum::Int:
  369. value = self.m_Reader->ReadPod<std::int32_t>();
  370. break;
  371. case JceStruct::TypeEnum::Long:
  372. self.m_Reader->ReadPod(value);
  373. break;
  374. case JceStruct::TypeEnum::ZeroTag:
  375. value = 0;
  376. break;
  377. default:
  378. nat_Throw(JceDecodeException, u8"Type mismatch, got unexpected got {0}", static_cast<std::uint32_t>(head.Type));
  379. }
  380. return true;
  381. }
  382. return false;
  383. }
  384. };
  385. template <>
  386. struct Reader<float>
  387. {
  388. static bool DoRead(JceInputStream& self, std::uint32_t tag, float& value)
  389. {
  390. if (self.SkipToTag(tag))
  391. {
  392. const auto[head, headSize] = self.ReadHead();
  393. switch (head.Type)
  394. {
  395. case JceStruct::TypeEnum::Float:
  396. self.m_Reader->ReadPod(value);
  397. break;
  398. case JceStruct::TypeEnum::ZeroTag:
  399. value = 0;
  400. break;
  401. default:
  402. nat_Throw(JceDecodeException, u8"Type mismatch, got unexpected {0}", static_cast<std::uint32_t>(head.Type));
  403. }
  404. return true;
  405. }
  406. return false;
  407. }
  408. };
  409. template <>
  410. struct Reader<double>
  411. {
  412. static bool DoRead(JceInputStream& self, std::uint32_t tag, double& value)
  413. {
  414. if (self.SkipToTag(tag))
  415. {
  416. const auto[head, headSize] = self.ReadHead();
  417. switch (head.Type)
  418. {
  419. case JceStruct::TypeEnum::Float:
  420. value = self.m_Reader->ReadPod<float>();
  421. break;
  422. case JceStruct::TypeEnum::Double:
  423. self.m_Reader->ReadPod(value);
  424. break;
  425. case JceStruct::TypeEnum::ZeroTag:
  426. value = 0;
  427. break;
  428. default:
  429. nat_Throw(JceDecodeException, u8"Type mismatch, got unexpected {0}", static_cast<std::uint32_t>(head.Type));
  430. }
  431. return true;
  432. }
  433. return false;
  434. }
  435. };
  436. template <>
  437. struct Reader<std::string>
  438. {
  439. static bool DoRead(JceInputStream& self, std::uint32_t tag, std::string& value)
  440. {
  441. if (self.SkipToTag(tag))
  442. {
  443. const auto [head, headSize] = self.ReadHead();
  444. std::size_t strSize;
  445. switch (head.Type)
  446. {
  447. case JceStruct::TypeEnum::String1:
  448. strSize = self.m_Reader->ReadPod<std::uint8_t>();
  449. break;
  450. case JceStruct::TypeEnum::String4:
  451. strSize = self.m_Reader->ReadPod<std::uint32_t>();
  452. if (strSize > JceStruct::MaxStringLength)
  453. {
  454. nat_Throw(JceDecodeException, u8"String too long, {0} sizes requested.", strSize);
  455. }
  456. break;
  457. default:
  458. nat_Throw(JceDecodeException, u8"Type mismatch, got unexpected {0}", static_cast<std::uint32_t>(head.Type));
  459. }
  460. // 为了异常安全,构造临时字符串而不是就地修改
  461. std::string tmpString(strSize, 0);
  462. self.m_Reader->GetUnderlyingStream()->ReadBytes(reinterpret_cast<nData>(tmpString.data()), strSize);
  463. value = std::move(tmpString);
  464. return true;
  465. }
  466. return false;
  467. }
  468. };
  469. template <typename Key, typename Value>
  470. struct Reader<std::unordered_map<Key, Value>>
  471. {
  472. static bool DoRead(JceInputStream& self, std::uint32_t tag, std::unordered_map<Key, Value>& value)
  473. {
  474. if (self.SkipToTag(tag))
  475. {
  476. const auto [head, headSize] = self.ReadHead();
  477. switch (head.Type)
  478. {
  479. case JceStruct::TypeEnum::Map:
  480. {
  481. std::int32_t size;
  482. if (!self.Read(0, size))
  483. {
  484. nat_Throw(JceDecodeException, u8"Read size failed.");
  485. }
  486. if (size < 0)
  487. {
  488. nat_Throw(JceDecodeException, u8"Invalid size({0}).", size);
  489. }
  490. // 为了异常安全,构造临时 map 而不是就地修改
  491. std::unordered_map<Key, Value> tmpMap;
  492. for (std::size_t i = 0; i < static_cast<std::size_t>(size); ++i)
  493. {
  494. Key entryKey;
  495. if (!self.Read(0, entryKey))
  496. {
  497. nat_Throw(JceDecodeException, u8"Read key failed.");
  498. }
  499. Value entryValue;
  500. if (!self.Read(1, entryValue))
  501. {
  502. nat_Throw(JceDecodeException, u8"Read value failed.");
  503. }
  504. tmpMap.emplace(std::move(entryKey), std::move(entryValue));
  505. }
  506. value = std::move(tmpMap);
  507. break;
  508. }
  509. default:
  510. nat_Throw(JceDecodeException, u8"Type mismatch, got unexpected {0}", static_cast<std::uint32_t>(head.Type));
  511. }
  512. return true;
  513. }
  514. return false;
  515. }
  516. };
  517. template <typename T>
  518. struct Reader<std::vector<T>>
  519. {
  520. static bool DoRead(JceInputStream& self, std::uint32_t tag, std::vector<T>& value)
  521. {
  522. if (self.SkipToTag(tag))
  523. {
  524. const auto[head, headSize] = self.ReadHead();
  525. switch (head.Type)
  526. {
  527. case JceStruct::TypeEnum::List:
  528. {
  529. std::int32_t size;
  530. if (!self.Read(0, size))
  531. {
  532. nat_Throw(JceDecodeException, u8"Read size failed.");
  533. }
  534. // 为了异常安全,构造临时 vector 而不是就地修改
  535. std::vector<T> tmpList;
  536. tmpList.reserve(size);
  537. if (size > 0)
  538. {
  539. for (std::size_t i = 0; i < static_cast<std::size_t>(size); ++i)
  540. {
  541. T elemValue;
  542. if (!self.Read(0, elemValue))
  543. {
  544. nat_Throw(JceDecodeException, u8"Read element failed.");
  545. }
  546. tmpList.emplace_back(std::move(elemValue));
  547. }
  548. }
  549. value = std::move(tmpList);
  550. break;
  551. }
  552. case JceStruct::TypeEnum::SimpleList:
  553. if constexpr (std::is_same_v<T, std::uint8_t>)
  554. {
  555. const auto[sizeField, sizeFieldSize] = self.ReadHead();
  556. if (sizeField.Type != JceStruct::TypeEnum::Byte)
  557. {
  558. nat_Throw(JceDecodeException, u8"Type mismatch, got unexpected {0}", static_cast<std::uint32_t>(sizeField.Type));
  559. }
  560. std::uint8_t size;
  561. if (!self.Read(0, size))
  562. {
  563. nat_Throw(JceDecodeException, u8"Read size failed.");
  564. }
  565. std::vector<std::uint8_t> tmpList(static_cast<std::size_t>(size));
  566. self.m_Reader->GetUnderlyingStream()->ReadBytes(tmpList.data(), size);
  567. value = std::move(tmpList);
  568. break;
  569. }
  570. else
  571. {
  572. [[fallthrough]];
  573. }
  574. default:
  575. nat_Throw(JceDecodeException, u8"Type mismatch, got unexpected {0}", static_cast<std::uint32_t>(head.Type));
  576. }
  577. return true;
  578. }
  579. return false;
  580. }
  581. };
  582. template <typename T>
  583. struct Reader<NatsuLib::natRefPointer<T>, std::enable_if_t<std::is_base_of_v<JceStruct, T>>>
  584. {
  585. static bool DoRead(JceInputStream& self, std::uint32_t tag, NatsuLib::natRefPointer<T>& value)
  586. {
  587. if (self.SkipToTag(tag))
  588. {
  589. const auto[head, headSize] = self.ReadHead();
  590. if (head.Type != JceStruct::TypeEnum::StructBegin)
  591. {
  592. nat_Throw(JceDecodeException, u8"Type mismatch, got unexpected {0}", static_cast<std::uint32_t>(head.Type));
  593. }
  594. value = TlvDeserializer<T>::Deserialize(self);
  595. self.SkipToStructEnd();
  596. return true;
  597. }
  598. return false;
  599. }
  600. };
  601. };
  602. class JceOutputStream
  603. : NatsuLib::noncopyable
  604. {
  605. public:
  606. explicit JceOutputStream(NatsuLib::natRefPointer<NatsuLib::natBinaryWriter> writer);
  607. ~JceOutputStream();
  608. NatsuLib::natRefPointer<NatsuLib::natBinaryWriter> GetWriter() const noexcept
  609. {
  610. return m_Writer;
  611. }
  612. void WriteHead(HeadData head)
  613. {
  614. if (head.Tag < 15)
  615. {
  616. m_Writer->WritePod(static_cast<std::uint8_t>((head.Tag << 4) | static_cast<std::uint8_t>(head.Type)));
  617. }
  618. else if (head.Tag < 256)
  619. {
  620. m_Writer->WritePod(static_cast<std::uint8_t>(static_cast<std::uint8_t>(head.Type) | 0xF0));
  621. m_Writer->WritePod(static_cast<std::uint8_t>(head.Tag));
  622. }
  623. else
  624. {
  625. nat_Throw(JceEncodeException, u8"Tag is too big({0}).", head.Tag);
  626. }
  627. }
  628. template <typename T>
  629. void Write(std::uint32_t tag, T const& value)
  630. {
  631. Writer<T>::DoWrite(*this, tag, value);
  632. }
  633. template <typename T>
  634. void Write(std::uint32_t tag, std::optional<T> const& value)
  635. {
  636. if (value.has_value())
  637. {
  638. Write(tag, value.value());
  639. }
  640. }
  641. template <typename T>
  642. void Write(std::uint32_t tag, NatsuLib::natRefPointer<T> const& value)
  643. {
  644. if (value)
  645. {
  646. Writer<NatsuLib::natRefPointer<T>>::DoWrite(*this, tag, value);
  647. }
  648. }
  649. private:
  650. NatsuLib::natRefPointer<NatsuLib::natBinaryWriter> m_Writer;
  651. template <typename T, typename = void>
  652. struct Writer;
  653. template <>
  654. struct Writer<std::uint8_t>
  655. {
  656. static void DoWrite(JceOutputStream& self, std::uint32_t tag, std::uint8_t value)
  657. {
  658. if (!value)
  659. {
  660. self.WriteHead({ tag, JceStruct::TypeEnum::ZeroTag });
  661. }
  662. else
  663. {
  664. self.WriteHead({ tag, JceStruct::TypeEnum::Byte });
  665. self.m_Writer->WritePod(value);
  666. }
  667. }
  668. };
  669. template <>
  670. struct Writer<std::int16_t>
  671. {
  672. static void DoWrite(JceOutputStream& self, std::uint32_t tag, std::int16_t value)
  673. {
  674. if (Utility::InRangeOf<std::int8_t>(value))
  675. {
  676. self.Write(tag, static_cast<std::uint8_t>(value));
  677. }
  678. else
  679. {
  680. self.WriteHead({ tag, JceStruct::TypeEnum::Short });
  681. self.m_Writer->WritePod(value);
  682. }
  683. }
  684. };
  685. template <>
  686. struct Writer<std::int32_t>
  687. {
  688. static void DoWrite(JceOutputStream& self, std::uint32_t tag, std::int32_t value)
  689. {
  690. if (Utility::InRangeOf<std::int16_t>(value))
  691. {
  692. self.Write(tag, static_cast<std::int16_t>(value));
  693. }
  694. else
  695. {
  696. self.WriteHead({ tag, JceStruct::TypeEnum::Int });
  697. self.m_Writer->WritePod(value);
  698. }
  699. }
  700. };
  701. template <>
  702. struct Writer<std::int64_t>
  703. {
  704. static void DoWrite(JceOutputStream& self, std::uint32_t tag, std::int64_t value)
  705. {
  706. if (Utility::InRangeOf<std::int32_t>(value))
  707. {
  708. self.Write(tag, static_cast<std::int32_t>(value));
  709. }
  710. else
  711. {
  712. self.WriteHead({ tag, JceStruct::TypeEnum::Long });
  713. self.m_Writer->WritePod(value);
  714. }
  715. }
  716. };
  717. template <>
  718. struct Writer<float>
  719. {
  720. static void DoWrite(JceOutputStream& self, std::uint32_t tag, float value)
  721. {
  722. self.WriteHead({ tag, JceStruct::TypeEnum::Float });
  723. self.m_Writer->WritePod(value);
  724. }
  725. };
  726. template <>
  727. struct Writer<double>
  728. {
  729. static void DoWrite(JceOutputStream& self, std::uint32_t tag, double value)
  730. {
  731. self.WriteHead({ tag, JceStruct::TypeEnum::Double });
  732. self.m_Writer->WritePod(value);
  733. }
  734. };
  735. template <>
  736. struct Writer<std::string>
  737. {
  738. static void DoWrite(JceOutputStream& self, std::uint32_t tag, std::string const& value)
  739. {
  740. const auto strSize = value.size();
  741. if (strSize <= std::numeric_limits<std::uint8_t>::max())
  742. {
  743. self.WriteHead({ tag, JceStruct::TypeEnum::String1 });
  744. self.m_Writer->WritePod(static_cast<std::uint8_t>(strSize));
  745. }
  746. else
  747. {
  748. if (strSize > std::numeric_limits<std::uint32_t>::max())
  749. {
  750. nat_Throw(JceDecodeException, u8"String is too long({0} bytes).", strSize);
  751. }
  752. self.WriteHead({ tag, JceStruct::TypeEnum::String4 });
  753. self.m_Writer->WritePod(static_cast<std::uint32_t>(strSize));
  754. }
  755. self.m_Writer->GetUnderlyingStream()->WriteBytes(reinterpret_cast<ncData>(value.data()), strSize);
  756. }
  757. };
  758. template <typename Key, typename Value>
  759. struct Writer<std::unordered_map<Key, Value>>
  760. {
  761. static void DoWrite(JceOutputStream& self, std::uint32_t tag, std::unordered_map<Key, Value> const& value)
  762. {
  763. self.WriteHead({ tag, JceStruct::TypeEnum::Map });
  764. self.Write(0, static_cast<std::int32_t>(value.size()));
  765. for (const auto& item : value)
  766. {
  767. self.Write(0, item.first);
  768. self.Write(1, item.second);
  769. }
  770. }
  771. };
  772. template <typename T>
  773. struct Writer<std::vector<T>>
  774. {
  775. static void DoWrite(JceOutputStream& self, std::uint32_t tag, std::vector<T> const& value)
  776. {
  777. self.WriteHead({ tag, JceStruct::TypeEnum::List });
  778. self.Write(0, static_cast<std::int32_t>(value.size()));
  779. for (const auto& item : value)
  780. {
  781. self.Write(0, item);
  782. }
  783. }
  784. };
  785. template <typename T>
  786. struct Writer<NatsuLib::natRefPointer<T>, std::enable_if_t<std::is_base_of_v<JceStruct, T>>>
  787. {
  788. static void DoWrite(JceOutputStream& self, std::uint32_t tag, NatsuLib::natRefPointer<T> const& value)
  789. {
  790. self.WriteHead({ tag, JceStruct::TypeEnum::StructBegin });
  791. TlvSerializer<T>::Serialize(self, value);
  792. self.WriteHead({ 0, JceStruct::TypeEnum::StructEnd });
  793. }
  794. };
  795. };
  796. enum class JceCode
  797. {
  798. #define TLV_CODE(name, code) name = code,
  799. #include "TlvCodeDef.h"
  800. };
  801. #define NO_OP NoOp
  802. #define IS_OPTIONAL(defaultValue) IsOptional
  803. #define TEMPLATE_ARGUMENT(...) TemplateArgs<__VA_ARGS__>
  804. #define FIELD(name, tag, type, ...) \
  805. private:\
  806. typename FieldTypeBuilder<JceStruct::TypeEnum::type, std::tuple<__VA_ARGS__>>::Type m_##name;\
  807. \
  808. public:\
  809. const auto& Get##name() const noexcept\
  810. {\
  811. return m_##name;\
  812. }\
  813. \
  814. auto& Get##name() noexcept\
  815. {\
  816. return m_##name;\
  817. }\
  818. \
  819. template <typename T>\
  820. void Set##name(T&& arg)\
  821. {\
  822. m_##name = std::forward<T>(arg);\
  823. }\
  824. \
  825. static constexpr std::size_t Get##name##Tag() noexcept\
  826. {\
  827. return tag;\
  828. }
  829. #define TLV_CODE(name, code) \
  830. class name\
  831. : public NatsuLib::natRefObjImpl<name, JceStruct>\
  832. {\
  833. public:\
  834. ~name();\
  835. \
  836. std::string_view GetJceStructName() const noexcept override;\
  837. JceCode GetJceStructType() const noexcept override;
  838. #define END_TLV_CODE(name) \
  839. };
  840. #include "TlvCodeDef.h"
  841. #define NO_OP Detail::None
  842. #define IS_OPTIONAL(defaultValue) defaultValue
  843. // 读取 optional 的时候不会返回 false
  844. #define FIELD(name, tag, type, ...) \
  845. {\
  846. using FieldType = typename Utility::MayRemoveTemplate<Utility::RemoveCvRef<decltype(ret->Get##name())>, std::optional>::Type;\
  847. if (!stream.Read(tag, ret->Get##name(),\
  848. Utility::ReturnFirst<Utility::ConcatTrait<Utility::BindTrait<std::is_same, Detail::NoneType>::template Result, std::negation>::template Result, Detail::NoneType>(__VA_ARGS__)))\
  849. {\
  850. nat_Throw(JceDecodeException, u8"Deserializing failed : Failed to read field \"" #name "\" which is not optional.");\
  851. }\
  852. }
  853. #define TLV_CODE(name, code) \
  854. template <>\
  855. struct TlvDeserializer<name>\
  856. {\
  857. static NatsuLib::natRefPointer<name> Deserialize(JceInputStream& stream)\
  858. {\
  859. auto ret = NatsuLib::make_ref<name>();
  860. #define END_TLV_CODE(name) \
  861. return ret;\
  862. }\
  863. };
  864. #include "TlvCodeDef.h"
  865. #define FIELD(name, tag, type, ...) stream.Write(tag, value->Get##name());
  866. #define TLV_CODE(name, code) \
  867. template <>\
  868. struct TlvSerializer<name>\
  869. {\
  870. static void Serialize(JceOutputStream& stream, NatsuLib::natRefPointer<name> const& value)\
  871. {
  872. #define END_TLV_CODE(name) \
  873. }\
  874. };
  875. #include "TlvCodeDef.h"
  876. }