serialize_common.h 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175
  1. /*
  2. This file is part of Telegram Desktop,
  3. the official desktop application for the Telegram messaging service.
  4. For license and copyright information please follow this link:
  5. https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
  6. */
  7. #pragma once
  8. #include "mtproto/mtproto_auth_key.h"
  9. #include "base/bytes.h"
  10. #include <QtCore/QDataStream>
  11. namespace Serialize {
  12. class ByteArrayWriter final {
  13. public:
  14. explicit ByteArrayWriter(int expectedSize = 0);
  15. [[nodiscard]] QDataStream &underlying() {
  16. return _stream;
  17. }
  18. [[nodiscard]] operator QDataStream &() {
  19. return _stream;
  20. }
  21. [[nodiscard]] QByteArray result() &&;
  22. private:
  23. QByteArray _result;
  24. QDataStream _stream;
  25. };
  26. template <typename T>
  27. inline ByteArrayWriter &operator<<(ByteArrayWriter &stream, const T &data) {
  28. stream.underlying() << data;
  29. return stream;
  30. }
  31. class ByteArrayReader final {
  32. public:
  33. explicit ByteArrayReader(QByteArray data);
  34. [[nodiscard]] QDataStream &underlying() {
  35. return _stream;
  36. }
  37. [[nodiscard]] operator QDataStream &() {
  38. return _stream;
  39. }
  40. [[nodiscard]] bool atEnd() const {
  41. return _stream.atEnd();
  42. }
  43. [[nodiscard]] bool status() const {
  44. return _stream.status();
  45. }
  46. [[nodiscard]] bool ok() const {
  47. return _stream.status() == QDataStream::Ok;
  48. }
  49. private:
  50. QByteArray _data;
  51. QDataStream _stream;
  52. };
  53. template <typename T>
  54. inline ByteArrayReader &operator>>(ByteArrayReader &stream, T &data) {
  55. if (!stream.ok()) {
  56. data = T();
  57. } else {
  58. stream.underlying() >> data;
  59. if (!stream.ok()) {
  60. data = T();
  61. }
  62. }
  63. return stream;
  64. }
  65. inline int stringSize(const QString &str) {
  66. return sizeof(quint32) + str.size() * sizeof(ushort);
  67. }
  68. inline int bytearraySize(const QByteArray &arr) {
  69. return sizeof(quint32) + arr.size();
  70. }
  71. inline int bytesSize(bytes::const_span bytes) {
  72. return sizeof(quint32) + bytes.size();
  73. }
  74. inline int colorSize() {
  75. return sizeof(quint32);
  76. }
  77. void writeColor(QDataStream &stream, const QColor &color);
  78. QColor readColor(QDataStream &stream);
  79. struct ReadBytesVectorWrap {
  80. bytes::vector &bytes;
  81. };
  82. inline ReadBytesVectorWrap bytes(bytes::vector &bytes) {
  83. return ReadBytesVectorWrap { bytes };
  84. }
  85. // Compatible with QDataStream &operator>>(QDataStream &, QByteArray &);
  86. inline QDataStream &operator>>(QDataStream &stream, ReadBytesVectorWrap data) {
  87. auto &bytes = data.bytes;
  88. bytes.clear();
  89. quint32 len;
  90. stream >> len;
  91. if (stream.status() != QDataStream::Ok || len == 0xFFFFFFFF) {
  92. return stream;
  93. }
  94. constexpr auto kStep = quint32(1024 * 1024);
  95. for (auto allocated = quint32(0); allocated < len;) {
  96. auto blockSize = qMin(kStep, len - allocated);
  97. bytes.resize(allocated + blockSize);
  98. if (stream.readRawData(reinterpret_cast<char*>(bytes.data()) + allocated, blockSize) != blockSize) {
  99. bytes.clear();
  100. stream.setStatus(QDataStream::ReadPastEnd);
  101. return stream;
  102. }
  103. allocated += blockSize;
  104. }
  105. return stream;
  106. }
  107. struct WriteBytesWrap {
  108. bytes::const_span bytes;
  109. };
  110. inline WriteBytesWrap bytes(bytes::const_span bytes) {
  111. return WriteBytesWrap { bytes };
  112. }
  113. inline QDataStream &operator<<(QDataStream &stream, WriteBytesWrap data) {
  114. auto bytes = data.bytes;
  115. if (bytes.empty()) {
  116. stream << quint32(0xFFFFFFFF);
  117. } else {
  118. auto size = quint32(bytes.size());
  119. stream << size;
  120. stream.writeRawData(reinterpret_cast<const char*>(bytes.data()), size);
  121. }
  122. return stream;
  123. }
  124. inline QDataStream &operator<<(QDataStream &stream, ReadBytesVectorWrap data) {
  125. return stream << WriteBytesWrap { data.bytes };
  126. }
  127. inline int dateTimeSize() {
  128. return (sizeof(qint64) + sizeof(quint32) + sizeof(qint8));
  129. }
  130. template <typename T>
  131. inline T read(QDataStream &stream) {
  132. auto result = T();
  133. stream >> result;
  134. return result;
  135. }
  136. template <>
  137. inline MTP::AuthKey::Data read<MTP::AuthKey::Data>(QDataStream &stream) {
  138. auto result = MTP::AuthKey::Data();
  139. stream.readRawData(reinterpret_cast<char*>(result.data()), result.size());
  140. return result;
  141. }
  142. } // namespace Serialize