1 /* 2 This file is part of Telegram Desktop, 3 the official desktop application for the Telegram messaging service. 4 5 For license and copyright information please follow this link: 6 https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL 7 */ 8 #pragma once 9 10 namespace Storage { 11 12 struct SparseIdsListQuery { SparseIdsListQuerySparseIdsListQuery13 SparseIdsListQuery( 14 MsgId aroundId, 15 int limitBefore, 16 int limitAfter) 17 : aroundId(aroundId) 18 , limitBefore(limitBefore) 19 , limitAfter(limitAfter) { 20 } 21 22 MsgId aroundId = 0; 23 int limitBefore = 0; 24 int limitAfter = 0; 25 26 }; 27 28 struct SparseIdsListResult { 29 std::optional<int> count; 30 std::optional<int> skippedBefore; 31 std::optional<int> skippedAfter; 32 base::flat_set<MsgId> messageIds; 33 }; 34 35 struct SparseIdsSliceUpdate { 36 const base::flat_set<MsgId> *messages = nullptr; 37 MsgRange range; 38 std::optional<int> count; 39 }; 40 41 class SparseIdsList { 42 public: 43 void addNew(MsgId messageId); 44 void addExisting(MsgId messageId, MsgRange noSkipRange); 45 void addSlice( 46 std::vector<MsgId> &&messageIds, 47 MsgRange noSkipRange, 48 std::optional<int> count); 49 void removeOne(MsgId messageId); 50 void removeAll(); 51 void invalidateBottom(); 52 rpl::producer<SparseIdsListResult> query(SparseIdsListQuery &&query) const; 53 rpl::producer<SparseIdsSliceUpdate> sliceUpdated() const; 54 SparseIdsListResult snapshot(const SparseIdsListQuery &query) const; 55 bool empty() const; 56 57 private: 58 struct Slice { 59 Slice(base::flat_set<MsgId> &&messages, MsgRange range); 60 61 template <typename Range> 62 void merge(const Range &moreMessages, MsgRange moreNoSkipRange); 63 64 base::flat_set<MsgId> messages; 65 MsgRange range; 66 67 inline bool operator<(const Slice &other) const { 68 return range.from < other.range.from; 69 } 70 71 }; 72 73 struct AddResult { 74 int added = 0; 75 }; 76 template <typename Range> 77 AddResult uniteAndAdd( 78 SparseIdsSliceUpdate &update, 79 base::flat_set<Slice>::iterator uniteFrom, 80 base::flat_set<Slice>::iterator uniteTill, 81 const Range &messages, 82 MsgRange noSkipRange); 83 template <typename Range> 84 AddResult addRangeItemsAndCountNew( 85 SparseIdsSliceUpdate &update, 86 const Range &messages, 87 MsgRange noSkipRange); 88 template <typename Range> 89 void addRange( 90 const Range &messages, 91 MsgRange noSkipRange, 92 std::optional<int> count, 93 bool incrementCount = false); 94 95 SparseIdsListResult queryFromSlice( 96 const SparseIdsListQuery &query, 97 const Slice &slice) const; 98 99 std::optional<int> _count; 100 base::flat_set<Slice> _slices; 101 102 rpl::event_stream<SparseIdsSliceUpdate> _sliceUpdated; 103 104 }; 105 106 } // namespace Storage 107