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 #include "data/data_peer_id.h"
11 
12 struct MsgId {
13 	constexpr MsgId() noexcept = default;
MsgIdMsgId14 	constexpr MsgId(int64 value) noexcept : bare(value) {
15 	}
16 
17 	[[nodiscard]] constexpr explicit operator bool() const noexcept {
18 		return (bare != 0);
19 	}
20 	[[nodiscard]] constexpr bool operator!() const noexcept {
21 		return !bare;
22 	}
23 	[[nodiscard]] constexpr MsgId operator-() const noexcept {
24 		return -bare;
25 	}
26 	constexpr MsgId operator++() noexcept {
27 		return ++bare;
28 	}
29 	constexpr MsgId operator++(int) noexcept {
30 		return bare++;
31 	}
32 	constexpr MsgId operator--() noexcept {
33 		return --bare;
34 	}
35 	constexpr MsgId operator--(int) noexcept {
36 		return bare--;
37 	}
38 
39 	int64 bare = 0;
40 };
41 
42 Q_DECLARE_METATYPE(MsgId);
43 
44 [[nodiscard]] inline constexpr MsgId operator+(MsgId a, MsgId b) noexcept {
45 	return MsgId(a.bare + b.bare);
46 }
47 
48 [[nodiscard]] inline constexpr MsgId operator-(MsgId a, MsgId b) noexcept {
49 	return MsgId(a.bare - b.bare);
50 }
51 
52 [[nodiscard]] inline constexpr bool operator==(MsgId a, MsgId b) noexcept {
53 	return (a.bare == b.bare);
54 }
55 
56 [[nodiscard]] inline constexpr bool operator!=(MsgId a, MsgId b) noexcept {
57 	return (a.bare != b.bare);
58 }
59 
60 [[nodiscard]] inline constexpr bool operator<(MsgId a, MsgId b) noexcept {
61 	return (a.bare < b.bare);
62 }
63 
64 [[nodiscard]] inline constexpr bool operator>(MsgId a, MsgId b) noexcept {
65 	return (a.bare > b.bare);
66 }
67 
68 [[nodiscard]] inline constexpr bool operator<=(MsgId a, MsgId b) noexcept {
69 	return (a.bare <= b.bare);
70 }
71 
72 [[nodiscard]] inline constexpr bool operator>=(MsgId a, MsgId b) noexcept {
73 	return (a.bare >= b.bare);
74 }
75 
76 constexpr auto StartClientMsgId = MsgId(0x01 - (1LL << 58));
77 constexpr auto EndClientMsgId = MsgId(-(1LL << 57));
78 constexpr auto ServerMaxMsgId = MsgId(1LL << 56);
79 constexpr auto ShowAtUnreadMsgId = MsgId(0);
80 
81 constexpr auto SpecialMsgIdShift = EndClientMsgId.bare;
82 constexpr auto ShowAtTheEndMsgId = MsgId(SpecialMsgIdShift + 1);
83 constexpr auto SwitchAtTopMsgId = MsgId(SpecialMsgIdShift + 2);
84 constexpr auto ShowAtProfileMsgId = MsgId(SpecialMsgIdShift + 3);
85 constexpr auto ShowAndStartBotMsgId = MsgId(SpecialMsgIdShift + 4);
86 constexpr auto ShowAtGameShareMsgId = MsgId(SpecialMsgIdShift + 5);
87 constexpr auto ShowForChooseMessagesMsgId = MsgId(SpecialMsgIdShift + 6);
88 
89 static_assert(SpecialMsgIdShift + 0xFF < 0);
90 static_assert(-(SpecialMsgIdShift + 0xFF) > ServerMaxMsgId);
91 
IsClientMsgId(MsgId id)92 [[nodiscard]] constexpr inline bool IsClientMsgId(MsgId id) noexcept {
93 	return (id >= StartClientMsgId && id < EndClientMsgId);
94 }
95 
IsServerMsgId(MsgId id)96 [[nodiscard]] constexpr inline bool IsServerMsgId(MsgId id) noexcept {
97 	return (id > 0 && id < ServerMaxMsgId);
98 }
99 
100 struct MsgRange {
101 	constexpr MsgRange() noexcept = default;
MsgRangeMsgRange102 	constexpr MsgRange(MsgId from, MsgId till) noexcept
103 	: from(from)
104 	, till(till) {
105 	}
106 
107 	MsgId from = 0;
108 	MsgId till = 0;
109 };
110 
111 [[nodiscard]] inline constexpr bool operator==(
112 		MsgRange a,
113 		MsgRange b) noexcept {
114 	return (a.from == b.from) && (a.till == b.till);
115 }
116 
117 [[nodiscard]] inline constexpr bool operator!=(
118 		MsgRange a,
119 		MsgRange b) noexcept {
120 	return !(a == b);
121 }
122 
123 struct FullMsgId {
124 	constexpr FullMsgId() noexcept = default;
FullMsgIdFullMsgId125 	constexpr FullMsgId(ChannelId channel, MsgId msg) noexcept
126 	: channel(channel), msg(msg) {
127 	}
128 
129 	constexpr explicit operator bool() const noexcept {
130 		return msg != 0;
131 	}
132 	constexpr bool operator!() const noexcept {
133 		return msg == 0;
134 	}
135 
136 	ChannelId channel = NoChannel;
137 	MsgId msg = 0;
138 };
139 
140 [[nodiscard]] inline constexpr bool operator<(
141 		const FullMsgId &a,
142 		const FullMsgId &b) noexcept {
143 	if (a.channel < b.channel) {
144 		return true;
145 	} else if (a.channel > b.channel) {
146 		return false;
147 	}
148 	return a.msg < b.msg;
149 }
150 
151 [[nodiscard]] inline constexpr bool operator>(
152 		const FullMsgId &a,
153 		const FullMsgId &b) noexcept {
154 	return b < a;
155 }
156 
157 [[nodiscard]] inline constexpr bool operator<=(
158 		const FullMsgId &a,
159 		const FullMsgId &b) noexcept {
160 	return !(b < a);
161 }
162 
163 [[nodiscard]] inline constexpr bool operator>=(
164 		const FullMsgId &a,
165 		const FullMsgId &b) noexcept {
166 	return !(a < b);
167 }
168 
169 [[nodiscard]] inline constexpr bool operator==(
170 		const FullMsgId &a,
171 		const FullMsgId &b) noexcept {
172 	return (a.channel == b.channel) && (a.msg == b.msg);
173 }
174 
175 [[nodiscard]] inline constexpr bool operator!=(
176 		const FullMsgId &a,
177 		const FullMsgId &b) noexcept {
178 	return !(a == b);
179 }
180 
181 Q_DECLARE_METATYPE(FullMsgId);
182 
183 namespace std {
184 
185 template <>
186 struct hash<MsgId> : private hash<int64> {
187 	size_t operator()(MsgId value) const noexcept {
188 		return hash<int64>::operator()(value.bare);
189 	}
190 };
191 
192 } // namespace std
193