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 using BareId = uint64;
11
12 struct PeerIdZeroHelper {
13 };
14 using PeerIdZero = void(PeerIdZeroHelper::*)();
15
16 template <uint8 Shift>
17 struct ChatIdType {
18 BareId bare = 0;
19 static constexpr BareId kShift = Shift;
20 static constexpr BareId kReservedBit = BareId(0x80);
21 static_assert((Shift & kReservedBit) == 0, "Last bit is reserved.");
22
23 constexpr ChatIdType() noexcept = default;
24 //constexpr ChatIdType(PeerIdZero) noexcept { // UserId id = 0;
25 //}
ChatIdTypeChatIdType26 constexpr ChatIdType(BareId value) noexcept : bare(value) {
27 }
ChatIdTypeChatIdType28 constexpr ChatIdType(MTPlong value) noexcept : bare(value.v) {
29 }
30
31 [[nodiscard]] constexpr explicit operator bool() const noexcept {
32 return (bare != 0);
33 }
34 [[nodiscard]] constexpr bool operator!() const noexcept {
35 return !bare;
36 }
37
38 };
39
40 template <uchar Shift>
41 [[nodiscard]] inline constexpr bool operator==(
42 ChatIdType<Shift> a,
43 ChatIdType<Shift> b) noexcept {
44 return (a.bare == b.bare);
45 }
46
47 template <uchar Shift>
48 [[nodiscard]] inline constexpr bool operator!=(
49 ChatIdType<Shift> a,
50 ChatIdType<Shift> b) noexcept {
51 return (a.bare != b.bare);
52 }
53
54 template <uchar Shift>
55 [[nodiscard]] inline constexpr bool operator<(
56 ChatIdType<Shift> a,
57 ChatIdType<Shift> b) noexcept {
58 return (a.bare < b.bare);
59 }
60
61 template <uchar Shift>
62 [[nodiscard]] inline constexpr bool operator>(
63 ChatIdType<Shift> a,
64 ChatIdType<Shift> b) noexcept {
65 return (a.bare > b.bare);
66 }
67
68 template <uchar Shift>
69 [[nodiscard]] inline constexpr bool operator<=(
70 ChatIdType<Shift> a,
71 ChatIdType<Shift> b) noexcept {
72 return (a.bare <= b.bare);
73 }
74
75 template <uchar Shift>
76 [[nodiscard]] inline constexpr bool operator>=(
77 ChatIdType<Shift> a,
78 ChatIdType<Shift> b) noexcept {
79 return (a.bare >= b.bare);
80 }
81
82 template <uchar Shift>
83 [[nodiscard]] inline constexpr bool operator==(
84 ChatIdType<Shift> a,
85 PeerIdZero) noexcept {
86 return (a.bare == 0);
87 }
88
89 template <uchar Shift>
90 [[nodiscard]] inline constexpr bool operator==(
91 PeerIdZero,
92 ChatIdType<Shift> a) noexcept {
93 return (0 == a.bare);
94 }
95
96 template <uchar Shift>
97 [[nodiscard]] inline constexpr bool operator!=(
98 ChatIdType<Shift> a,
99 PeerIdZero) noexcept {
100 return (a.bare != 0);
101 }
102
103 template <uchar Shift>
104 [[nodiscard]] inline constexpr bool operator!=(
105 PeerIdZero,
106 ChatIdType<Shift> a) noexcept {
107 return (0 != a.bare);
108 }
109
110 template <uchar Shift>
111 bool operator<(ChatIdType<Shift>, PeerIdZero) = delete;
112
113 template <uchar Shift>
114 bool operator<(PeerIdZero, ChatIdType<Shift>) = delete;
115
116 template <uchar Shift>
117 bool operator>(ChatIdType<Shift>, PeerIdZero) = delete;
118
119 template <uchar Shift>
120 bool operator>(PeerIdZero, ChatIdType<Shift>) = delete;
121
122 template <uchar Shift>
123 bool operator<=(ChatIdType<Shift>, PeerIdZero) = delete;
124
125 template <uchar Shift>
126 bool operator<=(PeerIdZero, ChatIdType<Shift>) = delete;
127
128 template <uchar Shift>
129 bool operator>=(ChatIdType<Shift>, PeerIdZero) = delete;
130
131 template <uchar Shift>
132 bool operator>=(PeerIdZero, ChatIdType<Shift>) = delete;
133
134 using UserId = ChatIdType<0>;
135 using ChatId = ChatIdType<1>;
136 using ChannelId = ChatIdType<2>;
137 using FakeChatId = ChatIdType<0x7F>;
138
139 inline constexpr auto NoChannel = ChannelId(0);
140
141 struct PeerIdHelper {
142 BareId value = 0;
PeerIdHelperPeerIdHelper143 constexpr PeerIdHelper(BareId value) noexcept : value(value) {
144 }
145 };
146
147 struct PeerId {
148 BareId value = 0;
149 static constexpr BareId kChatTypeMask = BareId(0xFFFFFFFFFFFFULL);
150
151 constexpr PeerId() noexcept = default;
PeerIdPeerId152 constexpr PeerId(PeerIdZero) noexcept { // PeerId id = 0;
153 }
154 template <uchar Shift>
PeerIdPeerId155 constexpr PeerId(ChatIdType<Shift> id) noexcept
156 : value(id.bare | (BareId(Shift) << 48)) {
157 }
158 // This instead of explicit PeerId(BareId) allows to use both
159 // PeerId(uint64(..)) and PeerId(0).
PeerIdPeerId160 constexpr PeerId(PeerIdHelper value) noexcept : value(value.value) {
161 }
162
163 template <typename SomeChatIdType, BareId = SomeChatIdType::kShift>
isPeerId164 [[nodiscard]] constexpr bool is() const noexcept {
165 return ((value >> 48) & BareId(0xFF)) == SomeChatIdType::kShift;
166 }
167
168 template <typename SomeChatIdType, BareId = SomeChatIdType::kShift>
toPeerId169 [[nodiscard]] constexpr SomeChatIdType to() const noexcept {
170 return is<SomeChatIdType>() ? (value & kChatTypeMask) : 0;
171 }
172
173 [[nodiscard]] constexpr explicit operator bool() const noexcept {
174 return (value != 0);
175 }
176 [[nodiscard]] constexpr bool operator!() const noexcept {
177 return !value;
178 }
179
180 };
181
182 [[nodiscard]] inline constexpr bool operator==(PeerId a, PeerId b) noexcept {
183 return (a.value == b.value);
184 }
185
186 [[nodiscard]] inline constexpr bool operator!=(PeerId a, PeerId b) noexcept {
187 return (a.value != b.value);
188 }
189
190 [[nodiscard]] inline constexpr bool operator<(PeerId a, PeerId b) noexcept {
191 return (a.value < b.value);
192 }
193
194 [[nodiscard]] inline constexpr bool operator>(PeerId a, PeerId b) noexcept {
195 return (a.value > b.value);
196 }
197
198 [[nodiscard]] inline constexpr bool operator<=(PeerId a, PeerId b) noexcept {
199 return (a.value <= b.value);
200 }
201
202 [[nodiscard]] inline constexpr bool operator>=(PeerId a, PeerId b) noexcept {
203 return (a.value >= b.value);
204 }
205
206 [[nodiscard]] inline constexpr bool operator==(
207 PeerId a,
208 PeerIdZero) noexcept {
209 return (a.value == 0);
210 }
211
212 [[nodiscard]] inline constexpr bool operator==(
213 PeerIdZero,
214 PeerId a) noexcept {
215 return (0 == a.value);
216 }
217
218 [[nodiscard]] inline constexpr bool operator!=(
219 PeerId a,
220 PeerIdZero) noexcept {
221 return (a.value != 0);
222 }
223
224 [[nodiscard]] inline constexpr bool operator!=(
225 PeerIdZero,
226 PeerId a) noexcept {
227 return (0 != a.value);
228 }
229
230 bool operator<(PeerId, PeerIdZero) = delete;
231 bool operator<(PeerIdZero, PeerId) = delete;
232 bool operator>(PeerId, PeerIdZero) = delete;
233 bool operator>(PeerIdZero, PeerId) = delete;
234 bool operator<=(PeerId, PeerIdZero) = delete;
235 bool operator<=(PeerIdZero, PeerId) = delete;
236 bool operator>=(PeerId, PeerIdZero) = delete;
237 bool operator>=(PeerIdZero, PeerId) = delete;
238
peerIsUser(PeerId id)239 [[nodiscard]] inline constexpr bool peerIsUser(PeerId id) noexcept {
240 return id.is<UserId>();
241 }
242
peerIsChat(PeerId id)243 [[nodiscard]] inline constexpr bool peerIsChat(PeerId id) noexcept {
244 return id.is<ChatId>();
245 }
246
peerIsChannel(PeerId id)247 [[nodiscard]] inline constexpr bool peerIsChannel(PeerId id) noexcept {
248 return id.is<ChannelId>();
249 }
250
peerFromUser(UserId userId)251 [[nodiscard]] inline constexpr PeerId peerFromUser(UserId userId) noexcept {
252 return userId;
253 }
254
peerFromChat(ChatId chatId)255 [[nodiscard]] inline constexpr PeerId peerFromChat(ChatId chatId) noexcept {
256 return chatId;
257 }
258
peerFromChannel(ChannelId channelId)259 [[nodiscard]] inline constexpr PeerId peerFromChannel(
260 ChannelId channelId) noexcept {
261 return channelId;
262 }
263
peerFromUser(MTPlong userId)264 [[nodiscard]] inline constexpr PeerId peerFromUser(MTPlong userId) noexcept {
265 return peerFromUser(userId.v);
266 }
267
peerFromChat(MTPint chatId)268 [[nodiscard]] inline constexpr PeerId peerFromChat(MTPint chatId) noexcept {
269 return peerFromChat(chatId.v);
270 }
271
peerFromChannel(MTPint channelId)272 [[nodiscard]] inline constexpr PeerId peerFromChannel(
273 MTPint channelId) noexcept {
274 return peerFromChannel(channelId.v);
275 }
276
peerToUser(PeerId id)277 [[nodiscard]] inline constexpr UserId peerToUser(PeerId id) noexcept {
278 return id.to<UserId>();
279 }
280
peerToChat(PeerId id)281 [[nodiscard]] inline constexpr ChatId peerToChat(PeerId id) noexcept {
282 return id.to<ChatId>();
283 }
284
peerToChannel(PeerId id)285 [[nodiscard]] inline constexpr ChannelId peerToChannel(PeerId id) noexcept {
286 return id.to<ChannelId>();
287 }
288
peerToBareMTPInt(PeerId id)289 [[nodiscard]] inline MTPlong peerToBareMTPInt(PeerId id) {
290 return MTP_long(id.value & PeerId::kChatTypeMask);
291 }
292
293 [[nodiscard]] PeerId peerFromMTP(const MTPPeer &peer);
294 [[nodiscard]] MTPpeer peerToMTP(PeerId id);
295
296 // Supports both modern and legacy serializations.
297 [[nodiscard]] PeerId DeserializePeerId(quint64 serialized);
298 [[nodiscard]] quint64 SerializePeerId(PeerId id);
299
300 namespace std {
301
302 template <uchar Shift>
303 struct hash<ChatIdType<Shift>> : private hash<BareId> {
304 size_t operator()(ChatIdType<Shift> value) const noexcept {
305 return hash<BareId>::operator()(value.bare);
306 }
307 };
308
309 template <>
310 struct hash<PeerId> : private hash<BareId> {
311 size_t operator()(PeerId value) const noexcept {
312 return hash<BareId>::operator()(value.value);
313 }
314 };
315
316 } // namespace std
317