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