tdesktop/Telegram/SourceFiles/data/data_msg_id.h
2023-10-26 14:08:40 +04:00

210 lines
5.4 KiB
C++

/*
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 "base/qt/qt_compare.h"
#include "data/data_peer_id.h"
#include "ui/text/text_entity.h"
struct MsgId {
constexpr MsgId() noexcept = default;
constexpr MsgId(int64 value) noexcept : bare(value) {
}
friend inline constexpr auto operator<=>(MsgId, MsgId) = default;
[[nodiscard]] constexpr explicit operator bool() const noexcept {
return (bare != 0);
}
[[nodiscard]] constexpr bool operator!() const noexcept {
return !bare;
}
[[nodiscard]] constexpr MsgId operator-() const noexcept {
return -bare;
}
constexpr MsgId operator++() noexcept {
return ++bare;
}
constexpr MsgId operator++(int) noexcept {
return bare++;
}
constexpr MsgId operator--() noexcept {
return --bare;
}
constexpr MsgId operator--(int) noexcept {
return bare--;
}
int64 bare = 0;
};
Q_DECLARE_METATYPE(MsgId);
[[nodiscard]] inline constexpr MsgId operator+(MsgId a, MsgId b) noexcept {
return MsgId(a.bare + b.bare);
}
[[nodiscard]] inline constexpr MsgId operator-(MsgId a, MsgId b) noexcept {
return MsgId(a.bare - b.bare);
}
using StoryId = int32;
struct FullStoryId {
PeerId peer = 0;
StoryId story = 0;
[[nodiscard]] bool valid() const {
return peer != 0 && story != 0;
}
explicit operator bool() const {
return valid();
}
friend inline auto operator<=>(FullStoryId, FullStoryId) = default;
friend inline bool operator==(FullStoryId, FullStoryId) = default;
};
constexpr auto StartClientMsgId = MsgId(0x01 - (1LL << 58));
constexpr auto ClientMsgIds = (1LL << 31);
constexpr auto EndClientMsgId = MsgId(StartClientMsgId.bare + ClientMsgIds);
constexpr auto StartStoryMsgId = MsgId(EndClientMsgId.bare + 1);
constexpr auto ServerMaxStoryId = StoryId(1 << 30);
constexpr auto StoryMsgIds = int64(ServerMaxStoryId);
constexpr auto EndStoryMsgId = MsgId(StartStoryMsgId.bare + StoryMsgIds);
constexpr auto ServerMaxMsgId = MsgId(1LL << 56);
constexpr auto ScheduledMsgIdsRange = (1LL << 32);
constexpr auto ShowAtUnreadMsgId = MsgId(0);
constexpr auto SpecialMsgIdShift = EndStoryMsgId.bare;
constexpr auto ShowAtTheEndMsgId = MsgId(SpecialMsgIdShift + 1);
constexpr auto SwitchAtTopMsgId = MsgId(SpecialMsgIdShift + 2);
constexpr auto ShowAndStartBotMsgId = MsgId(SpecialMsgIdShift + 4);
constexpr auto ShowForChooseMessagesMsgId = MsgId(SpecialMsgIdShift + 6);
static_assert(SpecialMsgIdShift + 0xFF < 0);
static_assert(-(SpecialMsgIdShift + 0xFF) > ServerMaxMsgId);
[[nodiscard]] constexpr inline bool IsClientMsgId(MsgId id) noexcept {
return (id >= StartClientMsgId && id < EndClientMsgId);
}
[[nodiscard]] constexpr inline int32 ClientMsgIndex(MsgId id) noexcept {
Expects(IsClientMsgId(id));
return int(id.bare - StartClientMsgId.bare);
}
[[nodiscard]] constexpr inline MsgId ClientMsgByIndex(int32 index) noexcept {
Expects(index >= 0);
return MsgId(StartClientMsgId.bare + index);
}
[[nodiscrd]] constexpr inline bool IsStoryMsgId(MsgId id) noexcept {
return (id >= StartStoryMsgId && id < EndStoryMsgId);
}
[[nodiscard]] constexpr inline StoryId StoryIdFromMsgId(MsgId id) noexcept {
Expects(IsStoryMsgId(id));
return StoryId(id.bare - StartStoryMsgId.bare);
}
[[nodiscard]] constexpr inline MsgId StoryIdToMsgId(StoryId id) noexcept {
Expects(id >= 0);
return MsgId(StartStoryMsgId.bare + id);
}
[[nodiscard]] constexpr inline bool IsServerMsgId(MsgId id) noexcept {
return (id > 0 && id < ServerMaxMsgId);
}
struct MsgRange {
constexpr MsgRange() noexcept = default;
constexpr MsgRange(MsgId from, MsgId till) noexcept
: from(from)
, till(till) {
}
friend inline constexpr bool operator==(MsgRange, MsgRange) = default;
MsgId from = 0;
MsgId till = 0;
};
struct FullMsgId {
constexpr FullMsgId() noexcept = default;
constexpr FullMsgId(PeerId peer, MsgId msg) noexcept
: peer(peer), msg(msg) {
}
FullMsgId(ChannelId channelId, MsgId msgId) = delete;
friend inline constexpr auto operator<=>(FullMsgId, FullMsgId) = default;
constexpr explicit operator bool() const noexcept {
return msg != 0;
}
constexpr bool operator!() const noexcept {
return msg == 0;
}
PeerId peer = 0;
MsgId msg = 0;
};
Q_DECLARE_METATYPE(FullMsgId);
struct FullReplyTo {
FullMsgId messageId;
TextWithTags quote;
FullStoryId storyId;
MsgId topicRootId = 0;
[[nodiscard]] bool valid() const {
return messageId || (storyId && peerIsUser(storyId.peer));
}
explicit operator bool() const {
return valid();
}
friend inline auto operator<=>(FullReplyTo, FullReplyTo) = default;
friend inline bool operator==(FullReplyTo, FullReplyTo) = default;
};
struct GlobalMsgId {
FullMsgId itemId;
uint64 sessionUniqueId = 0;
friend inline constexpr auto operator<=>(
GlobalMsgId,
GlobalMsgId) = default;
constexpr explicit operator bool() const noexcept {
return itemId && sessionUniqueId;
}
constexpr bool operator!() const noexcept {
return !itemId || !sessionUniqueId;
}
};
namespace std {
template <>
struct hash<MsgId> : private hash<int64> {
size_t operator()(MsgId value) const noexcept {
return hash<int64>::operator()(value.bare);
}
};
template <>
struct hash<FullStoryId> {
size_t operator()(FullStoryId value) const {
return QtPrivate::QHashCombine().operator()(
std::hash<BareId>()(value.peer.value),
value.story);
}
};
} // namespace std