diff --git a/td/telegram/Photo.h b/td/telegram/Photo.h index 838006bcb..f3448815f 100644 --- a/td/telegram/Photo.h +++ b/td/telegram/Photo.h @@ -53,7 +53,7 @@ struct PhotoSizeSource { // for photos, document thumbnails, encrypted thumbnails struct Thumbnail { Thumbnail() = default; - Thumbnail(FileType file_type, int32 thumbnail_type) : thumbnail_type(thumbnail_type) { + Thumbnail(FileType file_type, int32 thumbnail_type) : file_type(file_type), thumbnail_type(thumbnail_type) { } FileType file_type; diff --git a/td/telegram/Photo.hpp b/td/telegram/Photo.hpp index f1e3ac478..0502f37c9 100644 --- a/td/telegram/Photo.hpp +++ b/td/telegram/Photo.hpp @@ -73,51 +73,12 @@ void PhotoSizeSource::DialogPhoto::parse(ParserT &parser) { template void PhotoSizeSource::store(StorerT &storer) const { - using td::store; - auto type = get_type(); - store(type, storer); - switch (type) { - case Type::Thumbnail: - store(thumbnail(), storer); - break; - case Type::DialogPhoto: - store(dialog_photo(), storer); - break; - case Type::StickerSetThumbnail: - store(sticker_set_thumbnail(), storer); - break; - case Type::Empty: - break; - } + td::store(variant, storer); } template void PhotoSizeSource::parse(ParserT &parser) { - using td::parse; - Type type; - parse(type, parser); - switch (type) { - case Type::Thumbnail: { - Thumbnail thumbnail; - parse(thumbnail, parser); - variant = thumbnail; - break; - } - case Type::DialogPhoto: { - DialogPhoto dialog_photo; - parse(dialog_photo, parser); - variant = dialog_photo; - break; - } - case Type::StickerSetThumbnail: { - StickerSetThumbnail sticker_set_thumbnail; - parse(sticker_set_thumbnail, parser); - variant = sticker_set_thumbnail; - break; - } - case Type::Empty: - break; - } + td::parse(variant, parser); } template diff --git a/td/telegram/files/FileLocation.h b/td/telegram/files/FileLocation.h index 763c6f817..c68dbf4d2 100644 --- a/td/telegram/files/FileLocation.h +++ b/td/telegram/files/FileLocation.h @@ -744,6 +744,8 @@ struct PartialLocalFileLocationPtr { template void store(StorerT &storer) const; + template + void parse(ParserT &parser); }; inline bool operator==(const PartialLocalFileLocationPtr &lhs, const PartialLocalFileLocationPtr &rhs) { diff --git a/td/telegram/files/FileLocation.hpp b/td/telegram/files/FileLocation.hpp index 0ce224ead..bcb51df69 100644 --- a/td/telegram/files/FileLocation.hpp +++ b/td/telegram/files/FileLocation.hpp @@ -42,24 +42,48 @@ void PartialRemoteFileLocation::parse(ParserT &parser) { template void PhotoRemoteFileLocation::store(StorerT &storer) const { using td::store; + bool has_secret = secret_ != 0; + bool has_source = source_.get_type() != PhotoSizeSource::Type::Empty; + BEGIN_STORE_FLAGS(); + STORE_FLAG(has_secret); + STORE_FLAG(has_source); + END_STORE_FLAGS(); store(id_, storer); store(access_hash_, storer); store(volume_id_, storer); - store(secret_, storer); + if (has_secret) { + store(secret_, storer); + } store(local_id_, storer); - store(source_, storer); + if (has_source) { + store(source_, storer); + } } template void PhotoRemoteFileLocation::parse(ParserT &parser) { using td::parse; + bool has_secret = true; + bool has_source = false; + if (parser.version() >= static_cast(Version::AddPhotoSizeSource)) { + BEGIN_PARSE_FLAGS(); + PARSE_FLAG(has_secret); + PARSE_FLAG(has_source); + END_PARSE_FLAGS(); + } parse(id_, parser); parse(access_hash_, parser); parse(volume_id_, parser); - parse(secret_, parser); + if (has_secret) { + parse(secret_, parser); + } else { + secret_ = 0; + } parse(local_id_, parser); - if (parser.version() >= static_cast(Version::AddPhotoSizeSource)) { + if (has_source) { parse(source_, parser); + } else { + source_ = PhotoSizeSource(); } } @@ -177,31 +201,12 @@ void FullRemoteFileLocation::AsKey::store(StorerT &storer) const { template void RemoteFileLocation::store(StorerT &storer) const { - storer.store_int(variant_.get_offset()); - bool ok{false}; - variant_.visit([&](auto &&value) { - using td::store; - store(value, storer); - ok = true; - }); - CHECK(ok); + td::store(variant_, storer); } template void RemoteFileLocation::parse(ParserT &parser) { - auto type = static_cast(parser.fetch_int()); - switch (type) { - case Type::Empty: - variant_ = EmptyRemoteFileLocation(); - return; - case Type::Partial: - variant_ = PartialRemoteFileLocation(); - return partial().parse(parser); - case Type::Full: - variant_ = FullRemoteFileLocation(); - return full().parse(parser); - } - parser.set_error("Invalid type in RemoteFileLocation"); + td::parse(variant_, parser); } template @@ -261,32 +266,19 @@ void PartialLocalFileLocationPtr::store(StorerT &storer) const { td::store(*location_, storer); } +template +void PartialLocalFileLocationPtr::parse(ParserT &parser) { + td::parse(*location_, parser); +} + template void LocalFileLocation::store(StorerT &storer) const { - using td::store; - store(variant_.get_offset(), storer); - variant_.visit([&](auto &&value) { - using td::store; - store(value, storer); - }); + td::store(variant_, storer); } template void LocalFileLocation::parse(ParserT &parser) { - using td::parse; - auto type = static_cast(parser.fetch_int()); - switch (type) { - case Type::Empty: - variant_ = EmptyLocalFileLocation(); - return; - case Type::Partial: - variant_ = PartialLocalFileLocationPtr(); - return parse(partial(), parser); - case Type::Full: - variant_ = FullLocalFileLocation(); - return parse(full(), parser); - } - return parser.set_error("Invalid type in LocalFileLocation"); + td::parse(variant_, parser); } template diff --git a/tdutils/td/utils/tl_helpers.h b/tdutils/td/utils/tl_helpers.h index bd075d830..a25eda0e3 100644 --- a/tdutils/td/utils/tl_helpers.h +++ b/tdutils/td/utils/tl_helpers.h @@ -14,6 +14,7 @@ #include "td/utils/Status.h" #include "td/utils/tl_parsers.h" #include "td/utils/tl_storers.h" +#include "td/utils/Variant.h" #include #include @@ -186,6 +187,29 @@ std::enable_if_t::value> parse(T &val, ParserT &parser) { val.parse(parser); } +template +void store(const Variant &variant, StorerT &storer) { + store(variant.get_offset(), storer); + variant.visit([&storer](auto &&value) { + using td::store; + store(value, storer); + }); +} +template +void parse(Variant &variant, ParserT &parser) { + auto type_offset = parser.fetch_int(); + if (type_offset < 0 || type_offset >= static_cast(sizeof...(Types))) { + return parser.set_error("Invalid type"); + } + variant.for_each([type_offset, &parser, &variant](int offset, auto *ptr) { + using T = std::decay_t; + if (offset == type_offset) { + variant = T(); + parse(variant.get(), parser); + } + }); +} + template string serialize(const T &object) { TlStorerCalcLength calc_length;