Open ilya-fedin opened 1 year ago
The structures look like:
using int64 = long long;
using uint64 = unsigned long long;
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;
};
using BareId = uint64;
struct PeerIdZeroHelper {
};
using PeerIdZero = void(PeerIdZeroHelper::*)();
template <uint8 Shift>
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) {
}
friend inline constexpr auto operator<=>(
ChatIdType,
ChatIdType) = default;
[[nodiscard]] constexpr explicit operator bool() const noexcept {
return (bare != 0);
}
[[nodiscard]] constexpr bool operator!() const noexcept {
return !bare;
}
};
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 <uchar Shift>
constexpr PeerId(ChatIdType<Shift> 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) {
}
friend inline constexpr auto operator<=>(PeerId, PeerId) = default;
template <typename SomeChatIdType, BareId = SomeChatIdType::kShift>
[[nodiscard]] constexpr bool is() const noexcept {
return ((value >> 48) & BareId(0xFF)) == SomeChatIdType::kShift;
}
template <typename SomeChatIdType, BareId = SomeChatIdType::kShift>
[[nodiscard]] constexpr SomeChatIdType to() const noexcept {
return is<SomeChatIdType>() ? (value & kChatTypeMask) : 0;
}
[[nodiscard]] constexpr explicit operator bool() const noexcept {
return (value != 0);
}
[[nodiscard]] constexpr bool operator!() const noexcept {
return !value;
}
};
struct ContextId {
uint64 sessionId = 0;
PeerId peerId = 0;
MsgId topicRootId = 0;
friend inline auto operator<=>(
const ContextId&,
const ContextId&) = default;
};
struct NotificationId {
ContextId contextId;
MsgId msgId = 0;
friend inline auto operator<=>(
const NotificationId&,
const NotificationId&) = default;
};
I expected boost::pfr::structure_to_tuple<NotificationId>
to return std::tuple<std::tuple<uint64, uint64, int64>, int64>
or std::tuple<std::tuple<uint64, std::tuple<uint64>, std::tuple<int64>>, std::tuple<int64>>
but I got std::tuple<ContextId, MsgId>
My use-case is to send a structure that has other structures as members via D-Bus. The D-Bus library accepts std::tuple so structure_to_tuple/structure_tie seems like a good fit to convert a structure into a tuple and back. Sadly it seems they convert only the top-level structure...