/* 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 using BareId = uint64; struct PeerIdZeroHelper { }; using PeerIdZero = void(PeerIdZeroHelper::*)(); template struct ChatIdType { BareId bare = 0; static constexpr BareId kShift = Shift; static constexpr BareId kReservedBit = BareId(0x80); static_assert((Shift & kReservedBit) == 0, "Last bit is reserved."); constexpr ChatIdType() noexcept = default; //constexpr ChatIdType(PeerIdZero) noexcept { // UserId id = 0; //} constexpr ChatIdType(BareId value) noexcept : bare(value) { } constexpr ChatIdType(MTPlong value) noexcept : bare(value.v) { } [[nodiscard]] constexpr explicit operator bool() const noexcept { return (bare != 0); } [[nodiscard]] constexpr bool operator!() const noexcept { return !bare; } }; template [[nodiscard]] inline constexpr bool operator==( ChatIdType a, ChatIdType b) noexcept { return (a.bare == b.bare); } template [[nodiscard]] inline constexpr bool operator!=( ChatIdType a, ChatIdType b) noexcept { return (a.bare != b.bare); } template [[nodiscard]] inline constexpr bool operator<( ChatIdType a, ChatIdType b) noexcept { return (a.bare < b.bare); } template [[nodiscard]] inline constexpr bool operator>( ChatIdType a, ChatIdType b) noexcept { return (a.bare > b.bare); } template [[nodiscard]] inline constexpr bool operator<=( ChatIdType a, ChatIdType b) noexcept { return (a.bare <= b.bare); } template [[nodiscard]] inline constexpr bool operator>=( ChatIdType a, ChatIdType b) noexcept { return (a.bare >= b.bare); } template [[nodiscard]] inline constexpr bool operator==( ChatIdType a, PeerIdZero) noexcept { return (a.bare == 0); } template [[nodiscard]] inline constexpr bool operator==( PeerIdZero, ChatIdType a) noexcept { return (0 == a.bare); } template [[nodiscard]] inline constexpr bool operator!=( ChatIdType a, PeerIdZero) noexcept { return (a.bare != 0); } template [[nodiscard]] inline constexpr bool operator!=( PeerIdZero, ChatIdType a) noexcept { return (0 != a.bare); } template bool operator<(ChatIdType, PeerIdZero) = delete; template bool operator<(PeerIdZero, ChatIdType) = delete; template bool operator>(ChatIdType, PeerIdZero) = delete; template bool operator>(PeerIdZero, ChatIdType) = delete; template bool operator<=(ChatIdType, PeerIdZero) = delete; template bool operator<=(PeerIdZero, ChatIdType) = delete; template bool operator>=(ChatIdType, PeerIdZero) = delete; template bool operator>=(PeerIdZero, ChatIdType) = delete; using UserId = ChatIdType<0>; using ChatId = ChatIdType<1>; using ChannelId = ChatIdType<2>; using FakeChatId = ChatIdType<0x7F>; struct PeerIdHelper { BareId value = 0; constexpr PeerIdHelper(BareId value) noexcept : value(value) { } }; struct PeerId { BareId value = 0; static constexpr BareId kChatTypeMask = BareId(0xFFFFFFFFFFFFULL); constexpr PeerId() noexcept = default; constexpr PeerId(PeerIdZero) noexcept { // PeerId id = 0; } template constexpr PeerId(ChatIdType id) noexcept : value(id.bare | (BareId(Shift) << 48)) { } // This instead of explicit PeerId(BareId) allows to use both // PeerId(uint64(..)) and PeerId(0). constexpr PeerId(PeerIdHelper value) noexcept : value(value.value) { } template [[nodiscard]] constexpr bool is() const noexcept { return ((value >> 48) & BareId(0xFF)) == SomeChatIdType::kShift; } template [[nodiscard]] constexpr SomeChatIdType to() const noexcept { return is() ? (value & kChatTypeMask) : 0; } [[nodiscard]] constexpr explicit operator bool() const noexcept { return (value != 0); } [[nodiscard]] constexpr bool operator!() const noexcept { return !value; } }; [[nodiscard]] inline constexpr bool operator==(PeerId a, PeerId b) noexcept { return (a.value == b.value); } [[nodiscard]] inline constexpr bool operator!=(PeerId a, PeerId b) noexcept { return (a.value != b.value); } [[nodiscard]] inline constexpr bool operator<(PeerId a, PeerId b) noexcept { return (a.value < b.value); } [[nodiscard]] inline constexpr bool operator>(PeerId a, PeerId b) noexcept { return (a.value > b.value); } [[nodiscard]] inline constexpr bool operator<=(PeerId a, PeerId b) noexcept { return (a.value <= b.value); } [[nodiscard]] inline constexpr bool operator>=(PeerId a, PeerId b) noexcept { return (a.value >= b.value); } [[nodiscard]] inline constexpr bool operator==( PeerId a, PeerIdZero) noexcept { return (a.value == 0); } [[nodiscard]] inline constexpr bool operator==( PeerIdZero, PeerId a) noexcept { return (0 == a.value); } [[nodiscard]] inline constexpr bool operator!=( PeerId a, PeerIdZero) noexcept { return (a.value != 0); } [[nodiscard]] inline constexpr bool operator!=( PeerIdZero, PeerId a) noexcept { return (0 != a.value); } bool operator<(PeerId, PeerIdZero) = delete; bool operator<(PeerIdZero, PeerId) = delete; bool operator>(PeerId, PeerIdZero) = delete; bool operator>(PeerIdZero, PeerId) = delete; bool operator<=(PeerId, PeerIdZero) = delete; bool operator<=(PeerIdZero, PeerId) = delete; bool operator>=(PeerId, PeerIdZero) = delete; bool operator>=(PeerIdZero, PeerId) = delete; [[nodiscard]] inline constexpr bool peerIsUser(PeerId id) noexcept { return id.is(); } [[nodiscard]] inline constexpr bool peerIsChat(PeerId id) noexcept { return id.is(); } [[nodiscard]] inline constexpr bool peerIsChannel(PeerId id) noexcept { return id.is(); } [[nodiscard]] inline constexpr PeerId peerFromUser(UserId userId) noexcept { return userId; } [[nodiscard]] inline constexpr PeerId peerFromChat(ChatId chatId) noexcept { return chatId; } [[nodiscard]] inline constexpr PeerId peerFromChannel( ChannelId channelId) noexcept { return channelId; } [[nodiscard]] inline constexpr PeerId peerFromUser(MTPlong userId) noexcept { return peerFromUser(userId.v); } [[nodiscard]] inline constexpr PeerId peerFromChat(MTPint chatId) noexcept { return peerFromChat(chatId.v); } [[nodiscard]] inline constexpr PeerId peerFromChannel( MTPint channelId) noexcept { return peerFromChannel(channelId.v); } [[nodiscard]] inline constexpr UserId peerToUser(PeerId id) noexcept { return id.to(); } [[nodiscard]] inline constexpr ChatId peerToChat(PeerId id) noexcept { return id.to(); } [[nodiscard]] inline constexpr ChannelId peerToChannel(PeerId id) noexcept { return id.to(); } [[nodiscard]] inline MTPlong peerToBareMTPInt(PeerId id) { return MTP_long(id.value & PeerId::kChatTypeMask); } [[nodiscard]] PeerId peerFromMTP(const MTPPeer &peer); [[nodiscard]] MTPpeer peerToMTP(PeerId id); // Supports both modern and legacy serializations. [[nodiscard]] PeerId DeserializePeerId(quint64 serialized); [[nodiscard]] quint64 SerializePeerId(PeerId id); namespace std { template struct hash> : private hash { size_t operator()(ChatIdType value) const noexcept { return hash::operator()(value.bare); } }; template <> struct hash : private hash { size_t operator()(PeerId value) const noexcept { return hash::operator()(value.value); } }; } // namespace std