| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198 |
- /*
- This file is part of Telegram Desktop,
- the official desktop application for the Telegram messaging service.
- For license and copyright information please follow this link:
- https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
- */
- #pragma once
- #include "data/data_abstract_sparse_ids.h"
- #include "data/data_messages.h"
- namespace Storage {
- struct SparseIdsListResult;
- struct SparseIdsSliceUpdate;
- } // namespace Storage
- class SparseIdsSlice final : public AbstractSparseIds<base::flat_set<MsgId>> {
- public:
- using Key = MsgId;
- using AbstractSparseIds<base::flat_set<MsgId>>::AbstractSparseIds;
- };
- using SparseUnsortedIdsSlice = AbstractSparseIds<std::vector<MsgId>>;
- class SparseIdsMergedSlice {
- public:
- using UniversalMsgId = MsgId;
- static constexpr MsgId kScheduledTopicId = ScheduledMaxMsgId;
- struct Key {
- Key(
- PeerId peerId,
- MsgId topicRootId,
- PeerId migratedPeerId,
- UniversalMsgId universalId)
- : peerId(peerId)
- , topicRootId(topicRootId)
- , migratedPeerId(topicRootId ? 0 : migratedPeerId)
- , universalId(universalId) {
- }
- friend inline constexpr bool operator==(
- const Key &,
- const Key &) = default;
- PeerId peerId = 0;
- MsgId topicRootId = 0;
- PeerId migratedPeerId = 0;
- UniversalMsgId universalId = 0;
- };
- SparseIdsMergedSlice(Key key);
- SparseIdsMergedSlice(
- Key key,
- SparseIdsSlice part,
- std::optional<SparseIdsSlice> migrated);
- SparseIdsMergedSlice(
- Key key,
- SparseUnsortedIdsSlice unsorted);
- std::optional<int> fullCount() const;
- std::optional<int> skippedBefore() const;
- std::optional<int> skippedAfter() const;
- std::optional<int> indexOf(FullMsgId fullId) const;
- int size() const;
- FullMsgId operator[](int index) const;
- std::optional<int> distance(const Key &a, const Key &b) const;
- std::optional<FullMsgId> nearest(UniversalMsgId id) const;
- using SimpleViewerFunction = rpl::producer<SparseIdsSlice>(
- PeerId peerId,
- MsgId topicRootId,
- SparseIdsSlice::Key simpleKey,
- int limitBefore,
- int limitAfter);
- static rpl::producer<SparseIdsMergedSlice> CreateViewer(
- SparseIdsMergedSlice::Key key,
- int limitBefore,
- int limitAfter,
- Fn<SimpleViewerFunction> simpleViewer);
- private:
- static SparseIdsSlice::Key PartKey(const Key &key) {
- return (key.universalId < 0) ? 1 : key.universalId;
- }
- static SparseIdsSlice::Key MigratedKey(const Key &key) {
- return (key.universalId < 0)
- ? (ServerMaxMsgId + key.universalId)
- : (key.universalId > 0) ? (ServerMaxMsgId - 1) : 0;
- }
- static std::optional<SparseIdsSlice> MigratedSlice(const Key &key) {
- return key.migratedPeerId
- ? base::make_optional(SparseIdsSlice())
- : std::nullopt;
- }
- static bool IsFromSlice(PeerId peerId, FullMsgId fullId) {
- return (peerId == fullId.peer);
- }
- static FullMsgId ComputeId(PeerId peerId, MsgId msgId) {
- return FullMsgId(peerId, msgId);
- }
- static FullMsgId ComputeId(const Key &key) {
- return (key.universalId >= 0)
- ? ComputeId(key.peerId, key.universalId)
- : ComputeId(key.migratedPeerId, ServerMaxMsgId + key.universalId);
- }
- static std::optional<int> Add(
- const std::optional<int> &a,
- const std::optional<int> &b) {
- return (a && b) ? base::make_optional(*a + *b) : std::nullopt;
- }
- bool isFromPart(FullMsgId fullId) const {
- return IsFromSlice(_key.peerId, fullId);
- }
- bool isFromMigrated(FullMsgId fullId) const {
- return _migrated
- ? IsFromSlice(_key.migratedPeerId, fullId)
- : false;
- }
- int migratedSize() const {
- return isolatedInPart() ? 0 : _migrated->size();
- }
- bool isolatedInPart() const {
- return IsServerMsgId(_key.universalId)
- && (!_migrated || _part.skippedBefore() != 0);
- }
- bool isolatedInMigrated() const {
- return IsServerMsgId(ServerMaxMsgId + _key.universalId)
- && (_migrated->skippedAfter() != 0);
- }
- Key _key;
- SparseIdsSlice _part;
- std::optional<SparseIdsSlice> _migrated;
- std::optional<SparseUnsortedIdsSlice> _unsorted;
- };
- class SparseIdsSliceBuilder {
- public:
- using Key = SparseIdsSlice::Key;
- SparseIdsSliceBuilder(Key key, int limitBefore, int limitAfter);
- bool applyInitial(const Storage::SparseIdsListResult &result);
- bool applyUpdate(const Storage::SparseIdsSliceUpdate &update);
- bool removeOne(MsgId messageId);
- bool removeAll();
- bool invalidateBottom();
- void checkInsufficient();
- struct AroundData {
- MsgId aroundId = 0;
- Data::LoadDirection direction = Data::LoadDirection::Around;
- inline bool operator<(const AroundData &other) const {
- return (aroundId < other.aroundId)
- || ((aroundId == other.aroundId)
- && (direction < other.direction));
- }
- };
- auto insufficientAround() const {
- return _insufficientAround.events();
- }
- SparseIdsSlice snapshot() const;
- private:
- enum class RequestDirection {
- Before,
- After,
- };
- void requestMessages(RequestDirection direction);
- void requestMessagesCount();
- void fillSkippedAndSliceToLimits();
- void sliceToLimits();
- void mergeSliceData(
- std::optional<int> count,
- const base::flat_set<MsgId> &messageIds,
- std::optional<int> skippedBefore = std::nullopt,
- std::optional<int> skippedAfter = std::nullopt);
- Key _key;
- base::flat_set<MsgId> _ids;
- std::optional<int> _fullCount;
- std::optional<int> _skippedBefore;
- std::optional<int> _skippedAfter;
- int _limitBefore = 0;
- int _limitAfter = 0;
- rpl::event_stream<AroundData> _insufficientAround;
- };
|